Используя обратную связь для обработки изображений
CIImageAccumulator
класс (доступный только на OS X) идеально подходит для основанной на обратной связи обработки. Поскольку это - имя, предлагает, это накапливает данные изображения в течение долгого времени. Эта глава показывает, как использовать a CIImageAccumulator
возразите для реализации простого приложения рисования под названием MicroPaint, позволяющий пользователям подрисовывать холст для создания изображений, подобных показанному на рисунке 7-1.
«Изображение» запускается как пустое полотно. MicroPaint использует аккумулятор изображения для сбора краски, примененной пользователем. Когда пользователь нажимает Clear, MicroPaint сбрасывает аккумулятор изображения к белому холсту. Цвет хорошо позволяет пользователю изменять цвета краски. Пользователь может изменить размер кисти с помощью ползунка.
Существенные задачи для создания установки аккумулятора изображения для приложения MicroPaint:
В этой главе описываются только код, который важен для создания аккумулятора изображения и поддержки получения к ней. Методы для рисования к представлению и для обработки изменений размера представления не обсуждены здесь. Для этого посмотрите CIMicroPaint, который является проектом кода полной выборки, который можно загрузить и исследовать более подробно. CIMicroPaint
имеет несколько интересных подробных данных. Это показывает, как нарисовать к представлению OpenGL и поддержать обратную совместимость для предыдущих версий OS X.
Установите интерфейс для приложения MicroPaint
Интерфейсу к MicroPaint нужно следующее:
Аккумулятор изображения
«Кисть» для пользователя. Кисть является Базовым фильтром Изображения (CIRadialGradient), применяющийся, раскрашивают путь, моделирующий аэрограф.
Составной фильтр (CISourceOverCompositing), позволяющий новой краске быть составленной ранее примененная краска.
Переменные для того, чтобы отслеживать текущий цвет краски и размер кисти.
Создавание Словаря Фильтров объявляет MircoPaintView
как подкласс SampleCIView
. SampleCIView
класс не обсужден здесь; это - подкласс NSOpenGLView
класс. См. демонстрационное приложение CIMicroPaint для подробных данных.
Перечисление 7-1 интерфейс для приложения MicroPaint
@interface MicroPaintView : SampleCIView { |
CIImageAccumulator *imageAccumulator; |
CIFilter *brushFilter; |
CIFilter *compositeFilter; |
NSColor *color; |
CGFloat brushSize; |
} |
@end |
Инициализируйте фильтры и значения по умолчанию для рисования
При инициализации приложения MicroPaint (как показано в Перечислении 7-2), необходимо создать кисть и составные фильтры, и установить начальный размер кисти и цвет краски. Код в Перечислении 7-2 создается и инициализируется к прозрачному черному цвету с входным радиусом 0. Когда пользователь перетаскивает курсор, фильтр кисти берет текущую стоимость для размера кисти и цвета.
Перечисление 7-2 , Инициализирующее фильтры, размер кисти и цвет краски
brushFilter = [CIFilter filterWithName: @"CIRadialGradient" keysAndValues: |
@"inputColor1", [CIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0], |
@"inputRadius0", @0.0, |
nil]; |
compositeFilter = [CIFilter filterWithName: @"CISourceOverCompositing"]; |
brushSize = 25.0; |
color = [NSColor colorWithDeviceRed: 0.0 green: 0.0 blue: 0.0 alpha: 1.0]; |
Отследите и накопите операции рисования
mouseDragged:
метод вызывают каждый раз, когда пользователь или щелкает или перетаскивает курсор по холсту. Это обновляет кисть, и составляющий фильтр оценивает и добавляет новые операции рисования к накопленному изображению.
После установки изображения необходимо инициировать обновление дисплея. Ваш drawRect:
дескрипторы метода, получающие изображение. При рисовании к a CIContext
возразите, удостоверьтесь, что использовали drawImage:inRect:fromRect:
вместо устаревшего метода drawImage:atPoint:fromRect:
.
Перечисление 7-3 Установка и применение кисти фильтрует к накопленному изображению
- (void)mouseDragged:(NSEvent *)event |
{ |
CGRect rect; |
NSPoint loc = [self convertPoint: [event locationInWindow] fromView: nil]; |
CIColor *cicolor; |
// Make a rectangle that is centered on the drag location and |
// whose dimensions are twice of the current brush size |
rect = CGRectMake(loc.x-brushSize, loc.y-brushSize, |
2.0*brushSize, 2.0*brushSize); |
// Set the size of the brush |
// Recall this is really a radial gradient filter |
[brushFilter setValue: @(brushSize) |
forKey: @"inputRadius1"]; |
cicolor = [[CIColor alloc] initWithColor: color]; |
[brushFilter setValue: cicolor forKey: @"inputColor0"]; |
[brushFilter setValue: [CIVector vectorWithX: loc.x Y:loc.y] |
forKey: kCIInputCenterKey]; |
// Composite the output from the brush filter with the image |
// accummulated by the image accumulator |
[compositeFilter setValue: [brushFilter valueForKey: kCIOutputImageKey] |
forKey: kCIInputImageKey]; |
[compositeFilter setValue: [imageAccumulator image] |
forKey: kCIInputBackgroundImageKey]; |
// Set the image accumluator to the composited image |
[imageAccumulator setImage: [compositeFilter valueForKey: kCIOutputImageKey] |
dirtyRect: rect]; |
// After setting the image, you need to trigger an update of the display |
[self setImage: [imageAccumulator image] dirtyRect: rect]; |
} |