如何通过编程更改UIImage的颜色?请帮忙一下。如果我发送一个UIImage,它的颜色需要改变,请帮忙一下。如果我通过位图处理更改RGB颜色,它不起作用。
如果您只需要让它看起来不同,只需使用imageView.tintColor
(iOS 7+)。但问题是,默认情况下设置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
异步获取和设置图像可以减少滚动和动画延迟(特别是在 UICollectionViewCell
或 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
})
UIBarButtonItem
中的 UIButton
时遇到了问题。应该设置哪个图像?我使用 setImage(for: .normal)
配置了按钮中的图像,但似乎没有任何区别。 - Efren要实现这一点的一种方法是使您的图像脱色,然后在所需颜色的图像上方添加色调。
脱色
-(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];
您可以将色调的颜色更改为您想要的任何颜色。
CGContext
,使用新颜色在其上绘制图层,并从中返回一个新的UIImage
。我已经有一段时间没有深入研究这个代码了,但它似乎只是绘制一个与原始图像形状相同的UIImage
,因此具有局限性(会失去图像中的任何细节)。你正在操作的 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);
用户576924提到的这篇好文章对我非常有帮助: 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
}
}
注意,我还将"kCGBlendModeColorBurn"更改为"kCGBlendModeColor",正如帖子评论部分所提到的。试一下这个
- (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;
}
我认为你可以创建另一个上下文,并将其上下文颜色设置为你想要着色的RGB。然后将你的UIImage绘制到该上下文中,而不是直接使用你的图片。这是一个概念。这样,你就创建了一个带有彩色图像的离屏缓冲区。我没有在Cocoa中尝试过这个方法,只在Carbon中尝试过,但我认为它应该以相同的方式工作。