Thread: Coloring single pixels - performance killer

  1. #1
    Registered User
    Join Date
    Aug 2006
    Posts
    68

    Coloring single pixels - performance killer

    Hello again!

    I want to make an image viewer for files with a simple uncompressed RGBA file structure.
    That means it has an unimportant header followed by packs of 4 bytes for R,G,B and A for every pixel of the image.

    Well, I was playing around with the SetPixel() function and had to notice that the creation of a filled 200x200 box like:
    Code:
    case WM_PAINT:
    		int pixel_x, pixel_y;
    		for (pixel_x = 100; pixel_x < 300; pixel_x++) {
    			for (pixel_y = 100; pixel_y < 300; pixel_y++) {
    				SetPixel(hdc1,pixel_y,pixel_x,0xFFFF00);
    			}
    		}
    		break;
    is a cpu killer as if I move the window or loose focus the app is taking 60% - 100% cpu and the longer the process stays and the more often I move the window around it is lagging more and more until it freezes (sometimes).

    So... is there a better way of drawing the picture out of the file? What are the other programs doing like ms paint? I know bmp, jpg, png etc formats are not uncompressed but you can still do anything laglessly in ms paint independant of the pictures attributes...

    There must be a way of saving the created pixels permanently (as one image or something), so the app doesn't always have to redraw all of them... or probably a completely other method instead of SetPixel()... also, how do I include the alpha transparency? It doesn't seem to work with only SetPixel().

    Thanks for any help!
    Hawk

    Edit:
    I included BeginPaint() and EndPaint() tags and a "PAINTSTRUCT" and it has gotten better, but still: Is there a better method in doing this? And also, how can I include the alpha opaque/transparency now?
    Last edited by Hawkin; 08-28-2006 at 08:06 PM.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I've only used the SDL, but I know that if you blit a surface it's a lot faster than writing each pixel individually.

    [edit] Googling for "c windows function SetPixel alpha" turned up a tutorial: http://rossm.net/Electronics/Compute...hics/index.htm [/edit]
    Last edited by dwks; 08-28-2006 at 08:20 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    I'd recommend doing a windows board search (maybe start with "image")--you'll probably find lots of examples. GDI+ might be one of the better options if you're looking at multiple image formats.
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Instead of multiple calls to SetPixel, you should use a dib section.

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Since the GDI works best with BMPs it is best to load your format into a buffer and then convert it into the correct format that Windows likes. GDI+ will greatly aid you in this.

  6. #6
    Registered User
    Join Date
    Aug 2006
    Posts
    68
    Well, thanks for the answers! Creating a dib section seemed to be the simplest choice. As I need to implement alpha blending I am using the BITMAPV4HEADER.

    Code:
    memset (&bmiHeader, 0, sizeof (BITMAPV4HEADER));
    bmiHeader.bV4Size        = sizeof(BITMAPV4HEADER);
    bmiHeader.bV4Width       = 300;
    bmiHeader.bV4Height      = 300;
    bmiHeader.bV4Planes      = 1;
    bmiHeader.bV4BitCount    = 32;
    bmiHeader.bV4V4Compression = BI_BITFIELDS; //BI_RGB;
    bmiHeader.bV4RedMask = 0x00FF0000;
    bmiHeader.bV4GreenMask = 0x0000FF00;
    bmiHeader.bV4BlueMask = 0x000000FF;
    bmiHeader.bV4AlphaMask = 0xFF000000;
    The RGB masks do work but changing the Alpha value has no effect at all...
    What could I've done / not done that it won't blend?

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    In order to alpha blend you must call AlphaBlend() which takes yet another structure in order to work. GDI is sort of a huge mess.

  8. #8
    Registered User
    Join Date
    Aug 2006
    Posts
    68
    Is there an other way of alpha blending? Why's there a header made for 32 bit bmps if it needs a GDI function to display them?
    Sadly I can't get AlphaBlend() to work.
    code:

    Code:
    WINGDIAPI BOOL WINAPI AlphaBlend(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION); // used global
    and inside the WndProc():

    Code:
    BLENDFUNCTION bld;
    bld.BlendOp = AC_SRC_OVER;
    bld.BlendFlags = 0;
    bld.SourceConstantAlpha = 255;
    bld.AlphaFormat = AC_SRC_ALPHA;
    
    ...
    
    	case WM_PAINT:
    		BeginPaint(hwnd, &Ps);
    			BitBlt(Ps.hdc, 40, 40, 200, 200, hdc, 0, 0, SRCCOPY);
    			AlphaBlend(Ps.hdc, 40, 40, 200, 200, hdc, 0, 0, 200, 200, bld);
    		EndPaint(hwnd, &Ps);
    		break;

    The result is a:

    [Linker error] undefined reference to `_Z10AlphaBlendP5HDC__iiiiS0_iiii14_BLENDFUNCTION@ 44'
    ld returned 1 exit status

  9. #9
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    You need to link with correct library, msimg32.lib (-lmsimg32 with mingw).
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  10. #10
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Also, rather than declaring the function yourself (your declaration won't work because it is not extern "C"), use this above your includes:
    Code:
    #define WINVER 0x0500

  11. #11
    Registered User
    Join Date
    Aug 2006
    Posts
    68
    It's going on well, the program is likely done, but I have still 2 problems left.
    The main problem is that I can't get AlphaBlend to function. Thanks for the two last posts, I can compile and link with no errors now, but using the AlphaBlend() function right after BitBlt() just has no effect, independant of SourceConstantAlpha and AlphaFormat.

    Here is the code:

    Code:
    HDC        hdc = NULL;
    PAINTSTRUCT Ps;
    BLENDFUNCTION bld;
    
    ...
    
    hdc = CreateCompatibleDC(NULL);
    
    ...
    
    bld.BlendOp = AC_SRC_OVER;
    bld.BlendFlags = 0;
    bld.SourceConstantAlpha = 0; //Should make the creating bmp completely invisible
    bld.AlphaFormat = AC_SRC_ALPHA; // Also tried 0
    Code:
    	case WM_PAINT:
    		BeginPaint(hwnd, &Ps);
    			BitBlt(Ps.hdc, 0, 0, 512, 512, hdc, 0, 0, SRCCOPY);
    			AlphaBlend(Ps.hdc, 0, 0, 512, 512, hdc, 0, 0, 512, 512, bld);
    		EndPaint(hwnd, &Ps);
    		break;
    I am directly drawing the pic in the main window with CreateDIBSection. The area is black. Does DIB_RGB_COLORS restrict anything?

    Code:
    hBmp = CreateDIBSection(NULL, (BITMAPINFO *)&bmiHeader, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);

    As long as I am not working on an editor for these file formats, non working Alpha blending is not that tragic...

    My second problem now is that after opening the file it's not actually drawn inside the window, I have to lay another window over the application window or I have to wipe or mop the target area with another windows window before anything is being drawn...
    I've tried out UpdateWindow() but it had no effect, i tried sending a WM_PAINT message with SendMessage() but it also didn't help.

  12. #12
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    The purpose of the AlphaBlend function is to draw the source image over the destination image with a specified amount of transparency. In your case, the destination(Ps.hdc) is undefined and it is therefore unclear what you are trying to achieve. Are you trying to make the image look transparent over white or another colour or are you trying to make the window transparent?

    >> I have to lay another window over the application window or I have to wipe or mop the target area with another windows window before anything is being drawn. <<

    You need to call InvalidateRect when the window needs repainting.

  13. #13
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    > In your case, the destination(Ps.hdc) is undefined and it is therefore unclear what you are trying to achieve.

    Shouldn't Ps.hdc contain a handle to a DC for the current window after calling BeginPaint (unless it failed)? Did you mean the source (hdc) is undefined?
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  14. #14
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Quote Originally Posted by JaWiB
    > In your case, the destination(Ps.hdc) is undefined and it is therefore unclear what you are trying to achieve.

    Shouldn't Ps.hdc contain a handle to a DC for the current window after calling BeginPaint (unless it failed)? Did you mean the source (hdc) is undefined?
    Yep, Ps.hdc is defined. I meant to say that the contents of the window (Ps.hdc) is undefined, which is why it needs painting. Although, I guess if you are using a background brush (WM_ERASEBKGND), then it might be defined to be the background colour.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Manipulating single LCD pixels
    By finnepower in forum Networking/Device Communication
    Replies: 3
    Last Post: 02-22-2008, 08:45 PM
  2. SLI? Gimmick or performance?
    By VirtualAce in forum A Brief History of Cprogramming.com
    Replies: 30
    Last Post: 03-25-2005, 09:54 AM
  3. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  4. inheritance and performance
    By kuhnmi in forum C++ Programming
    Replies: 5
    Last Post: 08-04-2004, 12:46 PM
  5. fancy strcpy
    By heat511 in forum C++ Programming
    Replies: 34
    Last Post: 05-01-2002, 04:29 PM