diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 2b5ae374d44..caf3e6ca9ab 100644 --- a/dlls/gdi32/dib.c +++ b/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; diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index 67bb27fc82e..15a463b0175 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -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);