Я пытаюсь написать скрипт, который изменяет размер изображения PNG, а затем преобразует его в битовый режим PNG-8. Таким образом, размер полученного файла будет меньше, но без потери качества.
Изменение: стиль цитаты для изображений, чтобы лучше показать прозрачность
Изменение размера отлично работает, сохраняя прозрачность:
Проблема в том, что я конвертирую изображение в 8 бит:
imagetruecolortopalette($resizedImg, true, 255);
imagealphablending($resizedImg, false);
$transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
imagesavealpha($resizedImg, true);
В результате получается изображение с прозрачностью вокруг и немного внутри изображения:
Если я установлю 256 цветов вместо 255:
imagetruecolortopalette($resizedImg, true, 256);
изображение будет с черным фоном:
Аналогичный результат происходит с этим изображением (обратите внимание на полупрозрачность для случая с 255 цветами):
Полный код функции:
function resizePng($originalPath, $xImgNew='', $yImgNew='', $newPath='')
{
if(!trim($originalPath) || !$xyOriginalPath = getimagesize("$originalPath")) return false;
list($xImg, $yImg) = $xyOriginalPath;
if(!$originalImg = imagecreatefrompng($originalPath)) return false;
if(!$resizedImg = imagecreatetruecolor($xImgNew, $yImgNew)) return false;
// preserve alpha
imagealphablending($resizedImg, false);
$transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
imagesavealpha($resizedImg, true);
// copy content from originalImg to resizedImg
if(!imagecopyresampled($resizedImg, $originalImg, 0, 0, 0, 0, $xImgNew, $yImgNew, $xImg, $yImg)) return false;
// PNG-8 bit conversion
imagetruecolortopalette($resizedImg, true, 255);
// preserve alpha
imagealphablending($resizedImg, false);
$transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
imagesavealpha($resizedImg, true);
if(!imagepng($resizedImg, ($newPath) ?: null, 8)) return false;
return true;
}
Что я пробовал:
-
// PNG-8 bit conversion imagetruecolortopalette($resizedImg, true, 255); imagesavealpha($resizedImg, true); imagecolortransparent($resizedImg, imagecolorat($resizedImg,0,0)); // preserve alpha imagealphablending($resizedImg, false); $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127); if(!imagefill($resizedImg, 0, 0, $transparent)) return false; imagesavealpha($resizedImg, true); if(!imagepng($resizedImg, ($newPath) ?: null, 8)) return false;
Результаты:
ничего не меняется
- другие ТАК сообщения и некоторые в Интернете
Также без изменения размера изображения (удаление imagecopyresampled
и адаптация имени переменной) результат будет таким же.
Не могли бы вы помочь мне заставить его работать и понять причину этого странного поведения?
Некоторая информация в phpinfo()
:
- PHP
7.0.33
GD
в комплекте (совместимо с 2.1.0)PNG Support
включенlibPNG
1.5.13.
Изменить:
В GIMP v.2.8.22 я могу сохранить изображение для Web со следующими свойствами:
PNG-8
256 colors palette
Dither: Floyd-Steinberg / Floyd-Steinberg 2 / positioned
и это приводит к уменьшенному изображению, почти идентичному оригиналу.
Также pngquant, tinypng и многие другие выполняют ту же работу, но мне нужно сделать это с помощью PHP.
Edit2:
К сожалению, я не могу использовать ImageMagick, потому что мой код находится на общем хостинге без его установки.
Edit3:
в phpinfo()
приводит к тому, что модуль imagemagick
не установлен.
Edit4:
Срок действия награды истекает, в следующие дни позвольте мне провести несколько тестов с вашими ответами, возможно, есть решение только с PHP.
Edit5:
Это мои попытки с вашими ответами (обновлено на 2019-10-02).
Примечание. Я поместил базовую сетку, чтобы лучше показать альфа.
У пингвина видны цветные полосы, но утка в порядке (хотя иногда цветовой тон темнее).
Только если изображение имеет только пиксели, уже полностью прозрачные, оно работает очень хорошо (например, утка).
Это делает полностью прозрачными все пиксели с альфа-каналом, также, если эта альфа очень низкая, см. тень под пингвином. Также некоторые пиксели на краю утки преобразуются в черный пиксель или в полностью прозрачный пиксель.