Start a new topic

Runtime RGB565 conversion

This is a small simple function I made to convert normal rgb (like: 0xFF0000 for red) into 16-bits RGB565.

This makes it possible to write the colors as used in HTML code in the source code.

// Convert a hexadecimal rgb value into a rgb565 format.
// When a text is needed, then the result can converted into
// a decimal number as text with a sprintf with %u, or with ultoa().
uint16_t rgb565( const unsigned long rgb)
{
  byte R = (rgb >> 16) & 0xFF;
  byte G = (rgb >>  8) & 0xFF;
  byte B = (rgb      ) & 0xFF;
 
  uint16_t ret  = (R & 0xF8) << 11;   // 5 bits
           ret |= (G & 0xFC) << 5;    // 6 bits
           ret |= (B & 0xF8);         // 5 bits
       
  return( ret);
}

 The code is ment to be as clear as possible, not to be short or compressed.


2 people like this idea

Added to Tools, Tips, Tricks and How-TOs

New version of the function. Shifting a byte by 11 bits is not nice.

// Convert a hexadecimal rgb value into a rgb565 format.
// When a text is needed, then the result can converted into
// a decimal number as text with a sprintf with %u, or with ultoa().
uint16_t rgb565( const unsigned long rgb)
{
  uint16_t R = (rgb >> 16) & 0xFF;
  uint16_t G = (rgb >>  8) & 0xFF;
  uint16_t B = (rgb      ) & 0xFF;
 
  uint16_t ret  = (R & 0xF8) << 11;   // 5 bits
           ret |= (G & 0xFC) << 5;    // 6 bits
           ret |= (B & 0xF8);         // 5 bits
       
  return( ret);
}

 

 

@Koepel


Your code just doesn't quite work properly, try this... 

uint16_t rgb565(uint32_t rgb) {

  uint16_t R = (rgb >> 19);
  uint16_t G = (rgb >> 10) & 63;
  uint16_t B = (rgb >>  3) & 31; 

  uint16_t ret = ((R << 11) + (G << 5) + B);
  return (ret);  
}

 

BTW your code does work if you do a final shift during the 'ret' re-construction, as the mask values are correct. As you can see in my example, I take care of that in the initial de-consruction.

Hope this helps.


Steve.

uint16_t rgb565( const unsigned long rgb)
{
  uint16_t R = (rgb >> 16) & 0xFF;
  uint16_t G = (rgb >>  8) & 0xFF;
  uint16_t B = (rgb      ) & 0xFF;
 
  uint16_t ret  = (R & 0xF8 >> 3) << 11;   // 5 bits
                ret |= (G & 0xFC >> 2) << 5;    // 6 bits
                ret |= (B & 0xF8 >> 3);         // 5 bits
       
  return (ret);
}

 

For more even clarity (not for compression, speed, or other considerations)

RGB is a 24 bit value in binary one bit per letter RRRRRRRR GGGGGGGG BBBBBBBB

565 format is a 16 bit value using the most significant (bolded) bits of the RGB number.

RGB has a range of 0 to 16777215 and 565 has a range of 0 to 65535


uint16_t RGBto565 (uint32_t rgb) {

   byte r,g,b;


   // extract red byte and then / 8 to loose 3 least significant bits

    r = (byte)((long)(rgb / 65536) / 8);

   // extract green byte and then / 4 to loose 2 least significant bits

   g = (byte)((long)(rgb % 65536 / 256) / 4);

   // extract blue byte and then / 8 to loose 3 least significant bits

   b = (byte)((long)(rgb % 256) / 8);

   // build out 565 as red * 2048 + green * 32 + blue

   return (uint16_t)(r*2048+g*32+b);

}


Why all the typecasting?  Int is not standard across MCUs and could fail on smaller MCUs

But a bigger question might be why use RGB inside MCU side code and not just use the 565 values?

My function was wrong !

I'm very sorry, I put a function online without testing it.

Thank you indev2, I owe you one.


On some forums the top post can be edited, to create an updated tutorial. But I can't edit the top post.

I prefer shifting the bits into place. Therefor I have corrected the number of bits to shift.

This is version 2:

// ---------------------------------------------
// rgb565     version 2
// ---------------------------------------------
// Convert a hexadecimal rgb value into a rgb565 format.
// To be able to use HTML RGB color format in a Arduino sketch.
//
// When a text is needed, then the result can converted into 
// a decimal number as text with a sprintf with %u, or with utoa().
// Great HTML color picker tool: 
//   https://www.w3schools.com/colors/colors_picker.asp
uint16_t rgb565( const unsigned long rgb)
{
  uint16_t R = (rgb >> 16) & 0xFF;
  uint16_t G = (rgb >>  8) & 0xFF;
  uint16_t B = (rgb      ) & 0xFF;

  uint16_t ret  = (R & 0xF8) << 8;  // 5 bits
           ret |= (G & 0xFC) << 3;  // 6 bits
           ret |= (B & 0xF8) >> 3;  // 5 bits
       
  return( ret);
}


Here is a test sketch, other calculations could be added to it to compare the results.

//
// RGB565 test sketch, to test the conversion functions.
// Using Arduion IDE 1.8.2 with Arduino Uno
// April 2017
//
// Goal: Use HTML format RGB colors in the sketch.
// HTML format #00FF00 to 16-bit RGB565 format.
// The HTML format is used as 32-bit integer 0x00FF00
//
// Online tools for RGB565:
//   http://www.rinkydinkelectronics.com/calc_rgb565.php
//   http://www.barth-dev.de/online/rgb565-color-picker/
//
// Forum threads about RGB565 colors:
//   http://support.iteadstudio.com/support/discussions/topics/11000010590 (about this function)
//   http://support.iteadstudio.com/support/discussions/topics/11000008693
//   http://support.iteadstudio.com/support/discussions/topics/1000064883
//
// Examples:
//   RED   = #FF0000 = 0xF800
//   GREEN = #00FF00 = 0x07E0
//   BLUE  = #0000FF = 0x001F
//   WHITE = #FFFFFF = 0xFFFF
//   BLACK = #000000 = 0x0000
//   
//   

struct table_STRUCT
{
  uint32_t html_rgb;
  uint16_t rgb_565;
} const table[] =
{
  { 0xFF0000, 0xF800 },
  { 0x00FF00, 0x07E0 },
  { 0x0000FF, 0x001F },
  { 0xFFFFFF, 0xFFFF },
  { 0x000000, 0x0000 },
  { 0x808080, 0x8410 },
  { 0xAB7755, 0xABAA },
  { 0x64399B, 0x61D3 },
  { 0x95BAB9, 0x95D7 },
};

void setup()
{
  Serial.begin( 9600);
  while( !Serial);   // For Leonardo and Micro: wait for serial monitor to open.

  Serial.println( "RGB565 test sketch");
  Serial.println( "html    table rgb565");

  for( int i=0; i<sizeof(table)/sizeof(table_STRUCT); i++)
  {
    uint32_t table565 = table[i].rgb_565;
    uint16_t my565 = rgb565( table[i].html_rgb);

    char buffer[80];
    sprintf( buffer, "#%06lX #%04lX #%04lX ", table[i].html_rgb, (uint32_t) table565, (uint32_t) my565);
    Serial.println( buffer);
  }
}

void loop()
{
}


// ---------------------------------------------
// rgb565     version 2
// ---------------------------------------------
// Convert a hexadecimal rgb value into a rgb565 format.
// To be able to use HTML RGB color format in a Arduino sketch.
//
// When a text is needed, then the result can converted into 
// a decimal number as text with a sprintf with %u, or with utoa().
// Great HTML color picker tool: 
//   https://www.w3schools.com/colors/colors_picker.asp
uint16_t rgb565( const unsigned long rgb)
{
  uint16_t R = (rgb >> 16) & 0xFF;
  uint16_t G = (rgb >>  8) & 0xFF;
  uint16_t B = (rgb      ) & 0xFF;

  uint16_t ret  = (R & 0xF8) << 8;  // 5 bits
           ret |= (G & 0xFC) << 3;  // 6 bits
           ret |= (B & 0xF8) >> 3;  // 5 bits
       
  return( ret);
}

 

Login or Signup to post a comment