Содержание
Продолжаю тему «об интересном». В iOS 5 появилась замечательная возможность применять фильтры к изображениям. Это значит, что теперь, если вам нужно немного подкорректировать изображение не нужно прибегать к сторонним средствам. Все доступно «из коробки» в iOS SDK.
Мы будем использовать CoreImage-framework. В нашем действе будут так же участвовать — CIImage и CIFilter. Ну что ж, начнем. Будем регулировать на картинке яркость, контраст и насыщенность.
Для начала скачаем какую-нибудь картинку, я взял вот эту — картинка. Так же рекомендую скачать исходники.
Что же такое CIFilter? Это класс, который представляет собой фильтр для обработки изображения. Установка параметров изображения происходит с помощью KVC (если непонятно, что это такое — нестрашно, далее будет ясно).
CIImage — некая обертка над изображением. В iOS SDK существуют и другие обертки, такие как UIImage и CGImage.
Отображаем картинку
Нам нужно написать класс, который наследует UIView и отображает картинку с примененным фильтром. У класса должно быть свойство — картинка, которую хотим изменить (UIImage) и метод, который принимает фильтр. Обзовем его FilterImageView. Далее h-файл:
#import
#import
@interface FilterImageView : UIView
{
CIImage* m_filteredImage;
}
// картинка, которую будем менять
@property (nonatomic, retain) UIImage* image;
// применить фильтр к изображению
-(void) applyFilter:(CIFilter *)filter;
@end
Обратите внимание на то, что мы подключаем CoreImage. Так же необходимо добавить CoreImage в проект.
Немного вдадимся в работу класса. Логика следующая — если фильтр не был применен — отображается не измененная картинка, если был применен — отображаем измененную.
Метод применения фильтра:
-(void) applyFilter:(CIFilter *)filter
{
[m_filteredImage release];
m_filteredImage = nil;
if ( filter )
{
// применяем фильтр к картинке
CIImage* tempImage = [[CIImage alloc] initWithImage:self.image];
[filter setValue:tempImage forKey:@"inputImage"];
// забираем измененную картинку
m_filteredImage = [[filter outputImage] retain];
}
// перерисуемся
[self setNeedsDisplay];
}
Обратим внимание на
[filter setValue:tempImage forKey:@"inputImage"];
Это и есть применение KVC. Класс не имеет явного свойства inputImage. Т.к. класс CIFilter описывает множество разных фильтров, их входные параметры не логично описывать свойствами. Поэтому тут и применили KVC. Мы задаем картинку через ключ — inputImage.
Так же обратим внимание на
[self setNeedsDisplay];
После преобразования картинки мы перерисовываем вид, чтобы отобразить новую картинку. Для этого у нас должен быть метод drawRect:, вот он:
-(void) drawRect:(CGRect)rect
{
// если есть измененная картинка - рисуем ее
if ( m_filteredImage )
[[UIImage imageWithCIImage:m_filteredImage] drawInRect:self.bounds];
else
[self.image drawInRect:self.bounds];
}
Тут все просто, если есть новая картинка — рисуем ее, если нет — рисуем оригинал. Исходник класса вы можете скачать в конце статьи.
Основное действо
Чтобы все это имело какое-либо визуальное представление — создадим в Interface Builder, который будет содержать в себе картинку и три слайдера (яркость, контраст и насыщенность). У меня получилось вот что:
Назначьте слайдеру яркости максимальное значение 1, минимальное -1, значение по-умолчанию 0. Слайдеру контраста диапазон [0, 4], значение по-умолчанию 1. Слайдеру насыщенности — [0, 2], значение 1.
Добавьте обычный UIView и пропишите класс FilterImageView, как это показано на картинке:
Добавьте в ваш UIViewController Outlet на FilterImageView.
IBOutlet FilterImageView *m_imageView;
Так же назначьте метод, в который будут приходить все изменения состояния слайдеров:
- (IBAction)sliderValueChanged:(id)sender;
Полная сигнатура класса вашего UIViewController:
#import
#import "FilterImageView.h"
typedef enum {
kSliderBrightness = 1,
kSliderContrast,
kSliderSaturation
} Sliders;
@interface ViewController : UIViewController
{
IBOutlet FilterImageView *m_imageView;
CIFilter* m_filter;
}
- (IBAction)sliderValueChanged:(id)sender;
@end
Enum нам нужен для того, чтобы различать слайдеры. Назначьте слайдеру яркости тег 1, контрасту — 2, насыщенности — 3.
При загрузке view у UIViewController мы назначим картинку и подготовим фильтр:
- (void)viewDidLoad
{
[super viewDidLoad];
m_imageView.image = [UIImage imageNamed:@"52454.jpg"];
m_filter = [[self prepareFilter] retain];
}
Метод подготовки фильтра:
-(CIFilter *) prepareFilter
{
// cоздаем фильтр и ставим все параметры по-умолчанию
CIFilter* filter = [CIFilter filterWithName:@"CIColorControls"];
[filter setDefaults];
return filter;
}
Тут фильтр называется CIColorControls. В iOS SDK есть еще некоторое количество фильтров, названия которых можно найти в документации.
Теперь осталось самое главное — при изменении значения слайдера — изменять картинку:
- (IBAction)sliderValueChanged:(id)sender
{
// в зависимости от слайдера изменяем нужный параметр
UISlider* slider = (UISlider *)sender;
switch (slider.tag) {
case kSliderBrightness:
[m_filter setValue:[NSNumber numberWithDouble:[slider value]] forKey:@"inputBrightness"];
break;
case kSliderContrast:
[m_filter setValue:[NSNumber numberWithDouble:[slider value]] forKey:@"inputContrast"];
break;
case kSliderSaturation:
[m_filter setValue:[NSNumber numberWithDouble:[slider value]] forKey:@"inputSaturation"];
break;
}
[m_imageView applyFilter:m_filter];
}
Как видим, тут тоже используется KVC для назначения свойств фильтра.
На этом все, скачать исходники можно тут: ссылка
Вот несколько примеров работы приложения:
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: