UIImage颜色变化?

时间:2009-11-09 03:37:57

标签: iphone

如何通过编程更改UIImage的颜色,请帮忙吗?如果我发送UIImage,它的颜色需要改变任何帮助吗?如果我通过bitmaphandling改变RGB颜色,它就不起作用。

11 个答案:

答案 0 :(得分:36)

如果你只需要不同,只需使用imageView.tintColor(iOS 7+)。 Catch是,设置tintColor默认情况下不执行任何操作:

Why isn't my image blue?  I'm setting 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

现在它会起作用:

Now the image is orange!

Link to documentation.


<强>性能

配置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

获得&amp;异步设置图像可以减少滚动和动画延迟(特别是在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
})

答案 1 :(得分:7)

实现此目的的一种方法是对图像进行去饱和处理,并在图像上添加一种色调,并使用您想要的颜色。

<强>去色

-(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];

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

答案 2 :(得分:2)

查看我的post (mostly just remixing code)

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:2)

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

下载

答案 5 :(得分:1)

您正在操作的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);

答案 6 :(得分:0)

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

答案 7 :(得分:0)

嗯 - 不是应该是RGBA的字节的顺序?您将它们设置为ARGB ...

答案 8 :(得分:0)

试试这个

- (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;
}

答案 9 :(得分:0)

user576924提到的好帖子对我很有帮助: iPhone: How to Dynamically Color a UIImage

并在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
   }

}

请注意,我也更改了&#34; kCGBlendModeColorBurn&#34; to&#34; kCGBlendModeColor&#34;正如帖子评论部分所述。

答案 10 :(得分:0)

对我来说这很有效:

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
    }
}