簡體   English   中英

如何更改 UIImage 部分的顏色?

[英]how to change color of part of UIImage?

我有一張灰度圖像,我在該圖像的某些部分應用了它的原始顏色,我已經實現了。 現在我想改變我在圖像中應用原始顏色的那部分的顏色

我有這個:原始圖片

我想在這個轉換:結果圖像

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和所有東西,但沒有得到想要的結果。

有人知道嗎?

您可以嘗試通過使用 CGBitmapContextCreate 創建顏色空間來從圖像中獲取像素數據,然后通過 CGContextDrawImage 向其繪制圖像。

其次,您將收到一維字節數組。 像這樣: [r1, g1, b1, a1, r2, g2, b2, a2, ...] 其中 r,g,b,a - 顏色分量,1,2 - nu。 的像素。

在此之后,您可以遍歷數組並比較每個像素的顏色分量。 由於您應該跳過灰度像素,因此您需要比較rgb params,它們理論上必須相等,但您也可以支持一些數字+-的小錯誤。

如果具體像素不是灰度,只需交換紅色和綠色字節。

應該是要走的路。

更新示例:

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 允許差異 = 0
  2. 允許差異 = 50 允許差異 = 50

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM