При створенні фото-додатку з фільтрами розробники стикаються з проблемою продуктивності: карусель прев'ю має працювати при 60 FPS, але послідовна обробка на CPU займає 200–400 мс на кадр. GPU-шейдери вирішують це завдання: паралельна обробка пікселів займає 5–15 мс. При цьому вибір підходу — CIFilter, Metal або LUT — безпосередньо впливає на швидкість розробки та гнучкість готового рішення.
В одному проекті для e-commerce нам потрібно було 15 фільтрів з плавним прев'ю. Ми обрали комбінацію CIFilter для стандартних ефектів та кастомні Metal-шейдери для дуотону. Карусель працювала стабільно в 60 FPS на iPhone 11 і вище; бюджетні моделі (iPhone SE 2020) видавали 45–50 FPS — ми оптимізували, зменшивши розмір прев'ю до 200×200 та додавши кешування. Це заощадило близько 30% часу обробки на слабких пристроях.
iOS: CIFilter vs Metal
| Технологія | Швидкість | Гнучкість | Складність |
|---|---|---|---|
| CIFilter | 2–5 мс (на iPhone 14) | Обмежений набором Apple | Низька, вбудований в SDK |
| Metal | 1–3 мс | Повний контроль пікселів | Висока, пишемо MSL-шейдери |
CIFilter — простий шлях: CIColorMonochrome, CIPhotoEffectChrome, CIVignette. Будуємо ланцюжок через filter.outputImage, обов'язково використовуємо CIContext(options: [.useSoftwareRenderer: false]) для GPU. За даними Apple (WWDC 2020 Session 10040), це забезпечує до 90% завантаження GPU.
Metal потрібен для дуотону з кастомними кольорами, zonal adjustments, LUT-фільтрів. Приклад fragment shader:
fragment float4 duotoneFilter(VertexOut in [[stage_in]], texture2d<float> texture [[texture(0)]]) { float4 color = texture.sample(sampler, in.texCoord); float luma = dot(color.rgb, float3(0.299, 0.587, 0.114)); return mix(shadowColor, highlightColor, luma); } Android: GPUImage та Vulkan
| Бібліотека | API | Продуктивність |
|---|---|---|
| GPUImage (OpenGL ES) | GPUImageFilter + GPUImageView | 10–15 мс на флагманських пристроях |
| RenderScript Toolkit | Intrinsics Replacement | 5–10 мс |
| Vulkan (нові проекти) | Пряме керування GPU | 3–8 мс |
GPUImageFilterGroup дозволяє будувати ланцюжки. Для попереднього перегляду GPUImageView рендерить на SurfaceTexture без проміжного Bitmap — критично для продуктивності. За тестами, Vulkan обробляє складні ефекти в 1.5–2 рази швидше за OpenGL ES.
Flutter: міст до нативу
CPU-бібліотека image не підходить для прев'ю. Використовуємо ColorFiltered з матрицею для базових корекцій. Складні фільтри — через Flutter Texture та нативний код (Metal/OpenGL) на платформовій стороні. Ми підключаємо такі рішення «під ключ».
Як працює попередній перегляд з кешуванням?
Генеруємо прев'ю заздалегідь: при завантаженні екрану створюємо зменшену копію (300×300 px) через UIGraphicsImageRenderer, прогоняємо через кожен фільтр, кешуємо в NSCache. Користувач гортає карусель — картинки вже готові. Фінальний рендер у повному роздільності запускається тільки після вибору фільтру.
Покрокова реалізація попереднього перегляду
- Отримати оригінальне зображення.
- Створити зменшену копію (300×300).
- Для кожного фільтру застосувати до копії та зберегти результат у кеш.
- Відобразити кешовані прев'ю в каруселі.
- При виборі фільтру — запустити повний рендер на оригіналі.
Цей підхід забезпечує 60 FPS навіть на пристроях з 2 ГБ RAM.
Чому LUT-фільтри виграють у процедурних?
Look Up Table — це 3D-таблиця 64×64×64, де кожен RGB-вхід дає RGB-вихід через інтерполяцію. Дизайнер створює LUT у Lightroom, розробник підключає як текстуру. Переваги:
- Одна текстура замінює ланцюжок із 5–10 CIFilter-операцій.
- Якість кольорокорекції вища — не втрачаються деталі.
- Легко оновлювати: поміняли LUT — помінявся фільтр.
На iOS використовуємо CIColorCube або CIColorCubeWithColorSpace. На Android — GPUImageLUTFilter. Ми впроваджували LUT у проектах для e-commerce — це дало +15% до конверсії за рахунок реалістичних кольорів.
Збереження налаштувань фільтру
Користувач обрав «Хром» з інтенсивністю 0.7 — при поверненні до посту це значення має відновитися. Зберігаємо не готове зображення, а параметри фільтру (filterName, intensity) — це дозволяє редагувати фото після збереження чернетки без втрати якості.
Фінальний рендер у повному роздільності запускаємо тільки перед публікацією або експортом. Це зберігає оригінал незмінним і дає можливість скасувати фільтр у будь-який момент.
Що входить у розробку
- Аналіз вимог та прототипування інтерфейсу фільтрів
- Створення шейдерів Metal/OpenGL або налаштування CIFilter
- Реалізація попереднього перегляду з кешуванням
- Інтеграція LUT-фільтрів
- Оптимізація під цільові пристрої (iPhone, Android флагмани та бюджетні)
- Тестування на реальних девайсах (5+ моделей)
- Надання вихідного коду та документації
Терміни та вартість
Терміни залежать від складності: базовий набір фільтрів — від 3 до 7 днів, комплексне рішення з LUT та ML — 2–3 тижні. Вартість розраховується індивідуально після аналізу вимог.
У нас 7+ років досвіду в мобільній розробці та понад 50 реалізованих проектів з фільтрами. Ми гарантуємо 60 FPS у каруселі та відповідність App Store Review Guidelines (Section 4.2, 5.1). Зв'яжіться з нами для консультації щодо вашого проекту — ми допоможемо обрати оптимальне рішення та підготуємо шейдери під ваші завдання. Замовте впровадження фільтрів вже сьогодні, і ваш додаток отримає професійну обробку зображень.







