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

时间:2014-02-14 05:36:09

标签: ios objective-c uiimage

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

谢谢!

4 个答案:

答案 0 :(得分:6)

您可以使用CIFilter以编程方式以有趣的方式修改图像的颜色,如果这就是您所要求的。

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

答案 1 :(得分: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;
 }

答案 2 :(得分:0)

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

答案 3 :(得分:0)

基于Xu Yin's answer - 一个更适合 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;
}