Alpha images rendered correctly only to dark background

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Alpha images rendered correctly only to dark background

      I have many alpha images. For example:

      C Source Code

      1. static GUI_CONST_STORAGE unsigned char acopen[] = {
      2. /* ABS: 005 Pixels @ 000,000*/ 0, 5, 0xFF, 0xF4, 0xC5, 0x51, 0x02,
      3. /* RLE: 011 Pixels @ 005,000*/ 11, 0x00,
      4. /* ABS: 009 Pixels @ 016,000*/ 0, 9, 0x15, 0x7A, 0xEE, 0x74, 0x04, 0x5D, 0xD3, 0xDA, 0x6B,
      5. /* RLE: 010 Pixels @ 006,001*/ 10, 0x47,
      6. /* ABS: 009 Pixels @ 016,001*/ 0, 9, 0x32, 0x00, 0x7B, 0x0D, 0x00, 0x00, 0x01, 0x4C, 0xC4,
      7. /* RLE: 011 Pixels @ 006,002*/ 11, 0xFF,
      8. /* ABS: 002 Pixels @ 017,002*/ 0, 2, 0x32, 0x16,
      9. /* RLE: 006 Pixels @ 000,003*/ 6, 0x00,
      10. /* ABS: 003 Pixels @ 006,003*/ 0, 3, 0x3B, 0xB3, 0xFE,
      11. /* RLE: 008 Pixels @ 009,003*/ 8, 0xFF,
      12. /* RLE: 001 Pixels @ 017,003*/ 1, 0x47,
      13. /* RLE: 009 Pixels @ 018,003*/ 9, 0x00,
      14. /* ABS: 002 Pixels @ 008,004*/ 0, 2, 0x2C, 0xA4,
      15. /* RLE: 007 Pixels @ 010,004*/ 7, 0xFF,
      16. /* RLE: 001 Pixels @ 017,004*/ 1, 0x47,
      17. /* RLE: 011 Pixels @ 018,004*/ 11, 0x00,
      18. /* RLE: 001 Pixels @ 010,005*/ 1, 0x9E,
      19. /* RLE: 006 Pixels @ 011,005*/ 6, 0xFF,
      20. /* RLE: 001 Pixels @ 017,005*/ 1, 0x47,
      21. /* RLE: 011 Pixels @ 018,005*/ 11, 0x00,
      22. /* ABS: 002 Pixels @ 010,006*/ 0, 2, 0x0F, 0xFD,
      23. /* RLE: 005 Pixels @ 012,006*/ 5, 0xFF,
      24. /* RLE: 001 Pixels @ 017,006*/ 1, 0x47,
      25. /* RLE: 012 Pixels @ 018,006*/ 12, 0x00,
      26. /* RLE: 001 Pixels @ 011,007*/ 1, 0xD4,
      27. /* RLE: 005 Pixels @ 012,007*/ 5, 0xFF,
      28. /* RLE: 001 Pixels @ 017,007*/ 1, 0x47,
      29. /* RLE: 012 Pixels @ 018,007*/ 12, 0x00,
      30. /* RLE: 001 Pixels @ 011,008*/ 1, 0xB8,
      31. /* RLE: 005 Pixels @ 012,008*/ 5, 0xFF,
      32. /* RLE: 001 Pixels @ 017,008*/ 1, 0x47,
      33. /* RLE: 012 Pixels @ 018,008*/ 12, 0x00,
      34. /* RLE: 001 Pixels @ 011,009*/ 1, 0xB7,
      35. /* RLE: 005 Pixels @ 012,009*/ 5, 0xFF,
      36. /* RLE: 001 Pixels @ 017,009*/ 1, 0x47,
      37. /* RLE: 012 Pixels @ 018,009*/ 12, 0x00,
      38. /* RLE: 001 Pixels @ 011,010*/ 1, 0xB7,
      39. /* RLE: 005 Pixels @ 012,010*/ 5, 0xFF,
      40. /* RLE: 001 Pixels @ 017,010*/ 1, 0x47,
      41. /* RLE: 012 Pixels @ 018,010*/ 12, 0x00,
      42. /* RLE: 001 Pixels @ 011,011*/ 1, 0xB7,
      43. /* RLE: 005 Pixels @ 012,011*/ 5, 0xFF,
      44. /* RLE: 001 Pixels @ 017,011*/ 1, 0x47,
      45. /* RLE: 012 Pixels @ 018,011*/ 12, 0x00,
      46. /* RLE: 001 Pixels @ 011,012*/ 1, 0xB7,
      47. /* RLE: 005 Pixels @ 012,012*/ 5, 0xFF,
      48. /* RLE: 001 Pixels @ 017,012*/ 1, 0x47,
      49. /* RLE: 009 Pixels @ 018,012*/ 9, 0x00,
      50. /* ABS: 004 Pixels @ 008,013*/ 0, 4, 0x4E, 0x00, 0x00, 0xB7,
      51. /* RLE: 005 Pixels @ 012,013*/ 5, 0xFF,
      52. /* RLE: 001 Pixels @ 017,013*/ 1, 0x47,
      53. /* RLE: 008 Pixels @ 018,013*/ 8, 0x00,
      54. /* ABS: 005 Pixels @ 007,014*/ 0, 5, 0x44, 0xFF, 0x3A, 0x00, 0xB7,
      55. /* RLE: 005 Pixels @ 012,014*/ 5, 0xFF,
      56. /* RLE: 001 Pixels @ 017,014*/ 1, 0x47,
      57. /* RLE: 008 Pixels @ 018,014*/ 8, 0x00,
      58. /* ABS: 005 Pixels @ 007,015*/ 0, 5, 0x3D, 0xFF, 0x4A, 0x00, 0xB7,
      59. /* RLE: 005 Pixels @ 012,015*/ 5, 0xFF,
      60. /* RLE: 001 Pixels @ 017,015*/ 1, 0x47,
      61. /* RLE: 009 Pixels @ 018,015*/ 9, 0x00,
      62. /* ABS: 004 Pixels @ 008,016*/ 0, 4, 0x5F, 0x03, 0x00, 0xB7,
      63. /* RLE: 005 Pixels @ 012,016*/ 5, 0xFF,
      64. /* RLE: 001 Pixels @ 017,016*/ 1, 0x47,
      65. /* RLE: 012 Pixels @ 018,016*/ 12, 0x00,
      66. /* RLE: 001 Pixels @ 011,017*/ 1, 0xB7,
      67. /* RLE: 005 Pixels @ 012,017*/ 5, 0xFF,
      68. /* RLE: 001 Pixels @ 017,017*/ 1, 0x47,
      69. /* RLE: 012 Pixels @ 018,017*/ 12, 0x00,
      70. /* RLE: 001 Pixels @ 011,018*/ 1, 0xB7,
      71. /* RLE: 005 Pixels @ 012,018*/ 5, 0xFF,
      72. /* ABS: 003 Pixels @ 017,018*/ 0, 3, 0x47, 0x00, 0x24,
      73. /* RLE: 010 Pixels @ 001,019*/ 10, 0x00,
      74. /* ABS: 009 Pixels @ 011,019*/ 0, 9, 0xB7, 0xEA, 0xE7, 0xE7, 0xE7, 0xD2, 0x19, 0x36, 0x65,
      75. /* RLE: 010 Pixels @ 001,020*/ 10, 0x00,
      76. /* ABS: 002 Pixels @ 011,020*/ 0, 2, 0xB7, 0x17,
      77. /* RLE: 004 Pixels @ 013,020*/ 4, 0x00,
      78. /* ABS: 004 Pixels @ 017,020*/ 0, 4, 0x01, 0xA7, 0xEA, 0x1E,
      79. /* RLE: 009 Pixels @ 002,021*/ 9, 0x00,
      80. /* ABS: 012 Pixels @ 011,021*/ 0, 12, 0xB7, 0x6E, 0x5F, 0x5F, 0x5F, 0x75, 0xD8, 0xFF, 0xFF, 0xE0, 0x68, 0x08,
      81. /* RLE: 007 Pixels @ 004,022*/ 7, 0x00,
      82. /* RLE: 001 Pixels @ 011,022*/ 1, 0xB7,
      83. /* RLE: 010 Pixels @ 012,022*/ 10, 0xFF,
      84. /* ABS: 003 Pixels @ 003,023*/ 0, 3, 0xE8, 0x7A, 0x10,
      85. /* RLE: 005 Pixels @ 006,023*/ 5, 0x00,
      86. /* RLE: 001 Pixels @ 011,023*/ 1, 0xB7,
      87. /* RLE: 012 Pixels @ 012,023*/ 12, 0xFF,
      88. /* ABS: 007 Pixels @ 005,024*/ 0, 7, 0xF2, 0x8C, 0x1B, 0x00, 0x00, 0x00, 0xC7,
      89. /* RLE: 014 Pixels @ 012,024*/ 14, 0xFF,
      90. /* ABS: 005 Pixels @ 007,025*/ 0, 5, 0xF9, 0x9E, 0x2F, 0x3E, 0xFE,
      91. /* RLE: 007 Pixels @ 012,025*/ 7, 0xFF,
      92. 0}; /* 275 bytes for 494 pixels */
      93. GUI_CONST_STORAGE GUI_BITMAP bmopen = {
      94. 19, /* XSize */
      95. 26, /* YSize */
      96. 19, /* BytesPerLine */
      97. GUI_COMPRESS_RLE8, /* BitsPerPixel */
      98. (unsigned char *)acopen, /* Pointer to picture data */
      99. NULL, /* Pointer to palette */
      100. GUI_DRAW_RLEALPHA
      101. };
      Display All
      Every pixel is descripted as a single byte that represents the "quantity" of the image respect the background. Of course, the content of those images is only the shape.

      I draw alpha images with GUI_SetColor(), that selects the color of the shape, and GUI_DrawBitmap() that really draws the bitmap on the screen. It works very well during the simulation at the PC, and it seems working well on the embedded target when the background is dark (black) or blue (GUI_BLUE). When the background is light (GUI_RED or GUI_GREEN) the alpha blending doesn't work well. The shape isn't smooth. I don't know if it is correct, I think the real color used are calculated if the background was always black.

      My driver is GUIDRV_FLEXCOLOR_F66709. Here it is the initialization.

      C Source Code

      1. #define XSIZE_PHYS 320
      2. #define YSIZE_PHYS 240
      3. #define NUM_VSCREENS 1
      4. void LCD_X_Config(void) {
      5. GUI_DEVICE * pDevice;
      6. GUI_PORT_API PortAPI;
      7. CONFIG_FLEXCOLOR cfgFlexColor = { 0 };
      8. pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, COLOR_CONVERSION, 0, 0);
      9. if (DISPLAY_ORIENTATION & GUI_SWAP_XY) {
      10. LCD_SetSizeEx(0, YSIZE_PHYS, XSIZE_PHYS);
      11. if (NUM_VSCREENS > 0)
      12. LCD_SetVSizeEx(0, YSIZE_PHYS * NUM_VSCREENS, XSIZE_PHYS);
      13. } else {
      14. LCD_SetSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);
      15. if (NUM_VSCREENS > 0)
      16. LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS * NUM_VSCREENS);
      17. }
      18. cfgFlexColor.FirstCOM = 0;
      19. cfgFlexColor.FirstSEG = 0;
      20. cfgFlexColor.NumDummyReads = 1; // Sembra sia necessario per l'ILI9341
      21. cfgFlexColor.Orientation = DISPLAY_ORIENTATION;
      22. cfgFlexColor.RegEntryMode = 0; /* Gli altri bit per il registro che contiene l'orientation */
      23. GUIDRV_FlexColor_Config(pDevice, &cfgFlexColor);
      24. // GUIDRV_FlexColor_SetReadFunc();
      25. PortAPI.pfWrite16_A0 = LCD_X_8080_16_Write00_16;
      26. PortAPI.pfWrite16_A1 = LCD_X_8080_16_Write01_16;
      27. PortAPI.pfWriteM16_A1 = LCD_X_8080_16_WriteM01_16;
      28. PortAPI.pfReadM16_A1 = LCD_X_8080_16_ReadM01_16;
      29. GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI,
      30. GUIDRV_FLEXCOLOR_F66709,
      31. GUIDRV_FLEXCOLOR_M16C0B16);
      32. }
      Display All
      So I don't use cache (and I can't use cache for RAM restrictions). So I think emWin is forced to read back the color of pixels during drawing of an alpha image. One cause of my problem could be a wrong read back. For example, the behaviour I observed can be explined if the driver reads back always zero (black colors). So the alpha drawing works (or appears good) when the background is black or dark.


      How could I check if this is correct? I know ILI9341 supports read back.
    • Hi,

      I use the ILI9341 as well and had similar problems with the read function. I use the EDIT widget with the blinking cursor functionality. Therefore emWin reads back the color for the blinking functionality.
      It is important that you use the correct parameters for the read function GUIDRV_FlexColor_SetReadFunc66709_B16(). There are several different parameters. For me I have to pass GUIDRV_FLEXCOLOR_READ_FUNC_III as second parameter. (s. manual)

      It is also important to call the GUIDRV_FlexColor_SetReadFunc66709_B16() function befor calling the GUIDRV_FlexColor_SetFunc() function.

      here is my code:

      C Source Code

      1. void LCD_X_Config(void)
      2. {
      3. GUI_DEVICE * pDevice;
      4. GUI_PORT_API PortAPI = {0};
      5. CONFIG_FLEXCOLOR Config = {0};
      6. #if (NUM_BUFFERS > 1)
      7. GUI_MULTIBUF_Config(NUM_BUFFERS);
      8. #endif
      9. //
      10. // Set display driver and color conversion for 1st layer
      11. //
      12. pDevice = GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0);
      13. //
      14. // Common display driver configuration
      15. //
      16. if (LCD_GetSwapXY())
      17. {
      18. LCD_SetSizeEx (0, YSIZE_PHYS, XSIZE_PHYS);
      19. LCD_SetVSizeEx(0, YSIZE_PHYS * NUM_VSCREENS, XSIZE_PHYS);
      20. }
      21. else
      22. {
      23. LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);
      24. LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS * NUM_VSCREENS);
      25. }
      26. //
      27. // Configuration of GUIDRV_FLEX_COLOR
      28. //
      29. //
      30. // Set controller and operation mode
      31. //
      32. PortAPI.pfWrite16_A0 = LCD_X_Write0_16;
      33. PortAPI.pfWrite16_A1 = LCD_X_Write1_16;
      34. PortAPI.pfWriteM16_A1 = LCD_X_WriteM1_16;
      35. PortAPI.pfReadM16_A1 = LCD_X_ReadM1_16;
      36. PortAPI.pfRead16_A1 = LCD_X_Read1_16;
      37. GUIDRV_FlexColor_SetReadFunc66709_B16(pDevice, GUIDRV_FLEXCOLOR_READ_FUNC_III);
      38. GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66709, GUIDRV_FLEXCOLOR_M16C0B16);
      39. //
      40. // Orientation and offset of SEG/COM lines
      41. //
      42. Config.Orientation = DISPLAY_ORIENTATION;
      43. Config.RegEntryMode = 0;
      44. GUIDRV_FlexColor_Config(pDevice, &Config);
      45. }
      Display All
    • I didn't call GUIDRV_FlexColor_SetReadFunc66709_B16(), so I think the driver was using GUIDRV_FLEXCOLOR_READ_FUNC_I (the default function).

      When I tried to set GUIDRV_FLEXCOLOR_READ_FUNC_III, the program crashes with a HardFault. The call stack says that _ReadRect_16bpp_B16_III() calls guimem() that failed.
      Do you know why?

      Could you share the source code of LCD_X_ReadM1_16 and LCD_X_Read1_16?
    • Good morning,

      here we go:

      C Source Code

      1. /**
      2. @verbatim
      3. According to the address line pin we have to calculate the data address.
      4. For line A16 the address is calculated like this:
      5. RAM base address = 0X60000000 + 2^16 * 2 = 0X60000000 + 0X20000 = 0X60020000
      6. This address is the data address.
      7. Example code:
      8. #define Bank1_LCD_C ((uint32_t) 0x60000000) // Disp Reg ADDR
      9. #define Bank1_LCD_D ((uint32_t) 0x60020000) // Disp Data ADDR for A16
      10. @endverbatim
      11. */
      12. /* LCD /CS is NE1 - Bank 1 of NOR/SRAM Bank 1 */
      13. #define LCD_BASE (0x60000000UL) /* see memory map */
      14. #define LCD_REG16 (*((volatile uint16_t *)(LCD_BASE )))
      15. #define LCD_DAT16 (*((volatile uint16_t *)(LCD_BASE+0x20000U)))
      16. /**
      17. * @brief This function reads multiple data half words from the TFT.
      18. * The command/data pin is kept high during read operation.
      19. * @param Data Pointer to the data which is read from the TFT.
      20. * @param NumItems Number of data half words which were read.
      21. * @return None
      22. */
      23. void LCD_X_ReadM1_16(uint16_t * Data, int NumItems)
      24. {
      25. for (; NumItems; NumItems--)
      26. {
      27. *Data++ = LCD_DAT16;
      28. }
      29. }
      30. /**
      31. * @brief This function reades data from the TFT. The command/data pin is
      32. * kept high during read operation.
      33. * @return Read TFT data
      34. */
      35. uint16_t LCD_X_Read1_16(void)
      36. {
      37. return (LCD_DAT16);
      38. }
      Display All
      I am on a STM32F2 and use the FMSC peripheral for the communication with the display. Have you reserved enough memory for emWin in GUIConf.c (Function GUI_ALLOC_AssignMemory();)?
    • I found the problem that caused the crash. I forgot to set PortAPI.pfRead16_A1 for GUIDRV_FlexColor_SetFunc(). Now it works.

      Anyway I didin't understand. We configured ILI9341 to use the 16-bits interface in 16-bits per pixel (5-6-5). When the driver wants to set a pixel color, it issues a write command with a single 16-bits word where the color is packed in 5-6-5 format.
      Why the ILI9341 responds with 2-bytes (18-bits 6-6-6 format) during read commands? Is it possible to configure the driver to responds in 5-6-5 format, avoiding one read command for every pixel? In this case we could use GUIDRV_FLEXCOLOR_READ_FUNC_III.
    • Hello,

      to be honest, I tested the 3 different read function variants and the read function III was the only one which was working in my application. For the test I used a function where I can dump the screen content on a USB MSD with the aid of GUI_BMP_Serialize(). I took a lot of time in this issue, but I aborted the investigations after I got the correct behavior. Nevertheless this was a long time ago (2 years?) but today I took a deeper look into the ILI9341/emWin manuals and found the following:

      If I take a look into the ILI9341 manual to the section "8080-II Series Parallel Interface" there are 2 data packets in the drawing for the read cycle.

      emWin Manual:
      Commands supported by LCD_SetDevFunc()
      Further information about the LCD layer routines can be found under “LCD layer routines
      ” on page 1277.
      Important note on reading back pixel data from the controller
      Because of the plurality of the supported display controllers and their operation
      modes the driver has not been tested with each interface of each supported controller.
      The behavior of the controller when reading back pixel data often depends on
      custom configuration and hardware details. Because of that it could happen, that the
      driver has no appropriate reading function(s) available. In that case the above
      explained function LCD_SetDevFunc() can be used to set application defined functions
      for reading back pixel data.
      The main problem for the driver here is not getting data from the driver. Getting the
      color bits in the right order is the problem here. The custom defined functions need
      to supply ’pixel index’ values. This index format needs to comply to the index format
      determined by the color conversion routines configured for the driver device.
      Because the data supplied by the hardware interface functions of the driver in most
      cases does not have the right index format, the reading routines need to convert that
      raw data into the required pixel index format determined by the driver device configuration.
      For details about the hardware interface functions please also refer to
      GUIDRV_FlexColor_SetFunc() and its parameter pHW_API.
      For details about the pixel index format please also refer to
      GUI_DEVICE_CreateAndLink() and its parameter pColorConvAPI and the chapter
      ’Colors’.
      A sample configuration which shows how custom reading functions can be achieved is
      available in the configuration file sample folder shipped with the driver.

      Maybe you must define your own read back function in order to achieve single byte reads. But that is only an assumption...

      regards Thomas
    • Thomas W. wrote:

      Maybe you must define your own read back function in order to achieve single byte reads. But that is only an assumption...
      I don't think so. The controller (ILI9341) replies with one dummy plus two data bytes. Both bytes have colors, so one-byte read can't work.

      I was searching a command to configure the controller to reply with only one byte (encoded as 5-6-5), but it seems impossible. This behaviour can't be changed only by rewriting a new read back funtion on the host controller.