gdi32: Fixed initialization of bit masks in GetDIBits for 16-bit bitmaps.

Fix and improve the test cases.
This commit is contained in:
Alexandre Julliard 2008-04-18 12:08:12 +02:00
parent 6edfd10868
commit 99892d6bae
2 changed files with 128 additions and 93 deletions

View File

@ -620,8 +620,55 @@ INT WINAPI GetDIBits(
/* Transfer color info */
if (bpp <= 8 && bpp > 0)
switch (bpp)
{
case 0: /* query bitmap info only */
if (core_header)
{
BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
coreheader->bcWidth = bmp->bitmap.bmWidth;
coreheader->bcHeight = bmp->bitmap.bmHeight;
coreheader->bcPlanes = 1;
coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
}
else
{
info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biSizeImage =
DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
bmp->bitmap.bmHeight,
bmp->bitmap.bmBitsPixel );
switch(bmp->bitmap.bmBitsPixel)
{
case 15:
info->bmiHeader.biBitCount = 16;
info->bmiHeader.biCompression = BI_RGB;
break;
case 16:
info->bmiHeader.biBitCount = 16;
info->bmiHeader.biCompression = BI_BITFIELDS;
break;
default:
info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
info->bmiHeader.biCompression = BI_RGB;
break;
}
info->bmiHeader.biXPelsPerMeter = 0;
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrUsed = 0;
info->bmiHeader.biClrImportant = 0;
/* Windows 2000 doesn't touch the additional struct members if
it's a BITMAPV4HEADER or a BITMAPV5HEADER */
}
lines = abs(bmp->bitmap.bmHeight);
goto done;
case 1:
case 4:
case 8:
if (!core_header) info->bmiHeader.biClrUsed = 0;
/* If the bitmap object already has a dib section at the
@ -758,6 +805,25 @@ INT WINAPI GetDIBits(
}
}
}
break;
case 15:
if (info->bmiHeader.biCompression == BI_BITFIELDS)
{
((PDWORD)info->bmiColors)[0] = 0x7c00;
((PDWORD)info->bmiColors)[1] = 0x03e0;
((PDWORD)info->bmiColors)[2] = 0x001f;
}
break;
case 16:
if (info->bmiHeader.biCompression == BI_BITFIELDS)
{
((PDWORD)info->bmiColors)[0] = 0xf800;
((PDWORD)info->bmiColors)[1] = 0x07e0;
((PDWORD)info->bmiColors)[2] = 0x001f;
}
break;
}
if (bits && lines)
@ -981,84 +1047,21 @@ INT WINAPI GetDIBits(
}
}
}
else
{
/* fill in struct members */
if (bpp == 0)
{
if (core_header)
{
BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) info;
coreheader->bcWidth = bmp->bitmap.bmWidth;
coreheader->bcHeight = bmp->bitmap.bmHeight;
coreheader->bcPlanes = 1;
coreheader->bcBitCount = bmp->bitmap.bmBitsPixel;
}
else
{
info->bmiHeader.biWidth = bmp->bitmap.bmWidth;
info->bmiHeader.biHeight = bmp->bitmap.bmHeight;
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biSizeImage =
DIB_GetDIBImageBytes( bmp->bitmap.bmWidth,
bmp->bitmap.bmHeight,
bmp->bitmap.bmBitsPixel );
switch(bmp->bitmap.bmBitsPixel)
{
case 15:
info->bmiHeader.biBitCount = 16;
info->bmiHeader.biCompression = BI_RGB;
break;
case 16:
if (bits)
{
/* Add color only when bits is given, as per MSDN */
((PDWORD)info->bmiColors)[0] = 0xf800;
((PDWORD)info->bmiColors)[1] = 0x07e0;
((PDWORD)info->bmiColors)[2] = 0x001f;
}
info->bmiHeader.biBitCount = 16;
info->bmiHeader.biCompression = BI_BITFIELDS;
break;
default:
info->bmiHeader.biBitCount = bmp->bitmap.bmBitsPixel;
info->bmiHeader.biCompression = BI_RGB;
break;
}
info->bmiHeader.biXPelsPerMeter = 0;
info->bmiHeader.biYPelsPerMeter = 0;
info->bmiHeader.biClrUsed = 0;
info->bmiHeader.biClrImportant = 0;
/* Windows 2000 doesn't touch the additional struct members if
it's a BITMAPV4HEADER or a BITMAPV5HEADER */
}
lines = abs(bmp->bitmap.bmHeight);
}
else
{
/* The knowledge base article Q81498 ("DIBs and Their Uses") states that
if bits == NULL and bpp != 0, only biSizeImage and the color table are
filled in. */
if (!core_header)
{
/* FIXME: biSizeImage should be calculated according to the selected
compression algorithm if biCompression != BI_RGB */
info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
}
lines = abs(height);
}
}
else lines = abs(height);
/* The knowledge base article Q81498 ("DIBs and Their Uses") states that
if bits == NULL and bpp != 0, only biSizeImage and the color table are
filled in. */
if (!core_header)
{
/* FIXME: biSizeImage should be calculated according to the selected
compression algorithm if biCompression != BI_RGB */
info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( width, height, bpp );
TRACE("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
}
TRACE("biWidth = %d, biHeight = %d\n", width, height);
done:
release_dc_ptr( dc );
GDI_ReleaseObj( hbitmap );
return lines;

View File

@ -1606,6 +1606,7 @@ static void test_GetDIBits_BI_BITFIELDS(void)
* for the three primary colors in non-paletted 16 bit mode.
*/
char dibinfo_buf[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
DWORD bits[32];
LPBITMAPINFO dibinfo = (LPBITMAPINFO) dibinfo_buf;
HDC hdc;
HBITMAP hbm;
@ -1622,30 +1623,61 @@ static void test_GetDIBits_BI_BITFIELDS(void)
/* Call GetDIBits to fill in bmiHeader. */
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
ok(ret == 1, "GetDIBits failed\n");
if (dibinfo->bmiHeader.biBitCount == 16
&& dibinfo->bmiHeader.biCompression == BI_BITFIELDS) {
/* In the BITMAPINFOHEADER doc, this little struct is implicit.
* Making explicit for clarity.
*/
struct bi_bitfields_s {
DWORD red;
DWORD blue;
DWORD green;
} *bitmasks;
if (dibinfo->bmiHeader.biBitCount == 16 &&
dibinfo->bmiHeader.biCompression == BI_BITFIELDS)
{
DWORD *bitmasks = (DWORD *)dibinfo->bmiColors;
/* Retrieve the BI_BITFIELDS info (requires second call, honest). */
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
ok(ret == 1, "GetDIBits failed\n");
ok( !bitmasks[0], "red mask is set\n" );
ok( !bitmasks[1], "green mask is set\n" );
ok( !bitmasks[2], "blue mask is set\n" );
bitmasks = (struct bi_bitfields_s *) dibinfo->bmiColors;
todo_wine {
ok(bitmasks->red != 0, "expected space for red pixels\n");
ok(bitmasks->blue != 0, "expected space for blue pixels\n");
ok(bitmasks->green != 0, "expected space for green pixels\n");
}
} else {
skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
/* test with NULL bits pointer and correct bpp */
dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
ok(ret == 1, "GetDIBits failed\n");
ok( bitmasks[0] != 0, "red mask is not set\n" );
ok( bitmasks[1] != 0, "green mask is not set\n" );
ok( bitmasks[2] != 0, "blue mask is not set\n" );
ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
/* test with valid bits pointer */
memset(dibinfo, 0, sizeof(dibinfo_buf));
dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
ret = GetDIBits(hdc, hbm, 0, 1, bits, dibinfo, DIB_RGB_COLORS);
ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
ok( bitmasks[0] != 0, "red mask is not set\n" );
ok( bitmasks[1] != 0, "green mask is not set\n" );
ok( bitmasks[2] != 0, "blue mask is not set\n" );
ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
/* now with bits and 0 lines */
memset(dibinfo, 0, sizeof(dibinfo_buf));
dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
ok( !bitmasks[0], "red mask is set\n" );
ok( !bitmasks[1], "green mask is set\n" );
ok( !bitmasks[2], "blue mask is set\n" );
ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
memset(bitmasks, 0, 3*sizeof(DWORD));
dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
ok( bitmasks[0] != 0, "red mask is not set\n" );
ok( bitmasks[1] != 0, "green mask is not set\n" );
ok( bitmasks[2] != 0, "blue mask is not set\n" );
ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
}
else skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
DeleteObject(hbm);
ReleaseDC(NULL, hdc);