Question

Je voudrais teinter une image avec une référence de couleur. Les résultats doivent ressembler à mode de fusion dans Photoshop, où blancs seraient remplacés par teinte :

text alt

Je vais changer la valeur de couleur en continu.

Suivi: Je mettrais le code pour le faire dans drawRect de mon ImageView: méthode, droite

Comme toujours, extrait de code serait grandement à ma compréhension, par opposition à un lien.

Mise à jour: un Dériver UIImageView avec le code Ramin a suggéré.

Je mets cela dans viewDidLoad: de mon contrôleur de vue:

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

Je vois l'image, mais ce n'est pas teintés. J'ai aussi essayé de charger d'autres images, réglage de l'image IB, et appelant setNeedsDisplay:. Dans mon contrôleur de vue

Mise à jour : drawRect:. N'est pas appelé

Mise à jour finale: J'ai trouvé un vieux projet qui avait un imageView mis en place correctement pour que je puisse tester le code de Ramin et fonctionne comme un charme

finale, dernière mise à jour:

Pour ceux d'entre vous en train d'apprendre sur Core Graphics, voici la chose la plus simple qui pourrait éventuellement travailler.

Dans votre sous-classé 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
}
Était-ce utile?

La solution

D'abord, vous aurez envie de sous-classe UIImageView et remplacer la méthode de drawRect. Votre classe a besoin d'une propriété UIColor (appelons-le overlayColor) pour maintenir la couleur de fusion et un setter personnalisé qui force un rafraîchissement lorsque les changements de couleur. Quelque chose comme ceci:

- (void) setOverlayColor:(UIColor *)newColor {
   if (overlayColor)
     [overlayColor release];

   overlayColor = [newColor retain];
   [self setNeedsDisplay]; // fires off drawRect each time color changes
}

Dans la méthode drawRect vous voulez dessiner l'image première superposition puis avec un rectangle rempli de la couleur que vous voulez ainsi que le mode de mélange approprié, quelque chose comme ceci:

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

Ordinairement pour optimiser le dessin que vous souhaitez restreindre le dessin réel à la seule zone passée pour drawRect, mais étant donné que l'image de fond doit être redessinée à chaque fois que la couleur change, il est probable que tout cela aura besoin rafraîchissant.

Pour utiliser créer une instance de l'objet puis définissez la propriété image (héritée de UIImageView) à l'image et overlayColor à une valeur de UIColor (les niveaux de mélange peuvent être ajustés en modifiant la valeur alpha de la couleur que vous passez vers le bas) .

Autres conseils

Dans iOS 7, ils ont introduit la propriété tintColor sur UIImageView et renderingMode sur UIImage. Pour teinter un UIImage sur iOS 7, tout ce que vous avez à faire est:

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

Je voulais teinter une image alpha et j'ai créé la classe suivante. S'il vous plaît laissez-moi savoir si vous rencontrez le moindre problème avec elle.

J'ai nommé mon CSTintedImageView de classe et il hérite de UIView depuis UIImageView ne remet pas la méthode de drawRect:, comme mentionné dans les réponses précédentes. J'ai mis un initialiseur désigné semblable à celle qui se trouve dans la classe UIImageView.

Utilisation:

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

Juste une petite précision (après quelques recherches sur ce sujet). Les href="http://developer.apple.com/iphone/library/documentation/uikit/reference/UIImageView_Class/Reference/Reference.html" d'Apple doc clairement que:

  

La classe UIImageView est optimisée pour dessiner les images sur l'écran. UIImageView ne remet pas la méthode drawRect: de ses sous-classes. Si votre sous-classe doit inclure le code de dessin personnalisé, vous devez sous-classe de la classe à la place de UIView.

donc ne même pas perdre de temps tenter de passer outre cette méthode dans une sous-classe de UIImageView. Commencez par UIView à la place.

Cela pourrait être très utile: PhotoshopFramework est une puissante bibliothèque pour manipuler des images sur Objective-C. Cela a été développé pour apporter les mêmes fonctionnalités que les utilisateurs d'Adobe Photoshop sont familiers. Exemples: Couleurs RVB utilisant 0-255, appliquez filers de mélange, transformations ...

est open source, voici le lien du projet: https://sourceforge.net/projects/photoshopframew/

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

Voici une autre façon de mettre en œuvre teinter d'image, surtout si vous utilisez déjà QuartzCore pour autre chose. Ce fut ma réponse pour une question similaire.

Importer QuartzCore:

#import <QuartzCore/QuartzCore.h>

Créer CALayer transparent et l'ajouter comme une sous-couche pour l'image que vous voulez teinte:

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

Ajoutez QuartzCore à vos projets liste-cadre (si elle n'y est pas déjà), sinon vous aurez des erreurs du compilateur comme ceci:

Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"

Pour ceux qui tentent de sous-classe d'une classe UIImageView et de se coincer à « drawRect: n'est pas appelé », notez que vous devez sous-classe d'une classe à la place de UIView, parce que pour les classes UIImageView, la « drawRect: » méthode n'est pas appelé. Lire la suite ici: drawRect pas appelé dans ma sous-classe de UIImageView

Pour 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)

La seule chose que je peux penser serait de créer une forme rectangulaire vue la plupart du temps transparent avec la couleur désirée et posez-le sur votre point de vue de l'image en ajoutant comme sous-vue. Je ne sais pas si cela va vraiment teinter l'image de la façon dont vous imaginez bien, je ne sais pas comment vous pirater une image et remplacer sélectivement certaines couleurs avec d'autres ... semble assez ambitieux pour moi.

Par exemple:

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];

Documentation pour 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. 

Aussi, vous voudrez peut-être envisager la mise en cache l'image Composited pour des performances et juste le rendre dans drawRect :, puis mis à jour si un drapeau sale est en effet sale. Alors que vous pourriez être en train de changer souvent, il peut y avoir des cas où se dresse reveniez et que vous n'êtes pas sale, donc vous pouvez simplement rafraîchir à partir du cache. Si la mémoire est un problème plus important que la performance, vous pouvez ignorer ceci:)

J'ai une bibliothèque que j'open source pour cela: ios-image-filtres

J'ai fait des macros à cet effet:

#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];\
}

Pour utiliser, il suffit simplement appeler:

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];

Lors de la suppression de la teinte simplement appeler:

removeTint(yourView);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top