Используя обратную связь для обработки изображений

CIImageAccumulator класс (доступный только на OS X) идеально подходит для основанной на обратной связи обработки. Поскольку это - имя, предлагает, это накапливает данные изображения в течение долгого времени. Эта глава показывает, как использовать a CIImageAccumulator возразите для реализации простого приложения рисования под названием MicroPaint, позволяющий пользователям подрисовывать холст для создания изображений, подобных показанному на рисунке 7-1.

  Вывод рисунка 7-1 от MicroPaint
Output from MicroPaint

«Изображение» запускается как пустое полотно. MicroPaint использует аккумулятор изображения для сбора краски, примененной пользователем. Когда пользователь нажимает Clear, MicroPaint сбрасывает аккумулятор изображения к белому холсту. Цвет хорошо позволяет пользователю изменять цвета краски. Пользователь может изменить размер кисти с помощью ползунка.

Существенные задачи для создания установки аккумулятора изображения для приложения MicroPaint:

  1. Установите интерфейс для приложения MicroPaint

  2. Инициализируйте фильтры и значения по умолчанию для рисования

  3. Отследите и накопите операции рисования

В этой главе описываются только код, который важен для создания аккумулятора изображения и поддержки получения к ней. Методы для рисования к представлению и для обработки изменений размера представления не обсуждены здесь. Для этого посмотрите CIMicroPaint, который является проектом кода полной выборки, который можно загрузить и исследовать более подробно. CIMicroPaint имеет несколько интересных подробных данных. Это показывает, как нарисовать к представлению OpenGL и поддержать обратную совместимость для предыдущих версий OS X.

Установите интерфейс для приложения MicroPaint

Интерфейсу к MicroPaint нужно следующее:

Создавание Словаря Фильтров объявляет 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];
}