【问题标题】:PNG Image with BGRA CgBI premultiplied alpha带有 BGRA CgBI 预乘 alpha 的 PNG 图像
【发布时间】:2012-08-16 13:14:16
【问题描述】:

我有 Apple iOS 优化的 BGRA PNG 格式的 PNG(我使用 OptimizedPNG 得到的),并希望以一种告诉 CoreGraphics 不要忽略图像的 alpha 分量的方式绘制它们。我正在向drawRect: 中的CGContextRef 绘图

编辑:渲染图像在应该完全透明的地方显示为黑色(有时是其他随机伪影)。不透明区域正常渲染。 CGImageAlphaInfo 我从图片中得到的是kCGImageAlphaNoneSkipLast似乎表明 OptimizedPNG 保存图片的方式存在问题。我想这应该是kCGImageAlphaPremultipliedLast

也许 PNG 块是错误的,但我看不出 IHDR 有什么问题,而且我几乎找不到关于 CgBI 块的信息。

这是 OptimizedPNG 保存颜色数据的方式:

// IDAT
int size = width*height*4;
unsigned char *buffer = malloc(size);
CGContextRef context = CGBitmapContextCreate(buffer, width, height, 8, width*4, CGImageGetColorSpace(originalImage.CGImage), kCGImageAlphaPremultipliedLast);
CGRect rect = CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height);
CGContextDrawImage(context, rect, originalImage.CGImage);
CGContextRelease(context);

int size_line = 1 + width*4;
int size_in = height*size_line;
unsigned char *buffer_in = malloc(size_in);
for(int y = 0; y < height; ++y){
    unsigned char *src = &buffer[y*width*4];
    unsigned char *dst = &buffer_in[y*size_line];
    *dst++ = 1;
    unsigned char r = 0, g = 0, b = 0, a = 0;
    for(int x = 0; x < width; ++x){
        dst[0] = src[2] - b;
        dst[1] = src[1] - g;
        dst[2] = src[0] - r;
        dst[3] = src[3] - a;
        r = src[0], g = src[1], b = src[2], a = src[3];
        src += 4;
        dst += 4;
    }
}

【问题讨论】:

  • Core Graphics 尊重图像的 alpha 通道,如果它有的话。 Core Graphics 透明层实际上与图像 alpha 几乎没有关系。请发布您获得的结果的屏幕截图,并描述您希望它有何不同。
  • @robmayoff 编辑了更多信息。

标签: ios core-graphics cgcontext alpha-transparency premultiplied-alpha


【解决方案1】:

听起来您的 PNG 缺少 Alpha 通道。

可能 OptimizedPNG 中存在错误;我不知道。尝试使用UIImagePNGRepresentation

也许您的原始图像没有 Alpha 通道。您可以在预览中检查(工具 > 显示检查器,然后在更多信息 > 常规中查找“有 Alpha”)。

还要确保您的视图的 opaque 为 NO 并且其 backgroundColorclearColor。如果您没有绘制到系统创建的上下文,请确保您使用 Alpha 通道创建上下文。

根据您的 cmets,我在运行 iOS 5.1.1 的 iPad 3 上测试了此代码:

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://upload.wikimedia.org/wikipedia/commons/f/fb/Wikisource-logo.png"]]];
NSData *data = UIImagePNGRepresentation(image);
NSURL *documentDirectoryURL = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].lastObject;
NSURL *url = [documentDirectoryURL URLByAppendingPathComponent:@"test.png"];
[data writeToURL:url atomically:YES];

然后我使用 Xcode Organizer 从我的设备复制了test.png。我在预览中打开文件进行检查。它仍然有一个 Alpha 通道。

如果您仍然遇到问题,您需要向我们展示所有处理图像所涉及的代码,因为您遗漏了一些内容。编辑您的问题以包含更多详细信息和代码。

【讨论】:

  • 我尝试了UIImagePNGRepresentation,使用UIImagePNGRepresentation中的数据创建的图像也没有alpha:kCGImageAlphaNone,所以图像是错误的!原图肯定有 alpha。
  • 您需要向我们展示创建或加载您传递给UIImagePNGRepresentation的图像的代码。
  • 图片是从这样的服务器下载的:UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://upload.wikimedia.org/wikipedia/commons/f/fb/Wikisource-logo.png"]]];
  • 我想我误解了。根据CGImageGetAlphaInfo(),我使用UIImagePNGRepresentation() 只是为了确认使用OptimizedPNG 创建的图像实际上没有alpha。我知道UIImagePNGRepresentation() 在直接使用时会创建具有适当 alpha 的图像。但是,您是说 UIImagePNGRepresentation() 将数据优化为 BGRA 吗?如果是,则无法在预览中查看。
  • 最简单的判断 OptimizedPNG 是否是问题的方法是获取我的测试代码,将其放入您的项目中,将UIImagePNGRepresentation 替换为OptimizedPNG,并查看它是否会创建一个@ 987654335@ 带有阿尔法。如果是这样,问题就出在其他地方。如果不是,则问题出在 OptimizedPNG。
【解决方案2】:

根据您的说法,没有理由使用透明层。透明层用于组合两个或多个对象以产生被视为单个对象的复合图形。如果您想将效果应用到复合对象而不是每个单独的对象,这将非常有用。一个非常常见的情况是对多个对象的合成应用阴影。

考虑到 Alpha 通道,只需使用 CGContextDrawImage() 即可将图像合成到图形上下文中。新图像究竟如何在图形内容中已有的任何内容上合成取决于为图形内容设置的混合模式。您使用CGContextSetBlendMode() 设置混合模式。详细说明可以在Quartz 2D Programming Guide: Bitmaps Images and Masks 中找到。正如您从参考资料中看到的那样,有很多用于合成图像的选项,但我可能猜到您想到的是kCGBlendModeMultiplykCGBlendModeNormal。请注意,默认值为 kCGBlendModeNormal,它只是将源图像样本绘制在当前上下文中尊重 alpha 值的任何内容上。

【讨论】:

  • 你对透明层是完全正确的。我正在尝试寻找某种方法让 CG 不会忽略透明度。
猜你喜欢
  • 2011-06-30
  • 2018-03-30
  • 2016-07-26
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
相关资源
最近更新 更多