gdi32: Fixed initialization of bit masks in GetDIBits for 16-bit bitmaps.
Fix and improve the test cases.
This commit is contained in:
parent
6edfd10868
commit
99892d6bae
147
dlls/gdi32/dib.c
147
dlls/gdi32/dib.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue