перевод 24 разрядного изображения в 16 (5-6-5)
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
перевод 24 разрядного изображения в 16 (5-6-5)
всем Котам МЯУ!!! вот получилось у мну работать с картой памяти(ATmega32, LCD LS020). решил вывести на дисплей рисунок BMP. описание нашел, откуда начинать считывать - нашел. http://jenyay.net/Programming/Bmp но вот надо преобразовать 24 бита в 16 формата 5-6-5. прошу кинуть в меня ссылкой, алгоритмом. если кинете в меня код - не обижусь)))
радиоэлектроника - жизнь моя...
Re: перевод 24 разрядного изображения в 16 (5-6-5)
#define RGB24TOLCD(val) (((val & 0x00f80000) >> 8 ) | ((val & 0x0000fc00) >> 5) |((val & 0x000000f8) >> 3))
Это если экран у тебя RGB берет. Еще BGR популярно
Это если экран у тебя RGB берет. Еще BGR популярно
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
радиоэлектроника - жизнь моя...
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
«Ну вот опять»™
Приблизительно как в теме про преобразование текста в число
Такой #define выглядит красиво, но работает далеко от оптимального. Двигает слишком много.
Вот полный функциональный аналог макроса. Почти не думая записанный не в одну строку, зато с учетом того, что часть сдвигов полезна для других:
avr-gcc -Os -c -Wa,-al=rgb.txt -mmcu=atmega32 rgb.c
Итого первая функция занимает 102 байта, вторая -- 66. И время выполнения будет приблизительно в два раза меньше (около полусотни тактов вместо около сотни). Это при компиляции на размер. Если на скорость (-O2), то размер и время первой функции не меняются. Вторая становится на два байта длиннее, зато время выполнения тактов на шесть сокращается (второй сдвиг делается не циклом на два прохода, а линейным кодом).
Листинг компилятора цепляю.
Хотя, конечно, как раз в этом месте аккуратная ассемблерная вставочка не помешала бы. Как умеет gcc -- не ломая оптимизацию С-шного кода. Причём если в ней объединить и вывод на SPI, то преобразование вообще не будет занимать времени, будет делаться во время вывода предыдущего пиксела. Так на глаз, без написания кода, это тактов пятнадцать, не больше.
Приблизительно как в теме про преобразование текста в число
Такой #define выглядит красиво, но работает далеко от оптимального. Двигает слишком много.
Вот полный функциональный аналог макроса. Почти не думая записанный не в одну строку, зато с учетом того, что часть сдвигов полезна для других:
Код: Выделить всё
#include <stdint.h>
#define RGB24TOLCD(val) (((val & 0x00f80000) >> 8 ) | ((val & 0x0000fc00) >> 5) |((val & 0x000000f8) >> 3))
uint16_t rgb24to16(uint32_t rgb24)
{
return RGB24TOLCD(rgb24);
}
uint16_t rgb24to16a(uint32_t rgb24)
{
uint16_t rgb16;
rgb24 >>= 3;
rgb16 = rgb24 & 0x1F;
rgb24 >>= 2;
rgb16 |= rgb24 & (0x3F << 5);
rgb24 >>= 3;
rgb16 |= rgb24 & (0x1F << 11);
return rgb16;
}Итого первая функция занимает 102 байта, вторая -- 66. И время выполнения будет приблизительно в два раза меньше (около полусотни тактов вместо около сотни). Это при компиляции на размер. Если на скорость (-O2), то размер и время первой функции не меняются. Вторая становится на два байта длиннее, зато время выполнения тактов на шесть сокращается (второй сдвиг делается не циклом на два прохода, а линейным кодом).
Листинг компилятора цепляю.
Хотя, конечно, как раз в этом месте аккуратная ассемблерная вставочка не помешала бы. Как умеет gcc -- не ломая оптимизацию С-шного кода. Причём если в ней объединить и вывод на SPI, то преобразование вообще не будет занимать времени, будет делаться во время вывода предыдущего пиксела. Так на глаз, без написания кода, это тактов пятнадцать, не больше.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
avreal, и все кто знает - вопрос))) есть у меня буфер обьявленный как
допустим там лежат байты
для хранения пикселя объявляю 32-разрядную переменную
тут будет {0x00000000} либо {00000000.00000000.00000000.00000000} //вроде посчитал 32)))
нужно buf[0] записать в 3-й "байт" data, buf[1] во 2-й "байт" data и buf[1] - в первый)))
правильно ли я составил конструкцию которая эту чтуку реализует?
правильно ли я понимаю свою же задачу?
Код: Выделить всё
unsigned char buf[512];допустим там лежат байты
Код: Выделить всё
{0x00, 0x00, 0x00, ... , 0x00}для хранения пикселя объявляю 32-разрядную переменную
Код: Выделить всё
unsigned long data;тут будет {0x00000000} либо {00000000.00000000.00000000.00000000} //вроде посчитал 32)))
нужно buf[0] записать в 3-й "байт" data, buf[1] во 2-й "байт" data и buf[1] - в первый)))
правильно ли я составил конструкцию которая эту чтуку реализует?
Код: Выделить всё
data=((buf[0]<<15)|(buf[1]<<7)|(buf[2]<<0));правильно ли я понимаю свою же задачу?
Последний раз редактировалось demonchik Вс авг 14, 2011 12:21:57, всего редактировалось 1 раз.
радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
радиоэлектроника - жизнь моя...
Re:
avreal писал(а):Такой #define выглядит красиво, но работает далеко от оптимального. Двигает слишком много.
Смотря на чем. Это под 32 бит процессор.
Под 8 битном, возможно, чисто на оптимизатор компилятора надеяться не стоит.
Re: перевод 24 разрядного изображения в 16 (5-6-5)
Под 8бит целесообразней функцию вобще на манипуляцию над отдельными байтами переложиь, даюе без int16
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
и вот еще интьересно - МК не будет делать смещения в file_1.buf[i]? - ведь тогда будет переполнение... годится ли такая конструкция для записи в дата со смещением без изменения file_1.buf[]?
Код: Выделить всё
uint32_t data=(((file_1.buf[0])<<15)|((file_1.buf[1])<<7)|((file_1.buf[2])<<0));радиоэлектроника - жизнь моя...
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: Re:
Хоть и там, и там есть буквы «32», всё же не оноSatyr писал(а):Смотря на чем. Это под 32 бит процессор.avreal писал(а):Такой #define выглядит красиво, но работает далеко от оптимального. Двигает слишком много.
Для АРМ-а, у которого сдвиги практически "на шару" -- согласен, тот #define неплох.demonchik писал(а):всем Котам МЯУ!!! вот получилось у мну работать с картой памяти(ATmega32, LCD LS020).
Да нужно просто правильно объяснить ему, что нужно сделать с данными. Хотя тут правильнее будет выписать на асме преобразование вместе с выводом в SPI. Маленькая функция, которая всё сильно ускорит.Satyr писал(а):Под 8 битном, возможно, чисто на оптимизатор компилятора надеяться не стоит.
Пробовал и для входа, и для выхода union из uint32_t / uint16_t и соответствующих байтовых массивов. Чтобы манипулировать байтами, а заносить в union из входного 32-битного и возвращать из union из 16-битного. Оказалось даже слегка хуже, чем вторая функция.Satyr писал(а):Под 8бит целесообразней функцию вобще на манипуляцию над отдельными байтами переложиь, даюе без int16
Думаю, лучше в цикле по пикселам побайтно по указателю вынимать отдельные цвета и нужное форимровать. Но это «вообще не тот #define», а я хотел сравнить именно «красивую» запись и ориентированную на 8-битник.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
См. выше -- лучше вообще указателем побайтно идти. Просто зная, что байты лежат в таком-то порядке.demonchik писал(а):для хранения пикселя объявляю 32-разрядную переменнуютут будет {0x00000000} либо {00000000.00000000.00000000.00000000} //вроде посчитал 32)))Код: Выделить всё
unsigned long data;
нужно buf[0] записать в 3-й "байт" data, buf[1] во 2-й "байт" data и buf[1] - в первый)))
правильно ли я составил конструкцию которая эту чтуку реализует?Код: Выделить всё
data=((buf[0]<<15)|(buf[1]<<7)|(buf[2]<<0));
Код: Выделить всё
uint8_t *ptr = buf;
for( идём по пикселам ) {
// смещениями к указателю выбираем RGB
uint16_t rgb565 = ((ptr[0] & 0xF8) << 8) | (ptr[1] >> 3); //
rgb565 |= (ptr[1] & 0xFC) << 3; // G
// выводим
// смещаем указатель на 3 байта
ptr += 3;
}Красивее это можно записать так:
Код: Выделить всё
typedef struct {
uint8_t r, g, b; // или какой там порядок в буфере
} rgb888_t;
rgb888_t *pixels = (rgb888_t*)buf; // мапим массив структур на массив байтов
for( идём по пикселам ) {
// смещениями к указателю выбираем RGB
// я не знаю, какой порядок на входе и на выходе, это так, намёк
// 16-битная переменная тут и для AVR может оказаться лучше, так как сдвиг на 8
// с большой вероятностью компилятор превратит в один mov, а вот зелёный, который
// разносится на два байта, может обработаться лучше.
uint16_t rgb565 = ((pixels->r & 0xF8) << 8) | (pixels->b >> 3);
rgb565 |= (pixels->g & 0xFC) << 3;
// выводим
// смещаем указатель на размер структуры, переходим к следующему пикселу
++pixels;
}Недостаток -- на чём-то тольще 8-битника нужно думать про упаковку структур, компилятор не должен добавлять лишних байтов в структуру для выравнивания на слово. Платформо-зависимо, так что лучше врукопашную по байтам идти.
Ну и если думать про оптимальность, то лучше rgb565 объявить как uint_fast16_t, тогда на том же ARM-е будет заведена 32-битная переменная и построен код получше.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
Думаю, лучше всего основной цикл реализовать как
Функция void out_to_lcd(uint8_t r, uint8_t g, uint8_t b); должна сразу и сдвигать и выводить в индикатор. Плюсы:
1) При смене индикатора на имеющий цвет 8/8/8 эта часть не меняется.
2) При работе через SPI можно подготовить первый байт, послать, потом двигать/маскировать данные для второго байта и послать его. Еще и ожидания готовности SPI ставить перед выводом уже готового байта. Сильно ускорит процесс.
Поначалу функцию написать «как понятно», чтобы убедиться, что все работает.
Потом уже оптимизировать, inline от C99 поможет, а может, ассемблерную вставку в ней сделать -- это по месту смотреть.
Код: Выделить всё
uint8_t *ptr = buf;
for( по пикселам ) {
out_to_lcd( ptr[2], ptr[1], ptr[0]); // или какой там порядок
ptr += 3;
}1) При смене индикатора на имеющий цвет 8/8/8 эта часть не меняется.
2) При работе через SPI можно подготовить первый байт, послать, потом двигать/маскировать данные для второго байта и послать его. Еще и ожидания готовности SPI ставить перед выводом уже готового байта. Сильно ускорит процесс.
Поначалу функцию написать «как понятно», чтобы убедиться, что все работает.
Потом уже оптимизировать, inline от C99 поможет, а может, ассемблерную вставку в ней сделать -- это по месту смотреть.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
спасиб, хлопцы за направление на путь истинный)))
радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
наверно так
Код:
действительно, расписав все по битам понял что к чему. спасибо!!!
Код:
Код: Выделить всё
uint8_t *ptr = buf;
for( идём по пикселам ) {
// смещениями к указателю выбираем RGB
uint16_t rgb565 = ((ptr[0] & 0xF8) << 8) | ((ptr[2]&0xF8) >> 3); //
rgb565 |= (ptr[1] & 0xFC) << 3; // G
// выводим
// смещаем указатель на 3 байта
ptr += 3;
}действительно, расписав все по битам понял что к чему. спасибо!!!
радиоэлектроника - жизнь моя...
- avreal
- Опытный кот
- Сообщения: 842
- Зарегистрирован: Чт дек 31, 2009 19:27:45
- Откуда: Бровари, Україна
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
demonchik писал(а):Код: Выделить всё
uint16_t rgb565 = ((ptr[0] & 0xF8) << 8) | ((ptr[2]&0xF8) >> 3);
Для ptr[2] >> 3 маскирование не нужно, при сдвиге вправо эти биты всё равно уйдут за край.
Главное, чтобы слева не вдвинулось чего не надо, но это гарантируется для беззнакового числа (заполнение нулями слева при сдвиге вправо). Так что (ptr[2] >> 3) & 0x1F тоже не нужно.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
наваял я такую чтуку
но выводит только первую строку изображения(даже верно). по коду смотрю - вроде норма(( не могу понять своего затыка.
Код: Выделить всё
void BMP_show(unsigned char x, unsigned char y, unsigned char w, unsigned char h)
{
int i;
uint16_t rgb565;
uint8_t *ptr=&file_1.buf[54];
lcd_c(0xEF90);
lcd_c(0x0504);
lcd_c(0x0800+y);
lcd_c(0x0900+y+h-1);
lcd_c(0x0A00+DISP_H-x-w);
lcd_c(0x0B00+DISP_H-x-1);
if ((res=f_open(&file_1,"0:/AMANDA.BMP",FA_READ)) == FR_OK)
do
{
res=f_read(&file_1,file_1.buf,sizeof(file_1.buf)-1,&nbytes);
for(i=0;i<(nbytes/3);i++)
{
rgb565 = (((ptr[2] & 0xF8) << 8) | ((ptr[0] & 0xF8) >> 3)); // R B
rgb565 |= (ptr[1] & 0xFC) << 3; // G
//имеем rgb565 формата RRRRRGGGGGGBBBBB 5-6-5
// выводим
lcd_d(rgb565);
// смещаем указатель на 3 байта
ptr += 3;
}
}while(res==FR_OK/*|| nbytes == sizeof(file_1.buf)*/);но выводит только первую строку изображения(даже верно). по коду смотрю - вроде норма(( не могу понять своего затыка.
Последний раз редактировалось demonchik Пн авг 15, 2011 23:28:55, всего редактировалось 3 раза.
радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
заметил что в
nbytes/3 - это только в случае если не первая итерация цикла.... в первой итерации - тогда число может быть не целое. кажется изображение будет искаженным....
Код: Выделить всё
for(i=0;i<([color=#FF4040]nbytes/3[/color]);i++) nbytes/3 - это только в случае если не первая итерация цикла.... в первой итерации
Код: Выделить всё
(nbytes-ofset)/3радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
и с do while я намутил)))
- работает)) только бы сдвиг байт бы устранить)) а так весь дисплей заливает)))
- работает)) только бы сдвиг байт бы устранить)) а так весь дисплей заливает)))
радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
свершилось чудо!!!
- Вложения
-
- DSC04711.jpg
- (158.27 КБ) 309 скачиваний
радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
нашел тему - http://www.circuitidea.com/Article/DIY- ... 0PLUS.html
тут достаточно инфы, чтоб все получилось (по примеру делал)
тут достаточно инфы, чтоб все получилось (по примеру делал)
радиоэлектроника - жизнь моя...