Skip to content

Add imagemagick-heic to the Alpine variants - #1015

Open
LeoFidjeland wants to merge 1 commit into
docker-library:masterfrom
LeoFidjeland:alpine-imagemagick-heic
Open

LeoFidjeland wants to merge 1 commit into
docker-library:masterfrom
LeoFidjeland:alpine-imagemagick-heic

Conversation

@LeoFidjeland

Copy link
Copy Markdown

Alpine packages ImageMagick's coders as separate subpackages, and the base imagemagick
package ships none of them. So on the Alpine images Imagick::queryFormats('AVIF') is
empty, WP_Image_Editor_Imagick::supports_mime_type('image/avif') returns false, and
_wp_image_editor_choose() falls back to WP_Image_Editor_GD.

That fallback is lossy. GD's imageavif() discards the ICC profile and tags output as
sRGB, so uploads carrying Adobe RGB or Display P3 profiles get reinterpreted as sRGB and
render visibly desaturated. Nothing errors — the AVIF files are produced successfully,
just without their colour information — which makes this easy to run into without
realising. The Debian variants are unaffected, because there libmagickcore links libheif
directly.

This is the Alpine counterpart to #996 (fixed for Debian in #997). The difference is that #996 was decode-only
support failing loudly at encode time (no encode delegate for this image format 'AVIF'),
whereas here Imagick has no AVIF support at all, so it fails the editor-capability check
and WordPress quietly uses a different editor.

Before

$ docker run --rm wordpress:fpm-alpine php -r 'var_dump(Imagick::queryFormats("AVIF"));'
array(0) {
}

$ docker run --rm wordpress:fpm-alpine sh -c 'ls /usr/lib/ImageMagick-*/modules-*/coders/ | grep -c heic'
0

After

Built from latest/php8.3/fpm-alpine with this change:

$ docker run --rm wp-heic-test php -r 'var_dump(Imagick::queryFormats("AVIF"));'
array(1) {
  [0]=>
  string(4) "AVIF"
}

AVIF encodes, and the profile survives a JPEG → AVIF conversion:

src icc: 560 bytes (Adobe RGB (1998))
out icc: 560 bytes

Measured mean saturation on a real Adobe RGB photograph: source JPEG 44.25%, Imagick AVIF
44.41%. The GD output the images currently produce is visibly lower.

On size

The image grows 3 MB, from 310.4 MB to 313.4 MB.

AVIF encoding needs no new heavy dependency: libavif, aom-libs and libdav1d are
already in the image for GD's --with-avif, and imagemagick-heic brings libheif-aom
with it. The added weight is libheif itself (1.6 MB), libde265 (0.6 MB) and a few small
plugin shims; the ImageMagick coder module is 66 KiB.

I initially also added libheif-x265 for HEVC parity with the Debian variants after #997,
but dropped it - it is 6.8 MB on its own, more than twice the cost of this fix, and HEIC
encoding is not what breaks here. Happy to add it in a follow-up if that parity is wanted.

Dockerfile.template was edited and ./apply-templates.sh run; the 8 generated
fpm-alpine Dockerfiles are the only other files changed.

Alpine packages ImageMagick's coders separately and the base "imagemagick"
package ships none of them, so on the Alpine images
Imagick::queryFormats('AVIF') is empty,
WP_Image_Editor_Imagick::supports_mime_type('image/avif') returns false, and
_wp_image_editor_choose() falls back to WP_Image_Editor_GD.

That fallback is lossy: GD's imageavif() discards the ICC profile and tags the
output sRGB, so uploads carrying Adobe RGB or Display P3 profiles get
reinterpreted as sRGB and render desaturated. Nothing errors, which makes it
easy to miss - the AVIF files are produced successfully, just without their
colour information.

AV1 encoding needs no new dependency: libheif-aom comes in with
imagemagick-heic, and libavif/aom-libs are already present for GD's
--with-avif. The image grows 3 MB, from 310.4 MB to 313.4 MB.

Verified against latest/php8.3/fpm-alpine: a JPEG carrying a 560-byte Adobe RGB
profile round-trips through AVIF with the profile intact.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant