11

我有这个代码来掩盖图像。基本上,我只使用 PNG 图像。所以我有一个 24 位颜色 (PNG-24) 的 300x400 PNG 图像。我不确定它是否也有 alpha 通道。但它没有透明度。

然后是没有alpha通道的PNG-8bit的图像掩码。它只是黑色,灰度和白色。

我将两个图像都创建为 UIImage。将它们放入 UIImageView 时,两者都正确显示。

然后我使用以下代码创建一个 UIImage ,其中包含屏蔽操作的结果:

+ (UIImage*)maskImage:(UIImage*)image withMask:(UIImage*)maskImage {
 CGImageRef maskRef = maskImage.CGImage;
 CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
          CGImageGetHeight(maskRef),
          CGImageGetBitsPerComponent(maskRef),
          CGImageGetBitsPerPixel(maskRef),
          CGImageGetBytesPerRow(maskRef),
          CGImageGetDataProvider(maskRef), NULL, false);
 CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
 return [UIImage imageWithCGImage:masked];
}

这就是我所做的:

 UIImage *image = [UIImage imageNamed:@"coloredImagePNG24.png"];
 UIImage *maskImage = [UIImage imageNamed:@"theMaskPNG8_Grayscale_NoAlpha.png"];
 UIImage *maskedImage = [MyGraphicUtils maskImage:image withMask:maskImage];
 UIImageView *testImageView = [[UIImageView alloc] initWithImage:maskedImage];
 testImageView.backgroundColor = [UIColor clearColor];
 testImageView.opaque = NO;

毕竟,coloredImagePNG24.png 保持原样。没有掩蔽发生。但现在奇怪的是:如果我把它转过来,即使用这个图像作为蒙版,并将蒙版作为彩色图像到蒙版,那么我会得到一些非常难看的灰度(但被蒙版;))。

知道我的代码有什么问题吗?

更新:我只是在谷歌上搜索了一个不同的 b/w png 以将其用作掩码。然后这个成功了!但是我自己做的那个不行。所以我假设代码有很大的图像解码问题。我必须将图像“标准化”为特定格式,以便它工作。

4

7 回答 7

6

此代码可以帮助您

- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {

    CGImageRef maskRef = maskImage.CGImage; 

    CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef), NULL, false);

    CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
    return [UIImage imageWithCGImage:masked];

}

请参阅此示例演示

于 2012-07-21T05:37:33.353 回答
5

正如您所发现的,保存文件的方式会有所不同,因为 Core Graphics 非常注重用于掩码的位格式。

我发现从任意图像生成图像掩码的最佳和最可靠的方法是执行以下操作:

  1. 为图像掩码创建可接受格式的位图图形上下文(您不能为此使用 UIGraphicsBeginImageContext())
  2. 将您的图像绘制到此位图图形上下文中
  3. 从位图图形上下文的位创建图像掩码。

试试这个功能:

CGImageRef createMaskWithImage(CGImageRef image)
{
    int maskWidth               = CGImageGetWidth(image);
    int maskHeight              = CGImageGetHeight(image);
    //  round bytesPerRow to the nearest 16 bytes, for performance's sake
    int bytesPerRow             = (maskWidth + 15) & 0xfffffff0;
    int bufferSize              = bytesPerRow * maskHeight;

    //  allocate memory for the bits 
    CFMutableDataRef dataBuffer = CFDataCreateMutable(kCFAllocatorDefault, 0);
    CFDataSetLength(dataBuffer, bufferSize);

    //  the data will be 8 bits per pixel, no alpha
    CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceGray();
    CGContextRef ctx            = CGBitmapContextCreate(CFDataGetMutableBytePtr(dataBuffer),
                                                        maskWidth, maskHeight,
                                                        8, bytesPerRow, colourSpace, kCGImageAlphaNone);
    //  drawing into this context will draw into the dataBuffer.
    CGContextDrawImage(ctx, CGRectMake(0, 0, maskWidth, maskHeight), image);
    CGContextRelease(ctx);

    //  now make a mask from the data.
    CGDataProviderRef dataProvider  = CGDataProviderCreateWithCFData(dataBuffer);
    CGImageRef mask                 = CGImageMaskCreate(maskWidth, maskHeight, 8, 8, bytesPerRow,
                                                        dataProvider, NULL, FALSE);

    CGDataProviderRelease(dataProvider);
    CGColorSpaceRelease(colourSpace);
    CFRelease(dataBuffer);

    return mask;
}
于 2010-07-23T17:24:57.617 回答
3

CGImageMaskCreate符合您的预期。尤其是:

对于每个组件 2、4 或 8 位的图像掩码,每个组件通过使用以下公式进行缩放映射到 0 到 1 的范围:

1/(每个组件 2^bits – 1)

例如,4 位掩码的值范围为 0 到 15。这些值按 1/15 缩放,因此每个分量的范围为 0 到 1。重新缩放为 0 或 1 的分量值的行为方式与它们的行为相同用于 1 位图像掩码。缩放到 0 和 1 之间的值充当反 alpha。也就是说,填充颜色被绘制为好像它具有 (1 – MaskSampleValue) 的 alpha 值。例如,如果 8 位掩码的样本值缩放为 0.8,则当前填充颜色被绘制为好像它具有 0.2 的 alpha 值,即 (1–0.8)。

我的猜测是该函数正在以这种不同的格式重新解释您的 RGB 数据,这会扭曲颜色值。您是否尝试过直接使用蒙版 CGImage ?

快速编辑:我所说的“直接”就是写

+ (UIImage*)maskImage:(UIImage*)image withMask:(UIImage*)maskImage
{
    CGImageRef masked = CGImageCreateWithMask([image CGImage], [maskImage CGImage]);
    return [UIImage imageWithCGImage:masked];
}
于 2009-10-21T12:36:54.937 回答
2

以下代码行对我有用

    +(UIImage*)maskImageExt:(UIImage *)image withMask:(UIImage *)maskImage {
      CGImageRef maskRef = maskImage.CGImage;
      CGImageRef imageRef = image.CGImage;

      CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                    CGImageGetHeight(maskRef),
                                    CGImageGetBitsPerComponent(maskRef),
                                    CGImageGetBitsPerPixel(maskRef),
                                    CGImageGetBytesPerRow(maskRef),
                                    CGImageGetDataProvider(maskRef), NULL, true);

CGImageRef maskImageRef = CGImageCreateWithMask([image CGImage], mask);

CGContextRef context = CGBitmapContextCreate(nil,
                                             CGImageGetWidth(imageRef),
                                             CGImageGetHeight(imageRef),
                                             CGImageGetBitsPerComponent(imageRef),
                                             CGImageGetBytesPerRow(imageRef),
                                             CGImageGetColorSpace(imageRef),
                                             CGImageGetBitmapInfo(imageRef));
CGRect imageRect = CGRectMake(0, 0, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
CGContextDrawImage(context, imageRect, maskImageRef);
CGImageRef maskedImageRef = CGBitmapContextCreateImage(context);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];

CGImageRelease(mask);
CGContextRelease(context);
CGImageRelease(maskedImageRef);

return maskedImage;

}

于 2016-07-13T07:46:02.527 回答
0

看看它是否以这种方式工作得更好:

+ (UIImage*)maskImage:(UIImage*)image withMask:(UIImage*)maskImage {
   UIGraphicsBeginImageContext(image.size);
   CGImageRef maskRef = maskImage.CGImage;
   CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef), CGImageGetHeight(maskRef), CGImageGetBitsPerComponent(maskRef), CGImageGetBitsPerPixel(maskRef), CGImageGetBytesPerRow(maskRef), CGImageGetDataProvider(maskRef), NULL, false);
   CGImageRef masked = CGImageCreateWithMask(image.CGImage, mask);
   UIImage* result = [UIImage imageWithData:UIImagePNGRepresentation(UIGraphicsGetImageFromCurrentImageContext())];
   UIGraphicsEndImageContext();
   CGImageRelease(mask);
   CGImageRelease(masked);
   return result;
}
于 2009-07-15T19:38:48.080 回答
0

戴夫,我听说 PNG 图像具有可以影响此类代码的 Alpha 通道。

我刚刚搜索了 PNG Alpha Channel 并想出了这个链接:link text

因此,请确保您使用的 PNG 具有正确设置的 Alpha 通道

于 2009-10-13T20:30:25.273 回答
-6

您不能使用没有 Alpha 通道的核心图形创建任何类型的图像。

于 2012-02-23T06:02:53.557 回答