Is there a known issue with reading a 32-bit DIB as a CF_BITMAP? The
problem goes away if the DIB has BI_BITFIELDS compression, which makes
me suspect the conversion from CF_DIB to CF_BITMAP is assuming the
presence of three RGB mask words even in the BI_RGB case.
Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
And how do you read it? Do you use some library for that? There are two ways of saving 32bpp DIB, either as BI_RGB encoded and BI_BITFIELDS encoded. The only differnce will be that for BI_BITFIIELDS after BITMAPINFOHEADER there will be 3 DWORDS containing color masks (which for 32bpp will be anyway 0x00FF0000, 0x0000FF00, 0x000000FF). I've noticed that some poorly written clibboard libraries does not recognize BI_RGB format for 32bpp CF_DIB format, and always assume it's CF_BITFIELDS. So routine in such library, skips first 12 bytes after BITMAPINFOHEADER (regardless of the value of biCompression field!) and start reading scanlines from there. This is a bug and results in 3 pixel shift to the left of entire image as well as it theoretically might result in a crash (reading 12 more than available).
I know such clipboard library is for example provided with Delphi, since I could saw applications written in that language that do have this bug. Well written application don't have this issue as you noticed yourself, so you can either write CF_DIB clipboard handling yourself, or contact provider of the library/language you use and request that they fix it.
--
Grzegorz Wróbel
http://www.4neurons.com/
677265676F727940346E6575726F6E732E636F6D
No, everything is pure Win32 API. In my main code I first resize the
bitmap handle using CopyImage then reformat it to a different color
depth using GetDIBits, but to demonstrate that the problem wasn't in my
code I simply used:
OpenClipboard(hwnd);
hbm = GetClipboardData(CF_BITMAP);
SelectObject(hdcmem, hbm);
InvalidateRect(hwnd, NULL, FALSE);
(where my WM_PAINT blits the memory DC to the screen).
> I've noticed that some poorly written clibboard libraries does not
> recognize BI_RGB format for 32bpp CF_DIB format, and always assume
> it's CF_BITFIELDS.
Indeed, but I believe the fault is in Windows! Maybe you're too quick
to blame the library, they may simply be using API calls as I am.
Those programs which work correctly, like Paint, are probably reading
the clipboard data as CF_DIB thus circumventing the problem.
Maybe I am, I never used CF_BITMAP to retrieve or set bitmap into clipboard. If that's indeed the Window's flaw, then one should retrieve bitmap using CF_DIB instead and use CreateDibSection()/CreateDIBitmap() to obtain the bitmap handle.
(Same applies to a library anyway, if there is an API bug Microsoft won't fix soon or ever, author of the library should compensate for that.)
If you use GetDIBits with a NULL for the lpvBits field as microsoft does
during the conversion,
the function will fill out the BITMAPINFO structure for the bitmap.
For a 32bpp bitmap, the BITMAPINFOHEADER biCompression field will be filled
with BI_BITFIELDS.
This accounts for the 3 pixel shift that you are seeing.
The solution is simple. If you request a CF_BITMAP from the clipboard, do
your own conversion to a DIB.
You may use GetDIBits to convert a 32bpp bitmap with BI_RGB instead of
BI_BITFIELDS.
<ne...@rtrussell.co.uk> wrote in message
news:1159742679....@i3g2000cwc.googlegroups.com...
The original query was about conversion *from* CF_DIB *to* CF_BITMAP
(that is, the bitmap was written to the clipboard as CF_DIB and read as
CF_BITMAP); I don't see how GetDIBits is relevant to that. The
observed phenomenon is that the bitmap returned from the clipboard with
GetClipboardData(CF_BITMAP) is offset by three pixels compared with the
original DIB.
> The solution is simple. If you request a CF_BITMAP from the clipboard, do
> your own conversion to a DIB.
The returned HBITMAP is already corrupted (the first 3 pixels are
missing).
Do you know how Microsoft converts a CF_DIB to a CF_BITMAP?
He probably meant that after obtaining HBITMAP you could try to use GEtDIBBits() and then check whether the format is BI_RGN or BI_BITFIELDS. You could tgen recreate HBITMAP from the DIB bits( which would be pretty idiotic this way). The way it works for sure, is (as I mentioned before) to retrieve the bitmap as CF_DIB and then create HBITMAP using CreateDIBSection()/CreateDIBBitmap().
I have designed my own graphic file format once , and I needed to write simple converting application for it. You can check it out:
http://www.4neurons.com/other/mbm/mbm.html
You can paste 32bpp images from clipboard in that program and it will handle them well, regardless if the compression is BI_RGB or BI_BITFIELDS.
>
>>The solution is simple. If you request a CF_BITMAP from the clipboard, do
>>your own conversion to a DIB.
>
>
> The returned HBITMAP is already corrupted (the first 3 pixels are
> missing).
>
> Do you know how Microsoft converts a CF_DIB to a CF_BITMAP?
If you refer to MS-Paint, they probably do it the way I mentioned.
Microsoft uses CreateDIBitmap to convert a DIB to a DDB.
> The returned HBITMAP is already corrupted (the first 3 pixels are
> missing).
Grzegorz is correct. If you are working with DIB's, then query the
Clipboard for the CF_DIB format and only request that the clipboard do a
format conversion when the clipboard reports that the native CF_DIB was not
placed on the clipboard by the original application.
Grzegorz said "...recreate HBITMAP from the DIB bits( which would be pretty
idiotic this way)."
It may seem to be "idiotic" but if you know that the HBITMAP is corrupted
and you do not want to query the clipboard for the CF_DIB and you need to
use the DDB instead of the DIB, then you must recreate the HBITMAP to get
rid of the "3 pixel" corruption.
<ne...@rtrussell.co.uk> wrote in message
news:1159897537.5...@m73g2000cwd.googlegroups.com...