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 */
|
/* 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 (!core_header) info->bmiHeader.biClrUsed = 0;
|
||||||
|
|
||||||
/* If the bitmap object already has a dib section at the
|
/* 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)
|
if (bits && lines)
|
||||||
|
@ -981,84 +1047,21 @@ INT WINAPI GetDIBits(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else lines = abs(height);
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* 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)
|
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("biSizeImage = %d, ", info->bmiHeader.biSizeImage);
|
||||||
}
|
}
|
||||||
TRACE("biWidth = %d, biHeight = %d\n", width, height);
|
TRACE("biWidth = %d, biHeight = %d\n", width, height);
|
||||||
|
|
||||||
|
done:
|
||||||
release_dc_ptr( dc );
|
release_dc_ptr( dc );
|
||||||
GDI_ReleaseObj( hbitmap );
|
GDI_ReleaseObj( hbitmap );
|
||||||
return lines;
|
return lines;
|
||||||
|
|
|
@ -1606,6 +1606,7 @@ static void test_GetDIBits_BI_BITFIELDS(void)
|
||||||
* for the three primary colors in non-paletted 16 bit mode.
|
* for the three primary colors in non-paletted 16 bit mode.
|
||||||
*/
|
*/
|
||||||
char dibinfo_buf[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
|
char dibinfo_buf[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
|
||||||
|
DWORD bits[32];
|
||||||
LPBITMAPINFO dibinfo = (LPBITMAPINFO) dibinfo_buf;
|
LPBITMAPINFO dibinfo = (LPBITMAPINFO) dibinfo_buf;
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
HBITMAP hbm;
|
HBITMAP hbm;
|
||||||
|
@ -1622,30 +1623,61 @@ static void test_GetDIBits_BI_BITFIELDS(void)
|
||||||
/* Call GetDIBits to fill in bmiHeader. */
|
/* Call GetDIBits to fill in bmiHeader. */
|
||||||
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
|
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
|
||||||
ok(ret == 1, "GetDIBits failed\n");
|
ok(ret == 1, "GetDIBits failed\n");
|
||||||
if (dibinfo->bmiHeader.biBitCount == 16
|
if (dibinfo->bmiHeader.biBitCount == 16 &&
|
||||||
&& dibinfo->bmiHeader.biCompression == BI_BITFIELDS) {
|
dibinfo->bmiHeader.biCompression == BI_BITFIELDS)
|
||||||
/* In the BITMAPINFOHEADER doc, this little struct is implicit.
|
{
|
||||||
* Making explicit for clarity.
|
DWORD *bitmasks = (DWORD *)dibinfo->bmiColors;
|
||||||
*/
|
|
||||||
struct bi_bitfields_s {
|
|
||||||
DWORD red;
|
|
||||||
DWORD blue;
|
|
||||||
DWORD green;
|
|
||||||
} *bitmasks;
|
|
||||||
|
|
||||||
/* Retrieve the BI_BITFIELDS info (requires second call, honest). */
|
ok( !bitmasks[0], "red mask is set\n" );
|
||||||
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
|
ok( !bitmasks[1], "green mask is set\n" );
|
||||||
ok(ret == 1, "GetDIBits failed\n");
|
ok( !bitmasks[2], "blue mask is set\n" );
|
||||||
|
|
||||||
bitmasks = (struct bi_bitfields_s *) dibinfo->bmiColors;
|
/* test with NULL bits pointer and correct bpp */
|
||||||
todo_wine {
|
dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
|
||||||
ok(bitmasks->red != 0, "expected space for red pixels\n");
|
ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
|
||||||
ok(bitmasks->blue != 0, "expected space for blue pixels\n");
|
ok(ret == 1, "GetDIBits failed\n");
|
||||||
ok(bitmasks->green != 0, "expected space for green pixels\n");
|
|
||||||
}
|
ok( bitmasks[0] != 0, "red mask is not set\n" );
|
||||||
} else {
|
ok( bitmasks[1] != 0, "green mask is not set\n" );
|
||||||
skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\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);
|
DeleteObject(hbm);
|
||||||
ReleaseDC(NULL, hdc);
|
ReleaseDC(NULL, hdc);
|
||||||
|
|
Loading…
Reference in New Issue