Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

GDI: Do not redraw the window after each output

Posted on 2004-04-05
13
Medium Priority
?
451 Views
Last Modified: 2007-12-19
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
0
Comment
Question by:MainMa
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
13 Comments
 
LVL 6

Expert Comment

by:joghurt
ID: 10764027
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?
0
 

Author Comment

by:MainMa
ID: 10767480
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
0
 
LVL 6

Accepted Solution

by:
joghurt earned 80 total points
ID: 10768336
1. No. If it were redrawn, you would have to begin the painting again, triggering another repaint, etc.
2. There are various functions in the Windows API dealing with bitmap operations. For your purpose see BitBlt, StretchBlt/StretchDIBits and SetDIBits.
3. It's quite easy. Supposing you have an array of RGB values. The pixels are organized by line, for example
0 1 2 3
4 5 6 7

LONG picWidth = ...;      // Image width in pixels, MUST be a multiple of 4.
LONG picHeight = ...;      // Image height in pixels.
void* picPtr = ...;           // Image data

BITMAPINFO bmi;
ZeroMemory (&bmi, sizeof (bmi));
bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
bmi.bmiHeader.biBitCount = 24;              // 24-bit image, you can specify 32 if you have 32-bit (A)RGB values in your array.
bmi.bmiHeader.biClrImportant = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biCompression = BI_RGB;   // On Win98/Me and Win2k/XP you can specify BI_JPEG and BI_PNG if you pass a jpeg or png image
bmi.bmiHeader.biWidth = picWidth;
bmi.bmiHeader.biHeight = picHeight;        // If it's positive: bottom-up bitmap, if it's negative: top-down bitmap
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biXPelsPerMeter = GetDeviceCaps (hDC, HORZRES) / GetDeviceCaps (hDC, HORZSIZE);
bmi.bmiHeader.biYPelsPerMeter = GetDeviceCaps (hDC, VERTRES) / GetDeviceCaps (hDC, VERTSIZE);
bmi.bmiHeader.biSizeImage = 0;             // Must be set to zero for BI_RGB images.

StretchDIBits (hDC, 0, picWidth, picWidth, -picWidth, 0, 0, picWidth, picPtr, &bmi, DIB_RGB_COLORS, SRCCOPY);
// Check documentation for parameters of StretchDIBits
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:MainMa
ID: 10769715
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!
0
 
LVL 6

Expert Comment

by:joghurt
ID: 10770133
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?
0
 

Author Comment

by:MainMa
ID: 10772178
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].
0
 
LVL 6

Expert Comment

by:joghurt
ID: 10772894
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.
0
 

Author Comment

by:MainMa
ID: 10773675
Thank you, all works.
0
 

Author Comment

by:MainMa
ID: 10773919
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)?
0
 
LVL 6

Expert Comment

by:joghurt
ID: 10774297
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.
0
 

Author Comment

by:MainMa
ID: 10774775
Yes, I know. But if i want precisely to load a file into a matrix, how can I do it?
0
 
LVL 6

Expert Comment

by:joghurt
ID: 10775252
Ask a new question. It has nothing to do with the current topic.
0
 

Author Comment

by:MainMa
ID: 10776835
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

721 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question