Writing out a bitmap

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
hgm
Posts: 28355
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Writing out a bitmap

Post by hgm »

Can someone explain me how this device-context madness of Windows bitmaps works? it seems the MicroSoft doc I can dig up on this is just plain wrong.

What I want s very simple: I have a program that just prepared a bitmap, and copied it to the screen using BitBlt. Now I want to write that same bitmap to a file. One would expect there to be a standard call for that, as this does not seem such an outlandish action. But I could not find it.

The bitmap that was copied to the screen is only known to the program as a handle: HBITMAP bufferBitmap;

I got as far as using GetObject(bufferBitmap, sizeof(bm), &bm), where bm was declared as BITMAP, to dereference the handle pointer. (Can anyone explain me why simply writing *bufferBitmap does not work?)

The BITMAP structure that is written to bm by this call seems OK, in the sense that the bmWidth and bmHeight fields do indeed react to, and reflect the size of the image to be saved correctly. But according to the specs that structure should also contain a pointer to the actual bitmap pixels. But tht pointer is NULL.

How can Windows copy the image to the screen if it does not know eher the data is. Is this just a quirk of GetObject, that it tries to hide the data from th programmer to prevent tht it is useful? How does windows get to the data to be copied in a BitBlt? The BitBlt does not even get the bitmap to be copied as an argument, the only hint to what it must do is passed to it as a device context handle (HDC). Apparently this gets associated with a bitmap by a call to SelectObject. How would I get to the data starting from this handle, using only plain C pointer dereferencing in stead of calls to malignant functions? Or is this not possible at all, because the data is hidden in kernel memory space that a usere cannor access?
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: Writing out a bitmap

Post by Karlo Bala »

Working with windows bitmap without wrapper is painful task especially if you don't have experience with them. Maybe you should consult MSDN.

http://msdn.microsoft.com/en-us/library ... S.85).aspx

Good Luck!!!
Best Regards,
Karlo Balla Jr.
Gerd Isenberg
Posts: 2251
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: Writing out a bitmap

Post by Gerd Isenberg »

hgm wrote:Can someone explain me how this device-context madness of Windows bitmaps works? it seems the MicroSoft doc I can dig up on this is just plain wrong.

What I want s very simple: I have a program that just prepared a bitmap, and copied it to the screen using BitBlt. Now I want to write that same bitmap to a file. One would expect there to be a standard call for that, as this does not seem such an outlandish action. But I could not find it.

The bitmap that was copied to the screen is only known to the program as a handle: HBITMAP bufferBitmap;

I got as far as using GetObject(bufferBitmap, sizeof(bm), &bm), where bm was declared as BITMAP, to dereference the handle pointer. (Can anyone explain me why simply writing *bufferBitmap does not work?)

The BITMAP structure that is written to bm by this call seems OK, in the sense that the bmWidth and bmHeight fields do indeed react to, and reflect the size of the image to be saved correctly. But according to the specs that structure should also contain a pointer to the actual bitmap pixels. But tht pointer is NULL.

How can Windows copy the image to the screen if it does not know eher the data is. Is this just a quirk of GetObject, that it tries to hide the data from th programmer to prevent tht it is useful? How does windows get to the data to be copied in a BitBlt? The BitBlt does not even get the bitmap to be copied as an argument, the only hint to what it must do is passed to it as a device context handle (HDC). Apparently this gets associated with a bitmap by a call to SelectObject. How would I get to the data starting from this handle, using only plain C pointer dereferencing in stead of calls to malignant functions? Or is this not possible at all, because the data is hidden in kernel memory space that a usere cannor access?
Native Windows API is horror. Usually a Device Context is associated with a window or printer device.

If your windows-callback routine (assigned by RegisterWindowClass) receives a WM_PAINT message, one uses BeginPaint to get the DeviceContext, applies some drawing or TextOut methods with this DC and EndPaint to release it. Otherwise, if not processing WM_PAINT, you can use HDC GetDC(HWND hWnd) for a window device context or CreateDC/DeleteDC for other devices.

According to GetObject from MSDN:
if hgdiobj is a handle to a bitmap created by any other means, GetObject returns only the width, height, and color format information of the bitmap. You can obtain the bitmap's bit values by calling the GetDIBits or GetBitmapBits function.
In Win32 a handle is likely an "encapsulated" void*. There were/are issues with windows memory API even from 16-bit windows, related to getting a handle of a piece of "movable" allocated memory by LocalAlloc or GlobalAlloc, where LocalLock or GlobalLock receives the pointer and "Locks" the memory so that it is no longer "movable".
User avatar
hgm
Posts: 28355
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Writing out a bitmap

Post by hgm »

OK, thanks for the pointers. Indeed I have found something that works, using GetDIBits. Don't ask me why: I got it from a Chinese site where the C-code was the only thing that was displayed in western characters. :shock: Apparently it can copy the bitmap data to a user-declared array of bytes, and from there I can write it. Funny enough it seems to appear in that buffer upside down: if I want to delete the top part of the bitmap I have to refrain from writing the end of the array to file!

Anyway, I can write the WinBoard display as a diagram to a file, which other Windows software (like Paint) understands ithout complaints. Only thing is that this file is rather large, as it uses 32 bites per pixel. I guess for a Chess diagram 4 bits per pixel would be more than enough, so I should do a little processing on the bitmap before writing it to file.
plattyaj

Re: Writing out a bitmap

Post by plattyaj »

Bitmaps are stored in a file upside down. From the wikipage (that I know to be accurate "enough" because I implemented something from it in the past):

Bitmap data
This block of bytes describes the image, pixel by pixel. Pixels are stored "upside-down" with respect to normal image raster scan order, starting in the lower left corner, going from left to right, and then row by row from the bottom to the top of the image.[2]

Uncompressed Windows bitmaps can also be stored from the top row to the bottom, if the image height value is negative. If the number of bytes matching a row (scanline) in the image is not divisible by 4, the line is padded with one to three additional bytes of unspecified value so that the next row will start on a multiple of 4 byte location in memory or in the file. Following these rules there are several ways to store the pixel data depending on the color depth and the compression type of the bitmap.

http://en.wikipedia.org/wiki/Windows_bitmap


I hate bitmaps - no wonder base Java still refuses to support them ;)

Andy.
User avatar
hgm
Posts: 28355
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Writing out a bitmap

Post by hgm »

OK, I succeded in having the bitmap written in a somewhat more manageble format (4 bits/pixel, in stead of 32):

http://home.hccnet.nl/h.g.muller/diagram.bmp

(Apparently bmp files are not valid image type on this forum, so you will have to click the link.)

It is still a bit big (105 kB), though, since the bitmap is uncompressed, and the picture of course is imminently suitable for something like run-length coding.

When I try to convert it to a smarter format, like GIF, it shrinks to 21 kB. But then I get a very ugly effect on the square colors, though:

Image

Someone once told me that this is because the GIF format tries to approximate the original color with a much smaller pallette, using dither. Rather stupid, since the entire picture contains only 5 colors, and a color table describing these colors from a 4-billion-color palette would only cost 20 bytes.

Is there anything I can do about this, e.g. by picking the starting colors a bit smarter (i.e. have WinBoard 'round' them to colors in the GIF pallette, while rendering the diagram)? Is it know which colors can be used in GIF files without getting the dither, or is this a matter of trying out all 16 million colors?
User avatar
Jim Ablett
Posts: 2179
Joined: Fri Jul 14, 2006 7:56 am
Location: London, England
Full name: Jim Ablett

Re: Writing out a bitmap

Post by Jim Ablett »

Hi Harm,

I download your bmp and converted to gif using free Irfanview viewer/converter. http://www.irfanview.com/

Shrunk to 11.8kb.

Image

Jim.
Dirt
Posts: 2851
Joined: Wed Mar 08, 2006 10:01 pm
Location: Irvine, CA, USA

Re: Writing out a bitmap

Post by Dirt »

hgm wrote:When I try to convert it to a smarter format, like GIF, it shrinks to 21 kB. But then I get a very ugly effect on the square colors, though:

Image
I don't think that should happen. I tried converting the .bmp file to a .gif file using IrfanView and it came out looking fine, and smaller than your .gif too.

[Edit: I'm too slow! Incidentally, writing it as a .png would make it smaller still, and it's lossless.]
User avatar
hgm
Posts: 28355
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Writing out a bitmap

Post by hgm »

OK, so it is just this lousy MicroSoft Paint, and I hould not worry about it. 8-)