перевод 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}Код: Выделить всё
unsigned long data;нужно 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)
потом data пихать так думаю в uint16_t rgb24to16a(uint32_t rgb24)
Код: Выделить всё
rgb24to16a(data);радиоэлектроника - жизнь моя...
Re:
Смотря на чем. Это под 32 бит процессор.avreal писал(а): Такой #define выглядит красиво, но работает далеко от оптимального. Двигает слишком много.
Под 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? - ведь тогда будет переполнение... годится ли такая конструкция для записи в дата со смещением без изменения 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)
Для ptr[2] >> 3 маскирование не нужно, при сдвиге вправо эти биты всё равно уйдут за край.demonchik писал(а):Код: Выделить всё
uint16_t rgb565 = ((ptr[0] & 0xF8) << 8) | ((ptr[2]&0xF8) >> 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 КБ) 312 скачиваний
радиоэлектроника - жизнь моя...
- demonchik
- Встал на лапы
- Сообщения: 94
- Зарегистрирован: Вт апр 07, 2009 13:39:13
- Откуда: одесса
- Контактная информация:
Re: перевод 24 разрядного изображения в 16 (5-6-5)
нашел тему - http://www.circuitidea.com/Article/DIY- ... 0PLUS.html
тут достаточно инфы, чтоб все получилось (по примеру делал)
тут достаточно инфы, чтоб все получилось (по примеру делал)
радиоэлектроника - жизнь моя...


