1

是否可以CGContextClipToMask忽略蒙版图像的灰度值并像纯黑白一样工作?

我有一个灰度图像,当我将它用作蒙版时,灰色被解释为 alpha 通道。这很好,除了我需要完全掩盖那些不透明的像素。

简短的例子:

UIImage *mask = [self prepareMaskImage];
UIGraphicsBeginImageContextWithOptions(mask.size, NO, mask.scale); {
  // Custom code
  CGContextClipToMask(UIGraphicsGetCurrentContext(), mask.size, mask.CGImage);
  // Custom code
}

是否可以调整此代码以实现我的目标?

长话短说:我需要让一个透明的灰度图像在原来的地方变得透明,而在纯色的地方完全变黑。

4

3 回答 3

1

我的粗略想法如下:

  1. 您将输入图像转换为灰度 + alpha 格式的可读字节数据。由于 iOS 的限制,您可能不得不改用 RGBA。
  2. 您迭代字节数据以修改适当的值。

为了简化访问,使用

typedef struct RGBA {
    UInt8 red;
    UInt8 green;
    UInt8 blue;
    UInt8 alpha;
} RGBA;

让我们假设image您的输入掩码。

// First step, using RGBA (because I know it works and does not harm, just writes/consumes twice the amount of memory)
CGImageRef imageRef = image.CGImage;
NSInteger rawWidth = CGImageGetWidth(imageRef);
NSInteger rawHeight = CGImageGetHeight(imageRef);
NSInteger rawBitsPerComponent = 8;
NSInteger rawBytesPerPixel = 4;
NSInteger rawBytesPerRow = rawBytesPerPixel * rawWidth;
CGRect rawRect = CGRectMake(0, 0, rawWidth, rawHeight);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UInt8 *rawImage = (UInt8 *)malloc(rawHeight * rawWidth * rawBytesPerPixel);
CGContextRef rawContext = CGBitmapContextCreate(rawImage,
                                                rawWidth,
                                                rawHeight,
                                                rawBitsPerComponent,
                                                rawBytesPerRow,
                                                colorSpace,
                                                kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);

// At this point, rawContext is ready for drawing, everything drawn will be in rawImage's byte array.
CGContextDrawImage(rawContext, rawRect, imageRef);

// Second step, crawl the byte array and do the evil work:
for (NSInteger y = 0; y < rawHeight; ++y) {
    for (NSInteger x = 0; x < rawWidth; ++x) {
        UInt8 *address = rawImage + x * rawBytesPerPixel + y * rawBytesPerRow;
        RGBA *pixel = (RGBA *)address;
        // If it is a grey input image, it does not matter what RGB channel to use - they shall all be the same
        if (0 != pixel->red) {
            pixel->alpha = 0;
        } else {
            pixel->alpha = UINT8_MAX;
        }
        pixel->red = 0;
        pixel->green = 0;
        pixel->blue = 0;
        // I am still not sure if this is the transformation you are searching for, but it may give you the idea.
    }
}

// Third: rawContext is ready, transformation is done. Get the image out of it
CGImageRef outputImage1 = CGBitmapContextCreateImage(rawContext);
UIImage *outputImage2 = [UIImage imageWithCGImage:outputImage1];
CGImageRelease(outputImage1);

好的...输出是 RGBA,但您可以创建灰度 + alpha 上下文,然后将图像粘贴到那里进行转换。

于 2013-02-05T12:22:17.897 回答
1

有趣的问题! 这是我认为您在一个简单的示例项目中想要的代码。与上面类似,但可以正确处理缩放。如果需要,还可以选择保留蒙版图像中的 alpha。快速组合测试似乎有效。

于 2013-02-07T15:54:58.883 回答
0

这段代码帮助我在图像的非透明区域应用色调。

- (UIImage*)imageWithImage:(UIImageView*)source colorValue:(CGFloat)hue {
    CGSize imageSize = [source.image size];
    CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

    // Create a context containing the image.
    UIGraphicsBeginImageContext(imageSize);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [source.image drawAtPoint:CGPointMake(0, 0)];

    // Setup a clip region using the image
    CGContextSaveGState(context);
    CGContextClipToMask(context, source.bounds, source.image.CGImage);

    self.imageColor = [UIColor colorWithHue:hue saturation:1.0 brightness:1 alpha:1.0];
    [self.imageColor set];
    CGContextFillRect(context, source.bounds);

    // Draw the hue on top of the image.
    CGContextSetBlendMode(context, kCGBlendModeHue);
    [self.imageColor set];

    UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
    [imagePath fill];

    CGContextRestoreGState(context); // remove clip region

    // Retrieve the new image.
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}
于 2015-09-11T14:00:26.483 回答