2009-05-10 9 views
15

Ich versuche, eine schwarze Überlagerung über einige aktuelle UIImages hinzuzufügen (die weiß sind). Ich habe versucht, folgenden Code zu verwenden:Überlagern eines UIImage mit einer Farbe?

[[UIColor blackColor] set]; 
[image drawAtPoint:CGPointMake(0, 0) blendMode:kCGBlendModeOverlay alpha:1.0]; 

Aber es funktioniert nicht, und ich bin mir ziemlich sicher, dass Satz nicht da sein soll.

Antwort

29

Sie wollen den Kontext einer Bildmaske befestigen und dann mit einer Farbe füllen:

- (void)drawRect:(CGRect)rect 
{ 
    CGRect bounds = [self bounds]; 
    [[UIColor blackColor] set]; 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextClipToMask(context, bounds, [myImage CGImage]); 
    CGContextFillRect(context, bounds); 
} 

Hinweis: myImage sollte eine Instanz Variable sein, die ein UIImage enthält. Ich bin mir nicht sicher, ob es die Maske vom Alphakanal oder die Intensität braucht, also versuch beides.

+0

Kannst du darüber sprechen, wo das eigentlich gemacht wird? Mache ich eine Unterklasse von UIImage? – davis

+0

@DavisG. Der obige Code ist ein Beispiel für eine überschriebene drawRect: -Methode in einer UIView-Unterklasse. Es wäre sehr einfach, es zu ändern, um stattdessen einen Bitmap-Kontext zu verwenden. – rpetrich

+0

@rpetrich Sollte das nicht '[[UIColor blackColor] setFill] 'sein, da du mehr füllst als streichelst? –

0

-set wird verwendet, um die Farbe der nachfolgenden Ziehoperationen einzustellen, die blits nicht enthalten. Ich schlage vor, als ersten Anruf, eine andere (leer) UIView über Ihre UIImageView Anzeige und die Hintergrundfarbe einstellen:

myView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5]; 

Offensichtlich sollten Sie die weißen und Alpha-Werte verwenden, die Sie wollen.

+2

Das Problem dabei ist, meine UIImage kein Rechteck-Block ist, ist es ein Symbol ist. Würde diese Methode nicht auch die Farbe um das Bild zeichnen?Im Grunde will ich nur ein weißes UII-Bild in ein schwarzes UII-Bild umwandeln. – Oliver

3

Neben der Lösung von rpetrich (die übrigens toll ist - helfen Sie mir hervorragend), können Sie auch die Zeile mit CGContextClipToMask ersetzen:

CGContextSetBlendMode(context, kCGBlendModeSourceIn); //this is the main bit! 

Es ist die SourceIn blendmode, das die Arbeit der Maskierung tut die Farbe von was auch immer im GetCurrentContext ist.

+0

Es ist anzumerken, dass einer der Gründe, CGContextSetBlendMode zu verwenden, ist, dass Sie mit CGContextClipToMask eine dünne Kontur auf Ihrem Bild mit der alten Farbe erhalten können - nicht sicher, ob dies ein Fehler in der Implementierung oder ein Problem mit Antialiasing ist CGContextSetBlendMode hat es für mich repariert. – petrocket

11

Ich schrieb ein Tutorial, das dabei helfen wird. Mein Ansatz gibt Ihnen eine Kopie eines UIImage mit den gewünschten Farbänderungen. Der Ansatz von Rpetrich ist großartig, erfordert jedoch, dass Sie eine Unterklasse erstellen. Mein Ansatz besteht aus nur ein paar Zeilen Code, die Sie dort einfügen können, wo Sie sie benötigen. http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage

NSString *name = @"badge.png"; 
UIImage *img = [UIImage imageNamed:name]; 

// begin a new image context, to draw our colored image onto 
UIGraphicsBeginImageContext(img.size); 

// get a reference to that context we created 
CGContextRef context = UIGraphicsGetCurrentContext(); 

// set the fill color 
[color setFill]; 

// translate/flip the graphics context (for transforming from CG* coords to UI* coords 
CGContextTranslateCTM(context, 0, img.size.height); 
CGContextScaleCTM(context, 1.0, -1.0); 

// set the blend mode to color burn, and the original image 
CGContextSetBlendMode(context, kCGBlendModeColorBurn); 
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height); 
CGContextDrawImage(context, rect, img.CGImage); 

// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle 
CGContextClipToMask(context, rect, img.CGImage); 
CGContextAddRect(context, rect); 
CGContextDrawPath(context,kCGPathFill); 

// generate a new UIImage from the graphics context we drew onto 
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

//return the color-burned image 
return coloredImg; 
+2

Wenn Sie diese Methode verwenden, sollten Sie die CGContextClipToMask-Zeile durch CGContextSetBlendMode ersetzen (context, kCGBlendModeSourceIn); gemäß @seaniepie Empfehlung unten. Für mich wurde ein Problem behoben, bei dem CGContextClipToMask einen schwachen Umriss um alle Bilder in der Originalfarbe verursachte. – petrocket

+0

Ich denke, diese Methode ist besser als Rpetrichs Methode –

+0

@Chadwick Wood Ich habe versucht, Sie Lösung, aber kein Glück. Ich möchte ein getöntes Bild wie über [hier] (http://stackoverflow.com/questions/29330334/creating-a-tinted-uiimage-from-given-uiimage). Kannst du helfen? – meteors

8

Blick auf diese Methode

+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size; 
    { 
     UIImage *img = nil; 

     CGRect rect = CGRectMake(0, 0, size.width, size.height); 
     UIGraphicsBeginImageContext(rect.size); 
     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextSetFillColorWithColor(context, 
            color.CGColor); 
     CGContextFillRect(context, rect); 
     img = UIGraphicsGetImageFromCurrentImageContext(); 

     UIGraphicsEndImageContext(); 

     return img; 
    } 
50

Also, alle Antworten zusammenzufassen in einem hier ist der Drop-in-Verfahren, das perfekt von iOS 6 den ganzen Weg bis zu iOS 11 mit allen Arten Werke Bilder und Symbole:

+ (UIImage *)filledImageFrom:(UIImage *)source withColor:(UIColor *)color{ 

    // begin a new image context, to draw our colored image onto with the right scale 
    UIGraphicsBeginImageContextWithOptions(source.size, NO, [UIScreen mainScreen].scale); 

    // get a reference to that context we created 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // set the fill color 
    [color setFill]; 

    // translate/flip the graphics context (for transforming from CG* coords to UI* coords 
    CGContextTranslateCTM(context, 0, source.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 

    CGContextSetBlendMode(context, kCGBlendModeColorBurn); 
    CGRect rect = CGRectMake(0, 0, source.size.width, source.size.height); 
    CGContextDrawImage(context, rect, source.CGImage); 

    CGContextSetBlendMode(context, kCGBlendModeSourceIn); 
    CGContextAddRect(context, rect); 
    CGContextDrawPath(context,kCGPathFill); 

    // generate a new UIImage from the graphics context we drew onto 
    UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    //return the color-burned image 
    return coloredImg; 
} 

Update: Swift 3-Version

func filledImage(source: UIImage, fillColor: UIColor) -> UIImage { 

    UIGraphicsBeginImageContextWithOptions(source.size, false, UIScreen.main.scale) 

    let context = UIGraphicsGetCurrentContext() 
    fillColor.setFill() 

    context!.translateBy(x: 0, y: source.size.height) 
    context!.scaleBy(x: 1.0, y: -1.0) 

    context!.setBlendMode(CGBlendMode.colorBurn) 
    let rect = CGRect(x: 0, y: 0, width: source.size.width, height: source.size.height) 
    context!.draw(source.cgImage!, in: rect) 

    context!.setBlendMode(CGBlendMode.sourceIn) 
    context!.addRect(rect) 
    context!.drawPath(using: CGPathDrawingMode.fill) 

    let coloredImg : UIImage = UIGraphicsGetImageFromCurrentImageContext()! 
    UIGraphicsEndImageContext() 

    return coloredImg 
} 
+1

Schätzen Sie dies! Diese Lösung funktioniert gut auf 2x und 3x Bildschirm. – huyleit

+0

Hallo, das ist großartig, können wir das mit Animation machen? Wie zum Auffüllen? – Dilip

7

Seit iOS 7 gibt es eine viel einfachere Lösung:

UIImage* im = [UIImage imageNamed:@"blah"]; 
im = [im imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 
[[UIColor blackColor] setFill]; 
[im drawInRect:rect]; 
+0

aber wenn ich das Ergebnis anzeigen blaue Farbe haben. – Shial

+0

rufen Sie drawInRect selbst auf oder übergeben Sie das Bild einfach an eine andere Klasse? Der obige Code funktioniert nur innerhalb einer drawRect-Methode oder ähnlichem. – zeroimpl

+0

Ich übergebe es an uiview. Es funktioniert, wenn ich die Uiview Tintcolor für die gleiche Farbe wie Bild ändern – Shial

0

Hier ist, wie Sie es mit Swift 3.0 tun und Erweiterungen UIImage verwenden. Super einfach.

public extension UIImage { 
    func filledImage(fillColor: UIColor) -> UIImage { 
     UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale) 

     let context = UIGraphicsGetCurrentContext()! 
     fillColor.setFill() 

     context.translateBy(x: 0, y: self.size.height) 
     context.scaleBy(x: 1.0, y: -1.0) 

     context.setBlendMode(CGBlendMode.colorBurn) 

     let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) 
     context.draw(self.cgImage!, in: rect) 

     context.setBlendMode(CGBlendMode.sourceIn) 
     context.addRect(rect) 
     context.drawPath(using: CGPathDrawingMode.fill) 

     let coloredImg : UIImage = UIGraphicsGetImageFromCurrentImageContext()! 
     UIGraphicsEndImageContext() 

     return coloredImg 
    } 
} 

Dann ist es einfach tun zu laufen:

let image = UIImage(named: "image_name").filledImage(fillColor: UIColor.red) 
Verwandte Themen