#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    4
    Rep Power
    0

    Drawing in a Win32 App without SetPixel


    I am writing a GIF animator in C. I can't use SetPixel because it is too slow when drawing large images.

    I have a color array, which contains at most 256 colors.
    Additionally, I have a 2D array, which dimensions are width * height. Each cell in the two-dimensional array contains an index, which is a reference to a color in the first array.

    Please note, some of the indices are considered to be transparent, which means that if you encounter them, you need to skip over them in the drawing phase.

    I have read about SetDIBitsToDevice, but I couldn't understand how to use it.

    Any help? Much appreciated.
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,837
    Rep Power
    480

    The trick


    Fast drawing explained:

    Draw to a region off screen, then map the entire array all at once.
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    4
    Rep Power
    0
    Originally Posted by b49P23TIvg
    Fast drawing explained:

    Draw to a region off screen, then map the entire array all at once.
    Could you elaborate? I am not that familiar with WinApi, so a reference would be nice.
  6. #4
  7. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,607
    Rep Power
    4247
    He means that you should use a function such as BitBlt() to bulk copy your buffer into the screen device context as needed. Click on the link and you'll see that there is an example of how to use it in that page, but briefly, something like this ought to do it:

    Code:
    PAINTSTRUCT ps;
    hDC = BeginPaint(hWnd, &ps);
    
    RECT rect;
    GetClientRect(hWnd, &rect); // To get size of window
    
    HDC hDCMem = CreateCompatibleDC(hDC); // Create a device context in memory
    int savedDC = SaveDC(hDCMem);
    
    // Now do your drawing to hDCMem here:
    for (int x = 0; x < width; x++) {
       for (int y = 0; y < height; y++) {
            SetPixelV(hDCMem, x, y, colorref[x][y]);
       }
    }
    
    // Now BitBlt the stuff from memory buffer to screen
    BitBlt(hDC, 0, 0, rect.right, rect.bottom, hDCMem, 0, 0, SRCCOPY);
    
    // Cleanup time
    RestoreDC(hDCMem, savedDC);
    DeleteDC(hDCMem);
    EndPaint(hWnd, &ps);
    Also, note the use of SetPixelV() instead of SetPixel(), since it is faster. However, the main idea is to use a memory buffer, draw everything in it and then BitBlt() the whole thing over when ready to draw.

    Note that this code is untested.
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    4
    Rep Power
    0
    @Scorpions4ever thank you for responding.
    I tried the snippet you included in your comment. However, it seems like nothing is being drawn.

    After a bit of debugging I have found that SetPixelV fails (it returns zero). But, calling GetLastError() returns 0, which is considered to be a success code.
  10. #6
  11. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,607
    Rep Power
    4247
    Try SetPixel() instead of SetPixelV().

    Also, you might need to CreateCompatibleBitmap(). See here for details: http://www.robertelder.ca/doublebuffering/
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2013
    Posts
    4
    Rep Power
    0
    The article you provided has proven its self, and my program works almost perfectly. How do I tell SetPixelV to set a pixel to be transparent? It seems like the bitmap if already filled with the color black. When I draw inside my nested loop, there are pixels I want that will remain drawn.

IMN logo majestic logo threadwatch logo seochat tools logo