In Quartz 2D ist es möglich, ein Bild zu maskieren, indem alles, aber die Farbkanal entfernen Sie wollen?

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

Frage

So habe ich versucht, die Quartz CGImageCreateWithMaskingColors Funktion zu nutzen, aber er einziges Problem ist, dass sie die Farbe Bereich, den Sie auswählen.

Ich will alles, aber die Farbbereich maskieren Ich bin der Auswahl. Zum Beispiel möchte ich alle roten Farben in einem Bild zeigen, sondern auch die anderen Kanäle (Grün und Blau) entfernen.

Ich tue dies in Objective-C, und ich bin ein noob so bitte geben Sie mir Beispiele:)

Jede Hilfe wird sehr geschätzt.

War es hilfreich?

Lösung

verwenden diese methods.i fand sie in einem der SO Beiträge.

-(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;
}

dann changecolor Methode auf einem Schaltflächen klicken Ereignis aufrufen und sehen das Ergebnis

Andere Tipps

fand ich die Antwort für mein oben genanntes Problem, folgen Sie den obigen Code von Rahul mit einigen Änderungen Ihre eigene Farbe zu setzen,

-(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;
}

Hmmm ...

ich etwas fehlt, aber ich glaube nicht, dass die zur Verfügung gestellten Antworten auf die Frage anzuwenden. Die zweite Antwort wird zur Marke näher, aber es enthält falschen Code, der wenig mit der Lösung zu tun hat.

Die createMask Methode erstellt eine Kopie des Originalbildes unter der Annahme alpha in LSB-Position. Die changeColor führt eine Maskierung Anruf, geht nicht viel zu einem RGB-Bild zu tun - im Grunde nur schwarz (dh RGB-Triplets im Bereich / Kombinationen von (1,1,2) bis (3 maskiert werden wird, 2,1)).

Ich vermute, dass die Rotverschiebung, die aufgrund beobachtet wird auf den Parameter ist

kCGImageAlphaPremultipliedFirst

in der Zeile

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

durch unsachgemäße Behandlung des Alpha-Kanals. Wenn in der changeColor Methode Sie den Block ändern

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;

sein

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

Sie werden keinen Unterschied in der Anzeige sehen. Ändern der CGBitmapInfo konstant kCGImageAlphaPremultipliedLast sollte das Bild anzuzeigen, eine der oben genannten Codeblöcke korrekt verwendet wird.

Die nächste Antwort wird es ein wenig näher an, was die OP fragt nach, aber seine in Bezug auf die optische Wirkung, nicht die tatsächlichen Daten. Hier ist der relevante Code in createMask ist

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

, die das Bild richtig angezeigt wird, gefolgt von

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

und dann die Logik für das Bild zu konstruieren. Die Mischung Logik überlagert einen roten Farbton auf dem Originalbild, eine ähnliche Wirkung wie der unangebrachten Alphakanal in der ursprünglichen Antwort zu erreichen. Das nach wie vor wirklich nicht, was der OP fragt nach, die einen oder mehrere Kanäle zu maskieren ist, keine Farben mischen.

Dies entspricht wirklich die Kanalwerte für die Farben einstellen, die nicht auf Null erwünscht sind. Hier ist ein Beispiel für nur den roten Kanal wie die OP-Anforderungen zurückkehrt; die Annahme ist, dass das Format des Pixels 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;
}

Eine gute Zusammenfassung bitweise Operationen gefunden werden kann hier .

Wie wird darauf hingewiesen, hier , müssen Sie die Struktur der Maske auf der LSB / MSB Anordnung der Bits in dem Pixel in Abhängigkeit ändern. Dieses Beispiel nimmt an 32-Bit-Pixel aus einem Standard-iPhone PNG.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top