How to transcode RGB565 to custom 7 colors

Hi all,

I bought a multi-color e-paper display :

Waveshare 5.65inch ACeP 7-Color E-Paper E-Ink Display Module, 600×448 Pixels

This e-paper display can present black, white and 5 specific colors:

https://www.waveshare.com/wiki/5.65inch_e-Paper_Module_(F)

I intend to add support for this display to my library GxEPD2.

Initially it will handle exact RGB565 color values for these 7 colors.

But for handling of general RGB565 colors, such as for presenting BMP files, I need a transcoding function.
My mathematics knowledge is rusted quite a bit, so I don't know how to efficiently find the "nearest" color for a given RGB value. Maybe something like angular coordinates in a color circle?

Jean-Marc

Pythagoras?

for distance in a 3-dimensional space? good idea.

Is this the best approach, or are there other ideas?

deviation of the (two) other colors from the lowest color and a switch case look up?

just verbal

dominant green --> green
dominant red --> red
dominant blue --> blue
all three very equal --> white
green and red very similar --> yellow
...

@noiasca,

thank you, this approach should be good enough in practice.

I have drafted a method or function for this:

    uint8_t color7(uint16_t color)
    {
      static uint16_t _prev_color = GxEPD_BLACK;
      static uint8_t _prev_color7 = 0x00; // black
      if (color == _prev_color) return _prev_color7;
      uint8_t cv7 = 0x00;
      switch(color)
      {
        case GxEPD_BLACK: cv7 = 0x00; break;
        case GxEPD_WHITE: cv7 = 0x01; break;
        case GxEPD_GREEN: cv7 = 0x02; break;
        case GxEPD_BLUE:  cv7 = 0x03; break;
        case GxEPD_RED:   cv7 = 0x04; break;
        case GxEPD_YELLOW: cv7 = 0x05; break;
        case GxEPD_ORANGE: cv7 = 0x06; break;
        default:
        {
          uint16 red = color & 0xF800;
          uint16 green = (color & 0x03C0) << 5;
          uint16 blue = (color & 0x001F) << 11;
          if ((red < 0x8000) && (green < 0x8000) && (blue < 0x8000)) cv7 = 0x00; // black
          else if ((red >= 0x8000) && (green >= 0x8000) && (blue >= 0x8000)) cv7 = 0x01; // white
          else if ((green >= 0x8000) && (blue >= 0x8000)) cv7 = green > blue ? 0x02 : 0x03; // green, blue
          else if ((red >= 0x8000) && (green >= 0x8000))
          {
            static const uint16_t y2o_lim = ((GxEPD_YELLOW - GxEPD_ORANGE) / 2 + (GxEPD_ORANGE & 0x03C0)) << 5;
            cv7 = green > y2o_lim ? 0x05 : 0x06; // yellow, orange
          }
          else if (red >= 0x8000) cv7 = 0x04; // red
          else if (green >= 0x8000) cv7 = 0x02; // green
          else cv7 = 0x03; // blue
        }
      }
      _prev_color = color;
      _prev_color7 = cv7;
      return cv7;
    }

Not yet tested. There might be holes left.

Jean-Marc