Сортировка палитры RGB565

Nefelisk
Offline
Зарегистрирован: 09.09.2017

Может кто подсказать пример, как можно отсортировать набор цветов RGB565, находящиеся в случайном порядке что бы он соответсвовал спектру? Я находил и пробовал применить способы преобразования в HSL (HSV) и сортировку по hue и более менее что-то приближенное получалось, но все равно с третью цветов разбросанных как попало. Проблема в том, что все примеры рассчитаны на преобразование RGB888, и мне достаточно сложно на текущий момент понять, как можно примеры адаптировать под RGB565.

001typedef struct RgbColor{
002    unsigned char r;
003    unsigned char g;
004    unsigned char b;
005} RgbColor;
006 
007typedef struct HsvColor{
008    unsigned char h;
009    unsigned char s;
010    unsigned char v;
011} HsvColor;
012 
013RgbColor 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 
073HsvColor 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}
01void                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}
01void        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}

 

Nefelisk
Offline
Зарегистрирован: 09.09.2017

Это пример того что получается. До и после, типа.

https://pp.userapi.com/c846323/v846323252/bc1b7/K__ltXMXpLM.jpg

toc
Offline
Зарегистрирован: 09.02.2013

красиво.
что значит "чтобы соответствовал спектру"?
тут написано, что формат 15-16 битный а у вас 3 байта?
https://en.wikipedia.org/wiki/RGB565
текст программы не компилируется.

Nefelisk
Offline
Зарегистрирован: 09.09.2017

https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/HSV-RGB-compar... Что бы сортировались в таком или приближенном порядке. Что бы не были оттенки одного цвета разбросаны по всей палитре.

Да 16 битный, 5 - 6 - 5 бит на цвет, который я в силу своих познаний привел к байту каждый для передачи в конвертер.

Сейчас все соберу в один файл, ибо по кусочкам надрал что бы показать.

Что красиво?

Nefelisk
Offline
Зарегистрирован: 09.09.2017

toc пишет:
текст программы не компилируется.

https://www.dropbox.com/s/olgq9ity6sj0xk3/Test.7z?dl=0

toc
Offline
Зарегистрирован: 09.02.2013

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

Nefelisk
Offline
Зарегистрирован: 09.09.2017

toc пишет:
Красивая фотография дисплея с нанкой на борде.
На нижней части изображения видна сортировка сверху вниз от синего до синего.
На этой палитре отсутствуют белый, серый, чёрный.
В ваших данных есть похожие цвета.

И как со всем этим справиться?)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Nefelisk, глядя на приведенное Вами фото, можно предположить, что сортировка осуществляется правильно. Только "спектр" представлен в виде круга, а "разорван" этот круг не совсем в нужном месте: между синим и фиолетовым вместо того, чтобы между фиолетовым и красным.

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Подниму старую тему,

балуюсь со спрайтами на STM32, дисплей 320*240 ili9341, отображение в формате RGB565, конвертацию во время вывода из обычного RGB888 легко можно сделать и быстродействия хватит, но хранить во flash в 24 битном формате картинки - расточительство.

Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?

b707
Offline
Зарегистрирован: 26.05.2017

andycat пишет:

Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?

вот http://www.rinkydinkelectronics.com/t_imageconverter565.php

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

b707 пишет:

andycat пишет:

Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?

вот http://www.rinkydinkelectronics.com/t_imageconverter565.php

 

Спасибо, отлично работает, цвета правда съезжают, но надо над исходником поработать, это мелочи.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Мля.... Ребята, ну это же элементарная хрень :(

01// пиксель RGB 16 бит
02struct _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, а оно ннада ?

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Прочитал в пол глаза, ответил не в тему... Ну пусть остается.

brokly пишет:

// пиксель RGB 16 бит

01struct _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, а оно ннада ?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

На крошечном экране точность цветов нафиг не надо.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А на светодиодной ленте яркость сильно зависит от значений.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

andycat пишет:

b707 пишет:

andycat пишет:

Никто не встречал online сайт преобразования файлов или программу конвертации из RGB888/BMP в RGB565?

вот http://www.rinkydinkelectronics.com/t_imageconverter565.php

 

Спасибо, отлично работает, цвета правда съезжают, но надо над исходником поработать, это мелочи.

Дополнение:
цвета в моем случае съезжали из за другой последовательности битов в 16 битном слове, что бы не изобретать велосипед, вышел из положения следующим способом:
1. преобразую по выше указанной ссылке jpg файл в raw
2. перевожу набор байтов в СИ массив ссылкой:
Bin2C — преобразование бинарных файлов в массив C/C++ (krivyy.com)