Обработка изображений

Базовое Изображение имеет три класса, поддерживающие обработку изображений на iOS и OS X:

Остаток от этой главы обеспечивает все подробности, необходимо использовать Базовые фильтры Изображения и CIFilter, CIImage, и CIContext классы на iOS и OS X.

Обзор

Обработка изображения является прямой как показано в Перечислении 1-1. Этот пример использует Базовые методы Изображения, определенные для iOS; посмотрите ниже для соответствующих методов OS X. Каждый пронумерованный шаг в перечислении описан более подробно после перечисления.

Перечисление 1-1  основы применения фильтра к изображению на iOS

CIContext *context = [CIContext contextWithOptions:nil];               // 1
CIImage *image = [CIImage imageWithContentsOfURL:myURL];               // 2
CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];           // 3
[filter setValue:image forKey:kCIInputImageKey];
[filter setValue:@0.8f forKey:kCIInputIntensityKey];
CIImage *result = [filter valueForKey:kCIOutputImageKey];              // 4
CGRect extent = [result extent];
CGImageRef cgImage = [context createCGImage:result fromRect:extent];   // 5

Вот то, что делает код:

  1. Создайте a CIContext объект. contextWithOptions: метод только доступен на iOS. Для получения дополнительной информации на других методах для iOS и OS X посмотрите Таблицу 1-2.

  2. Создайте a CIImage объект. Можно создать a CIImage от множества источников, таких как URL. Посмотрите Создание Объекта CIImage для большего количества опций.

  3. Создайте фильтр и установите значения для его входных параметров. Существуют более компактные способы установить значения, чем показанный здесь. Посмотрите Создание Объекта CIFilter и Установку Значений.

  4. Получите выходное изображение. Выходное изображение является рецептом для того, как произвести изображение. Изображение еще не представляется. Посмотрите Получение Выходного Изображения.

  5. Представьте CIImage к Базовому Графическому изображению, которое готово к дисплею или сохраняющий к файлу.

Встроенные фильтры

Базовое Изображение идет с десятками встроенных фильтров, готовых поддерживать обработку изображений в Вашем приложении. Базовые Списки ссылок Фильтра Изображения эти фильтры, их характеристики, их iOS и доступность OS X, и показывают демонстрационное изображение, произведенное фильтром. Список встроенных фильтров может измениться, так по этой причине, Базовое Изображение обеспечивает методы, позволяющие Вам запросить систему для доступных фильтров (см. Запросы Системы для Фильтров).

Категория фильтра указывает тип эффекта — размытости, искажения, генератора, и т.д — или его надлежащее использование — неподвижные изображения, видео, неквадратные пиксели, и т.д. Фильтр может быть элементом больше чем одной категории. Фильтр также имеет имя дисплея, которое является именем, чтобы показать пользователям и имени фильтра, которое является именем, которое необходимо использовать для доступа к фильтру программно.

Большинство фильтров имеет один или несколько входные параметры, позволяющие Вам управлять, как сделана обработка. Каждый входной параметр имеет класс атрибута, указывающий его тип данных, такой как NSNumber. Входной параметр может дополнительно иметь другие атрибуты, такие как его значение по умолчанию, допустимые минимальные и максимальные значения, имя дисплея для параметра и любые другие атрибуты, описанные в Ссылке класса CIFilter.

Например, фильтр CIColorMonochrome имеет три входных параметра — изображение для обработки, монохромный цвет и интенсивность цвета. Вы предоставляете изображение и имеете опцию выбрать цвет и его интенсивность. Большинство фильтров, включая фильтр CIColorMonochrome, имеет значения по умолчанию для каждого входного параметра неизображения. Если Вы принимаете решение не предоставить свои собственные значения для входных параметров, базовое Изображение использует значения по умолчанию для обработки изображения.

Атрибуты фильтра сохранены как пары ключ/значение. Ключ является константой, идентифицирующей атрибут, и значение является установкой, связанной с ключом. Базовые значения Атрибута изображения обычно являются одним из типов данных, перечисленных в Таблице 1-1.

Табличные 1-1  типы данных Значения атрибута

Тип данных

Объект

Описание

Строки

NSString

Используемый для таких вещей как имена дисплея

Значения с плавающей точкой

NSNumber

Скалярные значения, такие как уровни яркости и радиусы

Векторы

CIVector

Укажите позиции, области и значения цвета; может иметь 2, 3, или 4 элемента, каждый из которых является числом с плавающей точкой

Цвета

CIColor

Содержите значения цвета и цветовое пространство, в котором можно интерпретировать значения

Изображения

CIImage

Легкие объекты, указывающие изображение «рецепты»

Преобразовывает

NSData на iOS

NSAffineTransform на OS X

Аффинное преобразование для применения к изображению

Базовое Изображение использует кодирование значения ключа, что означает, что можно получить и установить значения для атрибутов фильтра при помощи методов, предоставленных NSKeyValueCoding протокол. (Для получения дополнительной информации посмотрите, что Значение ключа Кодирует Руководство по программированию.)

Создание базового контекста изображения

Для рендеринга изображения необходимо создать Базовый контекст Изображения и затем использовать тот контекст для рисования выходного изображения. Базовый контекст Изображения представляет место назначения получения. Место назначения определяет, использует ли Базовое Изображение GPU или CPU для рендеринга. Таблица 1-2 перечисляет различные методы, которые можно использовать для определенных платформ и средств рендеринга.

Табличные 1-2  Методы, создающие Базовый контекст Изображения

Контекст

Средство рендеринга

Поддерживаемая платформа

contextWithOptions:

CPU или GPU

iOS

contextWithCGContext:options:

NSGraphicsContext

CPU или GPU

OS X

contextWithEAGLContext:

contextWithEAGLContext:options:

GPU

iOS

contextWithCGLContext:pixelFormat:options:

contextWithCGLContext:pixelFormat:colorSpace:options:

GPU

OS X

Создание Базового Контекста Изображения на iOS, Когда Вам не Нужна Производительность В реальном времени

Если Ваше приложение не требует отображения в режиме реального времени, можно создать a CIContext объект следующим образом:

CIContext *context = [CIContext contextWithOptions:nil];

Этот метод может использовать или CPU или GPU для рендеринга. Для указания, чтобы использовать установите словарь опций и добавьте ключ kCIContextUseSoftwareRenderer с надлежащим булевым значением для Вашего приложения. Рендеринг CPU медленнее, чем рендеринг GPU. Но в случае рендеринга GPU, не выведено на экран получающееся изображение, пока это не будет скопировано назад в память ЦП и преобразовано в другой тип изображения, такой как a UIImage объект.

Создание Базового Контекста Изображения на iOS, Когда Вы Потребность Производительность В реальном времени

Если Ваши поддержки приложений обработка изображений в реальном времени необходимо создать a CIContext объект от контекста EAGL вместо использования contextWithOptions: и указание GPU. Преимущество состоит в том, что представленное изображение остается на GPU и никогда не становится скопированным назад в память ЦП. Сначала необходимо создать контекст EAGL:

EAGLContext *myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

Тогда используйте метод contextWithEAGLContext: как показано в Перечислении 1-2 для создания a CIContext объект.

Необходимо выключить управление цветом путем предоставления null для рабочего цветового пространства. Управление цветом замедляет производительность. Вы захотите использовать управление цветом для ситуаций, требующих цветной точности. Но в приложении в реальном времени, цветная точность часто является не беспокойством. (См., что для Вашего Приложения Нужно управление цветом?.)

Перечисление 1-2  , Создающее CIContext на iOS для производительности в реальном времени

NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };
CIContext *myContext = [CIContext contextWithEAGLContext:myEAGLContext options:options];

Создание базового контекста изображения от CGContext на OS X

Можно создать Базовый контекст Изображения из Кварца 2D графический контекст с помощью кода, подобного показанному в Перечислении 1-3, которое является выборкой от drawRect: метод в приложении Какао. Вы получаете ток NSGraphicsContext, преобразуйте это в Кварц 2D графический контекст (CGContextRef), и затем обеспечьте Кварц 2D графический контекст как параметр contextWithCGContext:options: метод CIContext класс. Для получения информации о Кварце 2D графические контексты посмотрите Кварц 2D Руководство по программированию.

Перечисление 1-3  , Создающее Базовый контекст Изображения из Кварца 2D графический контекст

context = [CIContext contextWithCGContext:
                    [[NSGraphicsContext currentContext] graphicsPort]
                    options: nil]

Создание базового контекста изображения от контекста OpenGL на OS X

Код в Перечислении 1-4 показывает, как установить Базовый контекст Изображения от текущего контекста графики OpenGL. Важно, чтобы формат пикселя для контекста включал NSOpenGLPFANoRecovery постоянный как атрибут. Иначе Базовое Изображение может не быть в состоянии создать другой контекст, совместно использующий текстуры с этим. Необходимо также удостовериться, что Вы передаете формат пикселя, тип данных которого CGLPixelFormatObj, как показано в Перечислении 1-4. Для получения дополнительной информации о форматах пикселя и OpenGL, см. Руководство по программированию OpenGL для Mac.

Перечисление 1-4  , Создающее Базовый контекст Изображения из контекста графики OpenGL

const NSOpenGLPixelFormatAttribute attr[] = {
        NSOpenGLPFAAccelerated,
        NSOpenGLPFANoRecovery,
        NSOpenGLPFAColorSize, 32,
        0
    };
NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:(void *)&attr];
CIContext *myCIContext = [CIContext contextWithCGLContext: CGLGetCurrentContext()
                                pixelFormat: [pf CGLPixelFormatObj]
                                options: nil];

Создание базового контекста изображения от NSGraphicsContext на OS X

CIContext метод NSGraphicsContext класс возвращает a CIContext возразите, что можно использовать для рендеринга в NSGraphicsContext объект. CIContext объект создается по требованию и остается существующим для времени жизни его владения NSGraphicsContext объект. Вы создаете Базовый контекст Изображения с помощью строки кода, подобного следующему:

[[NSGraphicsContext currentContext] CIContext]

Для получения дополнительной информации об этом методе посмотрите Ссылку класса NSGraphicsContext.

Создание объекта CIImage

Базовое Изображение фильтрует изображения Изображения Ядра процесса (CIImage объекты). Таблица 1-3 перечисляет методы, создающие a CIImage объект. Метод, который Вы используете, зависит от источника изображения. Следует иметь в виду это a CIImage объект является действительно рецептом изображения; Базовое Изображение фактически не производит пикселей, пока к нему не обращаются с просьбой представить результаты месту назначения.

Табличные 1-3  Методы раньше создавали объект CIImage из существующих источников изображения

Источник изображения

Методы

Платформа

URL

imageWithContentsOfURL:

imageWithContentsOfURL:options:

iOS, OS X

Кварц 2D изображение (CGImageRef)

imageWithCGImage:

imageWithCGImage:options:

iOS, OS X

Растровые данные

imageWithBitmapData:bytesPerRow:size:format:colorSpace:

imageWithImageProvider:size:format:colorSpace:options:

iOS, OS X

Закодированные данные (изображение в памяти)

imageWithData:

imageWithData:options:

iOS, OS X

CIImageProvider

imageWithImageProvider:size:format:colorSpace:options:

iOS, OS X

Текстура OpenGL

imageWithTexture:size:flipped:colorSpace:

imageWithTexture:size:flipped:options:

iOS, OS X

Базовый Видео пиксельный буфер

imageWithCVPixelBuffer:

imageWithCVPixelBuffer:options:

iOS

Базовый буфер Видеоизображения

imageWithCVImageBuffer:

imageWithCVImageBuffer:options:

OS X

IOSurface

imageWithIOSurface:

imageWithIOSurface:options:

OS X

Уровень Quartz 2D (CGLayerRef)

imageWithCGLayer:

imageWithCGLayer:options:

OS X

NSCIImageRep

initWithBitmapImageRep:

OS X

Создание объекта CIFilter и установка значений

filterWithName: метод создает фильтр, тип которого указан name параметр. name параметром является строка, значение которой должно соответствовать точно имя фильтра встроенного фильтра (см. Встроенные Фильтры). Можно получить список имен фильтра путем следования инструкциям в Запросах Системы для Фильтров, или можно искать имя фильтра в Базовой Ссылке Фильтра Изображения.

Когда Вы вызываете, на iOS входные значения для фильтра установлены в значения по умолчанию filterWithName: метод.

На OS X входные значения для фильтра не определены при первом создании его который является, почему любой необходимо вызвать setDefaults метод для установки значений по умолчанию или предоставления оценивает за все входные параметры в то время, когда Вы создаете фильтр путем вызова метода filterWithName:keysAndValues:. Если Вы вызываете setDefaults, можно вызвать setValue:forKey: позже изменить входные значения параметров.

Если Вы не знаете входные параметры для фильтра, можно получить массив того, что они использовали метод inputKeys. (Или, можно искать входные параметры для большинства встроенных фильтров в Базовой Ссылке Фильтра Изображения.) Фильтры, за исключением фильтров генератора, требуют входного изображения. Некоторые требуют двух или больше изображений или текстур. Установите значение для каждого входного параметра, значение по умолчанию которого Вы хотите изменить путем вызова метода setValue:forKey:.

Давайте смотреть на пример установки фильтра для корректировки оттенка изображения. Именем фильтра является CIHueAdjust. Пока Вы вводите имя правильно, Вы будете в состоянии создать фильтр с этой строкой кода:

hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];

Значения по умолчанию установлены для Вас на iOS, но не на OS X. При создании фильтра на OS X желательно сразу установить входные значения. В этом случае установите значения по умолчанию:

[hueAdjust setDefaults];

Этот фильтр имеет два входных параметра: входное изображение и входной угол. Входной угол для фильтра корректировки оттенка относится к расположению оттенка в цветовых пространствах HLS и HSV. Это - угловое измерение, которое может варьироваться от 0,0 до 2 пи. Значение 0 указывает красный цвет; цветной зеленый соответствует 2/3 радианам пи, и цветной синий является 4/3 радианами пи.

Затем Вы захотите указать входное изображение и угол. Изображение может быть тем, создаваемым из любого из методов, перечисленных в Создании Объекта CIImage. Рисунок 1-1 показывает необработанное изображение.

Рисунок 1-1  необработанное изображение
The original image

Значение с плавающей точкой в этом коде указывает привлекательный оттенок:

[hueAdjust setValue: myCIImage forKey: kCIInputImageKey];
[hueAdjust setValue: @2.094f forKey: kCIInputAngleKey];

Следующий код показывает более компактный способ создать фильтр и установить значения для входных параметров:

hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"] keysAndValues:
                         kCIInputImageKey, myCIImage,
                         kCIInputAngleKey, @2.094f,
                         nil];

Можно предоставить как много входных параметров, которые хотели бы Вы, но необходимо закончить список nil.

Получение выходного изображения

Вы получаете выходное изображение путем получения значения для outputImage ключ:

CIImage *result = [hueAdjust valueForKey: kCIOutputImageKey];

Базовое Изображение не выполняет обработки изображений, пока Вы не вызываете метод, фактически представляющий изображение (см. Рендеринг Получающегося Выходного Изображения). Когда Вы запрашиваете выходное изображение, Базовое Изображение собирает вычисления, что это должно произвести выходное изображение и хранит те вычисления (т.е. изображение «рецепт») в a CIImage объект. Действительный образ только представляется (и следовательно, выполняемые вычисления), если существует явный вызов к одному из методов рисования изображения. Посмотрите Рендеринг Получающегося Выходного Изображения.

Задержка обрабатывающий до рендеринга времени делает Базовое Изображение быстрым и эффективным. При рендеринге времени видит Базовое Изображение, должен ли больше чем один фильтр быть применен к изображению. Если так, это автоматически связывает многократные «рецепты» в одну работу, что означает, что каждый пиксель обрабатывается только один раз, а не много раз. Рисунок 1-2 иллюстрирует поток операций многократных операций, который Базовое Изображение может сделать более эффективным. Заключительное изображение является упрощенной версией оригинала. Для случая большого изображения, применяя поправку цвета перед уменьшением масштаб изображения требует большей вычислительной мощности, чем уменьшение масштаб изображения и затем применение поправки цвета. Путем ожидания до времени отображения для применения фильтров Базовое Изображение может решить, что более эффективно выполнить эти операции в обратном порядке.

Рисунок 1-2  поток операций, который оптимизирует Базовое Изображение
A work flow that can benefit from lazy evaluation

Рендеринг получающегося выходного изображения

Рендеринг получающегося выходного изображения инициировал интенсивные действия процессора — или GPU или CPU, в зависимости от контекста, который Вы устанавливаете. Следующие методы доступны для рендеринга:

Метод

Использовать

drawImage:inRect:fromRect:

Представляет область изображения к прямоугольнику в месте назначения контекста.

На iOS этот метод представляет только к a CIContext объект, создающийся с contextWithEAGLContext:.

На OS X размерности целевого прямоугольника находятся в точках если CIContext объект создается с a CGContextRef. Размерности находятся в точках если CIContext объект создается с a CGLContext объект.

createCGImage:fromRect:

createCGImage:fromRect:format:colorSpace:

Создайте Кварц 2D изображение из области a CIImage объект. (iOS и OS X)

render:toBitmap:rowBytes:bounds:format:colorSpace:

Рендеринг a CIImage объект в битовый массив. (iOS и OS X)

createCGLayerWithSize:info:

Создает a CGLayer возразите представляет CIImage объект на уровень. ( Только OS X)

render:toCVPixelBuffer:

render:toCVPixelBuffer:bounds:colorSpace:

Рендеринг CIImage объект в Базовый Видео пиксельный буфер. (только iOS)

render:toIOSurface:bounds:colorSpace:

Рендеринг CIImage объект в объект IOSurface. ( Только OS X)

Представлять изображение обсудило в Создании Объекта CIFilter и Установке Значений, можно использовать эту строку кода OS X для рисования результата на экране:

[myContext drawImage:result inRect:destinationRect fromRect:contextRect];

Исходное изображение от этого примера (показанный на рисунке 1-1) теперь появляется в его обработанной форме, как показано на рисунке 1-3.

Рисунок 1-3  необработанное изображение после фильтра корректировки оттенка был применен
The image after applying the color controls filter

Поддержание потокобезопасности

CIContext и CIImage объекты являются неизменными, что означает, что каждый может быть совместно использован безопасно среди потоков. Многократные потоки могут использовать тот же GPU или CPU CIContext возразите для рендеринга CIImage объекты. Однако дело обстоит не так для CIFilter объекты, которые являются непостоянными. A CIFilter объект не может быть совместно использован безопасно среди потоков. Если Ваше приложение многопоточно, каждый поток должен создать свое собственное CIFilter объекты. Иначе, Ваше приложение могло неожиданно вести себя.

Объединение в цепочку фильтров

Можно создать удивительные эффекты путем объединения в цепочку фильтров — т.е. использования выходного изображения от одного фильтра, как введено к другому фильтру. Давайте посмотрим, как применить еще два фильтра к изображению, показанному на рисунке 1-3 — мрак (CIGloom) и искажение удара (CIBumpDistortion).

Фильтр мрака делает просто это; это делает изображение мрачным dulling его выделения. Заметьте, что код в Перечислении 1-5 очень подобен показанному в Создании Объекта CIFilter и Установке Значений. Это создает фильтр и устанавливает значения по умолчанию для фильтра мрака. На сей раз входное изображение является выходным изображением от фильтра корректировки оттенка. Это - это простое к цепочечным фильтрам вместе!

  Создание перечисления 1-5, установка и применение фильтра мрака

CIFilter *gloom = [CIFilter filterWithName:@"CIGloom"];
[gloom setDefaults];                                        // 1
[gloom setValue: result forKey: kCIInputImageKey];
[gloom setValue: @25.0f forKey: kCIInputRadiusKey];         // 2
[gloom setValue: @0.75f forKey: kCIInputIntensityKey];      // 3
result = [gloom valueForKey: kCIOutputImageKey];            // 4

Вот то, что делает код:

  1. Значения по умолчанию наборов. Необходимо установить значения по умолчанию на OS X. На iOS Вы не должны устанавливать значения по умолчанию, потому что они установлены автоматически.

  2. Устанавливает входной радиус в 25. Входной радиус указывает степень эффекта и может варьироваться от 0 до 100 со значением по умолчанию 10. Вспомните, что можно найти минимум, максимум и значения по умолчанию для фильтра программно путем получения словаря атрибута для фильтра.

  3. Устанавливает входную интенсивность в 0.75. Входная интенсивность является скалярным значением, указывающим линейное смешение между выводом фильтра и исходным изображением. Минимум 0.0, максимум 1.0, и значение по умолчанию 1.0.

  4. Запрашивает выходное изображение, но не рисует изображение.

Код запрашивает, чтобы вывод отобразил, но не рисует изображение. Рисунок 1-4 показывает то, на что было бы похоже изображение, нарисовали ли Вы его в этой точке после обработки его и с корректировкой оттенка и с фильтрами мрака.

Рисунок 1-4  изображение после применения поправки оттенка и фильтров мрака
The image after applying the hue adjustment and gloom filters

Фильтр искажения удара (CIBumpDistortion) создает выпуклость в изображении, происходящем в указанной точке. Перечисление 1-6 показывает, как создать, установить, и применить этот фильтр к выходному изображению от предыдущего фильтра, фильтра мрака. Искажение удара берет три параметра: расположение, указывающее центр эффекта, радиус эффекта и входной масштаб.

  Создание перечисления 1-6, установка и применение фильтра искажения удара

CIFilter *bumpDistortion = [CIFilter filterWithName:@"CIBumpDistortion"];    // 1
[bumpDistortion setDefaults];                                                // 2
[bumpDistortion setValue: result forKey: kCIInputImageKey];
[bumpDistortion setValue: [CIVector vectorWithX:200 Y:150]
                    forKey: kCIInputCenterKey];                              // 3
[bumpDistortion setValue: @100.0f forKey: kCIInputRadiusKey];                // 4
[bumpDistortion setValue: @3.0f forKey: kCIInputScaleKey];                   // 5
result = [bumpDistortion valueForKey: kCIOutputImageKey];

Вот то, что делает код:

  1. Создает фильтр путем обеспечения его имени.

  2. На OS X, устанавливает значения по умолчанию (не необходимый на iOS).

  3. Устанавливает центр эффекта к центру изображения.

  4. Устанавливает радиус удара к 100 пикселям.

  5. Устанавливает входной масштаб в 3. Входной масштаб указывает направление и сумму эффекта. Значение по умолчанию –0.5. Диапазон –10.0 до 10,0. Значение 0 не указывает эффекта. Отрицательная величина создает исходящий удар; положительное значение создает входящий удар.

Рисунок 1-5 показывает, что финал представил изображение.

Рисунок 1-5  изображение после применения поправки оттенка вместе с мраком и фильтрами искажения удара
The image after applying the hue adjustment, gloom, and bump distortion filters

Используя эффекты перехода

Переходы обычно используются между изображениями в показе слайдов или переключаться от одной сцены до другого в видео. Эти эффекты представляются в течение долгого времени и требуют, чтобы Вы установили таймер. Цель этого раздела состоит в том, чтобы показать, как установить таймер. Вы изучите, как сделать это путем установки и применения фильтра перехода копировального устройства (CICopyMachine) к двум неподвижным изображениям. Переход копировального устройства создает выделенную полосу, подобную тому, что Вы видите в копировальном устройстве или отображаете сканер. Выделенная полоса развертывается слева направо через начальное изображение для раскрытия целевого изображения. Рисунок 1-6 показывает то, на что этот фильтр похож прежде, отчасти через, и после перехода от изображения лыжных ботинок к изображению лыжника. (Для узнавания больше об определенном входном параметре фильтра CICopyMachine посмотрите Базовую Ссылку Фильтра Изображения.)

Рисунок 1-6  переход копировального устройства от лыжных ботинок до лыжника
A copy machine transition from ski boots to a skier

Фильтры перехода требуют следующих задач:

  1. Создайте Базовые изображения Изображения (CIImage объекты) для использования для перехода.

  2. Установленный и расписание таймер.

  3. Создайте a CIContext объект.

  4. Создайте a CIFilter объект для фильтра для применения к изображению.

  5. На OS X, набор значения по умолчанию для фильтра.

  6. Установите параметры фильтра.

  7. Установите источник и целевые изображения для обработки.

  8. Вычислите время.

  9. Примените фильтр.

  10. Нарисуйте результат.

  11. Повторите шаги 8-10, пока переход не будет завершен.

Вы заметите, что многие из этих задач совпадают с требуемыми обработать изображение с помощью фильтра кроме фильтра перехода. Различием, однако, является таймер, используемый для повторного рисования эффекта в различных интервалах в течение перехода.

awakeFromNib метод, показанный в Перечислении 1-7, получает два изображения (boots.jpg и skier.jpg) и устанавливает их как входные и выходные изображения. Используя NSTimer класс, таймер установлен повторить каждую 1/30 секунду. Отметьте переменные thumbnailWidth и thumbnailHeight. Они используются для ограничения представленных изображений к представлению, установленному в Интерфейсном Разработчике.

Перечисление 1-7  , Получающее изображения и настраивающее таймер

- (void)awakeFromNib
{
    NSTimer    *timer;
    NSURL      *url;
 
    thumbnailWidth  = 340.0;
    thumbnailHeight = 240.0;
 
    url   = [NSURL fileURLWithPath: [[NSBundle mainBundle]
                    pathForResource: @"boots" ofType: @"jpg"]];
    [self setSourceImage: [CIImage imageWithContentsOfURL: url]];
 
    url   = [NSURL fileURLWithPath: [[NSBundle mainBundle]
                    pathForResource: @"skier" ofType: @"jpg"]];
    [self setTargetImage: [CIImage imageWithContentsOfURL: url]];
 
    timer = [NSTimer scheduledTimerWithTimeInterval: 1.0/30.0
                                             target: self
                                           selector: @selector(timerFired:)
                                           userInfo: nil
                                            repeats: YES];
 
    base = [NSDate timeIntervalSinceReferenceDate];
    [[NSRunLoop currentRunLoop] addTimer: timer
                                 forMode: NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] addTimer: timer
                                 forMode: NSEventTrackingRunLoopMode];
}

Вы устанавливаете фильтр перехода, как Вы установили любой другой фильтр. Перечисление 1-8 использует filterWithName: метод для создания фильтра. Это тогда вызывает setDefaults инициализировать все входные параметры. Кодовые наборы степень для соответствия ширине миниатюры и высоте, объявленной в awakeFromNib: метод, показанный в Перечислении 1-7.

Подпрограмма использует переменные миниатюры для указания центра эффекта. Для этого примера центр эффекта является центром изображения, но это не должно быть.

Перечисление 1-8  , Настраивающее фильтр перехода

- (void)setupTransition
{
    CGFloat w = thumbnailWidth;
    CGFloat h = thumbnailHeight;
 
    CIVector *extent = [CIVector vectorWithX: 0  Y: 0  Z: w  W: h];
 
    transition  = [CIFilter filterWithName: @"CICopyMachineTransition"];
    // Set defaults on OS X; not necessary on iOS.
    [transition setDefaults];
    [transition setValue: extent forKey: kCIInputExtentKey];
}

drawRect: метод для эффекта перехода копировального устройства показан в Перечислении 1-9. Этот метод устанавливает прямоугольник, это - тот же размер как представление и затем устанавливает значение с плавающей точкой в течение времени рендеринга. Если CIContext объект не был уже создан, метод создает тот. Если переход еще не устанавливается, вызовы метода setupTransition метод (см. Перечисление 1-8). Наконец, вызовы метода drawImage:inRect:fromRect: метод, передавая изображение, которое должно быть показано в течение времени рендеринга. imageForTransition: метод, показанный в Перечислении 1-10, применяет фильтр и возвращает надлежащее изображение в течение времени рендеринга.

Перечисление 1-9  drawRect: метод для эффекта перехода копировального устройства

- (void)drawRect: (NSRect)rectangle
{
    CGRect  cg = CGRectMake(NSMinX(rectangle), NSMinY(rectangle),
                            NSWidth(rectangle), NSHeight(rectangle));
 
    CGFloat t = 0.4 * ([NSDate timeIntervalSinceReferenceDate] - base);
    if (context == nil) {
        context = [CIContext contextWithCGContext:
                        [[NSGraphicsContext currentContext] graphicsPort]
                                          options: nil];
    }
    if (transition == nil) {
        [self setupTransition];
    }
    [context drawImage: [self imageForTransition: t + 0.1]
                inRect: cg
              fromRect: cg];
}

imageForTransition: метод выясняет, на основе времени рендеринга, которое является исходным изображением и которое является целевым изображением. Это устанавливается для разрешения перехода к неоднократно циклу назад и вперед. Если Ваше приложение применяет переход, не циклично выполняющийся, ему не было бы нужно если еще конструкция, показанная в Перечислении 1-10.

Подпрограмма устанавливает inputTime оцените на основе времени рендеринга, переданного imageForTransition: метод. Это применяет переход, передавая выходное изображение с перехода на фильтр обрезки (CICrop). Обрезка гарантирует, что выходное изображение помещается в прямоугольник представления. Подпрограмма возвращает обрезанное изображение перехода drawRect: метод, тогда рисующий изображение.

Перечисление 1-10  , Применяющее фильтр перехода

- (CIImage *)imageForTransition: (float)t
{
    // Remove the if-else construct if you don't want the transition to loop
    if (fmodf(t, 2.0) < 1.0f) {
        [transition setValue: sourceImage  forKey: kCIInputImageKey];
        [transition setValue: targetImage  forKey: kCIInputTargetImageKey];
    } else {
        [transition setValue: targetImage  forKey: kCIInputImageKey];
        [transition setValue: sourceImage  forKey: kCIInputTargetImageKey];
    }
 
    [transition setValue: @( 0.5 * (1 - cos(fmodf(t, 1.0f) * M_PI)) )
                  forKey: kCIInputTimeKey];
 
    CIFilter  *crop = [CIFilter filterWithName: @"CICrop"
                                 keysAndValues:
                   kCIInputImageKey, [transition valueForKey: kCIOutputImageKey],
                   @"inputRectangle", [CIVector vectorWithX: 0  Y: 0
                                       Z: thumbnailWidth  W: thumbnailHeight],
                   nil];
    return [crop valueForKey: kCIOutputImageKey];
}

Каждый раз таймер, что Вы устанавливаете огни, дисплей должен быть обновлен. Перечисление 1-11 показывает a timerFired: подпрограмма, делающая просто это.

Перечисление 1-11  Используя таймер для обновления дисплея

- (void)timerFired: (id)sender
{
    [self setNeedsDisplay: YES];
}

Наконец, Перечисление 1-12 показывает обслуживание, которое должно быть выполнено, если Ваше приложение переключает входные и выходные изображения, как пример в Перечислении 1-10 делает.

Перечисление 1-12  , Устанавливающее входные и выходные изображения

- (void)setSourceImage: (CIImage *)source
{
    sourceImage = source;
}
 
- (void)setTargetImage: (CIImage *)target
{
    targetImage = target;
}

Применение фильтра к видео

Базовое Изображение и Базовое Видео могут сотрудничать для достижения множества эффектов. Например, можно использовать фильтр коррекции цвета на видео выстреле под водой для исправления для факта, что вода поглощает красный свет быстрее, чем зеленый и синий свет. Существует еще много способов, которыми можно использовать эти технологии вместе.

Выполните эти шаги для применения Базового фильтра Изображения к видео, выведенному на экран с помощью Базового Видео на OS X:

  1. Когда Вы разделяете на подклассы NSView для создания представления для видео объявите a CIFilter объект в интерфейсе, подобном тому, что показано в этом коде:

    @interface MyVideoView : NSView
    {
        NSRecursiveLock     *lock;
        QTMovie             *qtMovie;
        QTVisualContextRef  qtVisualContext;
        CVDisplayLinkRef    displayLink;
        CVImageBufferRef    currentFrame;
        CIFilter            *effectFilter;
        id                  delegate;
    }
  2. При инициализации представления с кадром Вы создаете a CIFilter объект для фильтра и набора значения по умолчанию с помощью кода, подобного следующему:

    effectFilter = [CIFilter filterWithName:@"CILineScreen"];
    [effectFilter setDefaults];

    Этот пример использует Базовый фильтр Изображения CILineScreen, но Вы использовали бы то, что является подходящим для Вашего приложения.

  3. Установите входные параметры фильтра, за исключением входного изображения.

  4. Каждый раз, когда Вы представляете кадр, необходимо установить входное изображение и нарисовать выходное изображение. Ваш renderCurrentFrame подпрограмма выглядела бы подобной следующему. Для предотвращения интерполяции этот пример использует интегральные координаты, когда это рисует вывод.

    - (void)renderCurrentFrame
    {
        NSRect frame = [self frame];
     
        if (currentFrame) {
            CIImage *inputImage = [CIImage imageWithCVImageBuffer:currentFrame];
            CGRect imageRect = [inputImage extent];
            CGFloat x = (frame.size.width - imageRect.size.width) * 0.5;
            CGFloat y = (frame.size.height - imageRect.size.height) * 0.5;
            [effectFilter setValue:inputImage forKey:kCIInputImageKey];
            [[[NSGraphicsContext currentContext] CIContext]
                drawImage:[effectFilter valueForKey:kCIOutputImageKey]
                  atPoint:CGPointMake(floor(x), floor(y))
                 fromRect:imageRect];
        }
    }