Сжатие Imagick PNG в переполнении стека

Я изучал stackoverflow, а также документацию PHP / Imagick, чтобы заставить это работать. На моем сервере хранятся изображения в формате PNG, которые затем возвращаются в мое приложение iOS. Мне нужно вернуть их в виде уменьшенных и обрезанных изображений, поэтому я использую Imagick. Итак, пока у меня есть:

$image_name = $_POST['filepath'];
if(!file_exists($image_name)){ return ""; }
header("Content-Type: image/png");

$image = new Imagick($image_name);
$image->resizeImage($_POST['width'], $_POST['height'], Imagick::FILTER_LANCZOS, 1);
$image->roundCorners($_POST['width'], $_POST['height']);
$image->setImageFormat("png");
$image->setImageCompression(\Imagick::COMPRESSION_UNDEFINED);
$image->setImageCompressionQuality(0);
$image->stripImage();
echo $image;

Для setImageCompression я попробовал каждую константу сжатия, перечисленную здесь: http://php.net/manual/en/imagick.constants.php, так как нет специфического для PNG, но ни один из них, похоже, не меняет размер файла. (Есть ли какой-то конкретный объект, который предполагается использовать для PNG?) Я также изменил значение в setImagesCompressionQuality, но ни одно из этих изменений, похоже, тоже не имеет значения. Я видел, что некоторые люди никогда не могли заставить Имаджика работать, в то время как другие были, и надеялись на более обновленный ответ. Любая помощь приветствуется!

4

Решение

Это функция setImageCompressionQuality установить уровень сжатия, который делается для изображений PNG. Поскольку PNG — это формат изображения без потерь, это не влияет на реальное качество изображения (как это происходит для изображений JPEG), а просто сообщает библиотеке, сколько усилий и какую стратегию использовать при сжатии изображений. Код ниже проходит через все возможные варианты.

Я тоже пробовал Pngcrush с командной строкой: pngcrush -brute Original.png pngcrushBrute.png чтобы увидеть, сколько еще места можно сэкономить.

Original.png: 192 382 байта — без установки какого-либо определенного уровня сжатия
FullColor92.png: 181 832 байта — лучший выход из всех возможных вариантов.
pngcrushBrute.png: 178,129 байт — что, вероятно, больше связано с удалением лишних заголовков, чем с гораздо лучшим сжатием.

$imagick->setImageFormat('jpg');
$imagick->setImageCompressionQuality(80);

Original.jpg: 27 626 байт \ o /

Чтобы подвести итог:

  • Imagick / ImageMagick уже приближается к наилучшему сжатию с настройками по умолчанию.
  • Если вам нужно получить лучшее сжатие, то использование PngCrush даст немного лучший результат, чем у Imagick.
  • Если изображение является фотографией, используйте его в качестве JPG. Если это диаграмма / должна быть снабжена png, вы можете попробовать уменьшить цвет, что даст хорошее «сжатие», но не подходит для фотографий, так как выглядит дерьмово.

Используемый код:

//10's digit:
//
//        0 or omitted: Use Z_HUFFMAN_ONLY strategy with the
//           zlib default compression level
//
//        1-9: the zlib compression level
//
//     1's digit:
//
//        0-4: the PNG filter method
//
//        5:   libpng adaptive filtering if compression level > 5
//             libpng filter type "none" if compression level <= 5
//or if image is grayscale or palette
//
//        6:   libpng adaptive filtering
//
//        7:   "LOCO" filtering (intrapixel differing) if writing
//a MNG, otherwise "none".  Did not work in IM-6.7.0-9
//and earlier because of a missing "else".
//
//8:   Z_RLE strategy (or Z_HUFFMAN_ONLY if quality < 10), adaptive
//             filtering. Unused prior to IM-6.7.0-10, was same as 6
//
//        9:   Z_RLE strategy (or Z_HUFFMAN_ONLY if quality < 10), no PNG filters
//             Unused prior to IM-6.7.0-10, was same as 6

$imagick = new Imagick("./Biter_500.jpg");

$imagick->setImageFormat('png');

$imagick->writeimage("./output/original.png");
compressAllTypes($imagick, "./output/FullColor");function compressAllTypes(Imagick $imagick, $filename) {
for ($compression = 0; $compression <= 9; $compression++) {
echo "Compression $compression \n";
for ($filter = 0; $filter <= 9; $filter++) {
echo "Filter $filter";
$output = clone $imagick;
$output->setImageFormat('png');
//$output->setOption('png:format', 'png8');
$compressionType = intval($compression . $filter);
$output->setImageCompressionQuality($compressionType);
$outputName = $filename."$compression$filter.png";
$output->writeImage($outputName);
}
echo "\n";
}
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]