Using memory devices with transparency

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

  • Using memory devices with transparency

    Hello to everyone,

    I'm working with emWin simulator and trying to implement a simple speedo- (or any other-) meter, just an abstract scale on the background and a needle moving under that scale.
    My idea is to use GUIBuilder for creating a window, placing a scale image and placing a needle image vertically upwards using IMAGE widget.
    After that I create a memory device as a source device for vertical needle and draw the needle image into this device from array (dta) generated by GUIBuilder.
    Next I create a second memory device as a destination for turned needle and set background colors as transparent in both devices.
    Next I create a PROGBAR widget under the scale with the same size as a second destination memory device. This PROGBAR is needed just for setting a value and triggering its WM_PAINT message and rotating the needle within the borders of this PROGBAR according to its value using memory devices instead of showing a real PROGBAR.

    My problems are:
    - memory devices have no transparency (the dest device with the black background);
    - artifacts (old needle position) when rotating the needle.

    Can anyone help with my problem.

    Thanks for your time.

    LCD size in simulation is 1024x768.
    NUM_BUFFERS is 3.

    My simple code:
    Main.c:

    C Source Code: Main.c

    1. #include "GUI.h"
    2. #include "DIALOG.h"
    3. #include "IMAGE_Private.h"
    4. #define RECOMMENDED_MEMORY (1024L * 5)
    5. WM_HWIN CreateWindowMeter(void);
    6. void MainTask(void) {
    7. GUI_Init();
    8. WM_MULTIBUF_Enable(1);
    9. //
    10. // Check if recommended memory for the sample is available
    11. //
    12. if (GUI_ALLOC_GetNumFreeBytes() < RECOMMENDED_MEMORY) {
    13. GUI_ErrorOut("Not enough memory available.");
    14. return;
    15. }
    16. CreateWindowMeter();
    17. while(1)
    18. {
    19. GUI_Delay(50);
    20. }
    21. }
    Display All


    Some code in WindowMeterDLG.c (attached):

    C Source Code: WindowMeterDLG.c

    1. ...
    2. GUI_MEMDEV_Handle hMemArrowSrc, hMemArrowDst;
    3. PROGBAR_Handle hProgbar;
    4. GUI_RECT pRect1, pRect2;
    5. int Val, dVal;
    6. WM_HTIMER hTimer;
    7. ...
    8. static void _cbProgbar(WM_MESSAGE * pMsg) {
    9. GUI_RECT pRect;
    10. int Val;
    11. switch (pMsg->MsgId) {
    12. case WM_PAINT:
    13. // get the relative coordinates of the PROGBAR area
    14. WM_GetClientRect(&pRect);
    15. // get the PROGBAR value
    16. Val = PROGBAR_GetValue(pMsg->hWin);
    17. // select the dest device
    18. GUI_MEMDEV_Select(hMemArrowDst);
    19. // clear it with transparency
    20. GUI_SetBkColor(GUI_TRANSPARENT);
    21. GUI_Clear();
    22. // rotate the source device and save the result in dest device
    23. GUI_MEMDEV_Rotate(hMemArrowSrc, hMemArrowDst, pRect1.y1 + 1 - pRect1.x1 - 1, 0, (90 - Val * 180 / 100) * 1000, 1000);
    24. // select lcd
    25. GUI_MEMDEV_Select(0);
    26. // get the absolute coordinates of the PROGBAR area
    27. WM_GetWindowRect(&pRect);
    28. // show the rotated needle
    29. GUI_MEMDEV_WriteAt(hMemArrowDst, pRect.x0, pRect.y0);
    30. break;
    31. default:
    32. PROGBAR_Callback(pMsg);
    33. break;
    34. }
    35. }
    36. static void _cbDialog(WM_MESSAGE * pMsg) {
    37. const void * pData;
    38. WM_HWIN hItem;
    39. U32 FileSize;
    40. // USER START (Optionally insert additional variables)
    41. int val;
    42. // USER END
    43. switch (pMsg->MsgId) {
    44. case WM_INIT_DIALOG:
    45. //
    46. // Initialization of 'WindowMeter'
    47. //
    48. hItem = pMsg->hWin;
    49. WINDOW_SetBkColor(hItem, GUI_MAKE_COLOR(0x00472D16));
    50. //
    51. // Initialization of 'ImageMeterBckgnd'
    52. //
    53. hItem = WM_GetDialogItem(pMsg->hWin, ID_IMAGE_0);
    54. pData = _GetImageById(ID_IMAGE_0_IMAGE_0, &FileSize);
    55. IMAGE_SetDTA(hItem, pData, FileSize);
    56. //
    57. // Initialization of 'Image'
    58. //
    59. hItem = WM_GetDialogItem(pMsg->hWin, ID_IMAGE_1);
    60. pData = _GetImageById(ID_IMAGE_1_IMAGE_0, &FileSize);
    61. IMAGE_SetDTA(hItem, pData, FileSize);
    62. // USER START (Optionally insert additional code for further widget initialization)
    63. hItem = WM_GetDialogItem(pMsg->hWin, ID_IMAGE_1); // get the needle image widget handlder
    64. WM_HideWin(hItem); // hide it, don't need anymore
    65. WM_GetClientRectEx(hItem, &pRect1); // get the relative coordinates
    66. WM_GetWindowRectEx(hItem, &pRect2); // and the absolute coordinates of the image for memory devices
    67. // create a source and dest devices
    68. hMemArrowSrc = GUI_MEMDEV_Create(0, 0, pRect1.x1 + 1, pRect1.y1 * 2 - pRect1.x1 + 1);
    69. hMemArrowDst = GUI_MEMDEV_Create(0, 0, GUI_MEMDEV_GetYSize(hMemArrowSrc), GUI_MEMDEV_GetYSize(hMemArrowSrc) / 2 + (pRect1.x1 + 1) / 2);
    70. // copy the vertical needle image to the source device
    71. GUI_MEMDEV_Select(hMemArrowSrc);
    72. GUI_SetBkColor(GUI_TRANSPARENT); // make it transparent
    73. GUI_Clear();
    74. GUI_DrawStreamedBitmapAuto(_acImage_1, 0, 0); // copy the image
    75. GUI_MEMDEV_Select(0); // select lcd
    76. // create a progbar under the scale with the size of dest device
    77. hProgbar = PROGBAR_Create(pRect2.x0 - WM_GetWinSizeY(hItem) + WM_GetWinSizeX(hItem), pRect2.y0, GUI_MEMDEV_GetYSize(hMemArrowSrc), GUI_MEMDEV_GetYSize(hMemArrowSrc), WM_CF_SHOW);
    78. WM_AttachWindow(hProgbar, pMsg->hWin); // attach to the current window
    79. WM_SetHasTrans(hProgbar); // hide it
    80. WM_SetCallback(hProgbar, _cbProgbar); // for handling WM_PAINT message
    81. dVal = 1; // for incrementing / decrementing the PROGBAR value
    82. hTimer = WM_CreateTimer(pMsg->hWin, 0, 50, 0); // for changing the PROGBAR value every 50 ms
    83. // USER END
    84. break;
    85. // USER START (Optionally insert additional message handling)
    86. case WM_TIMER:
    87. Val += dVal; // incrementing / decrementing the PROGBAR value
    88. if ((Val > 100) || (Val < 0))
    89. dVal = -dVal; // change the sign for incrementing / decrementing
    90. PROGBAR_SetValue(hProgbar, Val); // set the PROGBAR value
    91. WM_RestartTimer(hTimer, 50); // restart the timer
    92. break;
    93. // USER END
    94. default:
    95. WM_DefaultProc(pMsg);
    96. break;
    97. }
    98. }
    Display All
    Files

    The post was edited 10 times, last by LexaGb ().

  • Hello,

    I'm using Visual Studio 2010.
    I rebuilded the solution using "emWin Simulation & Trial version" pack downloaded from Segger's site (all header files, lib files and other...).
    The emWin version noticed there is v5.46.
    The color conversion macro defined there is GUICC_888. Previously I used GUICC_8888.
    GUI_NUMBYTES is 0x280000 by default.
    The only change I made in LCDConf.c file is resolution (1024 x 768).
    I use Bitmap Converter v5.32 for converting the arrow image from STemWin pack by ST (not demo version from Segger).
    And also for generating dialog code I use GUIBuilder v5.32 from that pack.
    The arrow image is converted to pallete with minimum colors (3 colors for the arrow itself, and white color on the background is a transparency color (0xFFFFFF)).
    And then the arrow image saved as dta with RLE4 compression and assigned to the IMAGE widget in GUIBuilder.
    I attached config files, and also arrow image files (bmp and dta), and also main() code and dialog code once again.

    There are fewer artifacts but they still exist and also no transparency.

    Thanks for your time.

    Files
    • Files.7z

      (11.02 kB, downloaded 14 times, last: )

    The post was edited 9 times, last by LexaGb ().

  • Hello, Sven.

    I slightly changed the dialog code, memory devices are both 32 bpp now, color conversion is GUICC_8888.
    I checked the data in both memory devices using GUI_MEMDEV_GetDataPtr() function.
    As I see in the debug session the source mem device correctly filled with GUI_TRANSPARENT color. The data is: 0xFF000000, 0xFF000000...


    But the dest mem device contains no transparency neither after using GUI_Clear() with GUI_TRANSPARENT color nor after using GUI_MEMDEV_Rotate(). The data is: 0x00000000, 0x00000000...

    So I tried to fill the dest device with transparency manually with direct access to memory.

    C Source Code: WindowMeterDLG.c

    1. ...
    2. unsigned long * pix;
    3. ...
    4. pData = GUI_MEMDEV_GetDataPtr(hMemArrowDst);
    5. // clear it with transparency
    6. for (pix = (unsigned long *) pData; pix < (unsigned long *) pData + memdev_dst_size; pix++)
    7. *pix = GUI_TRANSPARENT;

    After that I see transparency on the screen but there are still artifacts.


    I attached full dialog source code. The other change is only GUICC_8888 in LCDConf.c.

    Thanks for your time.
    Files
  • Hi,

    I got it, this was a bit tricky. The problem is the PROGBAR widget. When it gets a new value set (in WM_TIMER) it will also get redrawn, but only a small rectangle of the PROGBAR. This causes not the complete area to be redrawn and results in such a strange behavior.

    The solution is to simply call WM_InvalidateWindow(hProgbar) right after setting a new value for it.

    Sometimes it can be much easier to set up a normal WM window and modify it to your needs. With widgets it can get tricky sometimes because you don't know how they do things (like in this case).

    Regards,
    Sven
  • Hello, Sven

    It works!
    And I took your advice and changed the PROGBAR to a window using WM_CreateWindowAsChild() and just calling WM_Invalidate() for that window. In combination with manual filling the dest device with transparency it works fine.


    Thank you for your time.