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

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

03 апреля 2023

Изображения в формате RGB565

Все статьи по данной игровой консоли - по тегу G-BASIC


Примененный в G-Basic Console дисплей оперирует 18- или 16-битным цветом. 18-битный цвет - по 6 бит на каждую компоненту RGB хранить неудобно. Поэтому для простых применений дисплей поддерживает работу с 16-битным цветом - на компоненту G отводится по прежнему 6 бит, а на компоненты R и B - по 5 бит. Коротко такой формат обозначается RGB565. 

Соответственно, вся работа с изображениями и цветом в консоли идет в 16-битном формате. Как задание цвета для пера, так и хранение спрайтов в памяти консоли. Для легкой и быстрой работы с изображениями было принято решение хранить в файлах преобразованные к 16-битному цвету изображения.

Ниже - описание формата файла и утилиты конвертации изображений в такой файл.

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

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

Представление значений - 16-битное слово.

Фрагмент такого файла:


Первые 2 байта - ширина - 0x0032 = 50 пикселей
Вторые 2 байта - высота - 0x003C = 60 пикселей
Далее - 50 слов (100 байт) - цвета первой строки пикселей.
Далее вторая строка и т.д.

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

Так же, при загрузке изображений в память (в массив) следует учитывать объем доступной оперативной памяти - это 59000 байт за вычетом статических и временных переменных.

Объем доступной памяти ("кучи") виден при компиляции программы:

Доступную память используют все объявляемые массивы , а так же строки (которые по своей сути тоже одномерные массивы). 

Программа для кодирования изображений.

Для конвертации изображений в понятный G-Basic-у формат написана простая программа.

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

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


Программу можно взять тут.

Немножко о преобразованиях 24-битного цвета в 16-битный и обратно.[1]

Преобразование 24 битного цвета в 16-битный.

Самое простое преобразование - это сдвиг значения цвета вправо с потерей 2 или 3 бит значения:

r5 = r8 >> 3;
g6 = g8 >> 2;
b5 = b8 >> 3;

Это не всегда корректное, но самое простое и быстрое преобразование.

Правильная формула преобразования для канала с из формата X в Y выглядит следующим образом:
cY = cX * max(cY)/max(cX)

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

Но в любом случае такое преобразование - это преобразование с потерями, поскольку уменьшается глубина цвета.

Преобразование 16-битного цвета в 24-битный

Можно попробовать выполнить обратное преобразование простым сдвигом:

r8 = r5 << 3;
g8 = g6 << 2;
b8 = b5 << 3;

Но получится фигня. Следим за руками:

24-битный белый: (255, 255, 255) преобразовываем в 16-битный:

r5 = r8 >> 3 = 255 >> 3 = 31
g6 = g8 >> 2 = 255 >> 2 = 63
b5 = b8 >> 3 = 255 >> 3 = 31

И преобразовываем обратно: 

r8 = r5 << 3 = 31 << 3 = 248
g8 = g6 << 3 = 63 << 2 = 252
b8 = b5 << 3 = 31 << 3 = 248

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

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

Есть вариант табличного преобразования - у нас всего 32 значения для R и B-компонент и 64 значения  для G-компоненты цвета:

Table5 = {  0,   8,  16,  25,  33,  41,  49,  58,  66,  74,  82,  90,  99, 107, 115, 123,
         
 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255};

Table6 = {  0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  45,  49,  53,  57,  61,
         
  65,  69,  73,  77,  81,  85,  89,  93,  97, 101, 105, 109, 113, 117, 121, 125,
          130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190,
          194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255};

r8 = Table5[r5];
g8 = Table6[g6];
b8 = Table5[b5];

Метод быстрый, простой, но требует 96 байт для массивов)) На современных МК это ну вообще не проблема.

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

r8 = ( r5 << 3 ) | (r5 >> 2);
g8 = ( g6 << 2 ) | (g6 >> 4);
b8 = ( b5 << 3 ) | (b5 >> 2);

Этот способ при преобразовании RGB565 в RGB888 дает незначительную погрешность относительно математического преобразования. Способ тоже быстрый и не требует вычислений с плавающей запятой.

[1] tune it - Преобразование RGB888 <-> RGB565


3 комментария:

  1. Анонимный18 апреля, 2023 18:46

    JPEG на мк не приходилось декодировать? Пробовал 2 либы Elm Chan, так и не смог их запустить.

    ОтветитьУдалить

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