Image colors not displaying properly

Description

I’m trying to use some image buttons on a Mikroe 5" TFT display using 16 bit color depth. The colors on images get messed up when displayed on the LCD. I’m creating the UI in NXP’s GUI Guider and importing the code in MCU Expresso to run on an NXP MCX N94 development board. The GUI Guider stores the images as constants and the stored colors seem correct and follow the RGB565 format as the LCD driver expects, but they don’t seem to display correctly (see screenshots of GUI Guider simulator vs LCD). I checked the LCD pin mapping, checked LCD driver configuration (24 bit mode, with 16 bit color depth, RGB565 format), and I also checked the image format, which looks correct. I created a test image for one of the buttons where I made all the pixels in the image the same color to , see what gets displayed. I did full red (0xf8, 0x00) which displayed as bright blue, full green (0x03 0xe0) which displayed as bright red and full blue (0x00, 0x1f) which displayed as bright green. I also tried using both true color and true color alpha for the image formats, I tried converting the images in GIMP to RGB 24 bits, 16 bits, 8 bits, grayscale, png, jpg and the images always look exactly the same on the display. The buttons I tried are really just shades of gray, so any of these formats should have worked. I shared the relevant configuration code below.
I’m using Gui Guider version 1.51 which seems to be using LVGL version 8.2.0.
The LCD board uses the SSD1963 display driver.

lv_conf.c display config code:

#define LV_COLOR_DEPTH     16

/* Swap the 2 bytes of RGB565 color.
 * Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP   0

/* 1: Enable screen transparency.
 * Useful for OSD or other overlapping GUIs.
 * Requires `LV_COLOR_DEPTH = 32` colors and the screen's style should be modified: `style.body.opa = ...`*/
#define LV_COLOR_SCREEN_TRANSP    0

/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
 * 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 128 ? 0: 128)

/*Images pixels with this color will not be drawn (if they are chroma keyed)*/
//#define LV_COLOR_CHROMA_KEY    lv_color_hex(0x00ff00)         /*lv_color_hex(0x00ff00): pure green*/

/* Default display refresh period.
 * Can be changed in the display driver (`lv_disp_drv_t`).*/
#define LV_DISP_DEF_REFR_PERIOD     33      /*[ms]*/

LCD display initialization code (relevant parts only):

 Command = 0xB0;
    CommandValue[0U] = 0x20; //LCD resolution 20 - 24bit, 00 - 18 bit
    CommandValue[1U] = 0x00;
    CommandValue[2U] = (SSD_HOR_RESOLUTION - 1) >> 8;
    CommandValue[3U] = SSD_HOR_RESOLUTION - 1;
    CommandValue[4U] = (SSD_VER_RESOLUTION - 1) >> 8;
    CommandValue[5U] = SSD_VER_RESOLUTION - 1;
    CommandValue[6U] = 0x00;
    FLEXIO_8080_SglBeatWR_nPrm(Command, CommandValue, 7U);

Configuring color depth:

Command = 0xF0;
    CommandValue[0U] = 0x03; //Color format 03 - 16 bit 565 format, 02 - 16 bit packed
    FLEXIO_8080_SglBeatWR_nPrm(Command, CommandValue, 1U);

LCD driver datasheet (sorry I can’t share a screenshot of the relevant datasheet section. Your forum only lets me upload 2 images):
chrome-https://www.seacomp.com/sites/default/files/references/Solomon-Systech-SSD1963.pdf

Snippet of code of the stored button image:

const LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG__MINUS_90X90 uint8_t _minus_90x90_map[] = {
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP == 0
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

Screenshot of Gui Guider simulator screen:

Actual display screen:

I can’t think of anything else to try at this point.

as first try #define LV_COLOR_16_SWAP 1

1 Like

I tried it, it makes the colors wrong all over the display, including the background, which is now the correct color. I’m using a parallel 16b interface, so the bytes should not be swapped, so this does what it’s supposed to do.

Looks like I didn’t realize that in the generated image variable the bytes are normally swapped. I created a test image with three stripes: full red, full green and full blue and it displays correctly. The shades of gray in the image I used for my buttons though show up as green when they are lighter. I put the same colors in Paint custom color editor (scaling each color component), and as they should, they show up as shades of grey and have about the same amount of each color, not more green than red or blue. See color in paint:
image
Versus the + and - in the middle of the buttons and the green square just below the minus button which are all the same color:

It turned out to be a defective display. I got a new unit of the same mode and now everything works as it should.