Винаги съм намирал обработката на изображения за интересна и забавна. Въпреки това, въпреки че имах приличен опит с него, никога не съм работил много с инструментите за iOS. Реших да си поиграя малко с тях и за моя радост повечето библиотеки за обработка на изображения в iOS са невероятно лесни за използване. Тази тема има голяма повърхност, така че няма да мога да я опиша справедливо в една публикация. Тази публикация обаче трябва да е достатъчна, за да ви позволи да започнете с обработката на изображения в iOS.

Прост филтър

Нека започнем със стълба на обработката на изображения – филтри за изображения.

Филтрите за изображения са отговорни за заснемането на изображение, манипулирането му и създаването на различно изходно изображение. Елегантните филтри може да могат да приемат множество изображения като вход, но в по-голямата си част това е едно изображение на входа, едно изображение навън.

Функционалността за обработка на изображения в iOS се намира в рамките на Core Image. Оказва се, че Core Image идва с над 150 различни филтъра за изображения веднага. Можете да поискате списък с всички тях чрез:

See the code in the full post.

Повечето функции на филтъра са съсредоточени около класа CIFilter Core Image. CIFilter има статични методи като filterNames (по-горе). Въпреки това, за да приложите филтър за изображения, създавате екземпляр CIFilter и подавате тип филтър. Типовете филтри се дефинират от низови константи, което е много различно от Swift, тъй като позволява грешки по време на изпълнение.

Нека да разгледаме пример, който създава филтър за размазване и го прилага към изображение:

See the code in the full post.

Ето как изглежда прилагането на горния филтър:

По някаква странна причина има няколко различни подхода за инстанциране на филтри и прилагането им към изображения. Горният пример е само един подход. Това е малко грозно и има принудително разопаковани опции, но е лесно за разбиране и преминаване през него. Както входното изображение, така и всички параметри на филтъра могат да бъдат зададени чрез функцията setValue, където предавате стойност и константа тип параметър (дефинирана тук). Някои филтри имат няколко параметъра; някои нямат. Обикновено можете да ги пропуснете и се използва стойност на параметър по подразбиране.

По-долу са някои други интересни филтри, които се предоставят извън кутията с Core Image.

CICMYK Филтър за полутонове

Филтърът CICMYKHalftone добавя приятен ефект „полутонове“, симулирайки как може да изглежда печатната медия.

See the code in the full post.

CICrystallize филтър

Филтърът CICrystallize квантува изображението в еднакви цветни многоъгълници.

See the code in the full post.

В допълнение към тях има много други филтри, предоставени от Core Image веднага. За по-пълна справка вижте документи.

Комбиниране на филтри

Един от начините за създаване на ефекти, които не са уловени от някой от предоставените филтри, е комбинирането на филтри. Може да си представите прилагането на набор от филтри последователно, подавайки резултата от един като вход към следващия. Core Image има специална поддръжка за това и ви позволява да комбинирате филтри по такъв начин, че необходимото количество обработка да бъде сведено до минимум (напр. не е задължително да се изчислява пълно изходно изображение за всеки приложен филтър).

Да предположим, че искате да приложите филтър CICrystallize и след това филтър CICMYKHalftone. Можете да постигнете това чрез:

See the code in the full post.

Горният филтър създава изображение, което изглежда така:

Забележете как този път инстанцирахме и приложихме филтрите по различен начин, отколкото в първия пример. Вместо да създаваме CIFilter екземпляр, извикахме applyingFilter директно върху входния CIImage екземпляр. Това е друг начин, по който може да искате да напишете вашия филтриращ код. Мисля, че този подход е по-добър, но не е очевидно, че се създава екземпляр CIFilter, така че избрах да използвам другия подход в по-ранните примери.

Персонализирани филтри

Ако предоставените филтри за основно изображение (или някаква комбинация от тях) не произвеждат ефекта, който търсите, можете да напишете свой собствен персонализиран филтър. Тази функционалност беше нова в iOS 8 и е доста гладка. Тази тема може бързо да стане много сложна, така че ще засегна само основите. Може да напиша по-подробна публикация за писане на персонализирани филтри в бъдеще.

За да напишете персонализиран CIFilter, трябва да напишете персонализиран CIKernel. Ядрото казва на филтъра как да трансформира всеки пиксел от входното изображение. Има три различни типа ядра, които можете да пишете: цветни ядра, деформирани ядра и общи ядра. Ще разгледам накратко цветните ядра в тази публикация, тъй като те са най-лесни за разбиране.

За да напишете персонализирано цветно ядро, създавате екземпляр на CIColorKernel и му предоставяте персонализирания код на ядрото. Това е малко странно, защото кодът на ядрото трябва да бъде написан на GLSL, OpenGL език за засенчване. Предоставяте вашия GLSL код като низ към конструктора CIColorKernel. Това отново е някак ужасно, защото ще избухне по време на изпълнение, ако вашият GLSL код има някакви грешки.

Да разгледаме един пример. Да предположим, че искаме да напишем персонализирано ядро, което премахва червения цветен канал и разделя синия канал на две. Първо, ще трябва да подкласираме CIFilter и да заменим свойството outputImage, за да върнем нашето персонализирано обработено изображение. Това би изглеждало така:

See the code in the full post.

Забележете извикването за създаване на нашето персонализирано ядро: createCustomKernel. Тази функция трябва да върне нашето персонализирано CIColorKernel ядро ​​с нашия персонализиран GLSL код на ядрото. Ето как може да изглежда нашата реализация:

See the code in the full post.

Обърнете внимание на функцията GLSL, дефинирана като необработено String. Тази функция приема един пиксел, представен от променливата __sample, и трябва да преобразува входния пиксел в неговата изходна стойност. В нашия пример искахме да премахнем червения цветен канал и да разделим синия канал на две. Това е, което прави горният GLSL код. Тази функция ще се изпълни за всеки пиксел от входното изображение.

Извикването на нашия персонализиран филтър изглежда така:

See the code in the full post.

Полученото изходно изображение изглежда така:

Допълнителна информация

Тази публикация просто надраска повърхността на това, което е възможно с помощта на Core Image. Ако се интересувате да научите повече за това, препоръчвам да вземете „тази електронна книга“. Материята в нея е отлична.

Първоначално публикувано в spin.atomicobject.com на 20 октомври 2016 г.