netpbm формат и генерирование картинки в 5LoC bash
Что: 71870b1510dfc2727093f2767b994b8596f9b163
Когда: 2020-11-05 12:28:32+03:00
Темы: tip
netpbm формат и генерирование картинки в 5LoC bash
https://www.vidarholen.net/contents/blog/?p=904
Я давний "поклонник" netpbm утилит и форматов. Мне кажется что уже
наверное лет 15 я для работы с изображениями только его и использую.
#!/bin/bash
exec > my_image.ppm # All echo statements will write here
echo "P3 250 250 255" # magic, width, height, max component value
for ((y=0; y<250; y++)) {
for ((x=0; x<250; x++)) {
echo "$((x^y)) $((x^y)) $((x|y))" # r, g, b
}
}
netpbm это набор утилит для работы с PNM файлами. PNM-ы бывают: PBM
(bitmap, монохромный), PGM (graymap, серый), PPM (pixmap, цветной), PAM
(цветной, ещё и с альфа-каналом). Каждый из них может быть представлен
в ASCII текстовом формате (как в примере выше), где задаётся формат,
размеры изображения и глубина на канал. Или в аналогичном, но бинарном
формате. Например когда я недавно занимался сканированием фотографий, то
мне надо было и обрезать, и scale-ить, и менять глубину цвета, и кучу
других подобных вещей. Изображение перегоняется в PNM, дальше через
pipe-ы применяются фильтры, дальше PNM преобразуется в нужный формат
(JPEG2000, WebP, и т.д.).
Ещё вот позже появился suckless проект: https://tools.suckless.org/farbfeld/
где формат тоже предельно прост:
8 -- "farbfeld" magic value
4 -- 32-Bit BE unsigned integer (width)
4 -- 32-Bit BE unsigned integer (height)
[2222] -- 4x16-Bit BE unsigned integers [RGBA] / pixel, row-major
В принципе мне он нравится больше, так как наборы PNM форматов это
только ведь об эффективности. Хотя... в том числе и про удобство для
генерирования/обработки наверное тоже, но преобразовать в RGBA и обратно
совсем не проблема. Из коробки farbfeld, конечно же, имеет и конвертеры
в PAM/PPM.
оставить комментарий
комментарий 0:
From: Алексей
Date: 2020-11-05 19:43:05Z
Так есть же ImageMagick, где любые преобразования и фильтры делаются безо всяких пайпов и промежуточных форматов, одной командой convert. А для особых эстетов есть ещё и ffmpeg.
комментарий 1:
From: Sergey Matveev
Date: 2020-11-05 20:59:08Z
- ** Алексей [2020-11-05 22:42]:
>Так есть же ImageMagick
Он у меня тоже стоит как правило всегда, как минимум ради display (так
как иногда sxiv просмотрщика "не хватает"). Он будет гораздо мощнее, в
плане обработки изображений, но я за свою жизнь возможно только пару раз
использовал его возможности -- хватало netpbm.
А касательно его использования как конвертера, мне не люб его монолитный
подход: если нужно начать работать с каким-нибудь новым форматом (вот
недавно начал с webp и jpeg2000), то нужно его пересобирать и добавлять
зависимость, надеясь что в ImageMagick (IM) поддержка чего надо уже
есть. Прелесть промежуточных форматов (netpbm де факто, насколько вижу,
поддерживают всюду и все) в том, что вот появился у меня jpeg2000
какой-то реализации и он сам предоставляет кодер/декодер, работающий с
netpbm-ом. Появился cwebp -- и он сам умеет netpbm, опять же. Плюс
установив какой-нибудь cjpeg, cwebp, opj_compress, и возможно читая его
man-ы, видя его опции, я ещё параллельно должен читать доку IM по поиску
аналога задания этих опций в нём. Лично для меня -- ужасный геморрой и
неудобство во всём. Собственно netpbm это прям чисто Unix-way, а IM прям
не Unix-way (при всём моём уважении к IM).
Собственно, вот прям сейчас я хочу посмотреть как мне сделать
прогрессивный JPEG через convert. man convert и поиск по progressive
ничего не дал. pkg info выдаёт что установлена HTML документация. Иду в
неё, ищу по progressive, нахожу что -interlace Plane опция для этого.
Хорошо, добавляю. Я попробовал пересжать http://www.stargrave.org/photoes/fbsd-45.webp
картинку.
- convert выдал результат размером в 640019 байт
- -interlace 628200 байт
- попробовал своим привычным: cjpeg -optimize -progressive
вызовом -- 291603 байт, почти в два раза меньше!
- я не нашёл в выводе display чем эти файлы отличаются:
8-бит глубина, sRGB, interlace: JPEG, quality 75%
- пошёл гуглить как сделать маленькие по размеру JPEG-и. Нашёл только
-strip опцию, которая не помогает никак
- -optimize у cjpeg-а у меня никак на результат тоже не влияет
- убирание -progressive у cjpeg-а увеличивает файл до 304432 байт
(а у convert-а progressive наоборот увеличивает)
- так, решил сделать identify -verbose обоих файлов и diff-ом сравнить.
Оказалось что quality в convert файле был 92%! А display, ведь тот же
самый из состава того же IM-а, показывал 75%. Явно это похоже на багу
- добавил -quality 75 к convert-у и получил 290535 байт файл, даже чуть
поменьше "лучшего" результата cjpeg-а
Я вот сейчас не пытался как-то обосрать IM, но багу нашёл. Неприятно.
Прежде я ещё подумал что возможно IM и cjpeg используют разные
библиотеки для работы с JPEG-ом. Сравнил их ldd, но IM не зависит от
библиотек с "jp" в названии. Снова полез в документацию, увидел что
используется http://www.ijg.org/files/, который является libjpeg-ом. Но
мой libjpeg в системе, используемый cjpeg-ом, на самом деле
libjpeg-turbo (SIMD-оптимизированная версия). И, как оказалось,
действительно, time на convert показывает ~165мс, а на cjpeg ~95мс. Не
то чтобы мне это критично, но опять же, cjpeg в моей системе приятно
быстрее. Быстрое гугление вроде бы упоминает jpeg-turbo и IM, так что
наверное можно их совместно использовать. Поиск по turbo в исходниках
IM7 ничего не дал. Поиск по libjpeg намекает что он может использовать
системный libjpeg. Пересобрал и увидел что да, теперь зависит от libjpeg
(который turbo пакет). Попробовал time convert на нём... ~350мс -- в два
раза больше чем прежде. Дальше не хочу разбираться, а то уже квест
какой-то :-)
В общем... мне гораздо ближе и проще и удобнее Unix-way подход с
отдельными утилитами для работы с форматами/кодеками.
>А для особых эстетов есть ещё и ffmpeg.
На ffmpeg вместо mencoder я пересел в этом году
(4eda37b876957c98e77b296c33d1df0604d9397c), но всё равно по факту для
VP8/VP9 использую vpxenc "родной", в который перегоняю по pipe-у
YUV4MPEG несжатое видео. Да и прежде я аналогично кодировал в Theora
через mencoder (но он вроде просто по другому в неё и не умел). К доке
IM-а в целом у меня нет нареканий -- всё вот сейчас нашёл что искал (на
тему JPEG). А вот дока ffmpeg так себе, многое не понятно как задавать:
часто приходилось искать помощи в Интернете. Уже точно не помню, но в
theora по человечески мне не удалось ffmpeg-ом закодировать, только
через pipe во внешнюю программу. С VP8/VP9 вроде бы тоже были какие-то
проблемы. Так что и тут от промежуточных форматов никуда не деваюсь.
комментарий 2:
From: Oskar Sharipov
Date: 2020-11-06 01:42:16Z
> Собственно, вот прям сейчас я хочу посмотреть как мне сделать
> прогрессивный JPEG через convert. [...]
Ух ты. Вот это разбор. Спасибо за сравнение сложности работы с этими
утилитами.
Соглашусь, что convert сильно "сложнее", хотя и очень многое умеет.
Когда-то хотелось поиграть с WebP. Чтобы "играться" по-взрослому,
почитал гугловские документации[0], а там упоминались cwebp, dwebp и их
друзья. Попробовал их вместо привычного convert и был удивлен, что они
такие простые и удобные. Их man описывает всё, `man convert` же говорит
"открывайте html доку". Но IM, наверное, можно, он же весь такой
универсальный.
[0] https://developers.google.com/speed/webp
комментарий 3:
From: Sergey Matveev
Date: 2020-11-06 08:21:18Z
- ** Oskar Sharipov [2020-11-06 04:41]:
>Их man описывает всё, `man convert` же говорит
>"открывайте html доку". Но IM, наверное, можно, он же весь такой
>универсальный.
Я считаю что да -- IM, ffmpeg это настолько огромные по возможностям
программы, что один man это точно не стоит сувать. Можно наделать
огромную кучу man-ов (man imagemagick-formats-jpeg, или просто отдельно
imagemagick-formats отдельно описывая тему про форматы), как в zsh, git,
но это ограничит использование на не Unix-like системах, типа Windows. В
доке IM-а grep-ом я нашёл по JPEG-у прям всё что нужно (например как
задать DCT=float (для примера) и другие параметры).
Я не против HTML документации, ЕСЛИ она прилагается к программе (ну и
устанавливается, но это уже зависит от maintainer-а). А если программа
посылает тебя в Интернет, то я скорее её принципиально удалю (ok, скорее
рекурсивно wget-ом сзеркалирую сайт с документацией).
А вообще хотел тут написать про .info формат, но сделал в виде
отдельного поста: da160c3c7b3f5393aa37f2d042f9b281264273de
Недавно надо было поставить MySQL СУБД (штатно почти всю жизнь с
PostgreSQL только приходилось работать). Решил ставить его "трушный"
MariaDB форк. И для него не оказалось документации в скачиваемом виде
(пускай даже в виде одной огромной PDF-ки). Я больше суток ждал не
отзеркалирует ли мне wget его сайт, но не дождался. Плюнул и пошёл
ставить MySQL.
А вот nginx вообще уроды в этом плане. Документации ни в tarball, ни на
сайте! Точнее на сайте она есть только для их последней версии. А в
GNU/Linux мире maintainer-ы ОЧЕНЬ любят не ставить документацию для
программ и было очень "здорово" оказаться в ситуации когда у меня не
самый свежий nginx (на одной рабочей системе -- дома и в личных проектах
я никогда nginx не использовал), доки в системе нет (это ж GNU/Linux
дистрибутив) и на сайте нет. А там очень многие параметры меняются,
устаревают, и т.д..
Сгенерирован: SGBlog 0.34.0