我如何在iOS上以编程方式为图像着色?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何在iOS上以编程方式为图像着色?相关的知识,希望对你有一定的参考价值。
我想用颜色参考着色图像。结果应该类似于Photoshop中的“乘法”混合模式,其中白色将替换为色调:
我会不断改变颜色值。
跟进:我会把代码放在我的ImageView的drawRect:方法中,对吗?
与往常一样,代码片段将极大地帮助我理解,而不是链接。
更新:使用Ramin建议的代码对UIImageView进行子类化。
我把它放在viewDidLoad中:我的视图控制器:
[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];
我看到了图像,但没有被染色。我还尝试加载其他图像,在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
}
首先,您需要子类化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
}
在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);
}
通常为了优化绘图,您可以将实际绘图限制为仅传递到drawRect的区域,但由于每次颜色更改时都必须重新绘制背景图像,因此整个绘图可能需要刷新。
要使用它,请创建对象的实例,然后将image
属性(继承自UIImageView)设置为图片,将overlayColor
设置为UIColor值(可以通过更改传递的颜色的alpha值来调整混合级别)。
我唯一能想到的就是创建一个具有所需颜色的矩形大部分透明视图,并将其作为子视图添加到图像视图上。我不确定这是否会以你想象的方式对图像进行真正的着色,我不确定你是如何入侵图像并选择性地用其他颜色替换某些颜色的......对我来说听起来非常野心勃勃。
例如:
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];
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.
此外,您可能需要考虑缓存合成图像以获得性能,并在drawRect:中呈现它,然后在脏标志确实很脏的情况下更新它。虽然您可能经常更改它,但可能会出现绘图并且您没有脏的情况,因此您只需从缓存中刷新即可。如果内存比性能更重要,你可以忽略这个:)
我有一个我为此开源的库:ios-image-filters
我为此目的制作了宏:
#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];
}
要使用,只需致电:
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];
删除色调时只需调用:
removeTint(yourView);
在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
只需快速澄清一下(经过对该主题的一些研究)。 Apple doc here明确指出:
UIImageView
类经过优化,可将其图像绘制到显示器上。UIImageView
没有调用其子类的drawRect:
方法。如果您的子类需要包含自定义绘图代码,则应该改为继承UIView
类。
所以,甚至不要浪费任何时间试图在UIImageView
子类中重写该方法。从UIView
开始。
我想用alpha着色图像,我创建了以下类。如果您发现任何问题,请告诉我。
我将我的班级命名为CSTintedImageView
,它继承自UIView
,因为UIImageView
没有像前面的回复中提到的那样调用drawRect:
方法。我已经设置了一个类似于UIImageView
类中的指定初始化器。
用法:
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
这可能非常有用:PhotoshopFramework是一个强大的库来操作Objective-C上的图像。开发它是为了带来Adobe Photoshop用户熟悉的相同功能。示例:使用RGB 0-255设置颜色,应用混合文件管理器,转换......
是开源的,这里是项目链接: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
这是实现图像着色的另一种方法,特别是如果您已经将QuartzCore用于其他方面。这是我对a 以上是关于我如何在iOS上以编程方式为图像着色?的主要内容,如果未能解决你的问题,请参考以下文章