Thread: GetPixel and getting a screenshot.

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    8

    Question GetPixel and getting a screenshot.

    I got the following code in a DLL , also i got another function wrapping getPixel. But i got 2 problems with result i'm getting.

    - One is that the image looks more stretched than it should be

    - Secondly it doesn't seem to be a 24 bit image, but rather 256 colors

    I searched the internet for a solution but couldn't find one. I'm also a bit puzzled on what selectObject really does, msdn is rather vague about it.

    Anyone that can help me out with this ?

    Code:
    HDC doBitmap(HWND hwnd) {
    	int result;
    	int height = getHeight(hwnd);
    	int width = getWidth(hwnd);
    	HDC hdc = GetWindowDC(hwnd);
    	if (hdc)
    	{
    		HDC hdcMem = CreateCompatibleDC(hdc);
    		if (hdcMem)
    		{
    			HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width,height);
    			if (hbitmap)
    			{
    				SelectObject(hdcMem, hbitmap);
    				result = PrintWindow(hwnd, hdcMem, 0);
    				return hdcMem;
    			}
    			DeleteObject(hdcMem);
    		}
    		ReleaseDC(hwnd, hdc);
    	}
    	return 0;
    }

  2. #2
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    What's GetPixel() got to do with making a screenshot?
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  3. #3
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    I'm using the DLL in an different programming language, and i need to get a screen of a window in there. GetPixel is an easy way to retreive the color values.
    And getpixel can use the HDC pointer.

  4. #4
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Don't you think that copying the image to your bitmap using BitBlt() could be a little more effective?
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  5. #5
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    Where whould you put the bitblt line... ?


    i just tried to use bitblt , but then i'm not getting the window capture but just a part of it or the pixels on the same location of some other window that is on top of it.
    Last edited by pur; 02-08-2009 at 04:34 PM.

  6. #6
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by pur View Post
    I'm also a bit puzzled on what selectObject really does, msdn is rather vague about it.
    SelectObject() 'pushes' one GDI object into a DC, 'pop'ing the current GDI object of the same type out.

    Your current code has lots of GDI leaks.
    If using a .NET era IDE this _may_ not be too much of an issue, but it is bad code.
    If in MSVC 6 this code will mean the PC needs a reboot after a few calls to thei function.

    EDIT: use BitBlt()
    After you have the Screen DC (GetDC(NULL))
    After you have a compatible DC,
    with a screen sized compatible BMP selected into the compatible DC

    BitBlt() from the Screen DC to the compatible DC, the size of the screen.

    then clean up

    Code:
    //select in created compatible BMP
    HBITMAP hOrigBmp=(HBITMAP*)SelectObject(hdc,hCompatibleBmp);
    //use
    
    //return original GDI objects before clean up or we will leak the very limited GDI objects.
    //or the object (mainly bmps) will fail to delete while 'in' a DC
    
    SelectObject(hdc,hOrigBmp);//no need to catch return as we have the object.
    
    //now we can clean up the bitmap
    DelectObject(hCompatibleBmp);
    
    //and the DC
    //etc.....
    Last edited by novacain; 02-09-2009 at 01:30 AM.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  7. #7
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    If i do it like this , with use of bitbtl , i get a part of the screen back instead of the window. And it still seems to be in 256 colors. :/

    Code:
    HDC doBitmap(HWND hwnd) {
    	int result;
    	int height = getHeight(hwnd);
    	int width = getWidth(hwnd);
    	HDC hdc = GetWindowDC(hwnd);
    	if (hdc)
    	{
    		HDC hdcMem = CreateCompatibleDC(hdc);
    		if (hdcMem)
    		{
    			HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width,height);
    			if (hbitmap) {
    
    				SelectObject(hdcMem, hbitmap);
    
    				BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
    				
    				HBITMAP* hOrigBmp=(HBITMAP*)SelectObject(hdc,hbitmap);
    
    				SelectObject(hdc,hOrigBmp);
    
    				DeleteObject(hbitmap);
    
    
    				return hdcMem;
    			}
    			DeleteObject(hdcMem);
    		}
    		ReleaseDC(hwnd, hdc);
    	}
    	return 0;
    }

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    				SelectObject(hdcMem, hbitmap);
    
    				BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
    				
    				HBITMAP* hOrigBmp=(HBITMAP*)SelectObject(hdc,hbitmap);
    Surely, you want to store the original bitmap when you FIRST select the hbitmap, not after you've already selected it. I'm pretty sure that hOrigBmp is actually going to be equal to hbitmap in this case.

    How are you inspecting/saving/displaying the information gathered in your bitmap - or, how do you know it's an 8bpp image?

    This link is an example of how to do a screen copy in a standalone application:
    http://msdn.microsoft.com/en-us/libr...02(VS.85).aspx

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    I'm using getPixel on hdcMem . I'm getting more and more confused about the code you guys supply-ing and even if it's all needed.

  10. #10
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Quote Originally Posted by pur View Post
    I'm using getPixel on hdcMem . I'm getting more and more confused about the code you guys supply-ing and even if it's all needed.
    All the previous posts should have helped you get to the point of BitBlting. Your problem probably lies in what you do after the BitBlting. I've used the above posts to get to the point of BitBlting. At that point I wrote two additional functions. One to build the bitmap header and the second to write the desktop snapshot out to a bitmap file. Herein probably lies your problem. Incorrectly building the bitmap header structure and/or incorrectly writing the data out to a bitmap file will provide strange (incorrect) results.

  11. #11
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Quote Originally Posted by pur View Post
    If i do it like this , with use of bitbtl , i get a part of the screen back instead of the window. And it still seems to be in 256 colors. :/
    As you delete the bitmap you have drawn to (hbitmap) prior to any chance to use it, I would assume you get a totally black screen.

    A HDC is a holder for GDI objects.

    The GDI object you want is the BMP (which you can get from the HBITMAP), not the HDC.

    If in doubt do a search, I posted code to do screen capture years ago.

    Watch 24bit colour depth (if doing conversions to a consistent colour depth) where the colours are reversed (compared to 16 or 32 bit).
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  12. #12
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    Ah ok, but there isn't any equivalant of getpixel on HBitmap.

  13. #13
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Why do you need GetPixel()?

    You need to write the BMP parts.

    GetDIBits() (all at once) will be faster than individually getting each pixel.




    here is some code for the header

    http://cboard.cprogramming.com/showthread.php?t=40807

    rest should be around here somewhere......
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  14. #14
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    Why do you need GetPixel()?

    You need to write the BMP parts.

    GetDIBits() (all at once) will be faster than individually getting each pixel.
    I got the functions in a win32 DLL for wrapping. Because i'm using it in an different programming language. In that language i only have a setPixel function i can use.

  15. #15
    Registered User
    Join Date
    Feb 2009
    Posts
    8
    Is there maby a possiblity to retreive color values and position with use of the HBITMAP pointer?

Popular pages Recent additions subscribe to a feed