Обработка PNG БЕЗ Image Magick и imagefrompng ()

Мне нужно изменить каждый оттенок желтого на синий и каждый оттенок темно-серого на светло-серый в изображениях PNG с прозрачностью.

Проблема в:

Я не могу использовать Photoshop, потому что у меня 100 изображений, и мне нужно много раз менять оттенки. Я не могу использовать Image Magick, потому что мне нужны более сложные вычисления, чем можно с помощью «-fx». Я не могу использовать PHP imagefrompng (), потому что эта неприятная чушь не работает со многими моими изображениями, даже со всеми предлагаемыми исправлениями, такими как:

$background = imagecolorallocate($png, 255, 255, 255);
// removing the black from the placeholder
imagecolortransparent($png, $background);
// turning off alpha blending (to ensure alpha channel information is preserved, rather than removed (blending with the rest of the image in the form of black))
imagealphablending($png, true);
// turning on alpha channel information saving (to ensure the full range of transparency is preserved)
imagesavealpha($png, true);

и так далее. Он работает с некоторыми изображениями, но не работает с другими.

Все, что мне нужно, это библиотека PNG (возможно, не в PHP), которая может дать мне красный, зеленый, синий и альфа-компонент пикселя с координатами x, y, а затем установить этот пиксель после моих расчетов, например:

$rgba = getrgba($image, $x, $y);
$rgba = my_function($rgba);
setrgba($image, $x, $y, $rgba);

Может быть, вы можете предложить библиотеки на других языках, а не только на PHP?


person Gardner    schedule 07.11.2016    source источник
comment
Добро пожаловать в Stack Overflow! Пожалуйста, прочтите некоторое время вводный тур. Вопросы, требующие от нас порекомендовать или найти книгу, инструмент, библиотеку программного обеспечения, учебное пособие или другой внешний ресурс, не относятся к теме Stack Overflow, поскольку они, как правило, привлекают самоуверенные ответы и спам. См. Также Справочный центр: Какие темы можно спросить здесь?   -  person Jongware    schedule 07.11.2016


Ответы (2)


Если вы не против использования Python, ознакомьтесь с Pillow, особенно с его PixelAccess. Эти потоки (1, 2) должен быть полезным и содержать несколько примеров кода.

person evpav    schedule 07.11.2016

Способ 1

Если вы просто хотите получить необработанные значения пикселей R, G, B и Alpha, не беспокоясь о сжатии и кодировании, используйте ImageMagick, чтобы преобразовать изображение в простой, несжатый, некодированный двоичный файл, прочитать его и обработайте это как душе угодно.

Итак, если мы создадим файл PNG размером 1x1 пиксель с RGBA (0,64,255,0,5) для тестирования:

convert -size 1x1 xc:"rgba(0,64,255,0.5)" a.png

Теперь мы можем заставить ImageMagick создать необработанный файл RGBA, который вы можете читать и обрабатывать по своему усмотрению на любом языке, на любом желаемом уровне сложности:

convert a.png rgba:data.bin

и теперь мы можем заглянуть в этот файл:

xxd data.bin

Результат

0000000: 0040 ff80                                .@..

Там вы можете увидеть и прочитать все пиксели RGBA. Когда вы закончите, просто сделайте противоположное, чтобы вернуть PNG - обратите внимание, что вы должны сначала указать размер ImageMagick, поскольку он этого не знает:

convert -size 1x1 rgba:data.bin new.png

Обратите внимание, что ImageMagick - довольно большой пакет для установки, и вы можете добиться того же, что и выше, с гораздо более легким пакетом vips:

vips VipsForeignSaveRaw a.png data.rgb

Способ 2

В качестве альтернативы, если вы хотите, чтобы ваши данные были несжатыми, удобочитаемыми ASCII, используйте почтенные форматы NetPBM PPM (Portable Pixmap) и PGM (Portable Greymap) - см. NetPBM в Википедии.

Сделайте изображение 4x1 и напишите как PPM:

convert -size 4x1 xc:"rgba(0,64,255,0.1)" -compress none ppm:-
P3
4 1
65535
0 16448 65535 0 16448 65535 0 16448 65535 0 16448 65535

Надеюсь, вы увидите 4 повторяющихся значения RGB. Если вам нужен файл, просто замените ppm:- в конце на someFile.ppm.

Сделайте то же изображение еще раз и извлеките альфа-канал в отдельный файл:

convert -size 4x1 xc:"rgba(0,64,255,0.1)" -alpha extract -compress none pgm:-
P2
4 1
65535
6554 6554 6554 6554 

Надеюсь, вы видите, что 6554 равно 0.1 по шкале от 0 до 65535.

Если вам просто нужны 8-битные данные для любого из вышеперечисленных, добавьте -depth 8.

Способ 3

Как предлагает Гленн в комментариях, другой вариант - опустить -compress none в Варианте 2, который даст вам очень похожий формат файла, за исключением того, что данные пикселей будут в двоичном формате после заголовка, который остается в ASCII. Это обычно быстрее и меньше.

person Mark Setchell    schedule 07.11.2016
comment
Также существует метод 3, который является сырым PPM. Вы получаете скорость необработанного RGBA, но по-прежнему имеете заголовок изображения (с P6 вместо P3) для запоминания размеров. Это то же самое, что и метод 1, но без опции -compress none на начальном convert шаге. Обратите внимание, что если глубина больше 8, байт в образцах цвета будет в порядке MSB, LSB. - person Glenn Randers-Pehrson; 07.11.2016
comment
@ GlennRanders-Pehrson Да, спасибо. Я как бы пытался сделать один двоичный файл и один ASCII, чтобы дать OP некоторый выбор / гибкость. Отредактирую ваше предложение - спасибо. - person Mark Setchell; 07.11.2016
comment
@ GlennRanders-Pehrson Вторая команда convert в методах 2 и 3 специально извлекает альфа-канал. - person Mark Setchell; 08.11.2016
comment
@ GlennRanders-Pehrson Вы правы - я поправил. Даже не знаю, как это произошло, потому что я действительно помню, как набирал PGM в моем терминале. Спасибо. - person Mark Setchell; 08.11.2016