[О блоге] [наверх] [пред] [2020-11-05 12:28:32+03:00] [71870b1510dfc2727093f2767b994b8596f9b163]
Темы: [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
    дистрибутив) и на сайте нет. А там очень многие параметры меняются,
    устаревают, и т.д..