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

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

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

typedef struct RgbColor{
	unsigned char r;
	unsigned char g;
	unsigned char b;
} RgbColor;

typedef struct HsvColor{
	unsigned char h;
	unsigned char s;
	unsigned char v;
} HsvColor;

RgbColor HsvToRgb(HsvColor hsv){
	RgbColor rgb;
	unsigned char region, p, q, t;
	unsigned int h, s, v, remainder;

	if(hsv.s == 0){
		rgb.r = hsv.v;
		rgb.g = hsv.v;
		rgb.b = hsv.v;
		return rgb;
	}

	// converting to 16 bit to prevent overflow
	h = hsv.h;
	s = hsv.s;
	v = hsv.v;

	region = h / 43;
	remainder = (h - (region * 43)) * 6; 

	p = (v * (255 - s)) >> 8;
	q = (v * (255 - ((s * remainder) >> 8))) >> 8;
	t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;

	switch(region){
		case 0:
			rgb.r = v;
			rgb.g = t;
			rgb.b = p;
			break;
		case 1:
			rgb.r = q;
			rgb.g = v;
			rgb.b = p;
			break;
		case 2:
			rgb.r = p;
			rgb.g = v;
			rgb.b = t;
			break;
		case 3:
			rgb.r = p;
			rgb.g = q;
			rgb.b = v;
			break;
		case 4:
			rgb.r = t;
			rgb.g = p;
			rgb.b = v;
			break;
		default:
			rgb.r = v;
			rgb.g = p;
			rgb.b = q;
			break;
	}

	return rgb;
}

HsvColor RgbToHsv(RgbColor rgb){
	HsvColor hsv;
	unsigned char rgbMin, rgbMax;

	rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
	rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);

	hsv.v = rgbMax;
	if(hsv.v == 0){
		hsv.h = 0;
		hsv.s = 0;
		return hsv;
	}

	hsv.s = 255 * ((long)(rgbMax - rgbMin)) / hsv.v;
	if(hsv.s == 0){
		hsv.h = 0;
		return hsv;
	}

	if(rgbMax == rgb.r)
		hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
	else if (rgbMax == rgb.g)
		hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
	else
		hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);

	return hsv;
}

void				sort(uint16_t a[], int size,	uint16_t a2[]){
	for(int i=0; i<(size-1); i++){
		for(int o=0; o<(size-(i+1)); o++){
			if(a[o] > a[o+1]){
				int	t		=	a[o];
				a[o]			=	a[o+1];
				a[o+1]		=	t;
				
				int	t2		=	a2[o];
				a2[o]			=	a2[o+1];
				a2[o+1]		=	t2;
			}
		}
	}
}
void		colorsSort(){
	//randomSeed(analogRead(0));
	int		len			=	112;	//16, 112
	uint16_t	arr[len]		=	{0};
	uint16_t	arr2[len]	=	{0};
	byte		bb[]			=	{5,6,5};
	
	byte		x				=	0;
	byte		y				=	0;
	
	RgbColor rgb;
	
	for(byte a=0; a<2; a++){
		if(a)	sort(arr2,len,arr);
		
		for(int b=0; b<len; b++){
			if(!a){
				arr[b]		=	random(0,65536);
				
				for(byte c=0, e=0; c<3; c++){
					byte	z				=	0;
					for(byte d=0; d<bb[c]; d++, e++){
						bitWrite(z,d,bitRead(arr[b],e));
					}
					
					switch(c){
						case	0	:		rgb.r	=	z;	break;	//z << 3;	break;	//(z << 3) | (z >> 2);	break;	//z;	break;
						case	1	:		rgb.g	=	z;	break;	//z << 2;	break;	//(z << 2) | (z >> 4);	break;	//z;	break;
						case	2	:		rgb.b	=	z;	break;	//z << 3;	break;	//(z << 3) | (z >> 2);	break;	//z;	break;
					}
				}
				
				
				HsvColor hsv			=	RgbToHsv(rgb);
				arr2[b]					=	hsv.h;
			}
			
			tft.fillRect(x,y,6,6,arr[b]);
			
			x						+=	8;
			if(x >= 122){
				x						=	0;
				y						+=	8;
			}
		}
		
		x						=	0;
		y						+=	8;
	}
}

 

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

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

// пиксель RGB 16 бит
struct _color16{
   uint16_t c=0;
   void setRed(uint8_t r)  {c= (c &  0x7FF) | (((uint16_t)r<<8) & 0xF800);}  
   void setGreen(uint8_t g){c= (c & 0xF81F) | (((uint16_t)g<<3) &  0x7E0);}  
   void setBlue(uint8_t b) {c= (c & 0xFFE0) | (           b>>3)          ;}  
   uint8_t getRed()  { return ((c>>8) & 0xF8) | ((uint8_t)(c>>13));}
   uint8_t getGreen(){ return ((c>>3) & 0xFC) | ((uint8_t)(c>>8) & 0x7);}
   uint8_t getBlue() { return  (c<<3)         | ((uint8_t)(c>>2) & 0x7);}
   void set(uint8_t R, uint8_t G, uint8_t B){setRed(R); setGreen(G); setBlue(B);}
   void get(uint8_t* R, uint8_t* G, uint8_t* B){*R=getRed(); *G=getGreen(); *B=getBlue();}
};

Есть еще немного более продвинутый алгоритм, который копирует старшие биты цвета в обнуленные компрессией младшие, тогда диапазон расширяется вверх до максимальных 255. Но особого смысла в этом не  вижу. Можно еще использовать табличное преобразование которое растянет диапазон 8...248 в 1...255, а оно ннада ?

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

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

brokly пишет:

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

struct _color16{
   uint16_t c=0;
   void setRed(uint8_t r)  {c= (c &  0x7FF) | (((uint16_t)r<<8) & 0xF800);}  
   void setGreen(uint8_t g){c= (c & 0xF81F) | (((uint16_t)g<<3) &  0x7E0);}  
   void setBlue(uint8_t b) {c= (c & 0xFFE0) | (           b>>3)          ;}  
   uint8_t getRed()  { return ((c>>8) & 0xF8) | ((uint8_t)(c>>13));}
   uint8_t getGreen(){ return ((c>>3) & 0xFC) | ((uint8_t)(c>>8) & 0x7);}
   uint8_t getBlue() { return  (c<<3)         | ((uint8_t)(c>>2) & 0x7);}
   void set(uint8_t R, uint8_t G, uint8_t B){setRed(R); setGreen(G); setBlue(B);}
   void get(uint8_t* R, uint8_t* G, uint8_t* B){*R=getRed(); *G=getGreen(); *B=getBlue();}
};

Есть еще немного более продвинутый алгоритм, который копирует старшие биты цвета в обнуленные компрессией младшие, тогда диапазон расширяется вверх до максимальных 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)