iPhone:更改CGImageAlphaInfo的CGImage

26

我有一张PNG图片,其位图图形上下文像素格式不受支持。每当我尝试调整图像大小时,CGBitmapContextCreate()会在不支持的格式上噎住。

我收到以下错误(为方便阅读格式化的错误):

CGBitmapContextCreate: unsupported parameter combination: 
    8 integer bits/component; 
    32 bits/pixel; 
    3-component colorspace; 
    kCGImageAlphaLast; 
    1344 bytes/row.
支持的像素格式列表 绝对不支持这种组合。看来我需要重新绘制图像,并将 alpha 通道信息移动到 kCGImageAlphaPremultipliedFirst 或 kCGImageAlphaPremultipliedLast
我不知道如何进行此操作。
PNG 文件没有异常,也没有损坏。在所有其他情况下都可以正常使用。我只是偶然遇到了这个错误,但显然我的用户可能会有类似格式的文件,所以我需要检查我的应用程序导入的图像并纠正这个问题。
2个回答

59

是的,我在处理8位(索引).PNG时遇到了问题。我不得不将其转换为更本地的图像才能执行图形操作。我基本上做了这样的事情:

- (UIImage *) normalize {

    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL, 
                                                         self.size.width, 
                                                         self.size.height, 
                                                         8, (4 * self.size.width), 
                                                         genericColorSpace, 
                                                         kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);    
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage];
    CGImageRelease(tmpThumbImage);

    return result;    
}

看起来不错,我会试一下。我不太想进行过多的处理,因为我担心会无意中破坏保真度。 - TechZen
我终于开始测试了,结果表现良好,没有明显的保真度损失。 - TechZen
当UIImage的imageOrientation不是OrientationUp时,我遇到了上述代码的问题 - 这会导致图像被旋转。图像的边界保持不变,但图像内部的像素被旋转和拉伸以适应原始边界。这类似于https://dev59.com/BlfUa4cB1Zd3GeqPEhu4中描述的情况,但在这种情况下,似乎是normalize函数引起了问题。还有其他人遇到这个问题吗?有没有解决方法? - kurtzmarc
该代码不假设任何方向:定位信息不存储在UIImage中。(在将图像转换为UIImage之前,您应该先处理方向。) - Alfons
1
请查看我对这个问题的回答:https://dev59.com/D2035IYBdhLWcg3wPNZk#7868973 - unsynchronized
这比我之前使用的方法产生了更好的结果,谢谢。 - Echilon

5
这里是一个更新版本的方法,基于 Alfons 的答案,考虑了屏幕比例,并解决了 unsynchronized 在原始答案中提到的关于图像大小浮点值小数位的一些错误。
SCREEN_SCALE 是一个宏,如果未定义比例尺,则返回 1.0;否则返回设备实际比例尺([UIScreen mainScreen].scale)。
- (UIImage *) normalize {

    CGSize size = CGSizeMake(round(self.size.width*SCREEN_SCALE), round(self.size.height*SCREEN_SCALE));
    CGColorSpaceRef genericColorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef thumbBitmapCtxt = CGBitmapContextCreate(NULL, 
                                                         size.width, 
                                                         size.height, 
                                                         8, (4 * size.width), 
                                                         genericColorSpace, 
                                                         kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(genericColorSpace);
    CGContextSetInterpolationQuality(thumbBitmapCtxt, kCGInterpolationDefault);
    CGRect destRect = CGRectMake(0, 0, size.width, size.height);
    CGContextDrawImage(thumbBitmapCtxt, destRect, self.CGImage);
    CGImageRef tmpThumbImage = CGBitmapContextCreateImage(thumbBitmapCtxt);
    CGContextRelease(thumbBitmapCtxt);    
    UIImage *result = [UIImage imageWithCGImage:tmpThumbImage scale:SCREEN_SCALE orientation:UIImageOrientationUp];
    CGImageRelease(tmpThumbImage);

    return result;    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接