Imagick
| Language | PHP (C extension) |
|---|---|
| License | PHP License 3.01 |
| Repository | github.com/Imagick/imagick |
| Documentation | PHP manual: Imagick |
| Depends on | ImageMagick 7 (or 6.9) built with libjxl |
| Read / write | yes / yes, lossy and lossless, animation |
Imagick is the PHP extension that wraps ImageMagick’s MagickWand API. JPEG XL support depends entirely on the ImageMagick library it’s linked against: if ImageMagick was built with libjxl, Imagick reads and writes .jxl like any other format. ImageMagick 7 from current Debian, Ubuntu, Fedora and Homebrew includes libjxl; ImageMagick 6 from older distributions usually doesn’t.
Installation#
Shell
# Debian / Ubuntu
sudo apt install php-imagick
# macOS
brew install imagemagick && pecl install imagick
Check that JXL is available:
PHP
<?php
var_dump(Imagick::queryFormats('JXL')); // ["JXL"] when supported, [] otherwise
Basic usage: convert JXL to PNG and back#
PHP
<?php
$im = new Imagick('in.jxl');
printf("%d x %d\n", $im->getImageWidth(), $im->getImageHeight());
$im->writeImage('out.png');
$photo = new Imagick('photo.png');
$photo->setImageFormat('jxl');
$photo->setCompressionQuality(90); // JPEG-like scale; 100 = lossless
$photo->writeImage('photo.jxl');
How to save a lossless JPEG XL#
PHP
<?php
$im = new Imagick('screenshot.png');
$im->setCompressionQuality(100); // ImageMagick maps quality 100 to lossless
$im->writeImage('screenshot.jxl');
How to set effort and distance#
ImageMagick passes jxl: options to libjxl. Set them before reading or writing:
PHP
<?php
$im = new Imagick();
$im->setOption('jxl:effort', '9'); // 3-9: slower, smaller
$im->setOption('jxl:distance', '1.0'); // 0 = lossless, 1 = visually lossless
$im->readImage('photo.png');
$im->writeImage('photo.jxl');
How to get JXL dimensions without decoding#
pingImage reads only the header:
PHP
<?php
$im = new Imagick();
$im->pingImage('in.jxl');
printf("%d x %d\n", $im->getImageWidth(), $im->getImageHeight());
How to serve a JXL image converted from JPEG#
PHP
<?php
$im = new Imagick('photo.jpg');
$im->setImageFormat('jxl');
$im->setCompressionQuality(80);
header('Content-Type: image/jxl');
echo $im->getImageBlob();
The JPEG is decoded and re-encoded; ImageMagick doesn’t do lossless JPEG recompression. Use cjxl for that.
Tips#
- Use
setCompressionQuality, notsetImageCompressionQuality: ImageMagick’s JXL writer takes the quality from the write settings, not from the image.setOption('jxl:quality', '90')works too. - Read Exif values with
$im->getImageProperties('exif:*'). - Call
$im->stripImage()before writing to drop metadata and make the file smaller.