Сводный список записей блога

--->>>> Сводный список записей блога <<<<---

21 октября 2022

Инструмент сжатия изображений


Маленькая новость. Возможно, у меня появится соавтор. Обсуждение пары моих устройств вылилось в более широкое общение. И обмен идеями возродил одну старую задумку. Во всяком случае, эту идею коллега сейчас обдумывает и, возможно, обкатает на большом ПК.

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

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


Исходное изображение должно содержать в себе не более 256 цветов. И не должно быть более 255х255 пикселей. Ну вот такие вот ограничения. Для подготовки небольших растровых изображений достаточно.

Программа позволяет выбрать глубину цвета 1,2,3 или 4 бита и , если в изображении больше цветов, сопоставить лишние с выбранными 2,4,8, или 16 цветами.

Далее, изображение может быть просто закодировано с выбранным количеством бит на пиксель либо сжато по алгоритму RLE с настраиваемыми длинами серий.

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

Изображение загружается из буфера обмена, кнопкой "Вставить из буфера" в верхнем левом углу.
Там же можно выбрать масштаб отображения.

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

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

Возьмем вот такую картинку.

Она же, но побольше.

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

Для этого и нужна таблица подбора цветов. 

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


Слева, по вертикали, представлены все цвета из изображения - их может быть до 256.

Основные цвета можно выбрать и слева, нажав на клеточке с цветом правую кнопку мыши


После выбора всех основных цветов необходимо выполнить сопоставление остальных цветов с основными.


В таблице для сопоставленных цветов в ячейке на пересечении отрисовывается 2 прямоугольничка - с исходным и с основным цветом. Для не сопоставленных - все столбцы таблички заполнены основными цветами, для удобства поиска наиболее близкого цвета. 

Клик левой кнопкой мыши на пересечении исходного и основного цвета сопоставляет их.
Клик левой кнопкой мышки по исходному цвету (там где мы правой кнопкой выбирали основной)  - отменяет сопоставление.


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

После сопоставления всех цветов получится что то вот такое:


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

После сопоставления всех цветов в правой нижней части окна программы появляются данные закодированного изображения в виде константного массива на языке Си.


Здесь можно выбрать параметры формирования данных - модификаторы PROGMEM или __flash для AVR-контроллеров, имя переменной... Для монохромных дисплеев, где фон белый, а пиксель черный - есть переключатель инверсной палитры.

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

Количество пикселей и размер получившегося кода отображаются в правой верхней части блока "Код изображения". Пользуясь этими данными можно выбрать оптимальный метод сжатия и, в случае RLE-сжатия - подобрать длины последовательностей для минимального размера блока данных.

Так, кодирование 3 бита на цвет без сжатия вышеприведенную картинку 129 х 46 = 5934 пикселей ужимают в 2245 байт. 

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

Для вышеприведенной картинки при 7 битах на последовательность одинаковых пикселей и 6 битах на поток разных цветов удалось достичь результирующего размера изображения в 598 байт. Против 2245 байт при кодировании без сжатия. Почти в 4 раза.

Форматы данных для описания сжатых изображений

Утилита сжатия изображений "заточена" на форматы, применяемые в моей графической библиотечке.

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

Кодированное изображение без сжатия имеет следующий формат:

Заголовок - 3 байта.

Байт №1: ColorInfo0bCCPPTTTT

2 бита CC: Цветность: 00: 1 бит/пиксель 
01: 2 бита/пиксель
10: 3 бита/пиксель
11: 4 бита/пиксель

2 бита PP: Наличие и формат палитры цветов:
00: Нет палитры
01: 1R-1G-1B
10: 2R-2G-2B
11: 5R-6G-5B

4 бита TTTT: Индекс прозрачного цвета.

Байт №2: SpriteSize W: Ширина - 1..255 пикселей

Байт №3: SpriteSize H: Высота - 1..255 пикселей

Палитра. 

Если палитра отсутствует, то сразу после заголовка идут данные.
Иначе - перед данными будет сохранена палитра - 1 или 2 байта на цвет, по количеству цветов - 2, 4, 8 или 16 цветов.

Формат представления цвета в палитре:
1R-1G-1B - 1 байт : 0b00000RGB
2R-2G-2B - 1 байт: 0b00RRGGBB
5R-6G-5B - 2 байта: 0bRRRRRGGG GGGBBBBB

Если кратко, то размер палитры = 0/1/2  байта на цвет * 2/4/8/16 цветов

Данные. После палитры или, если палитра не задана, сразу после заголовка идут данные изображения. Их количество определяется размером изображения и числом бит на пиксель.

Кодированное изображение с RLE-сжатием имеет следующий формат:

Заголовок - 4 байта.

Байт №1: ColorInfo0bCCPPTTTT

2 бита CC: Цветность: 00: 1 бит/пиксель 
01: 2 бита/пиксель
10: 3 бита/пиксель
11: 4 бита/пиксель

2 бита PP: Наличие и формат палитры цветов:
00: Нет палитры
01: 1R-1G-1B
10: 2R-2G-2B
11: 5R-6G-5B

4 бита TTTT: Индекс прозрачного цвета.

Байт №2: Количество бит на размеры последовательностей : 0b00SSSDDD

3 бита SSS - размер данных для длины последовательности одного цвета:
000 - 2 бита
001 - 3 бита
...
111 - 9 бит

3 бита DDD - размер данных  для длины потока разных цветов:
000 - 2 бита
001 - 3 бита
...
111 - 9 бит

Байт №3: SpriteSize W: Ширина - 1..255 пикселей

Байт №4: SpriteSize H: Высота - 1..255 пикселей

Палитра. 

Если палитра отсутствует, то сразу после заголовка идут данные.
Иначе - перед данными будет сохранена палитра - 1 или 2 байта на цвет, по количеству цветов - 2, 4, 8 или 16 цветов.

Формат представления цвета в палитре:
1R-1G-1B - 1 байт : 0b00000RGB
2R-2G-2B - 1 байт: 0b00RRGGBB
5R-6G-5B - 2 байта: 0bRRRRRGGG GGGBBBBB

Если кратко, то размер палитры = 0/1/2  байта на цвет * 2/4/8/16 цветов

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

Где это всё взять?

Комментариев нет:

Отправить комментарий

======= !!! ВНИМАНИЕ !!! ======================================================================
Гугл умный и боится спама. Поэтому иногда ваши комментарии Гугл отправляет мне на премодерацию. Отправлять или нет - решаю не я, а алгоритмы Гугла. Если ваш комментарий не появился сразу, значит я получу уведомление и опубликую ваш комментарий через некоторое время. Я стараюсь это делать достаточно оперативно.