Me gustaría para colorear una imagen con un color de referencia. El resultado debe ser similar a la de Multiplicar el modo de fusión en Photoshop, donde blancos sería reemplazado con tinte:

¿Cómo puedo tinte de una imagen mediante programación en iOS?

Voy a estar cambiando el valor de color continuamente.

Seguimiento: me gustaría poner el código para hacer esto en mi ImageView del drawRect: método, derecho?

Como siempre, un fragmento de código sería de gran ayuda en mi entendimiento, en contraposición a un enlace.

Actualización: crear Subclases de una UIImageView con el código Ramin sugerido.

Poner esto en viewDidLoad: de mi punto de vista controlador:

[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];

Veo la imagen, pero no se está teñido. También traté de cargar otras imágenes, la configuración de la imagen en IB, y llamando setNeedsDisplay: en mi punto de vista controlador.

Actualización: drawRect: no es que se llama.

Última actualización: encontré un viejo proyecto que tenía un imageView configurado correctamente para poder probar Ramin del código y funciona como un encanto!

Final, última actualización:

Para aquellos de ustedes que sólo aprender acerca de Núcleo de Gráficos, aquí está la cosa más simple que eso podría funcionar.

En su subclases de UIView:

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColor(context, CGColorGetComponents([UIColor colorWithRed:0.5 green:0.5 blue:0 alpha:1].CGColor)); //don't make color too saturated

    CGContextFillRect(context, rect); //draw base

    [[UIImage imageNamed:@"someImage.png"] drawInRect: rect blendMode:kCGBlendModeOverlay alpha:1.0]; //draw image
}
  • He añadido el fragmento antes de publicar algunos de los antiguos drawRect código me había sentado alrededor y funcionó bien. Posible que desee probarlo sin el [super viewDidLoad] llamada (o moverlo de arriba). Compruebe también que asegúrese de quien es la asignación de este objeto es la asignación de la versión derivada no de vainilla UIImageView (he.e si es de carga en una punta, el asignador, etc).
  • Otra sugerencia, si lo anterior no funciona: en lugar de crear subclases de UIImageView subclase de una llanura UIView y agregar ambos overlayColor y un UIImage propiedad llamada ‘imagen’ que se puede establecer. A continuación, poner el drawRect allí. El drawRect código no importa si la «imagen» valor proviene de UIImageView o de una propiedad que usted haya definido.
  • Esto no fallar si la imagen es con alfa? Lo que si me gustaría tinte sólo se dibujan parte de la imagen? (Como UIButton ¿?)
InformationsquelleAutor willc2 | 2009-07-12

13 Comentarios

  1. 44

    Primer lugar, usted querrá subclase UIImageView y reemplazar el método drawRect. La clase necesita un UIColor propiedad (vamos a llamar a overlayColor) para contener la mezcla de color y un setter que obliga a un rediseño cuando los cambios de color. Algo como esto:

    - (void) setOverlayColor:(UIColor *)newColor {
       if (overlayColor)
         [overlayColor release];
    
       overlayColor = [newColor retain];
       [self setNeedsDisplay]; //fires off drawRect each time color changes
    }

    En el método drawRect usted querrá dibujar la imagen primero y luego de superposición con un rectángulo relleno con el color que usted desea, junto con el correcto modo de fusión, algo como esto:

    - (void) drawRect:(CGRect)area
    {
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGContextSaveGState(context);
    
      //Draw picture first
      //
      CGContextDrawImage(context, self.frame, self.image.CGImage);
    
      //Blend mode could be any of CGBlendMode values. Now draw filled rectangle
      //over top of image.
      //
      CGContextSetBlendMode (context, kCGBlendModeMultiply);
      CGContextSetFillColor(context, CGColorGetComponents(self.overlayColor.CGColor));      
      CGContextFillRect (context, self.bounds);
      CGContextRestoreGState(context);
    }

    Normalmente para optimizar el dibujo que restringiría el dibujo solo a la zona pasa a drawRect, pero desde el fondo de la imagen se vuelve a dibujar cada vez que cambia el color, es probable que todo esto se necesita refrescante.

    A utilizarlo para crear una instancia del objeto, a continuación, establezca el image propiedad (heredado de UIImageView) a la imagen y overlayColor a un UIColor valor (los niveles de mezcla puede ser ajustada cambiando el valor alfa del color que pase abajo).

    • probado el código, los resultados anteriores.
    • Siga las sugerencias adjunta a la solicitud original (arriba).
    • debe agregar CGContextSaveGState(contexto); antes de cambiar el modo de mezcla o de obtener una gstack subdesbordamiento.
    • D’oh, gracias. Copiar/pegar de error. Me he fijado en el fragmento de código.
    • (Como también lo ha dicho en otra respuesta aquí) Consideraciones Especiales El UIImageView clase está optimizada para dibujar sus imágenes a la pantalla. UIImageView no llame drawRect: una subclase. Si la subclase de las necesidades personalizadas de dibujo código, se recomienda el uso de UIView como la clase base. Esto significa que usted no puede subclase UIImageView y esperar drawRect a ser llamado, todo.
    • Hola, por desgracia, he probado el código y no funciona :/. Véase la respuesta de abajo por @mpstx, que dice drawRect no se llama desde un UIImageView y, en su lugar, usted debe utilizar un UIView (con un UIImage), que funcionó bien para mí.
    • ¿El cambio de la imagen original? Quiero un nuevo UIImage con aplicación de filtro de color. ¿Cómo puedo hacerlo?

  2. 76

    En iOS7, que han introducido tintColor propiedad en UIImageView y renderingMode en UIImage. Para teñir una UIImage en iOS7, todo lo que tienes que hacer es:

    UIImageView* imageView =UIImage* originalImage =UIImage* imageForRendering = [originalImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    imageView.image = imageForRendering;
    imageView.tintColor = [UIColor redColor]; // or any color you want to tint it with
    • Este es sin duda el mejor y más fácil camino para ir en iOS 7 si este es el tinte de comportamiento que usted está buscando. Pero este código se aplica un tono como si estuviera usando un 100% opaco «Superposición» modo de fusión en Photoshop, no la de «Multiplicar» modo de fusión de la pregunta original estaba buscando.
  3. 26

    Quería para colorear una imagen con canal alfa y he creado la siguiente clase. Por favor, hágamelo saber si usted encuentra cualquier problema con él.

    He llamado a mi clase CSTintedImageView y hereda de UIView desde UIImageView no llama a la drawRect: método, como se ha dicho en respuestas anteriores.
    He creado un inicializador designado similar a la hallada en el UIImageView clase.

    Uso:

    CSTintedImageView * imageView = [[CSTintedImageView alloc] initWithImage:[UIImage imageNamed:@"image"]];
    imageView.tintColor = [UIColor redColor];

    CSTintedImageView.h

    @interface CSTintedImageView : UIView
    
    @property (strong, nonatomic) UIImage * image;
    @property (strong, nonatomic) UIColor * tintColor;
    
    - (id)initWithImage:(UIImage *)image;
    
    @end

    CSTintedImageView.m

    #import "CSTintedImageView.h"
    
    @implementation CSTintedImageView
    
    @synthesize image=_image;
    @synthesize tintColor=_tintColor;
    
    - (id)initWithImage:(UIImage *)image
    {
        self = [super initWithFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
    
        if(self)
        {
            self.image = image;
    
            //set the view to opaque
            self.opaque = NO;
        }
    
        return self;
    }
    
    - (void)setTintColor:(UIColor *)color
    {
        _tintColor = color;
    
        //update every time the tint color is set
        [self setNeedsDisplay];
    }
    
    - (void)drawRect:(CGRect)rect
    {
        CGContextRef context = UIGraphicsGetCurrentContext();    
    
        //resolve CG/iOS coordinate mismatch
        CGContextScaleCTM(context, 1, -1);
        CGContextTranslateCTM(context, 0, -rect.size.height);
    
        //set the clipping area to the image
        CGContextClipToMask(context, rect, _image.CGImage);
    
        //set the fill color
        CGContextSetFillColor(context, CGColorGetComponents(_tintColor.CGColor));
        CGContextFillRect(context, rect);    
    
        //blend mode overlay
        CGContextSetBlendMode(context, kCGBlendModeOverlay);
    
        //draw the image
        CGContextDrawImage(context, rect, _image.CGImage);    
    }
    
    @end
    • Gracias. Esta fue la primera solución de esta pregunta que en realidad el apoyo transparencia de la imagen correctamente.
    • Cuando trato de usar esta respuesta, mi fondo (el área que debe ser transparente) es de color negro en su lugar. ¿Sabe usted lo que yo podría estar haciendo mal aquí?
    • No importa! (Yo tenía un color de fondo establecido en el guión! D’oh!) Esta solución es impresionante!!!
    • Esta solución funciona bien, aunque tengo mejores resultados mediante la representación de la imagen, y luego rellenar con el color en la parte superior con kCGBlendModeColor.
    • el drawRect: el método es realmente la «carne» de esta solución. El resto es una cuestión de gusto y estilo. Gracias! Trabajó para mí!
  4. 26

    Sólo una rápida aclaración (después de algunas investigaciones sobre este tema). El Apple doc aquí establece claramente que:

    La UIImageView clase está optimizada para dibujar sus imágenes a la pantalla. UIImageView no llama a la drawRect: método de sus subclases. Si la subclase debe incluir código personalizado de dibujo, usted debe crear una subclase de la UIView clase en su lugar.

    así que ni siquiera perder el tiempo tratando de reemplazar este método en un UIImageView subclase. Empezar con UIView lugar.

    • Oh, cómo me gustaría saber de esto hace seis meses. Deberían poner la advertencia en 72 tipo de punto, de color rojo con la etiqueta blink.
    • Sé que decir… he perdido la mitad de un día de jugar con él.
    • gracias @mpstx…También puesto que la documentación de la línea en la respuesta entre comillas…que Apple debería haber hecho lo mismo en la documentación…:-)
  5. 5

    Esto podría ser muy útil: PhotoshopFramework es una potente librería para manipular imágenes en Objective-C. Este fue desarrollado para traer las mismas funcionalidades que Adobe Photoshop usuarios están familiarizados. Ejemplos: Ajuste de colores mediante RGB de 0 a 255, aplique la mezcla de los contribuyentes, transformaciones…

    Es de código abierto, aquí está el link del proyecto: https://sourceforge.net/projects/photoshopframew/

    • Se ve interesante, pero ¿qué vas a cambiar el nombre para cuando Adobe abogados de averiguar?
    • Vamos a averiguar más tarde. No es un producto comercial de todos modos, es una especie de «nombre en clave». También es un interno de la biblioteca.
    • +1 por lo que sugiere una biblioteca (incluso si es un poco de auto promoción), y no dar pasos para reinventar la rueda.
  6. 4
    UIImage * image = mySourceImage;
    UIColor * color = [UIColor yellowColor];  
    UIGraphicsBeginImageContext(image.size);
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height) blendMode:kCGBlendModeNormal alpha:1];
    UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    [color setFill];
    [path fillWithBlendMode:kCGBlendModeMultiply alpha:1]; //look up blending modes for your needs
    UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //use newImage for something
    • Necesitaba un tinte UIImage, pero no para el uso en el interior de un UIImageView, pero como una imagen de fondo para un UINavigationBar, y su código hizo el truco. Gracias.
  7. 3

    Aquí es otra forma de implementar el teñido de la imagen, especialmente si usted ya está usando QuartzCore para algo más. Esta fue mi respuesta para una pregunta similar.

    De Importación QuartzCore:

    #import <QuartzCore/QuartzCore.h>

    Crear transparente CALayer y agregarlo como una subcapa de la imagen que desea matiz:

    CALayer *sublayer = [CALayer layer];
    [sublayer setBackgroundColor:[UIColor whiteColor].CGColor];
    [sublayer setOpacity:0.3];
    [sublayer setFrame:toBeTintedImage.frame];
    [toBeTintedImage.layer addSublayer:sublayer];

    Agregar QuartzCore a los proyectos de Marco de lista (si no está ya allí), de lo contrario, recibirá errores de compilador como este:

    Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"
  8. 2

    Para aquellos de ustedes que tratan de crear subclases de un UIImageView clase y quedar atrapado en el «drawRect: no ser llamado», tenga en cuenta que usted debe subclase de una UIView clase en lugar de eso, porque para UIImageView clases, la «drawRect:» el método no es llamado. Leer más aquí: drawRect no se llama en mi subclase de UIImageView

  9. 1

    Para Swift 2.0,

        let image: UIImage! = UIGraphicsGetImageFromCurrentImageContext()
    
        imgView.image = imgView.image!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
    
        imgView.tintColor = UIColor(red: 51/255.0, green: 51/255.0, blue: 
    
    51/255.0, alpha: 1.0)
  10. 0

    La única cosa que puedo pensar de sería la creación de un rectangular transparente ver con el color deseado y póngalo encima de la vista de imagen, añadiendo como una subvista. No estoy seguro de si esto realmente va a teñir la imagen en la forma en que te imaginas, aunque, no estoy seguro de cómo hackear una imagen y selectivamente reemplazar ciertos colores con los demás… suena bastante ambicioso para mí.

    Por ejemplo:

    UIImageView *yourPicture = (however you grab the image);
    UIView *colorBlock = [[UIView alloc] initWithFrame:yourPicture.frame];
    //Replace R G B and A with values from 0 - 1 based on your color and transparency
    colorBlock.backgroundColor = [UIColor colorWithRed:R green:G blue:B alpha:A];
    [yourPicture addSubView:colorBlock];

    Documentación para UIColor:

    colorWithRed:green:blue:alpha:
    
    Creates and returns a color object using the specified opacity and RGB component values.
    
    + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha
    
    Parameters
    
    red    - The red component of the color object, specified as a value from 0.0 to 1.0.
    
    green  - The green component of the color object, specified as a value from 0.0 to 1.0.
    
    blue   - The blue component of the color object, specified as a value from 0.0 to 1.0.
    
    
    
    alpha  - The opacity value of the color object, specified as a value from 0.0 to 1.0.
    
    Return Value
    
    The color object. The color information represented by this object is in the device RGB colorspace. 
    • Core Graphics parece ser capaz de aplicar los modos de flexión. Cómo es la cuestión.
  11. 0

    También usted puede ser que desee considerar el almacenamiento en caché de la imagen compuesta para el rendimiento y la justa representación en drawRect:, a continuación, se actualiza si una sucia bandera es realmente sucio. Mientras que usted podría estar cambiando a menudo, puede haber casos en los sorteos están llegando y no está sucio, así que usted puede simplemente actualizar desde la caché. Si la memoria es más de un problema de rendimiento, puede ignorar este 🙂

    • Eso es lo que el subyacente CALayer hace automáticamente para usted. No hay necesidad de almacenar en caché el dibujo de la vista de forma manual.
  12. 0

    Hice macros para este propósito:

    #define removeTint(view) \
    if ([((NSNumber *)[view.layer valueForKey:@"__hasTint"]) boolValue]) {\
    for (CALayer *layer in [view.layer sublayers]) {\
    if ([((NSNumber *)[layer valueForKey:@"__isTintLayer"]) boolValue]) {\
    [layer removeFromSuperlayer];\
    break;\
    }\
    }\
    }
    
    #define setTint(view, tintColor) \
    {\
    if ([((NSNumber *)[view.layer valueForKey:@"__hasTint"]) boolValue]) {\
    removeTint(view);\
    }\
    [view.layer setValue:@(YES) forKey:@"__hasTint"];\
    CALayer *tintLayer = [CALayer new];\
    tintLayer.frame = view.bounds;\
    tintLayer.backgroundColor = [tintColor CGColor];\
    [tintLayer setValue:@(YES) forKey:@"__isTintLayer"];\
    [view.layer addSublayer:tintLayer];\
    }

    De usar, simplemente llame a:

    setTint(yourView, yourUIColor);
    //Note: include opacity of tint in your UIColor using the alpha channel (RGBA), e.g. [UIColor colorWithRed:0.5f green:0.0 blue:0.0 alpha:0.25f];

    Al quitar el tinte simplemente llame a:

    removeTint(yourView);

Dejar respuesta

Please enter your comment!
Please enter your name here