是否有可能以编程方式更改图像的颜色?
我正在使用一个具有不同主题颜色的应用程序,但是我不想在项目中拥有太多的图像资源(基本上不想让项目大小太大),是可以使用一个图像但不同的颜色?
谢谢!
我同意马特,你应该检查CIFilter未来的图像修改。 但如果你正在寻找一个快速的代码示例,这是我是如何做到的。 对我来说工作很好,只需要这样调用:
[self useColor:[UIColor redColor] forImage:WHATEVER_IMAGE]; - (UIImage *)useColor:(UIColor *)color forImage:(UIImage *)image { if(!color) return image; NSUInteger width = CGImageGetWidth([image CGImage]); NSUInteger height = CGImageGetHeight([image CGImage]); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * width; NSUInteger bitsPerComponent = 8; NSUInteger bitmapByteCount = bytesPerRow * height; unsigned char *rawData = (unsigned char*) calloc(bitmapByteCount, sizeof(unsigned char)); CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]); CGColorRef cgColor = [color CGColor]; const CGFloat *components = CGColorGetComponents(cgColor); float r = components[0] * 255.0; float g = components[1] * 255.0; float b = components[2] * 255.0; //float a = components[3]; // not needed int byteIndex = 0; while (byteIndex < bitmapByteCount) { int oldR = rawData[byteIndex]; int oldG = rawData[byteIndex + 1]; int oldB = rawData[byteIndex + 2]; int oldA = rawData[byteIndex + 3]; if(oldR != 0 || oldG != 0 || oldB != 0 || oldA != 0) { rawData[byteIndex] = r; rawData[byteIndex + 1] = g; rawData[byteIndex + 2] = b; } byteIndex += 4; } UIImage *result = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context) scale:image.scale orientation:image.imageOrientation]; CGContextRelease(context); free(rawData); return result; }
你可以通过编程方式使用CIFilter以有趣的方式修改图像的颜色,如果这就是你要求的。
一个更简单的答案:如果你的图像可以是一个单一的颜色(例如线条图),那么只需指定你想要UIImageRenderingModeAlwaysTemplate。 现在图像将采用其容器的tintColor
,所以你可以通过改变tintColor
来改变它的颜色。
基于徐寅的回答 – 这个版本更适合SVG类图标 ,其中有一个循环模式 (因此可能会被代码的原始版本像素化)。
改变只是当前alpha级别对每个像素值的使用(乘法)。
- (UIImage *)useColor:(UIColor *)color forImage:(UIImage *)image { if(!color) return image; NSUInteger width = CGImageGetWidth([image CGImage]); NSUInteger height = CGImageGetHeight([image CGImage]); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * width; NSUInteger bitsPerComponent = 8; NSUInteger bitmapByteCount = bytesPerRow * height; unsigned char *rawData = (unsigned char*) calloc(bitmapByteCount, sizeof(unsigned char)); CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]); CGColorRef cgColor = [color CGColor]; const CGFloat *components = CGColorGetComponents(cgColor); float r = components[0] * 255.0; float g = components[1] * 255.0; float b = components[2] * 255.0; int byteIndex = 0; while (byteIndex < bitmapByteCount) { int oldR = rawData[byteIndex]; int oldG = rawData[byteIndex + 1]; int oldB = rawData[byteIndex + 2]; int oldA = rawData[byteIndex + 3]; if(oldR != 0 || oldG != 0 || oldB != 0 || oldA != 0) { rawData[byteIndex] = r * (oldA / 255.0); rawData[byteIndex + 1] = g * (oldA / 255.0); rawData[byteIndex + 2] = b * (oldA / 255.0); } byteIndex += 4; } UIImage *result = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context) scale:image.scale orientation:image.imageOrientation]; CGContextRelease(context); free(rawData); return result; }