Jump to content

    

Сжать битовое представление больших текстовых символов

На ЖКИ нужно написать большие цифры, размером, например, 48 х 30 пикселей. Многие байты в символах повторяются, и биты в байтах идут группами.
Какой алгоритм сжатия символов в шрифте здесь можно применить, попроще?

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

Share this post


Link to post
Share on other sites
12 минут назад, AlexRayne сказал:

А какой там принцип сжатия? Что-то с наскоку не откопал.
Например. Для одной строки растра символа задаётся начальный бит - 0 или 1, затем количество идущих подряд нулей или единиц, затем количество идущих подряд единиц или нулей, и т.д.

Share this post


Link to post
Share on other sites
2 часа назад, ViKo сказал:

На ЖКИ нужно написать большие цифры, размером, например, 48 х 30 пикселей. Многие байты в символах повторяются, и биты в байтах идут группами.
Какой алгоритм сжатия символов в шрифте здесь можно применить, попроще?

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

10 цифр, 6*30*10 = 1800 байтов. Вряд ли вы сможете сэкономить столько, чтобы отбить затраты кода на обработку сжатия :-)

Share this post


Link to post
Share on other sites
2 часа назад, ViKo сказал:

Какой алгоритм сжатия символов в шрифте здесь можно применить, попроще?

Если не заморачиваться с битами, то самое простое Кодирование длин серий (англ. run-length encoding, RLE)
 

2 часа назад, ViKo сказал:

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

Компактней будет таблица длин символов в начале фонта и вычисление смещений.

Share this post


Link to post
Share on other sites

48 x 4 x 10 = 1920
Потому и предполагаю примитивный алгоритм.

Кстати, да, если хранить символы боком, то там более длинные повторяющиеся последовательности.

 

Закодировать каждую строку символа (4 байта, в моём случае) одним байтом. Или столбец. 256 комбинаций с запасом хватит на все варианты начертания. Только таблица кодировки памяти потребует.

Ага. Собирать символы из примитивов - строк или столбцов. Или из кубиков. :biggrin:

Share this post


Link to post
Share on other sites

Закодировать кубики 4 x 4 одним байтом. Хватит одного байта, наверное? Тогда на символ потребуется 96 кубиков вместо 192 байтов.

Share this post


Link to post
Share on other sites

Если цифры "красивые" - унифицировать кривые, цифра сперва отрисовывается грубо, "квардатми-прямоугольниками", затем на нее дорисовываются изгибы (возможно, 4 шт, или вообще 1 в режиме зеркало/переворот). Напр. шрифт 5*8 масштабировать до требуемого, затем добавить стандартные кривые.

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

Share this post


Link to post
Share on other sites
29 минут назад, ViKo сказал:

Закодировать каждую строку символа (4 байта, в моём случае) одним байтом. Или столбец. 256 комбинаций с запасом хватит на все варианты начертания. Только таблица кодировки памяти потребует.:biggrin:

"Строка символа" - это как я понимаю - строка пикселей по ширине равная ширине символа?

Если так, то можно:

1. Подсчитать сколько всего таких 4-х-байтовых строк пикселей есть во всём шрифте (будет == число_символов_в_шрифте * число_строк_пикселей_в_символе (или высота символа по X)).

2. Подсчитать сколько из них уникальных (вычтя все повторяющиеся).

3. Составить таблицу (M) из уникальных строк пикселей.

4. Каждый символ описать не как массив строк пикселей, а как массив индексов таблицы M.

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

Share this post


Link to post
Share on other sites
21 минуту назад, ViKo сказал:

Закодировать кубики 4 x 4 одним байтом. Хватит одного байта, наверное? Тогда на символ потребуется 96 кубиков вместо 192 байтов.

Не забывайте, что при подстановочном сжатии вам все равно словарь хранить нужно (те самые кубики).

Share this post


Link to post
Share on other sites

Или другой алгоритм (будет эффективен если символы действительно большие с толстыми линиями):

1. Записать каждую строку пикселей как последовательность: количество сплошных 0-й, количество сплошных 1-ц, количество сплошных 0-й, количество сплошных 1-ц, ...

2. Запаковать получившуюся строку в одно слово (16 бит).

Share this post


Link to post
Share on other sites
4 минуты назад, jcxz сказал:

Или другой алгоритм (будет эффективен если символы действительно большие с толстыми линиями):

1. Записать каждую строку пикселей как последовательность: количество сплошных 0-й, количество сплошных 1-ц, количество сплошных 0-й, количество сплошных 1-ц, ...

2. Запаковать получившуюся строку в одно слово (16 бит).

jcxz, вы молодец! В первом вашем сообщении описали то, к чему я сейчас склоняюсь.
А второе сообщение описывает идею, мною же описанную выше.
В общем, ход мыслей правильный! :drinks:

33 минуты назад, k155la3 сказал:

Если цифры "красивые" - унифицировать кривые.

Да, будут красивые. У меня всё красивое. 
Но только растровые. Закодирую растровыми строками. Повторяющихся будет много. 

26 минут назад, Baser сказал:

Не забывайте, что при подстановочном сжатии вам все равно словарь хранить нужно (те самые кубики).

Помню, помню.

Share this post


Link to post
Share on other sites
19 минут назад, ViKo сказал:

В общем, ход мыслей правильный! :drinks:

Ну дык - здесь не так уж много вариантов. Если учитывать что ресурсы ограничены (МК).

Можно ещё использовать комбинацию этих методов. Очевидно, что метод 2 проигрывает если по горизонтали в символе часто происходит изменение бита. Например - на буквах Ш/Щ будет до 7-и членов в последовательности. И тогда может и не влезть всё в 16-битное слово. В таких случаях комбинирование методов 1 + 2 решает проблему: те символы, где чередований мало и всё влазит в 16 бит, сжимаем по алгоритму 2. Оставшиеся - по алгоритму 1. И например старший бит результирующего слова будет указывать какой метод использовался для сжатия данной строки пикселов.

Share this post


Link to post
Share on other sites

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

А здесь смотрю начертания:
https://ux.pub/luchshie-besplatnye-shrifty-dlya-raboty-s-chislami-i-dannymi/

Share this post


Link to post
Share on other sites
5 hours ago, ViKo said:

На ЖКИ нужно написать большие цифры, размером, например, 48 х 30 пикселей. Многие байты в символах повторяются, и биты в байтах идут группами.
Какой алгоритм сжатия символов в шрифте здесь можно применить, попроще?

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

Вот такой символ 
image.thumb.png.32dfd7eb11999188829a021787d3940b.png

pkzip сожмет в два раза с 288 байт до 135. 
И маленький скромный алгоритм sixpack сожмет до 139 

А RLE наоборот раздует код до 426 байт. Вот тут можно проверить - https://eleif.net/rle.html
Дамп вот такой - 

Spoiler

const uint8_t test_sym[] = {
        0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x01,
         0x00, 0x00, 0xF8, 0x03, 0x00, 0xFF, 0x07, 0x00, 0x00, 0xFE, 0x1F, 0xC0, 0xFF, 0x1F, 0x00, 0x00, 0xFF, 0x3F, 0xE0, 0xFF, 0x3F,
         0x00, 0x80, 0xFF, 0x7F, 0xF0, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF,
         0x00, 0xF0, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
         0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0x03, 0xF8, 0x1F, 0xFE, 0x7F, 0x00, 0xFF,
         0x03, 0xFC, 0x07, 0xFC, 0x3F, 0x00, 0xFE, 0x07, 0xFC, 0x07, 0xF8, 0x1F, 0x00, 0xFC, 0x07, 0xFC, 0x03, 0xF8, 0x1F, 0x00, 0xFC,
         0x07, 0xFC, 0x03, 0xF0, 0x3F, 0x00, 0xF8, 0x07, 0xFC, 0x03, 0xF0, 0x3F, 0x00, 0xF8, 0x07, 0xFC, 0x03, 0xF0, 0x3F, 0x00, 0xF8,
         0x07, 0xFC, 0x03, 0xE0, 0x7F, 0x00, 0xF8, 0x07, 0xFC, 0x03, 0xE0, 0x7F, 0x00, 0xF8, 0x07, 0xFC, 0x03, 0xE0, 0xFF, 0x00, 0xF8,
         0x07, 0xFC, 0x07, 0xC0, 0xFF, 0x00, 0xFC, 0x07, 0xFC, 0x0F, 0xF0, 0xFF, 0x01, 0xFC, 0x07, 0xF8, 0x1F, 0xFC, 0xFF, 0x01, 0xFE,
         0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
         0x03, 0xF0, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x01, 0xF0, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x01, 0xE0, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF,
         0x00, 0xE0, 0xFF, 0x3F, 0xFC, 0xFF, 0x7F, 0x00, 0xC0, 0xFF, 0x3F, 0xF8, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x1F, 0xF0, 0xFF, 0x3F,
         0x00, 0x00, 0xFF, 0x07, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0x01, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x01,
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // Code for char 8
        };

 


Так что не ведитесь на RLE и им подобные. 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now