Как я могу нарисовать изображение программно на iPhone?
Я хотел бы подкрасить изображение с помощью ссылки на цвет. Результаты должны выглядеть как режим смешивания Multiply в Photoshop, где белые будут заменены оттенком:
![alt text]()
Я буду менять значение цвета непрерывно.
Последующие действия: Я бы поставил код для этого в моем ImageView drawRect: метод, правильно?
Как всегда, фрагмент кода очень помог бы мне в понимании, в отличие от ссылки.
Обновление: Подклассификация UIImageView с помощью кода Ramin.
Я помещаю это в 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
}
Ответы
Ответ 1
Сначала вы захотите подклассифицировать 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 (уровни смешивания можно отрегулировать, изменив альфа-значение цвета вы пропустите).
Ответ 2
В 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
Ответ 3
Простое уточнение (после некоторых исследований по этой теме). В документе Apple здесь четко указано, что:
Класс UIImageView
оптимизирован для рисования его изображений на дисплее. UIImageView
не вызывает метод drawRect:
для своих подклассов. Если ваш подкласс должен включать специальный код чертежа, вы должны подклассифицировать класс UIView
.
поэтому даже не тратьте время на попытку переопределить этот метод в подклассе UIImageView
. Начните с UIView
вместо этого.
Ответ 4
Я хотел подкрасить изображение с помощью альфы, и я создал следующий класс. Пожалуйста, дайте мне знать, если у вас возникнут проблемы с этим.
Я назвал свой класс 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
Ответ 5
Это может быть очень полезно: PhotoshopFramework - это одна мощная библиотека для управления изображениями на Objective-C. Это было разработано, чтобы принести те же функции, что и пользователи Adobe Photoshop. Примеры: установите цвета с использованием RGB 0-255, примените фильтры смешивания, преобразования...
Является открытым исходным кодом, вот ссылка на проект: https://sourceforge.net/projects/photoshopframew/
Ответ 6
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
Ответ 7
Вот еще один способ реализации тонирования изображений, особенно если вы уже используете 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"
Ответ 8
Для тех из вас, кто пытается подклассифицировать класс UIImageView и застрять на "drawRect: не вызывается", обратите внимание, что вместо этого вы должны подклассифицировать класс UIView, потому что для классов UIImageView метод "drawRect:" не называется. Подробнее здесь: drawRect не вызывается в моем подклассе UIImageView
Ответ 9
Для 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
Единственное, о чем я могу думать, это создать прямоугольное прозрачное представление с желаемым цветом и наложить его на изображение, добавив его как подвью. Я не уверен, что это действительно закрасит изображение так, как вы себе представляете, я не уверен, как вы взломали изображение и выборочно замените некоторые цвета другими... звучит довольно амбициозно для меня.
Например:
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.
Ответ 11
Также вы можете подумать о кешировании композитного изображения для производительности и просто визуализировать его в drawRect:, а затем обновить его, если грязный флаг действительно грязный. Хотя вы, возможно, часто меняете его, могут быть случаи, когда втягиваются ничьи, и вы не грязны, поэтому вы можете просто обновить их из кеша. Если память больше связана с производительностью, вы можете игнорировать это:)
Ответ 12
У меня есть библиотека, которую я открываю для этого: ios-image-filters