AVIF в GD
Вчера ночью чах, в очередной раз, над форматом AVIF — мысль была в качестве эксперимента добавить его в наш документооборот — продукт, разработкой которого я управляю.
Сейчас, чтобы показать документ в браузере, мы его конвертируем в JPEG — дёшево, сердито и везде поддерживается. Но страницы получаются большими (200 с лишком килобайт каждая) и иногда грузятся дольше, чем хотелось бы. Вот я и придумал проверить гипотезу, что AVIF тут поможет.
Пока примотал реализацию на соплях, как концепт. Результаты, кстати, хорошие, можно посмотреть на скриншоте разницу:
Но пока мотал, наткнулся на прекрасное. 🤦🏻♂️
В ПХП есть несколько модулей для работы с картинками, но самых распространённых два — GD и Imagick. Я начал с GD, так как на виртуалке он собран с поддержкой AVIF (а Imagick — нет), по крайней мере сам модуль так утверждает:
var_dump(gd_info()['AVIF Support']); // true
var_dump(imagetypes() & IMG_AVIF); // 256
Так же существует функция imageavif, что хороший знак — модуль устроен так, что если поддержки какого-то формата нет, то функция просто отсутствует.
Но при попытке сконвертировать картинку из JPEG в AVIF создавался файл нулевой длины, хотя функция возвращала true:
var_dump(imageavif(imagecreatefromjpeg('0.jpg'), '0.jpg.avif')); // true
GD это очень старый модуль, он родился, когда в PHP главенствовал процедурный модуль, поэтому его суть — функции; в PHP, если мы вызываем функции и что-то идёт не так, мы можем узнать что именно при помощи функции error_get_last. Помогла она и на этот раз:
array(4) {
["type"]=>
int(2)
["message"]=>
string(50) "imageavif(): AVIF image support has been disabled
"
["file"]=>
string(17) "Command line code"
["line"]=>
int(1)
}
Я погуглил ошибку, но не смог быстро разобраться что с ней сделать, поэтому переключился на Imagick. Там всё завелось без особых проблем — заменил шестую версию на седьмую и поставил недостающие пакеты:
yum shell
> remove php-pecl-imagick-im6
> install php-pecl-imagick-im7
> install ImageMagick7-heic
> install libheif
> run
В этом модуле, кстати, проверка на поддержку AVIF делается вот таким немного неочевидным способом:
$isAVIFSupported = Imagick::queryformats("AVIF") !== [];