Сортировка палитры RGB565
- Войдите на сайт для отправки комментариев
Ср, 08/08/2018 - 09:26
Может кто подсказать пример, как можно отсортировать набор цветов RGB565, находящиеся в случайном порядке что бы он соответсвовал спектру? Я находил и пробовал применить способы преобразования в HSL (HSV) и сортировку по hue и более менее что-то приближенное получалось, но все равно с третью цветов разбросанных как попало. Проблема в том, что все примеры рассчитаны на преобразование RGB888, и мне достаточно сложно на текущий момент понять, как можно примеры адаптировать под RGB565.
001 | typedef struct RgbColor{ |
002 | unsigned char r; |
003 | unsigned char g; |
004 | unsigned char b; |
005 | } RgbColor; |
006 |
007 | typedef struct HsvColor{ |
008 | unsigned char h; |
009 | unsigned char s; |
010 | unsigned char v; |
011 | } HsvColor; |
012 |
013 | RgbColor HsvToRgb(HsvColor hsv){ |
014 | RgbColor rgb; |
015 | unsigned char region, p, q, t; |
016 | unsigned int h, s, v, remainder; |
017 |
018 | if (hsv.s == 0){ |
019 | rgb.r = hsv.v; |
020 | rgb.g = hsv.v; |
021 | rgb.b = hsv.v; |
022 | return rgb; |
023 | } |
024 |
025 | // converting to 16 bit to prevent overflow |
026 | h = hsv.h; |
027 | s = hsv.s; |
028 | v = hsv.v; |
029 |
030 | region = h / 43; |
031 | remainder = (h - (region * 43)) * 6; |
032 |
033 | p = (v * (255 - s)) >> 8; |
034 | q = (v * (255 - ((s * remainder) >> 8))) >> 8; |
035 | t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8; |
036 |
037 | switch (region){ |
038 | case 0: |
039 | rgb.r = v; |
040 | rgb.g = t; |
041 | rgb.b = p; |
042 | break ; |
043 | case 1: |
044 | rgb.r = q; |
045 | rgb.g = v; |
046 | rgb.b = p; |
047 | break ; |
048 | case 2: |
049 | rgb.r = p; |
050 | rgb.g = v; |
051 | rgb.b = t; |
052 | break ; |
053 | case 3: |
054 | rgb.r = p; |
055 | rgb.g = q; |
056 | rgb.b = v; |
057 | break ; |
058 | case 4: |
059 | rgb.r = t; |
060 | rgb.g = p; |
061 | rgb.b = v; |
062 | break ; |
063 | default : |
064 | rgb.r = v; |
065 | rgb.g = p; |
066 | rgb.b = q; |
067 | break ; |
068 | } |
069 |
070 | return rgb; |
071 | } |
072 |
073 | HsvColor RgbToHsv(RgbColor rgb){ |
074 | HsvColor hsv; |
075 | unsigned char rgbMin, rgbMax; |
076 |
077 | rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b); |
078 | rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b); |
079 |
080 | hsv.v = rgbMax; |
081 | if (hsv.v == 0){ |
082 | hsv.h = 0; |
083 | hsv.s = 0; |
084 | return hsv; |
085 | } |
086 |
087 | hsv.s = 255 * (( long )(rgbMax - rgbMin)) / hsv.v; |
088 | if (hsv.s == 0){ |
089 | hsv.h = 0; |
090 | return hsv; |
091 | } |
092 |
093 | if (rgbMax == rgb.r) |
094 | hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin); |
095 | else if (rgbMax == rgb.g) |
096 | hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin); |
097 | else |
098 | hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin); |
099 |
100 | return hsv; |
101 | } |
01 | void sort(uint16_t a[], int size, uint16_t a2[]){ |
02 | for ( int i=0; i<(size-1); i++){ |
03 | for ( int o=0; o<(size-(i+1)); o++){ |
04 | if (a[o] > a[o+1]){ |
05 | int t = a[o]; |
06 | a[o] = a[o+1]; |
07 | a[o+1] = t; |
08 | |
09 | int t2 = a2[o]; |
10 | a2[o] = a2[o+1]; |
11 | a2[o+1] = t2; |
12 | } |
13 | } |
14 | } |
15 | } |
01 | void colorsSort(){ |
02 | //randomSeed(analogRead(0)); |
03 | int len = 112; //16, 112 |
04 | uint16_t arr[len] = {0}; |
05 | uint16_t arr2[len] = {0}; |
06 | byte bb[] = {5,6,5}; |
07 | |
08 | byte x = 0; |
09 | byte y = 0; |
10 | |
11 | RgbColor rgb; |
12 | |
13 | for ( byte a=0; a<2; a++){ |
14 | if (a) sort(arr2,len,arr); |
15 | |
16 | for ( int b=0; b<len; b++){ |
17 | if (!a){ |
18 | arr[b] = random(0,65536); |
19 | |
20 | for ( byte c=0, e=0; c<3; c++){ |
21 | byte z = 0; |
22 | for ( byte d=0; d<bb[c]; d++, e++){ |
23 | bitWrite(z,d,bitRead(arr[b],e)); |
24 | } |
25 | |
26 | switch (c){ |
27 | case 0 : rgb.r = z; break ; //z << 3; break; //(z << 3) | (z >> 2); break; //z; break; |
28 | case 1 : rgb.g = z; break ; //z << 2; break; //(z << 2) | (z >> 4); break; //z; break; |
29 | case 2 : rgb.b = z; break ; //z << 3; break; //(z << 3) | (z >> 2); break; //z; break; |
30 | } |
31 | } |
32 | |
33 | |
34 | HsvColor hsv = RgbToHsv(rgb); |
35 | arr2[b] = hsv.h; |
36 | } |
37 | |
38 | tft.fillRect(x,y,6,6,arr[b]); |
39 | |
40 | x += 8; |
41 | if (x >= 122){ |
42 | x = 0; |
43 | y += 8; |
44 | } |
45 | } |
46 | |
47 | x = 0; |
48 | y += 8; |
49 | } |
50 | } |
Это пример того что получается. До и после, типа.
https://pp.userapi.com/c846323/v846323252/bc1b7/K__ltXMXpLM.jpg
красиво.
что значит "чтобы соответствовал спектру"?
тут написано, что формат 15-16 битный а у вас 3 байта?
https://en.wikipedia.org/wiki/RGB565
текст программы не компилируется.
https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/HSV-RGB-compar... Что бы сортировались в таком или приближенном порядке. Что бы не были оттенки одного цвета разбросаны по всей палитре.
Да 16 битный, 5 - 6 - 5 бит на цвет, который я в силу своих познаний привел к байту каждый для передачи в конвертер.
Сейчас все соберу в один файл, ибо по кусочкам надрал что бы показать.
Что красиво?
https://www.dropbox.com/s/olgq9ity6sj0xk3/Test.7z?dl=0
Красивая фотография дисплея с нанкой на борде.
На нижней части изображения видна сортировка сверху вниз от синего до синего.
На этой палитре отсутствуют белый, серый, чёрный.
В ваших данных есть похожие цвета.
На нижней части изображения видна сортировка сверху вниз от синего до синего.
На этой палитре отсутствуют белый, серый, чёрный.
В ваших данных есть похожие цвета.
И как со всем этим справиться?)
Nefelisk, глядя на приведенное Вами фото, можно предположить, что сортировка осуществляется правильно. Только "спектр" представлен в виде круга, а "разорван" этот круг не совсем в нужном месте: между синим и фиолетовым вместо того, чтобы между фиолетовым и красным.
И еще: если хотите конкретного совета, четко сформулируйте проблему. Повторяю, по фото проблемы не видно.
Подниму старую тему,
балуюсь со спрайтами на STM32, дисплей 320*240 ili9341, отображение в формате RGB565, конвертацию во время вывода из обычного RGB888 легко можно сделать и быстродействия хватит, но хранить во flash в 24 битном формате картинки - расточительство.
Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?
Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?
вот http://www.rinkydinkelectronics.com/t_imageconverter565.php
Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?
вот http://www.rinkydinkelectronics.com/t_imageconverter565.php
Спасибо, отлично работает, цвета правда съезжают, но надо над исходником поработать, это мелочи.
Мля.... Ребята, ну это же элементарная хрень :(
01
// пиксель RGB 16 бит
02
struct
_color16{
03
uint16_t c=0;
04
void
setRed(uint8_t r) {c= (c & 0x7FF) | (((uint16_t)r<<8) & 0xF800);}
05
void
setGreen(uint8_t g){c= (c & 0xF81F) | (((uint16_t)g<<3) & 0x7E0);}
06
void
setBlue(uint8_t b) {c= (c & 0xFFE0) | ( b>>3) ;}
07
uint8_t getRed() {
return
((c>>8) & 0xF8) | ((uint8_t)(c>>13));}
08
uint8_t getGreen(){
return
((c>>3) & 0xFC) | ((uint8_t)(c>>8) & 0x7);}
09
uint8_t getBlue() {
return
(c<<3) | ((uint8_t)(c>>2) & 0x7);}
10
void
set
(uint8_t R, uint8_t G, uint8_t B){setRed(R); setGreen(G); setBlue(B);}
11
void
get
(uint8_t* R, uint8_t* G, uint8_t* B){*R=getRed(); *G=getGreen(); *B=getBlue();}
12
};
Есть еще немного более продвинутый алгоритм, который копирует старшие биты цвета в обнуленные компрессией младшие, тогда диапазон расширяется вверх до максимальных 255. Но особого смысла в этом не вижу. Можно еще использовать табличное преобразование которое растянет диапазон 8...248 в 1...255, а оно ннада ?
Прочитал в пол глаза, ответил не в тему... Ну пусть остается.
// пиксель RGB 16 бит
01
struct
_color16{
02
uint16_t c=0;
03
void
setRed(uint8_t r) {c= (c & 0x7FF) | (((uint16_t)r<<8) & 0xF800);}
04
void
setGreen(uint8_t g){c= (c & 0xF81F) | (((uint16_t)g<<3) & 0x7E0);}
05
void
setBlue(uint8_t b) {c= (c & 0xFFE0) | ( b>>3) ;}
06
uint8_t getRed() {
return
((c>>8) & 0xF8) | ((uint8_t)(c>>13));}
07
uint8_t getGreen(){
return
((c>>3) & 0xFC) | ((uint8_t)(c>>8) & 0x7);}
08
uint8_t getBlue() {
return
(c<<3) | ((uint8_t)(c>>2) & 0x7);}
09
void
set
(uint8_t R, uint8_t G, uint8_t B){setRed(R); setGreen(G); setBlue(B);}
10
void
get
(uint8_t* R, uint8_t* G, uint8_t* B){*R=getRed(); *G=getGreen(); *B=getBlue();}
11
};
Есть еще немного более продвинутый алгоритм, который копирует старшие биты цвета в обнуленные компрессией младшие, тогда диапазон расширяется вверх до максимальных 255. Но особого смысла в этом не вижу. Можно еще использовать табличное преобразование которое растянет диапазон 8...248 в 1...255, а оно ннада ?
На крошечном экране точность цветов нафиг не надо.
А на светодиодной ленте яркость сильно зависит от значений.
Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?
вот http://www.rinkydinkelectronics.com/t_imageconverter565.php
Спасибо, отлично работает, цвета правда съезжают, но надо над исходником поработать, это мелочи.
Дополнение:
цвета в моем случае съезжали из за другой последовательности битов в 16 битном слове, что бы не изобретать велосипед, вышел из положения следующим способом:
1. преобразую по выше указанной ссылке jpg файл в raw
2. перевожу набор байтов в СИ массив ссылкой:
Bin2C — преобразование бинарных файлов в массив C/C++ (krivyy.com)