2009-08-28 9 views
9

ich eine UIImageView brauchen maskieren das Bild zu respektieren, die sich in Farbe oder s/w nach einer Flagge ziehen:Wie eine Form auf einem UIImage zu ziehen, während die alpha

BOOL isGrey; 

Ich versuche, Zeichnen Sie dazu ein schwarzes Rechteck über dem Originalbild, wobei der Quarz-Mischmodus auf Farbe eingestellt ist. Dies funktioniert, außer dass die Alpha-Maske des Bildes nicht berücksichtigt wird.

Siehe Abbildung: alt text http://img214.imageshack.us/img214/1407/converttogreyscaleillo.png

Google Suche und SO, fand ich und versuchte mehrere Lösungen, aber keine, die Maske entweder respektieren.

Hier ist der Code, der die ‚Was ich‘ Bild oben erzeugt:

- (void)drawRect:(CGRect)rect { 

    if (isGrey) { 
     CGContextRef context = UIGraphicsGetCurrentContext(); 

     // flip orientation 
     CGContextTranslateCTM(context, 0, self.bounds.size.height); 
     CGContextScaleCTM(context, 1.0, -1.0); 

     // draw the image 
     CGContextDrawImage(context, self.bounds, self.image.CGImage); 

     // set the blend mode and draw rectangle on top of image 
     CGContextSetBlendMode(context, kCGBlendModeSaturation); 
     CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0); 
     CGContextFillRect(context, rect);  
    } else { 
     [self.image drawInRect:rect]; 
    } 
} 

Gibt es eine Quarz-Zeichenmodus, die ich vergessen zu setzen? Ich habe durch den Quarz-Programmierungs-Führer geschaut, aber ist so schwer, das ein bisschen von Information zu extrahieren, die Sie von den überlappenden und hyperverlinkten Themen benötigen.

Offensichtlich suche ich nach einer allgemeinen Lösung, die auf Bilder mit irgendeiner maskierten Form, nicht nur dem gezeigten Kreis zutrifft.

Antwort

10

eine Form zu zeichnen, während ein Bild des Alpha-Maske zu respektieren, nur eine Zeile hinzufügen, bevor Sie ziehen:

CGContextClipToMask(context, self.bounds, image.CGImage); 

// example usage 
    - (void)drawRect:(CGRect)rect { 

    if (isGrey) { 
      CGContextRef context = UIGraphicsGetCurrentContext(); 

      // flip orientation 
      CGContextTranslateCTM(context, 0.0, self.bounds.size.height); 
      CGContextScaleCTM(context, 1.0, -1.0); 

      // draw the image 
      CGContextDrawImage(context, self.bounds, self.image.CGImage); 

      // set the blend mode and draw rectangle on top of image 
      CGContextSetBlendMode(context, kCGBlendModeColor); 
      CGContextClipToMask(context, self.bounds, image.CGImage); // respect alpha mask 
      CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0); 
      CGContextFillRect(context, rect);    
    } else { 
      [self.image drawInRect:rect]; 
    } 

}

+0

Ausgenommen, dass dies nicht funktioniert, wenn Ihre Ansicht backgroundColor UIColor clearColor ist. –

1

Obwohl es nicht direkt Ihre Frage beantworten, können Sie in der Lage sein, den Effekt zu erhalten, die Sie suchen, indem Sie den kCGBlendModeLuminosity Mischmodus:

- (void)drawRect:(CGRect)rect { 
    CGSize imageSize = [image size]; 
    CGContextRef c = UIGraphicsGetCurrentContext(); 
    if (isGrey) 
     CGContextSetBlendMode(c, kCGBlendModeLuminosity); 
    CGContextScaleCTM(c, 1.0, -1.0); 
    CGContextDrawImage(c, CGRectMake(0.0f, 0.0f, imageSize.width, -imageSize.height), [image CGImage]); 
} 

Auch die rect zu drawRect: geben der ungültige Bereich, nicht die gesamte Fläche. Sie sollten stattdessen die bounds

+0

Sie dies versuchen Haben? Weil es mir die gleichen falschen Ergebnisse gibt wie all die anderen Dinge, die ich ausprobiert habe. – willc2

+0

Es scheint - [UIImage drawInRect:] berücksichtigt nicht den Mischmodus für den CGContext. Ich habe meine Antwort aktualisiert, um stattdessen CGContextDrawImage zu verwenden - getestet und funktioniert :) – rpetrich

+0

Haben Sie dies in einem Bild mit einem Alpha-Kanal versucht, mit einer clearColor backgroundColor oder einer nicht-opaken UIImageView? Ihr Code funktioniert auf nicht maskierten Bildern oder imageViews, die eine undurchsichtige bg-Farbe haben, oder imageViews, die opak Eigenschaft = YES ist. Wenn das Bild in meinem Beispiel dem grünen Ball entspricht, ändert sich die Farbe nicht in Graustufen. – willc2

0

verwenden Sie können versuchen, eine Maske in der Core Animation Layer der Ansicht hinzuzufügen.

CALayer *maskLayer = [CALayer layer]; 
[maskLayer setBounds:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)]; 

// Center the layer 
[maskLayer setPosition:CGPointMake([self view].bounds.size.width/2, 
          [self view].bounds.size.height/2)]; 

// Set the cornerRadius to half the width/height to get a circle. 
[maskLayer setCornerRadius:50.f]; 
[maskLayer setMasksToBounds:YES]; 

// Any solid color will do. Just using black here. 
[maskLayer setBackgroundColor:[[UIColor blackColor] CGColor]]; 

// Set the mask which will only allow that which is in the 
// circle show through 
[[[self view] layer] setMask:maskLayer]; 

Ein anderer Gedanke. Warum können Sie nicht einfach eine b & w Version des Bildes erstellen und diese je nach Flagge wechseln?

+1

Weil ich lernen möchte, wie man das allgemeine Problem des Zeichnens in ein Bild löst, während man einen vorhandenen Alphakanal respektiert. Weißt du wie das geht? – willc2

+0

Ich sehe. Scheint vernünftig. Ich weiß nicht, wie ich das ohne Recherche machen soll. Es tut uns leid. –

+0

Verwenden Sie den Multiply-Blend-Modus ... nur eine Vermutung – dontWatchMyProfile

1

Ich würde den einfachen Ausweg nehmen und einen schwarzen Kreis mit der gleichen Größe wie das runde Bild zeichnen, das Sie haben. Wahrscheinlich nicht das, wonach du verlangst.