1

Could someone help me to convert 32bit RGBA color to 16 bit BGR565. What I did so far is:

//INPUT VALUES 32BIT RGBA Color
int alpha =  0.0 to 1.0 value here;
int red = 0.0 to 255.0 value here;
int green = 0.0 to 255.0 value here;
int blue = 0.0 to 255.0 value here;

//CONVERTING TO BGR565
int red0 = (red * 31) / 255;
int green0 = (green * 63) / 255;
int blue0 = (blue * 31) / 255;
uint16_t BGRColor = red0;
BGRColor |= (green0 << 5);
BGRColor |= (blue0 << 11);

I don't use alpha as my input color alpha is always set to 1.0. Conversion code seems to be correct for me but for some reason output BGR565 color is totally different than input one. Can someone tell me how to do it with C or ObjectiveC please.

Guferos
  • 4,337
  • 5
  • 18
  • 25

1 Answers1

1

Your conversion code could be made more accurate. The expression

(red * 31) / 255;

maps the values like this (8 bit to 5 bit):

0-8 => 0 (9 values)
9-16 => 1 (8 values)
17-24 => 2 (8 values)
25-32 => 3 (8 values)
33-41 => 4 (9 values)
42-49 => 5 (8 values)
50-57 => 6 (8 values)
58-65 => 7 (8 values)
66-74 => 8 (9 values)
75-82 => 9 (8 values)
83-90 => 10 (8 values)
91-98 => 11 (8 values)
99-106 => 12 (8 values)
107-115 => 13 (9 values)
116-123 => 14 (8 values)
124-131 => 15 (8 values)
132-139 => 16 (8 values)
140-148 => 17 (9 values)
149-156 => 18 (8 values)
157-164 => 19 (8 values)
165-172 => 20 (8 values)
173-180 => 21 (8 values)
181-189 => 22 (9 values)
190-197 => 23 (8 values)
198-205 => 24 (8 values)
206-213 => 25 (8 values)
214-222 => 26 (9 values)
223-230 => 27 (8 values)
231-238 => 28 (8 values)
239-246 => 29 (8 values)
247-254 => 30 (8 values)
255-255 => 31 (1 value)

This is obviously not uniform. If you simply divide the input value by eight (right shift by three)

red / 8

you'll get the following result:

0-7 => 0 (8 values)
8-15 => 1 (8 values)
16-23 => 2 (8 values)
24-31 => 3 (8 values)
32-39 => 4 (8 values)
40-47 => 5 (8 values)
48-55 => 6 (8 values)
56-63 => 7 (8 values)
64-71 => 8 (8 values)
72-79 => 9 (8 values)
80-87 => 10 (8 values)
88-95 => 11 (8 values)
96-103 => 12 (8 values)
104-111 => 13 (8 values)
112-119 => 14 (8 values)
120-127 => 15 (8 values)
128-135 => 16 (8 values)
136-143 => 17 (8 values)
144-151 => 18 (8 values)
152-159 => 19 (8 values)
160-167 => 20 (8 values)
168-175 => 21 (8 values)
176-183 => 22 (8 values)
184-191 => 23 (8 values)
192-199 => 24 (8 values)
200-207 => 25 (8 values)
208-215 => 26 (8 values)
216-223 => 27 (8 values)
224-231 => 28 (8 values)
232-239 => 29 (8 values)
240-247 => 30 (8 values)
248-255 => 31 (8 values)

So I'd recommend the following code:

int red0 = red / 8;
int green0 = green / 4;
int blue0 = blue / 8;

This is also more efficient since any decent compiler will convert the divisions into shift instructions.

You could also mask the relevant bits and shift them directly into the target position:

uint16_t BGRColor = red >> 3;
BGRColor |= (green & 0xFC) << 3;
BGRColor |= (blue  & 0xF8) << 8;
Community
  • 1
  • 1
nwellnhof
  • 32,319
  • 7
  • 89
  • 113
  • Excellent. This is definitely much more precise than my code. Colors look much better after conversion now. Thanks a lot. – Guferos Apr 09 '14 at 08:23