LINUX.ORG.RU

Новый формат изображений быстрее PNG в десятки раз

 , , , qoi

Новый формат изображений быстрее PNG в десятки раз

6

3

Доминик Саблевски представил новый и невероятно простой в реализации формат изображений QOI (Quite OK Image). По представленным тестам, при сжатии изображений QOI производительнее PNG в 20–30 раз, а при распаковке — в 3–4 раза.

Доминик признаётся, что не является экспертом в области сжатия изображений. Идея создать новый простой и эффективный формат изображений пришла к нему во времена работы с MPEG-1. Его целью была скорость и простота.

Файлы QOI больше по размеру, чем PNG на 10–50 % в зависимости от картинки, поэтому QOI стоит применять, когда необходима скорость.

Исходный код на C, состоящий из одного универсального файла, доступен на GitHub.

В данный момент формат проходит обсуждение финальной спецификации с заинтересованными пользователями.

Также доступны реализации на Zig, Rust, Go, TypeScript, Python, C#. Поддержка QOI добавлена в библиотеку SAIL.

Для пользователей Arch Linux в AUR доступен пакет qoi-git.

>>> Замеры скорости и размеров изображений

>>> Подробности

★★★

Проверено: Shaman007 ()
Последнее исправление: sudopacman (всего исправлений: 2)
Ответ на: комментарий от anonymous

Сначала, за то, что ты спрыгивашь. Потом, за память. Если помнишь, с этой темы ты тоже спрыгиваешь в данный момент. Вскукорек про память твой меня позабавил. Сперва это.

anonymous
()
Ответ на: комментарий от anonymous

Сначала, за то, что ты спрыгивашь.

Слышь, космонавт. Я не собираюсь запрыгивать к тебе в космолет. Лучше сам спрыгивай. На «20х» не спрыгивай, иначе жопа сгорит.

anonymous
()
Ответ на: комментарий от anonymous

Вскукорек

Какой-то неграмотный лжецарь попался.

anonymous
()
Ответ на: комментарий от annulen

во времена популярности 16-битных консолей, то он скорее всего был бы успешен

Если бы его полностью переделать. Под низкие разрешения. Под ограниченную палитру. Впрочем, и это бы тоже его не спасло, памяти у приставок было столь мало, что тратить её под распаковку позволить никто не мог, все использовали несжатые спрайты прямо из ROM, без задействования RAM.

быстро их распаковывать

Но по скорости обработки он не то, чтобы вау-вау быстрее. И это в сравнении с достаточно сложным png. В те годы были и существенно более быстродекодируемые форматы, оптимизированные под небольшие изображение с низким количеством цветов.

gremlin_the_red ★★★★★
()
Ответ на: комментарий от gremlin_the_red

Впрочем, и это бы тоже его не спасло, памяти у приставок было столь мало, что тратить её под распаковку позволить никто не мог, все использовали несжатые спрайты прямо из ROM, без задействования RAM.

Кстати да, даже у мощной N64 было всего 4 метра из коробки и 8 с расширением, какой уж тут кэш картинок

annulen ★★★★★
()

Новый формат изображений быстрее PNG в десятки раз

Ну и наqoi?

eternal_sorrow ★★★★★
()
Ответ на: комментарий от Vit

значит надо сначала загнать PNG [например] в такой же убогий режим как у qoi.

$ time pnmtopng -compression 1 djvul.x4.ppm > djvul.x4.1.png

real    0m0,681s
user    0m0,665s
sys     0m0,016s

$ time ./qoiconv djvul.x4.1.png djvul.x4.1.qoi

real    0m0,345s
user    0m0,318s
sys     0m0,017s

$ ls -s1
 6600 djvul.x4.1.png
 8392 djvul.x4.1.qoi
36916 djvul.x4.ppm
anonymous
()
Ответ на: комментарий от anonymous

time

$ time ./iz c djvul.x4.ppm djvul.x4.iz

real    0m0,160s
user    0m0,116s
sys     0m0,008s

$ ls -s1
 6440 djvul.x4.iz
36916 djvul.x4.ppm
anonymous
()

Как промежуточный формат в пайплайне, звучит годно. Сравнивать с форматами для веба, ну это надо иметь особо запущенную стадию аутизма

anonymous
()
Ответ на: комментарий от anonymous

Это изображение неслабо так увеличивается в размере

Image poloski.png 8.8 KiB
QUI encoding  181ms to 2.0 MiB, decoding   31ms
PNG encoding   52ms to 8.4 KiB, decoding   27ms

Оригинальное сжатие. 8 кило превращаются в 2 метра. Скорость тоже впечатляет.

anonymous
()
Ответ на: комментарий от anonymous
Image poloski.png 7.9 MiB
QOI encoding  155ms to 2.0 MiB, decoding   21ms
PNG encoding   48ms to 8.4 KiB, decoding   25ms

Вообще если сравнивать размер изображения как 4 байта на точку. То как-то так. А то получается что сравнивается PNG с QUI и с другим PNG.

anonymous
()
Ответ на: комментарий от anonymous

как-то так

Чо то после реальных тестов все «истинно верующие» куда то разбежались. Однако.

anonymous
()

QOI производительнее PNG в 20–30 раз

А местные бенчи показывают, что это фуфло. Это как?

anonymous
()

херня. вот @metaprog на метапроге перепишет будет в 100 раз быстрее

anonymous
()

Не взлетит. На него QOI положили

peregrine ★★★★★
()
Ответ на: комментарий от anonymous

Стандартный level 1 - всё еще недостаточно убого. Хотя для демонстрации кривизны оригинальных бенчмарков достаточно.

Специально для картинок, в дефлейте надо сканить (и искать повторы) по 4 байта, а не побайтно. И глубину скана тоже можно ограничить. Но это не со стандартной библиотекой.

Vit ★★★★★
()
Ответ на: комментарий от andreik

Они же оба с потерями и жмут естественно лучше в разы.

Не «жмут», а «фильтруют».

«Понаберут по объявлению».

anonymous
()
Ответ на: комментарий от anonymous

Можешь попробовать пережать тестовый png (который гонишь в qoi) с level0. Тогда точно не будет особых потерь на распаковке, хотя фик знает что с чтением с диска.

И непомню уже, можно ли в PNG вырубить префильтры, или хотя бы поставить самый тупой.

Vit ★★★★★
()
Ответ на: комментарий от Vit

с level0

Упирается в диск. Поэтому с level1 шустрее.

anonymous
()
Ответ на: комментарий от Vit

А можешь присоветовать куда копать про сжатие фонтовых глифов? Это буковки, в основном высотой 12-32 пикселя. Чернобелые с антиалиасингом.

Если упарываться с максимальным сжатием, и при том, что антиалиасинг вы как-то сделаете на лету, а сжимать надо монохромные ‘силуэты’ букв aka глифы, максимального сжатия можно достичь представляя глифы цепным кодом, и кодируя цепной код арифметическим кодером.

Есть мексиканский товарищ (Ernesto Bribiesca), который в этой науке сильно преуспел: https://www.sciencedirect.com/science/article/abs/pii/S0031320398001320 (это ссыль на одну из первых работ, дальше он развивал идею и на 3д итд.)

Если в двух словах, то модифицированный цепной код предложенный товарищем пожатый арифметическим кодером в разы уделывает jbig2 (в котором для словаря символов используется 2-мерный монохромный контекст в комбинации с арифметическим кодированием).

А вообще, для глифов, даже растровых выбор представления обычно диктуется контекстом применения. Если сильно надо экономить память и рендер-код с декодером сжатого потока занимает мало, то можно советовать цепные коды.

Если нужно делать операции посложнее, например кросс-корелировать, усреднять «форму» глифа на множестве «похожих», или там признаки считать для распознавания - то не нужно упарываться с максимальным сжатием, так как реализация операций над сжатым представлением будет тормозить.

Имею опыт реализации велосипедного хранения глифов в виде похожем на RLE: Набор троек вида {x, y, stripe_len} ну и адаптивный выбор представления троек вида горизонтальные или вертикальные, в зависимости от того, которых меньше. Для подсчета признаков в распознавалке работало хорошо, в рендерилке - тоже неплохо.

Если еще чуть более упороться, можно вместо «линий» искать оптимальное покрытие глифа прямоугольниками, но линии проще.

Можно сжатыми битмапами хранить, как в jbig2.

Кажется, мы с вами на эту тему «куда копать про сжатие фонтовых глифов» уже общались.

nikitos ★★★
()
Ответ на: комментарий от nikitos

Там на входе растровая картинка, с 3 битами на пиксель. Надо сжать, чтобы потом на чахлой железке просто разматывать, не напрягаясь.

Проблема в том, что сама картинка мелкая, и битов на пиксель мало. Негде особо развернуться. Можно рассчитывать на несколько особенностей:

  • картинки достаточно «прореженные» (не рандомный шум из пикселей)
  • промежуточные значения только по краям контуров
  • обычно букв все-таки «много», можно попробовать сделать общий алфавит

максимального сжатия можно достичь представляя глифы цепным кодом, и кодируя цепной код арифметическим кодером.

Это как у змейки, когда сигналим куда поворачивать? Идея интересная, но для эмбедов распаковывать тяжеловато будет.

Vit ★★★★★
()
Ответ на: комментарий от Vit

для эмбедов распаковывать тяжеловато будет.

CCITT Group 4 потянут. А антиалиасинг имитировать на базе схемы разбора соседних пикселей scale2x и scale3x.

anonymous
()
Ответ на: комментарий от anonymous

Имитация антиалиасинга не в кассу. Соответственно, CCITT Group 4 тоже пролетает, т.к. он только про бинарные картинки.

И еще, я бы предложил сначала прочитать уже существующую спеку https://github.com/lvgl/lv_font_conv/blob/master/doc/font_spec.md#compression-algorithm, и уже по ней писать каких принципов сжатия там может не хватать.

Vit ★★★★★
()
Ответ на: комментарий от Vit

Имитация антиалиасинга не в кассу.

Ну так оставляй как есть. Не сжимай. Зачем мучить жопу?

anonymous
()
Ответ на: комментарий от anonymous

Слухай, я спрашивал как сжимать, а не как жить. Найди кого-нибудь другого за жизнь трещать, если по сути вопроса ничего интересного нет.

Vit ★★★★★
()
Ответ на: комментарий от anonymous
  1. По ответам не похоже, чтобы ты вникал в специфику и вникал в то что уже сделано, т.к. предложил то что не подходят и то что смотрят/отбрасывают в первую очередь.
  2. Ты просто кинул умное название «CCITT Group 4», не сказав, что конкретно оттуда должно помочь.

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

Vit ★★★★★
()
Ответ на: комментарий от sandler2

png формат поддерживает анимацию (обычно это называется apng). А эта штука?

Да, есть. Называется aqoi. Только его одновременно и ещё, и уже никто не сделал.

anonymous
()
Ответ на: комментарий от sandler2

А эта штука?

Да всё поддерживает. И даже более того. Супер шняга. Или ты тред не читал? :)

anonymous
()
Ответ на: комментарий от anonymous

Попрыгунья стрекоза лето красное пропела, оглянуться не успела, как PNG светит в глаза.

anonymous
()
Ответ на: комментарий от Vit

Там на входе растровая картинка, с 3 битами на пиксель.

3 бита на пиксель можно представлять как 3 монохромные картинки-слоя с 1 битом на пиксель.

Если использовать код Грея для перехода от значений интенсивности к выяснению значения бита в каждом из 3х битовых слоёв, то и слои эти нешумные получатся, не «соль с перцем», а достаточно большие связные области.

nikitos ★★★
()
Ответ на: комментарий от anonymous

Как промежуточный формат в пайплайне, звучит годно.

Упс! КУЙ не поддерживает пайп. :(

anonymous
()
Ответ на: комментарий от nikitos

Я встречал на researchgate.net много работ, где картинки режут на слои (по цветам или по битам). А ты уверен вообще что движение в сторону однобитовых пикселей это хорошая идея? Чем меньше битов, тем гиморнее кодить по-моему.

  • Это же не факс, где длинные белые линии, которые можно обратно в байты утоптать. Это глифы букв, там типовой размер 16*12, и ширина *3 если субпиксельное сглаживание. Причем хранится только bounding box, без белых полей.
  • Можно резать картинку на битовые плоскости, если алгоритм заточен под однобитовые картинки, но мне кажется что однобитные алгоритмы довольно ущербные by design.
  • IMHO профит от битовой нарезки довольно сомнительный. По размеру хорошо если 20% выгадать, а распаковка замедлится в разы.

Может вместо нарезки на слои двинуть куда-то в сторону общего словаря энтропии для всех глифов?

Vit ★★★★★
()

Меня одного аж корежит от использования слова «формат»? Он там что действительно считает что достаточно переизобрести упаковку и это будет нужно кому-то? Почему не Bitmap? Там упаковка донельзя простая: заголовок и масив даных. В чем изобретение то? Зачем вообще пиарить это? Это ж фактически HelloWorld. Давайте каждый свой HelloWorld пиарить направо и налево.

FeyFre ★★★★
()
Ответ на: комментарий от Vit

А ты уверен вообще что движение в сторону однобитовых пикселей это хорошая идея?

Зависит от контекста применения, если тут всего 3 бита - то вполне может выстрелить.

типовой размер 16*12, и ширина *3 если субпиксельное сглаживание

Так одна ‘строка’ картинки влазит в 1 uint16_t, если совсем-по тупому битмапой кодировать (ну или в 3 uint16_t).

мне кажется что однобитные алгоритмы довольно ущербные by design.

Это от недостатка опыта, и наверно от влияния модных тенденций что «байто#бство это некруто, а бито- тем более». Есть хорошие академические примеры 1-битных алгоритмов, которые в идеологии SIMD работают, тоесть словами по 32 бита фигачат, получается быстрее чем у всех, и сильно экономно по памяти, и например очень круто ложится на GPU.

Вообщем мудоханье с битами часто похоже на оптимизацию логики в схемотехнике, и бывает так что одну задачу с картинками можно свести к задаче минимизации булевых функций. Примером такой связи является реализация фильтров над 1-битной картинкой в этом DWA-варианте от лептоники.

Даже дед Кнут проникся, и в 4м томе есть упоминание :)

XEROX-ы начинали с этого. Если интересно разбираться - то сюда: http://www.leptonica.org/binary-morphology.html http://www.leptonica.org/border-rep.html

Битовую нарезку на слои порекомендовал, так как это первое что рекомендуется в талмуде Соломона (David Solomon A guide to Data Compression methods). Есть и русский перевод «Сжатие данных, изображений и звука».

Да и вообще есть же https://compression.ru/download/ явно лучше чем researchgate в данном вопросе :)

nikitos ★★★
()
Последнее исправление: nikitos (всего исправлений: 1)
Ответ на: комментарий от nikitos

Зависит от контекста применения, если тут всего 3 бита - то вполне может выстрелить.

Ну фик знает, если на глаз, то профит от слоев - затухающая геометрическая прогрессия. То есть, там будет в пределе полтора-два раза, при сильно попутном ветре и положении звезд, которые сходятся раз в сто лет. Это очень скромно. Хотелось бы начать с методов, где вероятен профит 5-10 раз.

мне кажется что однобитные алгоритмы довольно ущербные by design.

Это от недостатка опыта. Есть хорошие академические примеры 1-битных алгоритмов, которые в идеологии SIMD работают, тоесть словами по 32 бита фигачат, получается быстрее чем у всех, и сильно экономно по памяти.

Я не про скорость, а про саму суть. Однобитные алгоритмы обычно основаны на наличии длинных серий, чтобы свернуть все обратно в повторяющиеся байты [ 00 / FF ] и [ остальное ]. Для листа бумаги такие серии найдутся, для мелкого глифа - нет.

Это конечно сильно утрировано. Но по смыслу - чем меньше в картинке битов, тем меньше шансов у алгоритма «разогнаться».

Единственное что в голову приходит - разделить эту проблему между всеми глифами. То есть, сделав общий словарь [чего-то]. Но это пока только на уровне ощущений, и в рамках того что я знаю. Может есть какие-то другие принципы.

типовой размер 16*12, и ширина *3 если субпиксельное сглаживание

Так одна ‘строка’ картинки влазит в 1 uint16_t, если совсем-по тупому битмапой кодировать (ну или в 3 uint16_t).

Лучше не думать в таких терминах. Есть базовый размер глифа («высота похожа для большинства глифов»). А реальная картинка может быть любой ширины, и даже по высоте за пределы вылазить.

Поэтому проще всегда задавать размер и смещение битмапа. Это заодно отсекает белые поля. И еще в заголовке фонта указывается размерность чисел, которые задают габариты и смещение.

Да и вообще есть же https://compression.ru/download/ явно лучше чем researchgate в данном вопросе :)

Посмотрю, спасибо.

PS. Если что, тот конвертор шрифтов, на который ссылался, показывает весьма достойные результаты. Мне просто интересно понять, реально ли улучшить результат в разы. На 10-20% не интересно.

Vit ★★★★★
()
Последнее исправление: Vit (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.