GPU acceleration of photo filters: Metal, Core Image, and LUT for iOS/Android

Photo filters in the app slow down and heat up the smartphone — users leave. We move image processing to the GPU turnkey: we select the approach, implement, and maintain. Response speed increases many times over without quality loss.

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a mobile application for FEEDME
    Development of a mobile application for FEEDME
    971
  • Development of a mobile application for XOOMER
    Development of a mobile application for XOOMER
    869
  • Development of a mobile application for RHL
    Development of a mobile application for RHL
    1289
  • Development of a mobile application for ZIPPY
    Development of a mobile application for ZIPPY
    1143
  • Development of a mobile application for Affhome
    Development of a mobile application for Affhome
    1076
  • Development of a mobile application for the FLAVORS company
    Development of a mobile application for the FLAVORS company
    677

Why photo filters slow down smartphones

When a filter is applied to a frame at the moment of capture, the user expects an instant result — and that's exactly where the bottleneck shows up.

Classic image processing on the CPU pushes pixels through a single thread of computation: while the core sequentially calculates convolution after convolution, the preview lags behind reality by fractions of a second.

On a single shot this goes unnoticed, but in burst shooting the queue of frames grows, the buffer overflows, and the preview delay becomes visible to the eye — the finger has already moved, but the screen still shows the previous frame.

Then physics kicks in. A processor loaded with frame-by-frame processing goes into constant load on all cores — the smartphone heats up, thermal throttling triggers, and the frame rate drops the longer the shooting goes on.

The temperature peak falls exactly at the moment when the user is shooting a burst or scrolling a feed with filters — that is, at the most demanding scenario.

The app starts to "chew" on the interface, and the battery drains faster than during normal shooting without effects.

GPU filters take this load off the processor and move the computations to where they belong — the graphics core, designed for parallel work with thousands of pixels at once.

One pass over the frame instead of dozens of sequential operations, the preview updates at the pace of the screen, not at the pace of the queue. The thermal profile evens out: the graphics core delivers the result faster and goes idle, instead of keeping the processor red-hot.

Let's break down how this is solved in practice — from choosing the processing path to color lookup tables that deliver the same result across different devices.

What moving filters to the GPU delivers

A filter on the GPU is computed in parallel per pixel: per-frame processing of a frame fits into a single pass through the pipeline, whereas on the CPU the same operations run sequentially and compete for cores with the UI, network, and application logic.

Hence the first measurable effect — response speed: real-time filter preview updates without lag between the user's gesture and the image, and heavy chains of multiple effects stop "chasing" the finger.

The second effect is frame stability. When computations move to the GPU, frame processing time becomes predictable, and the frame rate stays steady even when complex layers, text, and masks are overlaid.

Dips and jitter that the user reads as "the app is lagging" disappear — and along with them goes some of the negative reviews that are usually blamed on a "raw" app.

The third effect is power consumption and device longevity. The graphics pipeline does the same work in fewer clock cycles and with less heat on the chassis, so the phone doesn't go into throttling after a few minutes of shooting, and the battery drains more evenly.

For scenarios with long processing — burst shooting, batch export, video recording with a filter — this is the difference between "works for half an hour and heats up" and "works for as long as needed."

The practical takeaway: moving filters to the GPU is not cosmetic, but a change in the class of the app's behavior under load.

We profile every effect chain, take measurements before and after, and keep only those optimizations that are actually visible in the metrics of response, frames, and battery consumption.

Approaches to Implementing Filters: Comparing the Options

The choice of processing method determines how the app behaves on different devices and how much maintenance will cost.

Below are three real approaches that teams choose between at the start, along with their limitations in terms of cross-platform consistency and control over the result.

Option When it fits Limitations
Built-in platform tools Fast launch, standard effects, minimal code Different sets of effects and color rendering on iOS and Android, weak control over non-standard scenarios
Color lookup tables A unified visual style, work with color and tone Require careful preparation and interpolation; if configured incorrectly, detail is lost in shadows and highlights
Custom compute modules Non-standard effects, full control over the pipeline More expensive to develop and maintain, require separate optimization for each platform

Built-in platform tools offer the shortest path: processing relies on system modules, and the team doesn't write shaders by hand.

The trade-off is a discrepancy in the result between platforms: the same effect looks different on iOS and Android, and achieving a unified style requires workarounds.

Color lookup tables solve exactly this problem: the style is described once and reproduced identically on both platforms. The limitation lies in preparing the tables themselves and in the fact that complex effects tied to geometry or recognition can't be expressed with them.

Custom compute modules provide full control: non-standard effects, precise pipeline tuning, predictable performance. The price is higher labor intensity and the need to maintain code separately for each platform.

In practice, the pipeline is often assembled as a combination: a base layer on built-in tools, style via tables, and unique effects via a custom module. Such a hybrid covers both launch speed, a unified look, and non-standard scenarios.

Stages of accelerated image processing implementation

We start with an audit of the current pipeline: we measure how long frame processing takes on reference devices, where the bottleneck is — decoding, the filter itself, or display output — and which operations are performed on the CPU even though they could be moved to the GPU.

The audit results show which filters cause frame rate drops and on which device models the app starts to lag.

  1. Pipeline audit. We capture processing profiles on real devices from different price segments, record per-frame time and resource consumption, and identify candidate operations for offloading.
  2. Processing scheme design. We decide which steps go to the GPU, which remain on the CPU, and how to build the filter chain without unnecessary buffer copies between memory and video memory.
  3. Shader and color correction table setup. We write programs for the GPU and prepare color transformation tables — they allow changing the filter style without rebuilding the app.
  4. Pipeline assembly for both platforms. We implement the same set of filters for iOS and Android, accounting for differences in graphics interfaces, so the visual result matches.
  5. Device testing. We run the filters on a fleet of real models: we check frame rate, heating, battery consumption, and color correctness on different screens.
  6. Optimization based on measurements. We remove unnecessary passes, cache intermediate results, and reduce load on weak devices through simplified filter versions.
  7. System handover. We deliver the configured pipeline, documentation for adding new filters, and performance measurement instructions so the client's team can develop the processing independently.

Each stage ends with a measurable result: after the audit it's clear what exactly is causing lag; after shader setup — how many frames per second the filter delivers on a weak device; after testing — which models require a simplified mode.

This order eliminates rework: first measurement, then decision, then confirmation on a live fleet of devices.

What the client receives after implementation

GPU filter implementation ends not with a demonstration of the effect, but with a set of artifacts that the client's team can use to develop and maintain image processing without us. Below is what exactly remains in the project after handover.

  • Graphics pipeline configurations — profiles for target device models: what is computed on the graphics core, what is computed on the CPU, which texture and intermediate buffer formats are used. The profiles are stored in the repository and can be switched without rebuilding the filter logic.
  • Processing pipeline diagrams — the order in which a frame passes through: decoding, geometry, color correction, effect overlay, output. The diagram records at which step quality is lost and where the bottleneck in processing time is.
  • Color correction LUT sets — the tables themselves for each style, the rules for blending and interpolating them, as well as reference before/after frames to verify that the style has not "drifted" after edits.
  • Real-time preview configurations — the parameters under which the image in the viewfinder matches the final result, so that the user does not get a surprise after saving.
  • Build and dependency documentation — which versions of libraries and tools are used, how to build for each platform, and what changes when the graphics stack is updated.
  • Release and rollback procedures — how to test a new filter before release, by which processing time and quality metrics to consider it ready, and how to revert to the previous LUT set if the style or speed is unsatisfactory.
  • Instructions for designers and the content team — how to add new color correction tables and styles without developer involvement.

Each item is handed over in working form: configurations and tables — in the repository with change history, diagrams and procedures — in the project documentation.

The client's team can change styles and tune performance independently, while we remain on support wherever pipeline improvements are needed.

Case study: speeding up filters in a photo editing app

A photo editing app with a preset library: filter preview lagged behind the slider movement by 300–400 ms, on the mid-range device segment the frame rate dropped to 18–22, and after 10 minutes of shooting the body noticeably heated up and the system dimmed the screen brightness.

Users perceived this as "the filter is laggy" and left to adjust the shot in a third-party editor — conversion to saving the result dropped.

What it was before the changes

Processing ran on the CPU: the full frame at high resolution was run through a chain of per-pixel operations on every slider movement, and the result was handed to the UI without an intermediate buffer.

This led to three related problems: response latency, frame drops while dragging, and constant load on the compute unit, which made the device heat up. Presets were stored as sets of parameters and recalculated from scratch on every change.

What was changed

Our engineers moved the computation to the graphics pipeline and converted the presets into color correction tables — compact files that are applied to a frame in a single operation instead of a chain.

The preview began to be computed on a downscaled copy of the frame, and full resolution is only engaged at the moment of saving. Intermediate results are cached, so re-selecting the same preset does not trigger the computation again.

Metrics after

Metric Before After
Preview latency 300–400 ms 30–50 ms
Frame rate while dragging 18–22 a stable 55–60
Heating over 10 minutes of shooting noticeable, with brightness dimming within normal limits
Frame save time 1.8–2.5 s 0.4–0.7 s

We separately tested behavior on previous-generation devices: there the frame rate holds at 40–45, which is enough for a smooth preview. The preset logic was moved into a separate layer — a new color correction set can be added without rebuilding the processing core.

The project was led by our team — from profiling the bottleneck to rolling out to app stores.

How does a color correction lookup table differ from a compute shader?

A color correction lookup table is a precomputed mapping: each input shade is matched to an output one. It is applied as a single texture fetch operation, so a frame takes a predictable amount of time regardless of the complexity of the correction itself.

The artist prepares the table in a familiar editor, exports it to a standard format, and the application simply plugs it in — without rebuilding code for each new palette.

A compute shader is a program that runs on the graphics processing unit and computes color by formula: it mixes channels, builds curves, takes into account the brightness of neighboring pixels, and applies masks by hue or saturation.

It can do what a table fundamentally cannot express — local effects that depend on the content of the frame, not just on the value of a single pixel.

The difference shows up in three places. Flexibility: a table is a fixed transformation, a shader is any math you like. Cost: a table is cheaper and more stable in terms of frame time, a shader requires more computation and memory for intermediate buffers.

Maintenance: a table is changed by a designer without a developer, a shader requires only a code edit and a new release.

The task dictates the choice of approach. Mass presets like "warm," "film," "b&w" are a color correction lookup table: cheap, uniform, updated via content. Artistic processing that reacts to the subject is a compute shader.

In practice they are combined: the shader does the base color correction and preparation, and the table applies the final style.

We measure frame processing time on real devices, not on a test bench, and we lock in the scheme based on those numbers — otherwise a filter that looks beautiful in a demo tanks the frame rate on a live device.

Technical doubts and answers

GPU filters live in two different worlds: on iOS it's Metal and Core Image, on Android it's shaders and hardware camera effects.

Below are answers to the questions that most often come up before work starts: they determine the architecture, the timeline, and how the app will behave on real devices.

How widely are GPU filters supported across devices?

We target the current branch of mobile systems and keep a compatibility margin: filters work on the vast majority of devices released over the past few years.

For older models, we provide a software fallback — the effect is applied, albeit more slowly, so the app doesn't "crash" on weak hardware. We finalize the exact list of supported devices at the design stage.

How does this affect performance and battery consumption?

Processing runs on the graphics accelerator rather than the CPU, so the filter is applied to a frame almost instantly — the preview stays smooth even when switching effects.

The main energy drain comes not from the filter itself but from the camera and the screen, so the GPU layer has little impact on operating time in shooting mode. We measure heat and responsiveness on real devices, not just in the emulator.

How are filters integrated into an existing app?

The effects layer connects to the current camera or gallery without rewriting the app's logic. We describe filters as separate configurable profiles, so a new effect can be added later without releasing all the code.

If the app already uses its own image processing, we integrate carefully alongside it and maintain compatibility.

How do you test filters before release?

We check not only the "pretty picture" but also behavior on weak and strong devices, under different lighting, and on different cameras. Separately, we look at how a filter behaves during rapid switching and in the background. The result is a stable effect without stutters or discrepancies between platforms.

What about support after launch?

New versions of systems and device models are released constantly, and filters need to be maintained alongside them. We build this into support: we monitor compatibility, update effect profiles, and come back with a work plan when platform behavior changes.

Let's discuss your GPU filter task

Send over the inputs — we'll come back with an estimate and a work plan for GPU filters. To keep the conversation concrete rather than "tell us about filters in general," it helps to close several questions up front.

  • What kind of filters and where the effects come from. Is the set of presets fixed, or does the user adjust parameters themselves? Are there ready-made LUT tables from design, and in what form — files, matrices, separate layers? This determines whether we're building a processing pipeline or just plugging in ready-made chains.
  • Where we compute — on the device or on the server. Processing on the phone gives instant preview and doesn't depend on the network; server-side gives a consistent result across all models. A hybrid scheme is often needed: preview locally, final render on save.
  • Target devices and minimum requirements. The list of models, OS versions, the share of low-end devices in the audience. This determines where we enable hardware acceleration and where we keep a fallback path on the CPU.
  • Formats and resolutions. What images are we working with — camera shots, imports from the gallery, video? Are batch processing and saving in the original quality needed?
  • What already exists in the project. The current app code, the libraries in use, restrictions on access to the camera and gallery, app store requirements.
  • Acceptance criteria. What we consider a finished result: preview response time, stability on low-end devices, color matching the design, absence of artifacts at frame edges.

Based on these points, our engineers prepare an estimate and a work plan: the stages, what we do at each, what risks we see and how we close them. If some of the inputs aren't defined yet — we'll work through them on a call and lock them into the technical specification.

Describe the task in whatever format is convenient — we'll come back with an estimate and a work plan.