ios – 着色图像忽略了alpha通道 – 为什么以及如何修复?

这是我正在尝试做的事情:左边是一个通用的,未着色的RGBA图像,我在屏幕外创建并缓存速度(最初创建速度非常慢,但很快就能用任何颜色进行着色,如同需要).这是一个圆形漩涡的方形图像.在圆圈内,图像的alpha /不透明度为1.在圆圈外,它的alpha /不透明度为0.我在UIView中显示了它,背景颜色为[UIColor scrollViewTexturedBackgroundColor].在右边是当我尝试通过在设置CGContextSetBlendMode(context,kCGBlendModeColor)之后在其顶部填充一个红色矩形颜色来着色图像时会发生什么.

这不是我想要的,也不是我的预期.显然,将完全透明的像素着色(例如,α值为0)会因某些奇怪的原因导致全开填充颜色,而不是像我预期的那样保持透明.

我想要的实际上是这样的:

现在,在这种特殊情况下,我可以将剪裁区域设置为圆形,这样圆圈外的区域保持不变 – 这就是我在这里所做的解决方法.

但在我的应用程序中,我还需要能够着色任意形状,我不知道剪切/轮廓路径.一个例子是通过叠加渐变来着色白色文本.这是怎么做到的?我怀疑必须有一些方法来有效地做到这一点 – 通常,没有奇怪的路径/剪辑技巧 – 使用图像掩码……但我还没有找到这方面的教程.显然这是可能的,因为我在其他游戏中看过彩色渐变文本.

顺便说一句,我不能做的是从渐变开始并剪切/清除掉我不需要的部分 – 因为(如上例所示)我的未着色源图像通常是灰度而不是纯白色.所以我真的需要从未着色的图像开始,然后着色它.

附: – 对于部分透明图像的着色,kCGBlendModeMultiply也有相同的缺陷/缺点/特性.有谁知道为什么Apple决定这样做?就好像Quartz着色代码将RGBA(0,0,0,0)视为RGBA(0,0,0,1),即它完全忽略并破坏alpha通道.

您可以采用的一种方法是从原始图像构造蒙版,然后在使用乘法混合模式集渲染图像之前调用CGContextClipToMask()方法.以下是在将图像绘制为颜色之前设置蒙版的CoreGraphics代码.

CGContextRef context = [frameBuffer createBitmapContext];
  CGRect bounds = CGRectMake( 0.0f, 0.0f, width, height );
  CGContextClipToMask(context, bounds, maskImage.CGImage);
  CGContextDrawImage(context, bounds, greyImage.CGImage);

稍微棘手的部分是获取原始图像并生成maskImage.你能做的就是写一个循环来检查每个像素并写一个黑色或白色像素作为掩码值.如果图像中的原始像素颜色是完全透明的,则写入黑色像素,否则写入白色像素.请注意,掩码值将是24BPP图像.这里有一些代码可以为您提供正确的想法.

uint32_t *inPixels = (uint32_t*) MEMORY_ADDR_OF_ORIGINAL_IMAGE;
  uint32_t *maskPixels = malloc(numPixels * sizeof(uint32_t));
  uint32_t *maskPixelsPtr = maskPixels;

  for (int rowi = 0; rowi < height; rowi++) {
    for (int coli = 0; coli < width; coli++) {
      uint32_t inPixel = *inPixels++;
      uint32_t inAlpha = (inPixel >> 24) & 0xFF;
      uint32_t cval = 0;
      if (inAlpha != 0) {
        cval = 0xFF;
      }
      uint32_t outPixel = (0xFF << 24) | (cval << 16) | (cval << 8) | cval;
      *maskPixelsPtr++ = outPixel;
    }
  }

您当然需要填写所有细节并创建图形上下文等.但一般的想法是简单地创建自己的蒙版来过滤掉圆圈外部的红色部分的绘制.

相关文章
相关标签/搜索