【问题标题】:how to change color of part of UIImage?如何更改部分 UIImage 的颜色?
【发布时间】:2015-11-04 11:51:23
【问题描述】:

我有一张灰度图像,我在该图像的某些部分应用了它的原始颜色,我已经实现了它。现在我想改变我在图像中应用原始颜色的那部分的颜色

我有这个: Original Image

我想在这个转换: Result Image

CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);

NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;

NSUInteger bytesCount = height * width * bytesPerPixel;

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char *)calloc(bytesCount, sizeof(unsigned char));
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

unsigned char *outputData = (unsigned char *)calloc(bytesCount, sizeof(unsigned char));

NSUInteger byteIndex = 0;
for (NSUInteger i=0; i<bytesCount / bytesPerPixel; ++i) {
    CGFloat red = (CGFloat)rawData[byteIndex];
    CGFloat green = (CGFloat)rawData[byteIndex+1];
    CGFloat blue = (CGFloat)rawData[byteIndex+2];
    CGFloat alpha = (CGFloat)rawData[byteIndex+3];

    BOOL grayscale = red == green == blue;

    if (!grayscale) {
        // test for near values
        CGFloat diff = MAX(ABS(red-green), MAX(ABS(red-blue), ABS(green-blue)));

        static CGFloat allowedDifference = 100; // in range of 0-255

        if (diff > allowedDifference) {

//                CGFloat redTemp = 236;
//                red = green;
//                green = redTemp;
            red = 236.0;
            green = 17.0;
            blue = 17.0;

        }
    }

    outputData[byteIndex] = red;
    outputData[byteIndex+1] = green;
    outputData[byteIndex+2] = blue;
    outputData[byteIndex+3] = alpha;

    byteIndex += bytesPerPixel;
}

free(rawData);


CGDataProviderRef outputDataProvider = CGDataProviderCreateWithData(NULL,
                                                                    outputData,
                                                                    bytesCount,
                                                                    NULL);
free(outputData);

CGImageRef outputImageRef = CGImageCreate(width,
                                          height,
                                          bitsPerComponent,
                                          bytesPerPixel * 8,
                                          bytesPerRow,
                                          colorSpace,
                                          kCGBitmapByteOrderDefault,
                                          outputDataProvider,
                                          NULL,NO,
                                          kCGRenderingIntentDefault);


CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(outputDataProvider);

UIImage *outputImage = [UIImage imageWithCGImage:outputImageRef];
CGImageRelease(outputImageRef);

我尝试了bitmapcontext 和所有方法,但没有得到想要的结果。

有人知道吗?

【问题讨论】:

    标签: ios objective-c bitmap uiimage cgbitmapcontextcreate


    【解决方案1】:

    您可以尝试通过使用 CGBitmapContextCreate 从图像中获取像素数据来创建颜色空间,然后通过 CGContextDrawImage 将图像绘制到它。

    其次,您将收到一个一维字节数组。 像这样: [r1, g1, b1, a1, r2, g2, b2, a2, ...] 其中 r,g,b,a - 颜色分量,1,2 - nu。像素。

    之后,您可以遍历数组并比较每个像素的颜色分量。由于要跳过灰度像素,因此需要比较 rgb 参数,理论上它们必须相等,但您也可以支持几位数字的一些小错误 +-。

    如果具体像素不是灰度,只需交换红色和绿色字节。

    应该是要走的路。

    更新示例:

    UIImage *image = [UIImage imageNamed:@"qfjsc.png"];
    
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    
    NSUInteger bytesCount = height * width * bytesPerPixel;
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char *)calloc(bytesCount, sizeof(unsigned char));
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);
    
    unsigned char *outputData = (unsigned char *)calloc(bytesCount, sizeof(unsigned char));
    
    NSUInteger byteIndex = 0;
    for (NSUInteger i=0; i<bytesCount / bytesPerPixel; ++i) {
        CGFloat red = (CGFloat)rawData[byteIndex];
        CGFloat green = (CGFloat)rawData[byteIndex+1];
        CGFloat blue = (CGFloat)rawData[byteIndex+2];
        CGFloat alpha = (CGFloat)rawData[byteIndex+3];
    
        BOOL grayscale = red == green == blue;
    
        if (!grayscale) {
            // test for near values
            CGFloat diff = MAX(ABS(red-green), MAX(ABS(red-blue), ABS(green-blue)));
    
            static CGFloat allowedDifference = 50.0; // in range of 0-255
    
            if (diff > allowedDifference) {
    
                CGFloat redTemp = red;
                red = green;
                green = redTemp;
    
            }
        }
    
        outputData[byteIndex] = red;
        outputData[byteIndex+1] = green;
        outputData[byteIndex+2] = blue;
        outputData[byteIndex+3] = alpha;
    
        byteIndex += bytesPerPixel;
    }
    
    free(rawData);
    
    
    CGDataProviderRef outputDataProvider = CGDataProviderCreateWithData(NULL,
                                                                        outputData,
                                                                        bytesCount,
                                                                        NULL);
    free(outputData);
    
    CGImageRef outputImageRef = CGImageCreate(width,
                                              height,
                                              bitsPerComponent,
                                              bytesPerPixel * 8,
                                              bytesPerRow,
                                              colorSpace,
                                              kCGBitmapByteOrderDefault,
                                              outputDataProvider,
                                              NULL,NO,
                                              kCGRenderingIntentDefault);
    
    
    CGColorSpaceRelease(colorSpace);
    CGDataProviderRelease(outputDataProvider);
    
    UIImage *outputImage = [UIImage imageWithCGImage:outputImageRef];
    CGImageRelease(outputImageRef);
    

    注意静态允许的差异变量。它允许您跳过几乎非灰度像素,但它们在 RGB 颜色空间中并且本质上几乎是灰度的。

    以下是示例:

    1. 允许的差异 = 0
    2. 允许的差异 = 50

    【讨论】:

    • 你能发布任何代码吗?因为写这一切太复杂了。
    • @krishnapatel 我已经用测试示例更新了答案
    • @krishnapatel 您生成的图像看起来更加明亮和橙色,因此,如果您有这个想法,您可以通过更改颜色组件来轻松使用生成的颜色以达到所需的结果
    • 我试过你的代码,但是当我在 if (diff > allowedDifference) 条件下改变红色和绿色时,结果太糟糕了
    • @krishnapatel 你不能用你所做的改变来更新你的问题,因为我的例子工作正常
    猜你喜欢
    • 2021-09-09
    • 2018-08-20
    • 2012-06-01
    • 1970-01-01
    • 2012-09-05
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多