CreateDIBSection fails with EDivideZero exception

93 views
Skip to first unread message

Ian Boyd

unread,
Jul 24, 2008, 5:18:35 PM7/24/08
to
function CreateDIBSection_V5(DC: HDC;
p2: PBitmapV5Header;
p3: UINT;
var p4: Pointer;
p5: THandle; p6: DWORD): HBITMAP; stdcall; external GDI32 name
'CreateDIBSection';


procedure TForm1.Button1Click(Sender: TObject);
var
bm: HBITMAP;
dc: HDC;
BitmapHeader: TBitmapV5Header;
pBits: Pointer;
begin
ZeroMemory(@BitmapHeader, SizeOf(BITMAPV5HEADER));
BitmapHeader.bV5Size := SizeOf(BITMAPV5HEADER);
BitmapHeader.bV5Width := 32;
BitmapHeader.bV5Height := 32;
BitmapHeader.bV5Planes := 1;
BitmapHeader.bV5BitCount := 32;
BitmapHeader.bV5Compression := BI_BITFIELDS;
BitmapHeader.bV5RedMask := $00FF0000;
BitmapHeader.bV5GreenMask := $0000FF00;
BitmapHeader.bV5BlueMask := $000000FF;
BitmapHeader.bV5AlphaMask := $FF000000;

dc := GetDC(0);

bm := CreateDIBSection_V5(
dc,
@BitmapHeader,
DIB_RGB_COLORS,
pBits,
0, 0);
end;


The call to CreateDIBSection throws an EDivideZero exception.

It doesn't fail for others:
How To Create an Alpha Blended Cursor or Icon in Windows XP
http://support.microsoft.com/kb/318876

http://www.delphipraxis.net/topic125964.html
http://www.delphipraxis.net/post539759.html

i step into it in the CPU windows, i get into GDI32.CreateDIBSection, i keep
tracing it down, and i eventually see yes - it's dividing by zero:

gdi32.CreateDIBSection

mscms.CreateProfileFromLogColorSpaceW
73b36089 call -$00000495

ICM32.CMCreateProfileW
55e9433e fdivr qword ptr [eax]


Which doesn't really help me. Plus i'm sure it's not a bug in
CreateDIBSection.

But i can't figure it out.


David Ninnes

unread,
Jul 24, 2008, 7:34:18 PM7/24/08
to

Works for me,

Vista /D2007

if you've got a bigger sample it would be good, I don't know if the bitmap
created is valid.

cheers,
Dave

Ian Boyd

unread,
Jul 24, 2008, 10:47:25 PM7/24/08
to

That's the exact code i can run that fails.

XP/D5

Grrrr.

David Ninnes

unread,
Jul 25, 2008, 12:34:13 AM7/25/08
to

"Ian Boyd" <ian.borla...@zunblvlda1.dyndns.org.spamsucks> wrote in
message news:4889...@newsgroups.borland.com...

Nope, fails for me on XP/2007

David Ninnes

unread,
Jul 25, 2008, 12:16:24 AM7/25/08
to

"Ian Boyd" <ian.borla...@zunblvlda1.dyndns.org.spamsucks> wrote in
message news:4889...@newsgroups.borland.com...

maybe the D5 data structure definitions aren't quite right? V5 bitmaps were
fairly new then I think.

cheers,
Dave

David Ninnes

unread,
Jul 25, 2008, 5:25:23 AM7/25/08
to

"Ian Boyd" <ian.borla...@zunblvlda1.dyndns.org.spamsucks> wrote in
message news:4889...@newsgroups.borland.com...

It's because you followed the MS docs and did a ZeroMemory, if you'd ignored
that like everyone else did it would work :-). It set bV5CSType to 0 which
means it uses the bV5Endpoints fields, now they're all zero as well and so
it tries to divide by zero somewhere and throws an exception.

It's a bug in the MS docs, the other delphi examples omit the ZeroMemory and
so it will usually work unless all those fields are set to 0 when the memory
is malloced, the bug is probably everywhere in applications, but you'd
seldom hit it.

(I changed a couple of other non crtical bits below (at least I think they
are))

cheers,
Dave


function CreateDIBSection_V5(DC: HDC; const p2: TBitmapV5Header; p3: UINT;


var p4: Pointer; p5: THandle; p6: DWORD): HBITMAP; stdcall;external GDI32
name
'CreateDIBSection';

procedure TForm12.Button1Click(Sender: TObject);


var
bm: HBITMAP;
dc: HDC;
BitmapHeader: TBitmapV5Header;
pBits: Pointer;
begin

FillMemory(@BitmapHeader, SizeOf(BITMAPV5HEADER), 0);

with BitmapHeader do
begin
{ bV5Size := 0;
bV5Width := 0;
bV5Height := 0;
bV5Planes := 0;
bV5BitCount := 0;
bV5Compression := 0;
bV5SizeImage := 0;
bV5XPelsPerMeter := 0;
bV5YPelsPerMeter := 0;
bV5ClrUsed := 0;
bV5ClrImportant := 0;
bV5RedMask := 0;
bV5GreenMask := 0;
bV5BlueMask := 0;
bV5AlphaMask := 0; }
bV5CSType := 1; <-------------- This flag here
bV5Endpoints.ciexyzRed.ciexyzX := 0;
bV5Endpoints.ciexyzRed.ciexyzY := 0;
bV5Endpoints.ciexyzRed.ciexyzZ := 0;
bV5Endpoints.ciexyzGreen.ciexyzX := 0;
bV5Endpoints.ciexyzGreen.ciexyzY := 0;
bV5Endpoints.ciexyzGreen.ciexyzZ := 0;
bV5Endpoints.ciexyzBlue.ciexyzX := 0;
bV5Endpoints.ciexyzBlue.ciexyzY := 0;
bV5Endpoints.ciexyzBlue.ciexyzZ := 0;
{ bV5GammaRed := 0;
bV5GammaGreen := 0;
bV5GammaBlue := 0;
bV5Intent := 0;
bV5ProfileData := 0;
bV5ProfileSize := 0;
bV5Reserved := 0; }
end;


BitmapHeader.bV5Size := SizeOf(BITMAPV5HEADER);
BitmapHeader.bV5Width := 32;
BitmapHeader.bV5Height := 32;
BitmapHeader.bV5Planes := 1;
BitmapHeader.bV5BitCount := 32;
BitmapHeader.bV5Compression := BI_BITFIELDS;

BitmapHeader.bv5clrused := 1;


BitmapHeader.bV5RedMask := $00FF0000;
BitmapHeader.bV5GreenMask := $0000FF00;
BitmapHeader.bV5BlueMask := $000000FF;
BitmapHeader.bV5AlphaMask := $FF000000;

dc := GetDC(0);

bm := CreateDIBSection_V5(
dc,

Ian Boyd

unread,
Jul 25, 2008, 9:26:19 AM7/25/08
to
> It's because you did a ZeroMemory

> It set bV5CSType to 0 which means it uses the bV5Endpoints fields, now
> they're all zero as well

> It's a bug in the MS docs, the other delphi examples omit the ZeroMemory

> and so it will usually work unless all those fields are set to 0 when the
> memory is malloced, the bug is probably everywhere in applications, but
> you'd seldom hit it.

Oh...my...god.

That is truely terrifying.


Ian Boyd

unread,
Jul 25, 2008, 3:11:49 PM7/25/08
to
Here's the working call.

People should note the bug in the MS KB article leaves bV5CSType as zero
(LCS_CALIBRATED_RGB), which then means you have to specify 3 xyz coordinates
of red, green and blue in bV5Endpoints, and the three red, green and blue
gamma values in bV5GammaRed, bV5GammaGreen, bV5GammaBlue. If you don't you
(might) get a division by zero. (who knows if SP2 added more security
checks to CreateDIBSection to catch the missing values)

function CreateDIBSection_V5(
DC: HDC; // handle to DC
pbmi: PBitmapV5Header; // bitmap data
iUsage: UINT; // data type indicator
var pBits: Pointer; // bit values
hSection: THandle; // handle to file mapping object
dwOffset: DWORD // offset to bitmap bit values


): HBITMAP; stdcall; external GDI32 name 'CreateDIBSection';

var


bm: HBITMAP;
dc: HDC;
BitmapHeader: TBitmapV5Header;

Bits: Pointer;
const
LCS_CALIBRATED_RGB = $00000000;
LCS_sRGB = $73524742; //ASCII encoding of "sRGB"
LCS_WINDOWS_COLOR_SPACE = $57696E20; //ASCII encoding of "Win "

LCS_GM_BUSINESS = $00000001; //Saturation
LCS_GM_GRAPHICS = $00000002; //Relative Colorimetric
LCS_GM_IMAGES = $00000004; //Perceptual
LCS_GM_ABS_COLORIMETRIC = $00000008; //Absolute Colorimetric
begin
ZeroMemory(@BitmapHeader, SizeOf(TBitmapV5Header));
BitmapHeader.bV5Size := SizeOf(TBitmapV5Header);


BitmapHeader.bV5Width := 32;
BitmapHeader.bV5Height := 32;

BitmapHeader.bV5Planes := 1; //must be 1


BitmapHeader.bV5BitCount := 32;
BitmapHeader.bV5Compression := BI_BITFIELDS;
BitmapHeader.bV5RedMask := $00FF0000;
BitmapHeader.bV5GreenMask := $0000FF00;
BitmapHeader.bV5BlueMask := $000000FF;
BitmapHeader.bV5AlphaMask := $FF000000;

BitmapHeader.bV5CSType := LCS_sRGB;
BitmapHeader.bV5Intent := LCS_GM_ABS_COLORIMETRIC;
BitmapHeader.bV5Reserved := 0; //should be zero

dc := GetDC(0);
if dc = 0 then
RaiseLastWin32Error;
try


bm := CreateDIBSection_V5(
dc,
@BitmapHeader,
DIB_RGB_COLORS,

Bits,
0, 0);
finally
ReleaseDC(0, dc);
end;
end;

Note: Just because you can create a 32bpp bitmap, doesn't mean you'll ever
be able to figure out how to use the alpha values to achive actual
transparency.


GrandmasterB

unread,
Jul 25, 2008, 5:48:24 PM7/25/08
to
"Ian Boyd" <ian.borla...@avatopia.com> wrote in message
news:488a2574$1...@newsgroups.borland.com...

> Here's the working call.

Thanks for posting this. Figuring out how to do this in Delphi was on my
'long term' things to-do list because I think it may help me speed up
certain operations that I'm doing in straight gdi+ right now (which can be
very slow due to the way it locks/unlocks pixel data).

David Ninnes

unread,
Jul 25, 2008, 7:40:50 PM7/25/08
to

"GrandmasterB" <Fiz...@shizzle.com> wrote in message
news:488a3c82$1...@newsgroups.borland.com...

ditto, I was hoping V5 bitmaps will be in the next version of delphi,
particularly in the clipboard for copying and pasting alpha channel images.

David Ninnes

unread,
Jul 25, 2008, 7:47:06 PM7/25/08
to

"Ian Boyd" <ian.borla...@avatopia.com> wrote in message

news:4889d47b$1...@newsgroups.borland.com...

Don't know if I'd go that far :-). Thanks for formalizing it.

cheers,
Dave

Ian Boyd

unread,
Jul 28, 2008, 11:03:37 AM7/28/08
to
>> That is truely terrifying.
>>
> Don't know if I'd go that far :-). Thanks for formalizing it.

It's terrifying because everyone follows code the find. And when the actual
MS KB article has a crash in it, everyone's code can potentially crash
depending on how the random gamma rays from M31 flipped the bits in a
person's RAM.


i can't blame them though; people don't realize that a KB article isn't a
formal piece of documentation from Microsoft - it's just something that a
guy at MS figured out and can share with the world.


David Ninnes

unread,
Jul 28, 2008, 1:54:03 PM7/28/08
to

"Ian Boyd" <ian.borla...@avatopia.com> wrote in message

news:488d...@newsgroups.borland.com...

There's a feedback down the bottom of the MS article, I made a comment,
we'll see what happens. It may be worthwhile if you make an entry too? not
sure if more complaints gets things changed :-).

cheers,
Dave

Ian Boyd

unread,
Jul 28, 2008, 2:06:13 PM7/28/08
to
> There's a feedback down the bottom of the MS article, I made a comment,
> we'll see what happens. It may be worthwhile if you make an entry too? not
> sure if more complaints gets things changed :-).

Reading Raymond Chen's blog, it's apparent that even the formal documention
is incomplete or sometimes in error.

One story was how a guy at MS discovered that something worked, and had to
docs team change it.

Turns out the guy was relying on 'undocumented' behaviour, which then broke
in the next version of Windows.

adrian...@gmail.com

unread,
Dec 16, 2013, 7:46:04 AM12/16/13
to
Just found out a solution that works for me.
My problem was that software that was developed on Win7, when running on XP was throwing the division by 0 error when loading one of my BMPs.
It turns out that the problematic BMP was saved using Win7 Paint (other BMPs that were ok were saved from Gimp).
All I needed to do to fix it was to open this BMP on XP Paint and save it from there.
Reply all
Reply to author
Forward
0 new messages