Thursday, October 19th 2017, 7:22am UTC+2

You are not logged in.

  • Login
  • Register

Dear visitor, welcome to SEGGER Forum. If this is your first visit here, please read the Help. It explains how this page works. You must be registered before you can use all the page's features. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

kenmux

Beginner

Date of registration: Jan 18th 2016

Posts: 36

1

Wednesday, March 2nd 2016, 6:07am

[SOLVED] Efficient way to draw bitmap using array of pixel data

Recently, I was stuck with drawing bitmap using array of pixel data.

The scenario is like:

Quoted

The image size is 320 x 240.
The array is something like uint32_t array[320*240].
All pixel data is 32-bit with RGB888.
The LCD works at GUICC_M565.
As a test, I drew the image pixel by pixel as follows:

C/C++ Source code

1
2
3
4
5
6
7
8
9
10
11
uint32_t  c, r;
uint32_t  * ibPtr = array;
for (r = 0; r < 240; r++)
{
  for (c = 0;  c < 320; c++)
  {
    GUI_SetColor (*ibPtr);
    GUI_DrawPixel (c, r);
    ibPtr++;
  }
}

The result was right, but too slow.
My question is: is there an efficient way to accomplish that?
I read UM03001 over and over again with no answer.

This post has been edited 1 times, last edit by "kenmux" (Mar 4th 2016, 6:55am)


XT-Matz

Beginner

Date of registration: Jul 16th 2015

Posts: 39

2

Wednesday, March 2nd 2016, 3:07pm

Hi kenmux,

Consider the following:

Dont let emWin draw each of the 76800 Pixel one by one when you want to diplay a bitmap.
The best way is to use the emWin "Bitmap Drawing" routines.
Look at chapter 8.1.4. and start e.g. with GUI_DrawBitmap().

You have to adapt your bitmap array to the needs of GUI_DrawBitmap() paramter definition.
An easy way to bild the bitmap is to use the Segger Bitmap Converter (see chapter 10):
Load any kind of picture / bitmap file
"Save As..." C-File and choose emWin color format (e.g. 565).
You will get an bitmap array.
This array you can directly use with GUI_DrawBitmap.
Quite simple and fast.

For a good performance: define the bitmaparray in the same color format your hardware is using, e.g. 565.
Otherwise emWin has to do a colorconversion for each(!) pixel (shifting bits back and forth). This comsumes a lot of processing power.
See hint in the documentation under 10.6.5:

"Further it is strongly recommended to save the C files in the exact same format used
by the hardware. Note that using the right format will have a positive effect on the
drawing performance. If a high color bitmap for example should be shown on a sys-
tem with a color depth of 16bpp which has the red and blue components swapped,
the best format is Â’High color 565, red and blue swappedÂ’. Already a slightly other
format has the effect, that each pixel needs color conversion, whereas a bitmap in
the right format can be rendered very fast without color conversion. The difference of
drawing performance in this case can be factor 10 and more."


Hope this helps.
Matz

kenmux

Beginner

Date of registration: Jan 18th 2016

Posts: 36

3

Thursday, March 3rd 2016, 3:49am

Hi XT-Matz,
Thanks for your reply! Your idea is bright & helpful.

Quoted

An easy way to bild the bitmap is to use the Segger Bitmap Converter (see chapter 10):
Load any kind of picture / bitmap file
"Save As..." C-File and choose emWin color format (e.g. 565).
Yep. The data is generated from a camera and stored in RAM. So, this is impossible.

Quoted

Dont let emWin draw each of the 76800 Pixel one by one when you want to diplay a bitmap.
The best way is to use the emWin "Bitmap Drawing" routines.
Look at chapter 8.1.4. and start e.g. with GUI_DrawBitmap().
This idea is good, and the problem is how to struct a bitmap using the pixel data (complicated but feasible).
Also, memory block copy may be involved (not very efficient).

So, is there any way to tell emWin how to fetch the pixel data in the array without bitmap header & info header?

This post has been edited 1 times, last edit by "kenmux" (Mar 3rd 2016, 3:52am)


XT-Matz

Beginner

Date of registration: Jul 16th 2015

Posts: 39

4

Thursday, March 3rd 2016, 10:41am

Hi kenmux,

Quoted

data is generated from a camera and stored in RAM
OK. With this new information my idea was a dog's breakfast...

I dont know wether it will work, but one idea could be:

GUI_DrawBitmap() needs a pointer to a GUI_BITMAP struct, containing all information needed: Sizes, BytesPerLine, BitsPerPixel,color Format, pointer to the bitmap.
Put into such a GUI_BITMAP structure all information about the arrangement of your graphic memory data.
A sample structure could be something like that:

Source code

1
2
3
4
5
6
7
8
9
10
11
GUI_CONST_STORAGE GUI_BITMAP bmgraphicmemory = {
  320, // xSize
  240, // ySize
  960, // BytesPerLine
  24, // BitsPerPixel
  (unsigned char *)_pgraphicmemory,  // Pointer to picture data
  NULL,  // Pointer to palette
  GUI_DRAW_BMP24
};

void GUI_DrawBitmap(bmgraphicmemory , 0, 0);

Please compare to chapter 8.1.4 and 8.1.5!

In the worst case if your bitmap data in memory is arranged in a way which is not supported by GUI_DrawBitmap (see 8.1.5), you may have to rearrange it previously. If you are limited with memory - who is not? - you must do it in multiple smaller portions.

I can imagine that this way will be much faster, than DrawPixel one by one.

Its only an idea. Dont hit me if it dont work, because I'm also a emWin beginner. But maybe the idea is helpful to you.

Regards.
XT-Matz

kenmux

Beginner

Date of registration: Jan 18th 2016

Posts: 36

5

Friday, March 4th 2016, 6:54am

Hi XT-Matz,

Quoted

OK. With this new information my idea was a dog's breakfast...
Take it easy, man. Your idea is feasible & helpful anyhow.

Quoted

GUI_DrawBitmap() needs a pointer to a GUI_BITMAP struct, containing all information needed: Sizes, BytesPerLine, BitsPerPixel,color Format, pointer to the bitmap.
Put into such a GUI_BITMAP structure all information about the arrangement of your graphic memory data.
The idea is great! And I tested with the code showed below:

C/C++ Source code

1
2
3
4
5
6
7
8
9
GUI_BITMAP bitmap = {0};
bitmap.XSize = 320;
bitmap.YSize = 240;
bitmap.BytesPerLine = 1280;
bitmap.BitsPerPixel = 32;
bitmap.pData = (const uint8_t *)array;
bitmap.pPal = NULL;
bitmap.pMethods = GUI_DRAW_BMP8888;
GUI_DrawBitmap (&bitmap, 0, 0);


The result was right except the red and blue swapped.
And to my surprise, there's no method api called 'GUI_DRAW_BMPM8888'!
So I tried to convert the data pixel by pixel and use GUI_DRAW_BMPM565 instead.
Hmm, it was not sound that efficient, but acceptable.

Thanks. You saved me!

Similar threads