是否有可能以编程方式更改图像的颜色?

我正在使用一个具有不同主题颜色的应用程序,但是我不想在项目中拥有太多的图像资源(基本上不想让项目大小太大),是可以使用一个图像但不同的颜色?

谢谢!

我同意马特,你应该检查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以有趣的方式修改图像的颜色,如果这就是你要求的。

漫步目录… https://developer.apple.com/library/ios/documentation/graphicsimaging/reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/uid/TP40004346

一个更简单的答案:如果你的图像可以是一个单一的颜色(例如线条图),那么只需指定你想要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; }