【问题标题】:Swap color channels on UIImage from transparent png with quartz 2D用石英 2D 从透明 png 交换 UIImage 上的颜色通道
【发布时间】:2019-12-24 01:07:56
【问题描述】:

我有一个奇怪的问题。我想交换从 png 加载的 UIImage 的红色和绿色通道。我查找了示例并使用了以下代码,该代码适用于没有透明度的 png 图像:

- (UIImage *)redToGreen {

CGImageRef imgRef = [self CGImage];

size_t width = CGImageGetWidth(imgRef);
size_t height = CGImageGetHeight(imgRef);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
size_t bitsPerComponent = 8;
size_t bytesPerPixel = 4;
size_t bytesPerRow = bytesPerPixel * width;
size_t totalBytes = bytesPerRow * height;


//Allocate Image space
uint8_t* rawData = malloc(totalBytes);

//Create Bitmap of same size
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

//Draw our image to the context
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imgRef);

for ( int i = 0; i < totalBytes; i += 4 ) {

    uint8_t* red = rawData + i;
    uint8_t* green = rawData + (i + 1);
    uint8_t red_old = *red;

    *red = *green;
    *green = red_old;
}

//Create Image
CGImageRef newImg = CGBitmapContextCreateImage(context);

//Release Created Data Structs
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
free(rawData);

//Create UIImage struct around image
UIImage* newImage = [UIImage imageWithCGImage:newImg];

//Release our hold on the image
CGImageRelease(newImg);

//return new image!
return newImage;
}

但是,当我在透明 png 上尝试时,我在背景中得到了奇怪的人工制品。

所以以这个透明图片为例:

在黑色背景上加载显示为:

我在代码中所做的只是:

[btn setImage:[[UIImage imageNamed:@"trash.png"] redToGreen] forState:UIControlStateNormal];

我尝试更改 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big,因为有些示例存在差异,但似乎没有任何效果。有什么想法吗?

更新: 我觉得奇怪的是这段代码被复制粘贴而没有抱怨。除了不清除缓冲区的问题外,另一个缺陷是比例始终设置为 1,因此如果您打开 @2x 图像,结果将具有两倍的点大小。制作 UIImage 的正确调用是:

UIImage* newImage = [UIImage imageWithCGImage:newImg scale:self.scale orientation:self.imageOrientation];

【问题讨论】:

    标签: objective-c core-graphics quartz-2d


    【解决方案1】:

    当您创建位图上下文时,它不会清除缓冲区。 (例如,使用包含预先存在的图像的缓冲区创建位图上下文是非常明智的。)

    有两种方法:

    1) 在绘制原始图像之前明确清除它,使用CGContextClearRect()

    2) 在绘制原始图像之前将上下文的混合模式设置为“复制”,以便它“绘制”缓冲区中可能存在的任何垃圾;你会使用CGContextSetBlendMode(context, kCGBlendModeCopy) 来做到这一点

    【讨论】:

    • 哇,谢谢。过去我不需要太多使用石英,所以这对我来说绝对不是显而易见的。我粘贴的代码示例可以作为 Obj-C 或 swift 中几个问题的答案 - 我想知道为什么没有人提到这个问题,因为在这个重新发布的代码中缓冲区从未被清除......
    猜你喜欢
    • 2012-11-05
    • 2012-05-03
    • 1970-01-01
    • 2021-07-02
    • 2012-09-04
    • 1970-01-01
    • 2010-10-12
    • 2019-03-18
    • 1970-01-01
    相关资源
    最近更新 更多