Link to home
Start Free TrialLog in
Avatar of MainMa
MainMa

asked on

GDI: Do not redraw the window after each output

I have a matrix 512*512, containing a color value. I want to draw on the screen an image, where each pixel will be at the color, defined by my matrix. I mustn't pass by image, but only using directly GDI output to the screen. If I output all pixels one by one, the entire time of outputing 512^2 pixels is about 5 seconds. It seems that GDI redraws the window each time it outputs a pixel. I'm right, am I? How is it possible to redraw only once, at the end, when all pixels are set?

How Paint does? It also inputs each pixel, but it doesn't take much time?

Thanks,
MainMa
Avatar of joghurt
joghurt

No, it's SetPixel that is slow, not the redraw.

You should create a bitmap in the memory (don't worry, in fact you have only to create a bitmap header) and use bitmap drawing functions.

What kind of colour array do you have? RGB values on three bytes for each pixel, ARGB values on four bytes or do you have some indexed image?
Avatar of MainMa

ASKER

1. Were I right when I said that in fact, the window is redrawed each time I draw a pixel?
2. How does Windows do to output to the screen a bitmap created in memory? There must be some function in some Windows DLL which does it...
3. I had an idea of using bitmap images like you said, but I hadn't got too much information. Can you give an idea of something, which will output an image, built from array of RGB values?

Thanks,
MainMa
ASKER CERTIFIED SOLUTION
Avatar of joghurt
joghurt

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of MainMa

ASKER

Help!
> void* picPtr = ...; // Image data
What type of variable must-it be? I tried to set a matrix "COLORREF Matrix[size][size];" but I can's see something correct on the screen (horisontal red/green/blue/black lines). If, instead of COLORREF I use int, the result is the same!
A COLORREF is 4-bytes large, so in this case you should change bmi.bmiHeader.biBitCount to 32. The same applies to "int".
Do you have any special reason for using COLORREFs for each pixel instead of 24-bit values? This latter one can be done by using a simple character (or BYTE) array in which the R, G and B bytes come after each other: R1, G1, B1, R2, G2, B2...
BYTE Matrix[size][size * 3];

Btw, how do you initialize this array?
Avatar of MainMa

ASKER

This is my new code:

----------------------------------------------------------------------------------------------------
BYTE Matrix[8][8*3];
// Fill some cells
void initialise()
{
      Matrix[0][0] = 255; Matrix[0][1] = 0; Matrix[0][2] = 0;
      Matrix[0][3] = 0; Matrix[0][4] = 255; Matrix[0][5] = 0;
      Matrix[0][6] = 0; Matrix[0][7] = 0; Matrix[0][8] = 255;
      Matrix[0][9] = 255; Matrix[0][10] = 255; Matrix[0][11] = 0;
}
[...]
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
      LONG picWidth = 8; // Image width in pixels, MUST be a multiple of 4.
      LONG picHeight = 8; // Image height in pixels.
      void* picPtr = &Matrix; // Image data
[...]
case WM_PAINT:
      StretchDIBits(hdc,
            10, 10, picWidth*20, picHeight*20,
            0, 0, picWidth, picHeight,
            picPtr, &bmi, DIB_RGB_COLORS, SRCCOPY);
[...]
----------------------------------------------------------------------------------------------------

OK, it works, but first, "Matrix[0][0] = 255; Matrix[0][1] = 0; Matrix[0][2] = 0;" gives a blue pixel instead of red one, green stays green, and blue becomes red. I can, of course, invert each time first and third values, but maybe this invertion is an error...
It seems to me that having BYTE Matrix[size][size*3]; is compicated to store an image. For example, when I would store 1024*1024 image, it will take too much time to the program to convert Matrix1[a][b][3] to Matrix2[a][b*3].
Sorry, it was my fault, not yours. Parameter order for the RGB macro is R, G, B but in the memory the byte order is reversed so it's B, G, R.

In my view Matrix1[a][b][3] and Matrix2[a][b*3] are equivalent in the memory. So you can use the first declaration if you prefer that one.
Avatar of MainMa

ASKER

Thank you, all works.
Avatar of MainMa

ASKER

Just another question: how can I load an image (a file) to Matrix1[a][b][3] (we suppose that the size of image is a*b)?
If you have a bitmap file, you don't have to do the above trick. A simple LoadImage will supply you with a HBITMAP that can be used for drawing. But that's another question.
Avatar of MainMa

ASKER

Yes, I know. But if i want precisely to load a file into a matrix, how can I do it?
Ask a new question. It has nothing to do with the current topic.