代码之家  ›  专栏  ›  技术社区  ›  Phobis

在Quartz 2d中,除了您想要的颜色通道之外,是否可以通过移除所有内容来隐藏图像?

  •  1
  • Phobis  · 技术社区  · 15 年前

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

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

    我在Objective-C中这样做,我是一个noob,所以请给我举个例子:)

    非常感谢您的帮助。

    3 回复  |  直到 15 年前
        1
  •  0
  •   P.J.Radadiya Yevgen THD    8 年前

    使用这些方法。我在一个这样的帖子里找到了它们。

    -(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方法单击事件并查看结果

        2
  •  0
  •   Pugalmuni Tom Tharakan    13 年前

    我找到了上述问题的答案,按照上面的rahul代码进行一些更改以设置您自己的颜色,

    -(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;
    }
    
        3
  •  0
  •   Community Daniel Roseman    7 年前

    六羟甲基三聚氰胺六甲醚。。。

    我可能遗漏了一些东西,但我不相信提供的答案适用于这个问题。第二个响应越来越接近标记,但它包含与解决方案无关的伪代码。

    这个 createMask 方法复制原始图像,假设alpha位于lsb位置。changecolor执行一个对RGB图像不起多大作用的蒙版调用——基本上只有黑色会被蒙版(即,在(1,1,2)到(3,2,1)的范围/组合中的RGB三元组)。

    我猜观察到的红移是由参数引起的

    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要求的内容,但它在视觉效果方面,而不是实际数据。这里的相关代码 创建掩模

    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请求时只返回红色通道;假设像素的格式为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;
    }
    

    可以找到按位运算的良好摘要 here .

    正如所指出的 here ,您可能需要根据像素中位的lsb/msb顺序更改遮罩的结构。本例假设来自标准iPhone PNG的32位像素。