将遮罩图像写入磁盘作为PNG文件

12

我基本上是从Web服务器下载图像并将它们缓存到磁盘上,但在这样做之前,我想对它们进行遮罩处理。 我正在使用大家都在指向的遮罩代码,可以在此处找到: http://iosdevelopertips.com/cocoa/how-to-mask-an-image.html

然而,发生的情况是,图像显示正常,但写入磁盘的版本缺失了一个

UIImage *img = [self maskImage:[UIImage imageWithData:data] withMask:self.imageMask];
[UIImagePNGRepresentation(img) writeToFile:cachePath atomically:NO];

当与稍后显示的内容进行比较时(在此处使用相同的UIImage实例),其alpha通道被反转。

有什么想法吗?我确实需要缓存版本进行遮罩,否则如果每次都要遮罩它们,则在表视图中显示图像会变得非常缓慢。

编辑:是的,UIImagePNGRepresentation(img)似乎反转了alpha通道,这与写入磁盘的代码无关,这是相当明显的,但我还是检查了一下。


如果您使用UIImageJPEGRepresentation,是否会得到相同的结果?我并不建议您切换到JPEG。只是想知道它是否具有相同的效果。 - Matt Long
我会尝试,尽管JPEG确实违背了拥有alpha掩码的目的。 - Joonas Trussmann
奇怪的是JPEG看起来很好,遮罩已经正确应用。 - Joonas Trussmann
我也在这个问题上苦苦挣扎。在我的情况下,需要一个PNG作为遮罩图像本身是半透明的。在代码中创建的遮罩看起来很好(它是一个放置在视图上的晕影效果),但是在将UIImagePNGRepresentation()保存到磁盘并使用它来创建UIImage之后,晕影就变成了反向的。非常感谢能够解决这个问题的答案。 - Stuart
我遇到了同样的问题,当我使用UIImageJPEGRepresentation在磁盘上创建图像时,它也被应用了一个倒置的掩码。 - Klaas
3个回答

14

可以尝试在一个新的图像中绘制,然后保存它吗?

UIGraphicsBeginImageContext(img.size);
[img drawAtPoint:CGPointZero];
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[UIImagePNGRepresentation(newImg) writeToFile:cachePath atomically:NO];

(未经测试)


是的,那个可行。不过并不理想,因为根据我的(非常简陋的)测量,与使用Core Graphics命令从头开始绘制图像相比,在重新绘制图像方面需要更长的时间(减去-writeToFile:atomically)。您是否对为什么您的建议有效以及是否有更有效的方法执行相同操作有进一步的见解? - Stuart
我的猜测是,遮罩是与图像分开的“东西”。UIKit/Quartz可以处理和绘制它,但当您想将其保存为具有遮罩作为alpha通道的图像时,需要将图像与遮罩合成以获得其最终的“位图”,然后再保存。 - epatel
@epatel 我爱你,老兄。我已经快被折磨疯了。我正在尝试在我的正常代码读取文件之前掩盖并保存到文件(缓存),这样我只需要掩盖一次,而不是每次显示视图时都掩盖。 在我的“UIImage * maskedIcon = [UIImage imageWithCGImage:maskedImageRef];”之后,您的代码对使其工作至关重要。谢谢! - Alex the Ukrainian

5
请参阅CGImage ReferenceCGImageCreateWithMask的描述:

生成的图像取决于mask参数是图像掩模还是图像。 如果mask参数是图像掩模,则图像掩模的源样本充当反向alpha值。也就是说,如果图像掩模中源样本的值为S,则使用alpha值(1-S)将图像中的相应区域与目标混合。例如,如果S为1,则该区域未被绘制,而如果S为0,则该区域完全被绘制。

如果mask参数是图像,则它用作将图像混合到目标的alpha掩模。mask的源样本充当alpha值。如果mask中源样本的值为S,则使用alpha S将图像中的相应区域与目标混合。例如,如果S为0,则该区域未被绘制,而如果S为1,则该区域完全被绘制。

看起来由于某种原因,图像掩模被视为要在保存时进行掩蔽的掩码图像。根据以下链接: 为了正确使用UIImagePNGRepresentation保存,有几个选择:
  1. 使用图像掩模的反向版本。
  2. 使用“掩码图像”而不是“图像掩模”。
  3. 先呈现到位图上下文中,然后再保存它,如epatel所提到的。

0
Swift 和 UIGraphicsImageRenderer
let renderer = UIGraphicsImageRenderer(size: maskedImage.size)
let newImage = renderer.image { _ in maskedImage.draw(at: .zero) }
newImage.pngData()?.write(to: ...)

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