UIImage颜色改变?

发布于 2024-08-10 17:27:07 字数 84 浏览 7 评论 0原文

如何通过编程改变UIImage的颜色,请帮忙?如果我发送 UIImage,其颜色需要更改,有什么帮助吗?如果我通过位图处理更改 RGB 颜色,则不起作用。

How can I change the UIImage's color through programming, any help please? If I send a UIImage, its color needs to change any help please? If I change the RGB color through bitmaphandling, it does not work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

野生奥特曼 2024-08-17 17:27:07

如果您只需要它看起来不同,只需使用imageView.tintColor(iOS 7+)。问题是,设置 tintColor 默认情况下不会执行任何操作:

为什么我的图像不是蓝色的?我正在设置tintColor...

要使其工作,请使用imageWithRenderingMode:

var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)

let imageView = ...
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)
imageView.image = image

现在它可以工作:

现在图像是橙色的!

文档链接。


性能

配置 UIImageView 后设置图像可避免重复昂贵的操作:

// Good usage
let imageView = ...
imageView.tintColor = yourTintColor
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
imageView.image = image        // Expensive

// Bad usage
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
let imageView = ...
imageView.image = image        // Expensive
imageView.frame = ...          // Expensive
imageView.tintColor = yourTint // Expensive

Getting &异步设置图像可减少滚动和动画延迟(尤其是在 UICollectionViewCellUITableViewCell 内对图像进行着色时):

let imageView = cell.yourImageView
imageView.image = nil // Clear out old image
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)

// Setting the image asynchronously reduces stuttering 
// while scrolling.  Remember, the image should be set as
// late as possible to avoid repeating expensive operations
// unnecessarily.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
    var image = UIImage(named: "stackoverflow")!
    image = image.imageWithRenderingMode(.AlwaysTemplate)
    imageView.image = image
})

If you only need it to look different, just use imageView.tintColor (iOS 7+). Catch is, setting tintColor doesn't do anything by default:

Why isn't my image blue?  I'm setting tintColor...

To make it work, use imageWithRenderingMode:

var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)

let imageView = ...
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)
imageView.image = image

And now it will work:

Now the image is orange!

Link to documentation.


Performance

Setting the image after configuring the UIImageView avoids repeating expensive operations:

// Good usage
let imageView = ...
imageView.tintColor = yourTintColor
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
imageView.image = image        // Expensive

// Bad usage
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
let imageView = ...
imageView.image = image        // Expensive
imageView.frame = ...          // Expensive
imageView.tintColor = yourTint // Expensive

Getting & setting the image asynchronously reduces scrolling and animation lag (especially when tinting an image inside of a UICollectionViewCell or UITableViewCell):

let imageView = cell.yourImageView
imageView.image = nil // Clear out old image
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)

// Setting the image asynchronously reduces stuttering 
// while scrolling.  Remember, the image should be set as
// late as possible to avoid repeating expensive operations
// unnecessarily.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
    var image = UIImage(named: "stackoverflow")!
    image = image.imageWithRenderingMode(.AlwaysTemplate)
    imageView.image = image
})
天气好吗我好吗 2024-08-17 17:27:07

实现此目的的一种方法是降低图像的饱和度,并使用您想要的颜色在该图像上添加色调。

去饱和度

-(UIImage *) getImageWithUnsaturatedPixelsOfImage:(UIImage *)image {
    const int RED = 1, GREEN = 2, BLUE = 3;

    CGRect imageRect = CGRectMake(0, 0, image.size.width*2, image.size.height*2);

    int width = imageRect.size.width, height = imageRect.size.height;

    uint32_t * pixels = (uint32_t *) malloc(width*height*sizeof(uint32_t));
    memset(pixels, 0, width * height * sizeof(uint32_t));

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]);

    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            uint8_t * rgbaPixel = (uint8_t *) &pixels[y*width+x];
            uint32_t gray = (0.3*rgbaPixel[RED]+0.59*rgbaPixel[GREEN]+0.11*rgbaPixel[BLUE]);

            rgbaPixel[RED] = gray;
            rgbaPixel[GREEN] = gray;
            rgbaPixel[BLUE] = gray;
        }
    }

    CGImageRef newImage = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);

    UIImage * resultUIImage = [UIImage imageWithCGImage:newImage scale:2 orientation:0];
    CGImageRelease(newImage);

    return resultUIImage;
}

叠加颜色

-(UIImage *) getImageWithTintedColor:(UIImage *)image withTint:(UIColor *)color withIntensity:(float)alpha {
    CGSize size = image.size;

    UIGraphicsBeginImageContextWithOptions(size, FALSE, 2);
    CGContextRef context = UIGraphicsGetCurrentContext();

    [image drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:1.0];

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextSetBlendMode(context, kCGBlendModeOverlay);
    CGContextSetAlpha(context, alpha);

    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(CGPointZero.x, CGPointZero.y, image.size.width, image.size.height));

    UIImage * tintedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return tintedImage;
}

操作方法

//For a UIImageView
yourImageView.image = [self getImageWithUnsaturatedPixelsOfImage:yourImageView.image];
yourImageView.image = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];

//For a UIImage
yourImage = [self getImageWithUnsaturatedPixelsOfImage:yourImage];
yourImage = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];

您可以将色调的颜色更改为您想要的任何颜色。

One way to accomplish this is to desaturate your image, and add a tint on top of that image with the color you desire.

Desaturate

-(UIImage *) getImageWithUnsaturatedPixelsOfImage:(UIImage *)image {
    const int RED = 1, GREEN = 2, BLUE = 3;

    CGRect imageRect = CGRectMake(0, 0, image.size.width*2, image.size.height*2);

    int width = imageRect.size.width, height = imageRect.size.height;

    uint32_t * pixels = (uint32_t *) malloc(width*height*sizeof(uint32_t));
    memset(pixels, 0, width * height * sizeof(uint32_t));

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]);

    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            uint8_t * rgbaPixel = (uint8_t *) &pixels[y*width+x];
            uint32_t gray = (0.3*rgbaPixel[RED]+0.59*rgbaPixel[GREEN]+0.11*rgbaPixel[BLUE]);

            rgbaPixel[RED] = gray;
            rgbaPixel[GREEN] = gray;
            rgbaPixel[BLUE] = gray;
        }
    }

    CGImageRef newImage = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    free(pixels);

    UIImage * resultUIImage = [UIImage imageWithCGImage:newImage scale:2 orientation:0];
    CGImageRelease(newImage);

    return resultUIImage;
}

Overlay With Color

-(UIImage *) getImageWithTintedColor:(UIImage *)image withTint:(UIColor *)color withIntensity:(float)alpha {
    CGSize size = image.size;

    UIGraphicsBeginImageContextWithOptions(size, FALSE, 2);
    CGContextRef context = UIGraphicsGetCurrentContext();

    [image drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:1.0];

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextSetBlendMode(context, kCGBlendModeOverlay);
    CGContextSetAlpha(context, alpha);

    CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(CGPointZero.x, CGPointZero.y, image.size.width, image.size.height));

    UIImage * tintedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return tintedImage;
}

How-To

//For a UIImageView
yourImageView.image = [self getImageWithUnsaturatedPixelsOfImage:yourImageView.image];
yourImageView.image = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];

//For a UIImage
yourImage = [self getImageWithUnsaturatedPixelsOfImage:yourImage];
yourImage = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];

You can change the color of the tint to whatever you desire.

給妳壹絲溫柔 2024-08-17 17:27:07

这里有一篇关于此的很棒的帖子:
http://coffeeshopped.com/2010/09/iphone -how-to-dynamically-color-a-uiimage

我对当前代码的一个警告是,在视网膜图像上使用它会导致这些图像失去更高的“分辨率”。我目前正在寻找解决方案......

There's a great post about this here:
http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage

The one caveat that I have with the current code is that using it on retina images will result in a loss of the higher 'resolution' for these images. I am currently looking for a solution for this...

风渺 2024-08-17 17:27:07

查看我的帖子(主要只是重新混合代码)< /a>.

编辑:此代码基本上创建一个新的CGContext,用新颜色在其上绘制一个图层,并从中返回一个新的UIImage。我已经有一段时间没有深入研究这段代码了,但它似乎只是绘制了一个与原始形状相同的 UIImage ,所以这是一个限制(丢失图像中的任何细节)。

Check out my post (mostly just remixing code).

Edit: This code basically creates a new CGContext, draws a layer on it with the new color, and returns a new UIImage from that. I haven't gone in depth on this code in a while, but it seems to just draw a UIImage with the same shape as the original, so that's a limit (loses any detail in the image).

盗梦空间 2024-08-17 17:27:07

如果您需要高性能,我强烈建议您使用GPUImage
您可以在 https://github.com/BradLarson/GPUImage 下载它

If you need high performance, I strongly recommend you to use GPUImage.
You may download it at https://github.com/BradLarson/GPUImage

左岸枫 2024-08-17 17:27:07

您正在操作的 RGB 数据只是一个副本。完成更改后,您需要将该数据转换回图像。

我首先制作一个新的位图:

CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
ctx = CGBitmapContextCreate( malloc(dataSize), width, height,
                                8, //   CGImageGetBitsPerComponent(cgImage),
                                bytesPerRow, //CGImageGetBytesPerRow(cgImage),
                                space,
                                //kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big );
                                kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
                                //kCGImageAlphaPremultipliedFirst  | kCGBitmapByteOrder32Little);

    CGColorSpaceRelease( space );

// now draw the image into the context
CGRect rect = CGRectMake( 0, 0, CGImageGetWidth(cgImage), CGImageGetHeight(cgImage) );
CGContextDrawImage( ctx, rect, cgImage );

并获取像素:

pixels = CGBitmapContextGetData( ctx );

假设您的像素数据来自 pixels = CGBitmapContextGetData( ctx ); 然后获取该上下文并从中构建一个新图像:

CGImageRef newImg = CGBitmapContextCreateImage(ctx);
[[UIImage imageWithCGImage:newImg] drawInRect:rect];
CGImageRelease(newImg);

The RGB data you are operating on is just a copy. After you finish making changes, you need to turn that data back into an image.

I first make a new bitmap:

CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
ctx = CGBitmapContextCreate( malloc(dataSize), width, height,
                                8, //   CGImageGetBitsPerComponent(cgImage),
                                bytesPerRow, //CGImageGetBytesPerRow(cgImage),
                                space,
                                //kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big );
                                kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
                                //kCGImageAlphaPremultipliedFirst  | kCGBitmapByteOrder32Little);

    CGColorSpaceRelease( space );

// now draw the image into the context
CGRect rect = CGRectMake( 0, 0, CGImageGetWidth(cgImage), CGImageGetHeight(cgImage) );
CGContextDrawImage( ctx, rect, cgImage );

And get the pixels:

pixels = CGBitmapContextGetData( ctx );

Assuming that your pixel data came from pixels = CGBitmapContextGetData( ctx ); then take that context and build a new image from it:

CGImageRef newImg = CGBitmapContextCreateImage(ctx);
[[UIImage imageWithCGImage:newImg] drawInRect:rect];
CGImageRelease(newImg);
花开雨落又逢春i 2024-08-17 17:27:07

我认为您可以创建另一个上下文,将上下文颜色设置为您想要为图片着色的 RGB。然后将您的 UIImage 绘制到该上下文中并使用该上下文,而不是直接使用您的图片。这是一个概念。这样您就可以使用彩色图像创建离屏缓冲区。我没有在可可中尝试过这个,只在碳中尝试过,但我想它也会以同样的方式起作用。

I think you can create another context with setting there context color to RGB you want to color your picture. Then draw your UIImage into that context and use that context instead of using directly your picture. This is a concept. This way you're creating offscreen buffer with a colored image. I didn't try this in cocoa, only in carbon, but i suppose it will work in the same way.

不乱于心 2024-08-17 17:27:07

嗯——字节顺序不是应该是 RGBA 吗?您正在将它们设置为 ARGB...

Hmmm -- isn't the order of the bytes supposed to be RGBA? You are setting them as ARGB...

几味少女 2024-08-17 17:27:07

试试这个

- (UIImage *)imageWithOverlayColor:(UIColor *)color
{
    CGRect rect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);

    if (UIGraphicsBeginImageContextWithOptions) {
        CGFloat imageScale = 1.0f;
        if ([self respondsToSelector:@selector(scale)])  // The scale property is new with iOS4.
            imageScale = self.scale;
        UIGraphicsBeginImageContextWithOptions(self.size, NO, imageScale);
    }
    else {
        UIGraphicsBeginImageContext(self.size);
    }

    [self drawInRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(context, kCGBlendModeSourceIn);

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

try this

- (UIImage *)imageWithOverlayColor:(UIColor *)color
{
    CGRect rect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);

    if (UIGraphicsBeginImageContextWithOptions) {
        CGFloat imageScale = 1.0f;
        if ([self respondsToSelector:@selector(scale)])  // The scale property is new with iOS4.
            imageScale = self.scale;
        UIGraphicsBeginImageContextWithOptions(self.size, NO, imageScale);
    }
    else {
        UIGraphicsBeginImageContext(self.size);
    }

    [self drawInRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetBlendMode(context, kCGBlendModeSourceIn);

    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextFillRect(context, rect);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}
苏佲洛 2024-08-17 17:27:07

user576924 提到的很棒的帖子对我来说非常有用:
iPhone:如何动态为 UIImage 着色

和请

extension UIImage {

    func imageWithColor( color : UIColor ) -> UIImage {

       // begin a new image context, to draw our colored image onto
       UIGraphicsBeginImageContext(self.size)

       // get a reference to that context we created
       let context = UIGraphicsGetCurrentContext();

       // set the fill color
       color.setFill()

       // translate/flip the graphics context (for transforming from CG* coords to UI* coords
       CGContextTranslateCTM(context, 0, self.size.height)
       CGContextScaleCTM(context, 1.0, -1.0)

       // set the blend mode to color burn, and the original image
       CGContextSetBlendMode(context, kCGBlendModeColor)
       let rect = CGRect(origin: CGPointZero, size: self.size)
       CGContextDrawImage(context, rect, self.CGImage)

       // set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
       CGContextClipToMask(context, rect, self.CGImage)
       CGContextAddRect(context, rect)
       CGContextDrawPath(context,kCGPathFill)

       // generate a new UIImage from the graphics context we drew onto
       let coloredImg = UIGraphicsGetImageFromCurrentImageContext()
       UIGraphicsEndImageContext()

       //return the color-burned image
       return coloredImg
   }

注意

,我还将“kCGBlendModeColorBurn”更改为“kCGBlendModeColor”,如帖子评论部分中所述。

The great post mentioned by user576924 worked great for me:
iPhone: How to Dynamically Color a UIImage

and in swift:

extension UIImage {

    func imageWithColor( color : UIColor ) -> UIImage {

       // begin a new image context, to draw our colored image onto
       UIGraphicsBeginImageContext(self.size)

       // get a reference to that context we created
       let context = UIGraphicsGetCurrentContext();

       // set the fill color
       color.setFill()

       // translate/flip the graphics context (for transforming from CG* coords to UI* coords
       CGContextTranslateCTM(context, 0, self.size.height)
       CGContextScaleCTM(context, 1.0, -1.0)

       // set the blend mode to color burn, and the original image
       CGContextSetBlendMode(context, kCGBlendModeColor)
       let rect = CGRect(origin: CGPointZero, size: self.size)
       CGContextDrawImage(context, rect, self.CGImage)

       // set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
       CGContextClipToMask(context, rect, self.CGImage)
       CGContextAddRect(context, rect)
       CGContextDrawPath(context,kCGPathFill)

       // generate a new UIImage from the graphics context we drew onto
       let coloredImg = UIGraphicsGetImageFromCurrentImageContext()
       UIGraphicsEndImageContext()

       //return the color-burned image
       return coloredImg
   }

}

Note that I also changed "kCGBlendModeColorBurn" to "kCGBlendModeColor" as mentioned in the post's comments section.

木槿暧夏七纪年 2024-08-17 17:27:07

对我来说这有效:

extension UIImage {
    class func image(image: UIImage, withColor color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height), false, image.scale)
        let context = UIGraphicsGetCurrentContext()
        color.set()
        CGContextTranslateCTM(context, 0, image.size.height)
        CGContextScaleCTM(context, 1, -1)
        let rect = CGRectMake(0, 0, image.size.width, image.size.height)
        CGContextClipToMask(context, rect, image.CGImage)
        CGContextFillRect(context, rect)
        let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return coloredImage
    }
}

For me this worked:

extension UIImage {
    class func image(image: UIImage, withColor color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height), false, image.scale)
        let context = UIGraphicsGetCurrentContext()
        color.set()
        CGContextTranslateCTM(context, 0, image.size.height)
        CGContextScaleCTM(context, 1, -1)
        let rect = CGRectMake(0, 0, image.size.width, image.size.height)
        CGContextClipToMask(context, rect, image.CGImage)
        CGContextFillRect(context, rect)
        let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return coloredImage
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文