2009-05-10 5 views
15

Sto tentando di aggiungere una sovrapposizione nera su alcuni UIImage correnti (che sono bianchi). Ho cercato di utilizzare il codice seguente:Sovrapposizione di una UIImmagine con un colore?

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

Ma non sta funzionando, e sono abbastanza sicuro che insieme non dovrebbe essere lì.

risposta

29

Si vuole agganciare il contesto per una maschera di immagine e poi riempire con un colore a tinta unita:

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

Nota: myImage dovrebbe essere una variabile di istanza che contiene un UIImage. Non sono sicuro se toglie la maschera dal canale alfa o l'intensità, quindi prova entrambi.

+0

Puoi parlare di dove è stato effettivamente fatto? Sto creando una sottoclasse di UIImage? – davis

+0

@DavisG. Il codice sopra riportato è un esempio di drawRect sovrascritto: metodo in una sottoclasse UIView. Sarebbe molto semplice modificarlo per utilizzare invece un contesto bitmap. – rpetrich

+0

@rpetrich Non dovrebbe essere '[[UIColor blackColor] setFill]' dato che stai riempiendo piuttosto che accarezzarlo? –

0

-set viene utilizzato per impostare il colore delle successive operazioni di disegno che non includono le blit. Suggerisco come prima chiamata, la visualizzazione di un altro (vuoto) UIView sopra la vostra UIImageView e impostare il colore di sfondo:

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

Ovviamente si dovrebbe utilizzare i valori bianchi e alfa che si desidera.

+2

Il problema di questo è il mio UIImage non è un blocco rettangolare, è un'icona. Questo metodo non disegnerebbe anche il colore attorno all'immagine?Fondamentalmente, voglio solo convertire un UIImage bianco in un UIImage nero. – Oliver

3

Oltre alla soluzione da rpetrich (che è grande tra l'altro - aiutami superbamente), si può anche sostituire la linea CGContextClipToMask con:

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

E 'la modalità di miscelatura SourceIn che fa il lavoro di mascheramento il colore in base a qualunque cosa si trovi in ​​GetCurrentContext.

+0

Va notato che uno dei motivi per preferire l'uso di CGContextSetBlendMode è che con CGContextClipToMask è possibile ottenere un contorno sottile sull'immagine con il vecchio colore - non è sicuro se si tratta di un bug nell'implementazione o di un problema con antialiasing, ma usando CGContextSetBlendMode l'ha risolto per me. – petrocket

11

Ho appena scritto un tutorial che aiuterà in questo. Il mio approccio ti dà una copia di un UIImage, con le alterazioni di colore che vuoi. L'approccio di rpetrich è ottimo, ma richiede che tu stia creando una sottoclasse. Il mio approccio è costituito da poche righe di codice che possono essere rilasciate ovunque siano necessarie. 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

Se si utilizza questo metodo, è necessario sostituire la riga CGContextClipToMask con CGContextSetBlendMode (context, kCGBlendModeSourceIn); come da raccomandazione @seaniepie di seguito. Per me è stato risolto un problema in cui CGContextClipToMask ha causato un contorno debole attorno a tutte le immagini nel colore originale. – petrocket

+0

Penso che questo metodo sia migliore del metodo di rpetrich –

+0

@Chadwick Wood Ho provato la soluzione ma ho avuto fortuna. Voglio un'immagine colorata come sopra [qui] (http://stackoverflow.com/questions/29330334/creating-a-tinted-uiimage-from-given-uiimage). Puoi aiutare? – meteors

8

un'occhiata a questo metodo di

+ (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

Quindi, per riassumere tutte le risposte in una sola ecco il metodo drop-in che funziona perfettamente da iOS 6 tutta la strada fino a iOS 11 con tutti i tipi di le immagini e le icone:

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

Aggiornamento: Swift 3 versione

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

Apprezzo questo! Questa soluzione funziona bene su schermo 2x e 3x. – huyleit

+0

Ciao, questo è fantastico, possiamo farlo con l'animazione? Mi piace riempire? – Dilip

7

Dal iOS 7 c'è una soluzione molto più semplice:

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

ma quando visualizzo il risultato ha il colore blu. – Shial

+0

stai chiamando drawInRect da solo o semplicemente passando l'immagine a un'altra classe? Il codice sopra funziona solo all'interno di un metodo drawRect o simile. – zeroimpl

+0

Lo sto passando per visualizzare. Funziona quando cambio Uiview tintcolor dello stesso colore dell'immagine – Shial

0

Ecco come si fa con Swift 3.0 e utilizzando le estensioni a UIImage. Super semplice.

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

Poi per eseguirlo semplicemente fare:

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