Problem/Motivation
The core "Convert" image effect (image_convert) converts every derivative to the configured format. A common production setup is "Scale + Convert to JPEG" so that large photographic PNG uploads don't ship as multi-megabyte derivatives. But JPEG has no alpha channel, so any PNG with real transparency (people cut-outs, icons, logos, screenshots with rounded corners or drop shadows) comes out flattened onto a solid background. Editors upload a transparent PNG and see a filled square on the site.
Today the only options are:
- no Convert effect at all, which keeps transparency but serves photographic PNG uploads as 1.5–2 MB derivatives, or
- separate image styles per use case, which pushes the decision onto site builders and templates and still fails as soon as one field mixes photos and transparent artwork.
On a real site (Drupal 11.4, GD toolkit) an audit found about 160 transparent PNGs silently flattened: person photos, ~120 small icons rendered through responsive image styles, ~40 1920×1080 slides with rounded corners. At the same time most PNG uploads do carry an alpha channel but are fully opaque (design-tool exports), so "skip PNG files" is not a usable rule either: the decision has to look at the pixels.
Steps to reproduce
- Create an image style with the effects Scale (any width) + Convert (JPEG).
- Upload a PNG with a transparent background (e.g. an 80×80 RGBA cut-out portrait) and render it through that style on a coloured page background.
- The derivative is
<name>.png.jpegwith the transparent area filled with a solid colour.
Expected: an opt-in way for the same style to leave transparent PNGs in PNG while still converting opaque uploads to JPEG.
Proposed resolution
Give the Convert effect an option such as "Keep the source format for images with transparency" (default off to preserve current behaviour). When enabled and the source is a PNG (or GIF/WebP) with at least one non-opaque pixel, the effect does not convert and the derivative keeps its own extension. Opaque images convert exactly as now.
Transparency detection can be cheap: read the PNG IHDR colour type (4 = grey+alpha, 6 = RGBA) or the presence of a tRNS chunk first; only then decode with the toolkit and sample the alpha channel; cache the result per file (path + mtime + size).
The obstacle is architectural: the derivative extension is decided in ImageStyle::addExtension() from the extension string alone (ImageEffectInterface::getDerivativeExtension($extension)), with no access to the source file, so an effect cannot make a per-file decision on its own. Options:
- Pass the source URI to
getDerivativeExtension()(a new interface method, or an optional second argument with a BC shim) and let the effect answer per file;ImageStyle::buildUri()already knows the URI. - Let
ImageStyle::buildUri()/createDerivative()ask effects through a new interface method (e.g.ImageEffectInterface::appliesTo(string $uri)).
Proof of concept: on the site above this was implemented without touching config by swapping the image_style entity class (hook_entity_type_alter()) for a subclass that overrides buildUri() (strip the appended .jpeg for transparent PNGs) and createDerivative() (skip ConvertImageEffect for them). It works with core responsive_image and contrib image_replace, and ImageStyleDownloadController serves the derivative unchanged because it resolves everything through buildUri() / getPathToken(). Happy to turn that into an MR once the API direction is agreed.
Remaining tasks
- Agree on how an effect can make a per-file decision about the derivative extension (see the options above).
- Implement the option on
ConvertImageEffectplus a transparency check on the toolkit/image side. - Tests: opaque PNG converts, transparent PNG keeps its format, derivative URI matches the generated file.
- Change record for the new interface method/argument.
User interface changes
One new checkbox on the Convert effect configuration form.
Introduced terminology
None.
API changes
Likely a new argument or method for deciding the derivative extension per source file (see Proposed resolution).
Data model changes
None.
Release notes snippet
The Convert image effect can now be configured to keep the source format for images with real transparency instead of flattening them.
| Comment | File | Size | Author |
|---|---|---|---|
| Screenshot_3.png | 81.25 KB | morovinger |
Comments