#php #png #zlib
#php #png #zlib
Вопрос:
Ситуация
В настоящее время я создаю функцию, которая создаст изображение из идентификатора пользователя. Я успешно сгенерировал необработанные пиксели RGBA, а также успешно отфильтровал их следующим образом:
При ширине изображения 22 пикселя и высоте 2 пикселя.
идентификатор пользователя: a308193d1eff2f15df7bedb4cb992bcf25cee012ca41751c35ce1d5500497063
, который будет дополнен, если он слишком короткий для генерации пикселей.
отфильтрованные необработанные пиксели:
01a30819ff000000009a16e60000000000f2f7e000000000004cd8d5000000000050ac770000000000048ca3000000000011edfc00000000006163520000000000f45901000000000020322c00000000001b63b600000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Я также успешно сгенерировал рабочий SVG из идентификатора пользователя, но SVG — это не то, что мне нужно.
Проблема
Библиотека PHP zlib, похоже, неправильно сжимает данные. Он всегда выводит сжатые данные, которые несовместимы с PNG-форматом, даже если zlib изначально разработан для PNG. Каждая функция библиотеки zlib генерирует неправильное сжатие, например:
78da 635ccc21f99f010866893d03510c9fbe3f00d33e37ae82e98035e5609aa5673198167cfb074c27260781e92f918c605ac148074c4b276f03d34c0c340200 54f010d5
(Я разделил заголовок ZLIB, сжатые данные и adler32 пробелом).
Что оно должно выводить (или, по крайней мере, похоже):
0899 B5C1210A83500000D0E730582D03B1780093E730C8DAE2F0105EC213587F357B13C168B259646011B653F85E1492EC07C37303C7B9827A9941337620EE0348F70B7CDA17F8BE23505425C8DB093CDCE40F 54F010D5
(Для PNG сжатая строка всегда должна начинаться с 0x08 байта)
Каждый раз корректна только контрольная сумма Adler32.
Я перепробовал все функции сжатия zlib, и каждая из них генерирует бесполезные данные. Наиболее настраиваемыми функциями из них являются deflate_init() deflate_add(), но они так же бесполезны, как и любая другая функция.
Например:
$filtered_pixels = "01a30819ff000000009a16e60000000000f2f7e000000000004cd8d5000000000050ac770000000000048ca3000000000011edfc00000000006163520000000000f45901000000000020322c00000000001b63b600000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
$options = array(
"level" => 9, // Best compression
"memory" => 1, // No need to use much memory for such small image
"window" => 8, // 256-bit window size
"strategy" => ZLIB_RLE, // Especially good for PNG compression
"dictionary" => "", // No dictionary
);
$context = deflate_init(ZLIB_ENCODING_DEFLATE , $options);
$deflate = deflate_add($context, hex2bin($filtered_pixels));
// Outputs "1819 625ccc21f99f010866893d6300814fdf1f308080cf8dab0c2010b0a69c0104587a16338080e0db3f0c2090981cc400025f2219194040c148870104a493b731800013038d00000000ffff" without adler32 checksum
echo bin2hex($deflate);
Я боролся с этой проблемой уже неделю, и она просто не будет работать, какую бы функцию я ни пробовал, с какими бы параметрами я ни пробовал для каждой функции. Я упускаю что-то очевидное? Я также знаю, как кодировать PNG из других частей, и я это сделал. Только сжатие фрагмента IDAT — это то, что заставляет меня сходить с ума.
Комментарии:
1. Это очень интересная тема, но я ничего об этом не знаю. Чтение libpng.org/pub/png/spec/1.2/PNG-Compression.html может
Note that the zlib compression method number is not the same as the PNG compression method number.
быть, это даст полезную подсказку.
Ответ №1:
Нет, оно не всегда должно начинаться с a 0x08
. Я понятия не имею, откуда ты это взял. Оба 78da
и 0899
являются допустимыми заголовками zlib. В потоке zlib, который начинается с, нет ничего плохого 78da
. Оба потока действительны, и оба распаковываются в ваши данные. Оба могут использоваться в блоке IDAT изображения PNG.
Хотя у меня есть некоторые придирки к тому, что, по вашему мнению, «должно» быть результатом. Это довольно плохо сжато, тратит место на заголовок динамического блока, когда он должен был использовать фиксированный заголовок, и не сжимает много прогонов нулей. В результате этот поток дефляции на 32% больше, чем поток, генерируемый zlib. Интересно, что создало плохо сжатый файл.