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


>Так есть же 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
картинку.


  вызовом -- 291603 байт, почти в два раза меньше!

  8-бит глубина, sRGB, interlace: JPEG, quality 75%

  -strip опцию, которая не помогает никак

  (а у convert-а progressive наоборот увеличивает)

  Оказалось что quality в convert файле был 92%! А display, ведь тот же
  самый из состава того же IM-а, показывал 75%. Явно это похоже на багу

  поменьше "лучшего" результата 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


>Их 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