Image Description

Продолжаю тему «об интересном». В 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, который будет содержать в себе картинку и три слайдера (яркость, контраст и насыщенность). У меня получилось вот что:

Image Description

Назначьте слайдеру яркости максимальное значение 1, минимальное -1, значение по-умолчанию 0. Слайдеру контраста диапазон [0, 4], значение по-умолчанию 1. Слайдеру насыщенности — [0, 2], значение 1.

Добавьте обычный UIView и пропишите класс FilterImageView, как это показано на картинке:

Image Description

Добавьте в ваш 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 для назначения свойств фильтра.

На этом все, скачать исходники можно тут: ссылка

Вот несколько примеров работы приложения:

Image Description


Image Description

Image Description

Image Description

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *