我如何在iPhone上以编程方式为图像着色?

wil*_*lc2 87 cocoa-touch tint image-processing uiimage ios

我想用颜色参考着色图像.结果应该类似于Photoshop中的"乘法"混合模式,其中白色将替换为色调:

替代文字

我会不断改变颜色值.

跟进:我会把代码放在我的ImageView的drawRect:方法中,对吗?

与往常一样,代码片段将极大地帮助我理解,而不是链接.

更新:使用Ramin建议的代码对UIImageView进行子类化.

我把它放在viewDidLoad中:我的视图控制器:

[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];
Run Code Online (Sandbox Code Playgroud)

我看到了图像,但没有被染色.我还尝试加载其他图像,在IB中设置图像,并在我的视图控制器中调用setNeedsDisplay:

更新:drawRect:未被调用.

最后更新:我找到了一个正确设置了imageView的旧项目,所以我可以测试Ramin的代码,它就像一个魅力!

最后的最后更新:

对于那些刚学习Core Graphics的人来说,这是最简单的事情.

在您的子类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
}
Run Code Online (Sandbox Code Playgroud)

Tol*_*Hon 76

在iOS7中,他们在UIImageView上引入了tintColor属性,在UIImage上引入了renderingMode.要在iOS7上为UIImage着色,您所要做的就是:

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
Run Code Online (Sandbox Code Playgroud)

  • 这绝对是iOS 7*的最佳和最简单的方法,如果*这是您正在寻找的色调行为.但是这段代码应用了一种色彩,就好像你在Photoshop中使用100%不透明的"叠加"混合模式,而不是原始问题所寻找的"乘法"混合模式. (18认同)

Ram*_*min 44

首先,您需要子类化UIImageView并覆盖drawRect方法.你的类需要一个UIColor属性(让我们称之为overlayColor)来保存混合颜色和一个自定义的setter,它会在颜色变化时强制重绘.像这样的东西:

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

   overlayColor = [newColor retain];
   [self setNeedsDisplay]; // fires off drawRect each time color changes
}
Run Code Online (Sandbox Code Playgroud)

在drawRect方法中,您需要首先绘制图像,然后使用填充了所需颜色的矩形以及正确的混合模式覆盖它,如下所示:

- (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);
}
Run Code Online (Sandbox Code Playgroud)

通常为了优化绘图,您可以将实际绘图限制为仅传递到drawRect的区域,但由于每次颜色更改时都必须重新绘制背景图像,因此整个绘图可能需要刷新.

要使用它,请创建对象的实例,然后将image属性(从UIImageView继承)设置为图片和overlayColorUIColor值(可以通过更改传递的颜色的alpha值来调整混合级别).

  • (正如此处的另一个答案中所述)_特殊注意事项UIImageView类已经过优化,可以将其图像绘制到显示器上.UIImageView不会调用drawRect:一个子类.如果您的子类需要自定义绘图代码,建议您使用UIView作为基类.这意味着您不能继承UIImageView并期望调用drawRect,*at all*. (10认同)

mat*_*orb 26

只需快速澄清一下(经过对该主题的一些研究).这里的Apple文档明确指出:

所述UIImageView类被优化以绘制其图像的显示.UIImageView不会调用drawRect:其子类的方法.如果您的子类需要包含自定义绘图代码,则应该UIView替代该类.

因此,甚至不要浪费任何时间尝试在UIImageView子类中重写该方法.从UIView相反开始.

  • 哦,我希望六个月前我能知道这件事.他们应该将警告设置为72点类型,红色带有闪烁标记. (9认同)

小智 26

我想用alpha着色图像,我创建了以下类.如果您发现任何问题,请告诉我.

我已经命名了我的类CSTintedImageView,它继承UIView自从UIImageView不调用drawRect:方法,就像之前的回复中提到的那样.我已经设置了一个类似于在UIImageView类中找到的初始化器.

用法:

CSTintedImageView * imageView = [[CSTintedImageView alloc] initWithImage:[UIImage imageNamed:@"image"]];
imageView.tintColor = [UIColor redColor];
Run Code Online (Sandbox Code Playgroud)

CSTintedImageView.h

@interface CSTintedImageView : UIView

@property (strong, nonatomic) UIImage * image;
@property (strong, nonatomic) UIColor * tintColor;

- (id)initWithImage:(UIImage *)image;

@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.这是该问题中第一个真正支持图像透明度的解决方案. (2认同)
  • 此解决方案效果很好,尽管先渲染图像,然后用kCGBlendModeColor在顶部填充颜色,以获得更好的结果。 (2认同)

SEQ*_*eam 5

这可能非常有用:PhotoshopFramework是一个强大的库来操作Objective-C上的图像.开发它是为了带来Adobe Photoshop用户熟悉的相同功能.示例:使用RGB 0-255设置颜色,应用混合文件管理器,转换......

是开源的,这里是项目链接:https://sourceforge.net/projects/photoshopframew/

  • 看起来很有趣,但是当Adobe的律师发现它时,您打算将名称更改为什么? (2认同)