如何去除UIImage的不透明度但保留Alpha通道?

3

我有一个图层,希望用户可以在上面绘制“掩码”来剪切图像。这个图层是半透明的,这样用户就可以看到他们所选择区域下面的内容。

如何处理这样的图层,让绘制出来的数据 alpha 通道的值为1.0,但是保留 alpha 通道(用于遮罩)?

简而言之 - 我想让黑色区域成为一个纯色块。

  • 以下是期望的效果图(两张图片中的白色背景都应该是透明的): 期望的效果图

例如这样:

for (pixel in image) {
  if (pixel.alpha != 0.0) {
    fill solid black
  }
}
2个回答

2
以下代码应该能满足您的需求。大部分代码来自于如何设置UIImage的不透明度/透明度?我只添加了一个alpha值测试,在将像素的颜色转换为黑色之前进行测试。
// Create a pixel buffer in an easy to use format
CGImageRef imageRef = [[UIImage imageNamed:@"testImage"] CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

UInt8 * m_PixelBuf = malloc(sizeof(UInt8) * height * width * 4);

NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(m_PixelBuf, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

//alter the alpha when the alpha of the source != 0
int length = height * width * 4;
for (int i=0; i<length; i+=4) {
  if (m_PixelBuf[i+3] != 0) {
    m_PixelBuf[i+3] = 255;
  }
}

//create a new image
CGContextRef ctx = CGBitmapContextCreate(m_PixelBuf, width, height,
                                         bitsPerComponent, bytesPerRow, colorSpace,
                                         kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGImageRef newImgRef = CGBitmapContextCreateImage(ctx);
CGColorSpaceRelease(colorSpace);
CGContextRelease(ctx);
free(m_PixelBuf);

UIImage *finalImage = [UIImage imageWithCGImage:newImgRef];
CGImageRelease(newImgRef);

finalImage现在将包含一张图像,在这张图像上所有不透明度不为0.0的像素都将具有1.0的透明度。


很好,只需要进行小调整就可以将像素变为黑色:for (int i=0; i - Halpo
恕我直言,我认为这种调整原始位图的像素缓冲区的技术并不正确。这假定了 alpha 通道仅反映线路径的不透明度。但是您呈现的路径可能具有抗锯齿边缘;这种技术将在掩模中不必要地引入锯齿。我建议不要像这样编辑像素缓冲区。相反,您应该使用 alpha 值为 1.0 重新呈现模型的原始路径。这样,您的掩模将享受到边缘的抗锯齿特性,同时使主笔画路径完全不透明。 - Rob

1
这个应用的基础模型不应该是图像,这不是“如何从另一个图像创建一个版本”的问题。相反,底层对象模型应该是路径数组。然后,当你想用半透明路径和不透明路径创建图像时,只需要考虑如何渲染这个路径数组。一旦你以这种方式解决了它,问题就不是一个复杂的图像操作问题,而是一个简单的渲染问题。
顺便说一下,我真的很喜欢这个路径数组模型,因为这样做起来就变得非常简单,比如“让我提供一个撤销功能,让用户一次删除一个笔画。”它为你打开了各种不错的功能增强。
关于如何渲染这些路径的具体细节,可以用各种不同的方式实现。你可以使用自定义的UIView子类的drawRect函数来渲染具有适当alpha值的路径。或者你也可以使用CAShapeLayer对象来完成。或者你可以使用一些混合方法(在添加每条路径时创建新的图像快照,使你不必每次重新渲染所有路径)。有很多方法可以解决这个问题。
但关键的洞见是采用路径数组的基本模型,然后呈现你的两种类型的图像就变得相当简单了。

paths mask

第一张图片是将一堆路径渲染为alpha为0.5的CAShapeLayer对象。第二张图片也是同样的渲染,但alpha为1.0。无论您是使用形状图层还是低级别的Core Graphics调用,基本原理是相同的。可以使用半透明或不透明方式渲染您的路径。


我的应用程序使用路径(具有撤消功能等),这仅用于最终渲染解决方案。 - Halpo
那我不明白这个问题。将您的路径渲染两次以获取两张图片,一次使用小于一的alpha值,然后再次使用等于一的alpha值。这样就得到了您需要的两张图片。 - Rob

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