Я хочу подкрасить изображение с помощью цветовой ссылки. Результат должен выглядеть как режим смешивания Multiply в Photoshop, где белые цвета будут заменены оттенком :
Я буду постоянно менять значение цвета.
Дальнейшие действия: я бы поместил код для этого в метод drawRect: моего ImageView, верно?
Как всегда, в моем понимании мне очень помогли бы фрагменты кода , а не ссылка.
Обновление: создание подкласса UIImageView с кодом, предложенным Рамином .
Я поместил это в viewDidLoad: моего контроллера представления:
[self.lena setImage:[UIImage imageNamed:kImageName]];
[self.lena setOverlayColor:[UIColor blueColor]];
[super viewDidLoad];
Я вижу изображение, но оно не тонируется. Я также попытался загрузить другие изображения, установить изображение в IB и вызвать setNeedsDisplay: в моем контроллере представления.
Обновление : drawRect: не вызывается.
Последнее обновление: я нашел старый проект, в котором был правильно настроен imageView, чтобы я мог протестировать код Рамина, и он работает как шарм!
Финальное, окончательное обновление:
Для тех из вас, кто только изучает 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) для хранения смешанного цвета и настраиваемый установщик, который вызывает перерисовку при изменении цвета. Что-то вроде этого:
- (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 (уровни наложения можно настроить, изменив альфа-значение передаваемого вами цвета).источник
В iOS7 они представили свойство tintColor в UIImageView и renderMode в UIImage. Чтобы подкрасить UIImage на iOS7, все, что вам нужно сделать, это:
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
источник
Я хотел тонировать изображение с помощью альфы и создал следующий класс. Пожалуйста, дайте мне знать, если у вас возникнут проблемы.
Я назвал свой класс,
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
источник
Просто краткое пояснение (после некоторых исследований по этой теме). В Apple док здесь ясно говорится , что:
так что даже не тратьте время на попытки переопределить этот метод в
UIImageView
подклассе.UIView
Вместо этого начните с .источник
Это может быть очень полезно: 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 для чего-то другого. Это был мой ответ на аналогичный вопрос .
Импортировать QuartzCore:
#import <QuartzCore/QuartzCore.h>
Создайте прозрачный CALayer и добавьте его как подслой для изображения, которое вы хотите тонировать:
CALayer *sublayer = [CALayer layer]; [sublayer setBackgroundColor:[UIColor whiteColor].CGColor]; [sublayer setOpacity:0.3]; [sublayer setFrame:toBeTintedImage.frame]; [toBeTintedImage.layer addSublayer:sublayer];
Добавьте QuartzCore в список ваших проектов Framework (если его еще нет), иначе вы получите такие ошибки компилятора:
Undefined symbols for architecture i386: "_OBJC_CLASS_$_CALayer"
источник
Тем из вас, кто пытается создать подкласс класса UIImageView и застрять на «drawRect: не вызывается», обратите внимание, что вместо этого вы должны создать подкласс класса UIView, потому что для классов UIImageView метод «drawRect:» не вызывается. Подробнее здесь: drawRect не вызывается в моем подклассе UIImageView
источник
Единственное, что я могу придумать, - это создать прямоугольный, в основном прозрачный вид с желаемым цветом и наложить его на вид изображения, добавив его в качестве подвида. Я не уверен, действительно ли это окрасит изображение так, как вы себе представляете, хотя я не уверен, как бы вы взломали изображение и выборочно заменили одни цвета другими ... звучит для меня довольно амбициозно.
Например:
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
источник
Для 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)
источник
Я сделал для этого макросы:
#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);
источник