В Quartz 2D, возможно ли замаскировать изображение, удалив все, кроме цветового канала, который вы хотите? - PullRequest
1 голос
/ 27 мая 2009

Поэтому я попытался использовать функцию Quartz CGImageCreateWithMaskingColors, но единственная проблема в том, что он маскирует выбранный вами цветовой диапазон.

Я хочу замаскировать все, кроме выбранного диапазона цветов. Например, я хочу показать все красные цвета на картинке, но удалить другие каналы (зеленый и синий).

Я делаю это в Objective-C, и я новичок, поэтому, пожалуйста, дайте мне примеры:)

Любая помощь очень ценится.

Ответы [ 3 ]

0 голосов
/ 20 мая 2010

Я нашел ответ на мою вышеуказанную проблему. Следуйте приведенному выше коду Рахула с некоторыми изменениями, чтобы установить свой собственный цвет,

-(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;
}
0 голосов
/ 05 октября 2011

Ммм ...

Возможно, я что-то упускаю, но я не верю, что приведенные ответы относятся к вопросу. Второй ответ становится ближе к отметке, но он содержит ложный код, который не имеет ничего общего с решением.

Метод createMask создает копию исходного изображения, предполагая альфа в позиции LSB. 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);

и затем логика построения изображения. Логика наложения накладывает красный оттенок на исходное изображение, достигая эффекта, аналогичного неуместному альфа-каналу в исходном ответе. Это все еще не то, о чем просит 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 битов в пикселе. В этом примере предполагается использование 32-битных пикселей из стандартного iPhone PNG.

0 голосов
/ 28 сентября 2009

используйте эти методы. Я нашел их в одном из сообщений 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 для события нажатия кнопки и посмотрите результат

...