能否通过编程更改图片的颜色?

5

我正在开发一款应用程序,它有不同的主题颜色,但我不想在项目中使用过多的图像资源(基本上不想让项目大小变得太大),那么是否有可能使用一张图片但不同的颜色呢?

谢谢!


https://dev59.com/K3M_5IYBdhLWcg3wzmgw#4630136 和 https://dev59.com/i23Xa4cB1Zd3GeqPbB-7 和 https://dev59.com/5Wct5IYBdhLWcg3wCZIT - iPatel
@iPatel 谢谢您让我知道,我会检查所有这些问题。 - user3288387
4个回答

6

我同意Matt的观点,你应该考虑使用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;
 }

6

0
又来一个简单的答案:如果你的图像可以是单色的(例如线条绘图),那么只需指定希望采用UIImageRenderingModeAlwaysTemplate。现在,图像将采用其容器的tintColor,因此您只需更改tintColor即可更改其颜色。

0

基于徐寅的回答 - 一个更适合具有圆形图案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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接