在 Quartz 2D 中,是否可以通过删除除所需颜色通道之外的所有内容来掩盖图像?

StackOverflow https://stackoverflow.com/questions/913719

所以我尝试使用 Quartz CGImageCreateWithMaskingColors 函数,但他唯一的问题是它掩盖了您选择的颜色范围。

我想掩盖除我选择的颜色范围之外的所有内容。例如,我想显示图片中的所有红色,但删除其他通道(绿色和蓝色)。

我在 Objective-C 中做这件事,我是个菜鸟,所以请给我例子:)

任何帮助是极大的赞赏。

有帮助吗?

解决方案

使用这些methods.i发现他们在SO职位之一。

-(void)changeColor
{
    UIImage *temp23=Image;//Pass your image here
    CGImageRef ref1=[self createMask:temp23];
    const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0};
    CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking);
    UIImage *resultedimage=[UIImage imageWithCGImage:New];
    EditImageView.image = resultedimage;
    [EditImageView setNeedsDisplay];
}

-(CGImageRef)createMask:(UIImage*)temp
{


    CGImageRef ref=temp.CGImage;
    int mWidth=CGImageGetWidth(ref);
    int mHeight=CGImageGetHeight(ref);
    int count=mWidth*mHeight*4;
    void *bufferdata=malloc(count);

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst); 

    CGRect rect = {0,0,mWidth,mHeight};
    CGContextDrawImage(cgctx, rect, ref); 
    bufferdata = CGBitmapContextGetData (cgctx);

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferdata, mWidth*mHeight*4, NULL);
    CGImageRef savedimageref = CGImageCreate(mWidth,mHeight, 8, 32, mWidth*4, colorSpaceRef, bitmapInfo,provider , NULL, NO, renderingIntent);
    CFRelease(colorSpaceRef);
    return savedimageref;
}

然后调用上的按钮changecolor方法点击事件和查看结果

其他提示

我发现我的上述问题的答案,请拉胡尔的上面的代码有了一些变化来设定自己的颜色,

-(void)changeColor
{
    UIImage *temp23=Image;//Pass your image here
    CGImageRef ref1=[self createMask:temp23];
    const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0};
    CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking);
    UIImage *resultedimage=[UIImage imageWithCGImage:New];
    EditImageView.image = resultedimage;
    [EditImageView setNeedsDisplay];
}

-(CGImageRef)createMask:(UIImage*)temp
{
   CGImageRef ref=temp.CGImage;
   int mWidth=CGImageGetWidth(ref);
   int mHeight=CGImageGetHeight(ref);
   int count=mWidth*mHeight*4;
   void *bufferdata=malloc(count);

   CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
   CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
   CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

   CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4,colorSpaceRef, kCGImageAlphaPremultipliedLast); 
   CGRect rect = {0,0,mWidth,mHeight};  
   CGContextDrawImage(cgctx, rect, ref); 
   CGContextSaveGState(cgctx);  
   CGContextSetBlendMode(cgctx, kCGBlendModeColor); 
   CGContextSetRGBFillColor (cgctx, 1.0, 0.0, 0.0, 1.0);
   CGContextFillRect(cgctx, rect);


   bufferdata = CGBitmapContextGetData (cgctx);
   const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0};
   CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bufferdata, mWidth*mHeight*4, NULL);
   CGImageRef savedimageref = CGImageCreate(mWidth,mHeight, 8, 32, mWidth*4, colorSpaceRef, bitmapInfo,provider , NULL, NO, renderingIntent);
   CFRelease(colorSpaceRef);
   return savedimageref;
}

嗯...

我可能遗漏了一些东西,但我不认为所提供的答案适用于该问题。第二个响应更接近目标,但它包含与解决方案无关的虚假代码。

createMask 方法制作原始图像的副本,假设 LSB 位置有 alpha。ChangeColor 执行的屏蔽调用不会对 RGB 图像产生太大影响——基本上只有黑色会被屏蔽(即,RGB 三元组在 (1,1,2) 到 (3, 2,1))。

我猜测观察到的红移是由于参数造成的

kCGImageAlphaPremultipliedFirst

在行中

CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4, colorSpaceRef, kCGImageAlphaPremultipliedFirst);

由于α通道处理不当。如果在 changeColor 修改块的方法

CGImageRef ref1=[self createMask:temp23];
const float colorMasking[6] = {1.0, 3.0, 1.0, 2.0, 2.0, 3.0};
CGImageRef New=CGImageCreateWithMaskingColors(ref1, colorMasking);
UIImage *resultedimage=[UIImage imageWithCGImage:New];
EditImageView.image = resultedimage;

成为

CGImageRef ref1=[self createMask:temp23];
UIImage *resultedimage=[UIImage imageWithCGImage:ref];
EditImageView.image = resultedimage;

您在显示中不会发现任何差异。将 CGBitmapInfo 常量更改为 kCGImageAlphaPremultipliedLast 应该使用上述代码块正确显示图像。

下一个响应更接近OP的要求,但它是在视觉效果方面,而不是实际数据方面。这里是相关代码 createMask

CGContextRef cgctx = CGBitmapContextCreate (bufferdata,mWidth,mHeight, 8,mWidth*4,colorSpaceRef, kCGImageAlphaPremultipliedLast);

正确显示图像,然后是

CGContextSetBlendMode(cgctx, kCGBlendModeColor); 
CGContextSetRGBFillColor (cgctx, 1.0, 0.0, 0.0, 1.0);
CGContextFillRect(cgctx, rect);

然后是构建图像的逻辑。混合逻辑在原始图像上覆盖红色色调,实现与原始响应中错位的 Alpha 通道类似的效果。这仍然不是OP所要求的,即屏蔽一个或多个通道,而不是混合颜色。

这实际上相当于将不需要的颜色的通道值设置为零。这是一个根据 OP 请求仅返回红色通道的示例;假设像素的格式为 ABGR:

- (CGImageRef) redChannel:(CGImageRef)image 
{
    CGDataProviderRef provider = CGImageGetDataProvider(image);
    NSMutableData* data = (id)CGDataProviderCopyData(provider);

    int width = CGImageGetWidth(image);
    int height = CGImageGetHeight(image);

    [data autorelease];

    // get a mutable reference to the image data
    uint32_t* dwords = [data mutableBytes];

    for (size_t idx = 0; idx < width*height; idx++) {
        uint32_t* pixel = &dwords[idx];
        // perform a logical AND of the pixel with a mask that zeroes out green and blue pixels
        *pixel &= 0x000000ff;
    }

    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    // now create a new image using the masked original data
    CGDataProviderRef iprovider = CGDataProviderCreateWithData(NULL, dwords, width*height*4, NULL);
    CGImageRef savedimageref = CGImageCreate(width, height, 8, 32, width*4, colorSpaceRef, bitmapInfo, iprovider, NULL, NO, renderingIntent);
    CGColorSpaceRelease(colorSpaceRef);
    CGDataProviderRelease(iprovider);

    return savedimageref;
}

可以找到很好的按位运算总结 这里.

正如所指出的 这里, ,您可能需要根据像素中位的 LSB/MSB 顺序更改掩码的结构。此示例假设标准 iPhone PNG 为 32 位像素。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top