从石英2D透明png交换UIImage上的颜色通道

问题描述 投票:0回答:1

我有一个奇怪的问题。我想交换从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上尝试时,背景中出现了奇怪的伪像。

因此,此透明图像例如:

Original image

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

After redToGreen

我在代码中所做的就是:

[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
投票

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

有两种方法:

1)使用CGContextClearRect()]在绘制原始图像之前将其明确清除>

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

© www.soinside.com 2019 - 2024. All rights reserved.