Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/user32/tests/cursoricon.c | 49 +++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index c598b232a0..f00d3f2a0c 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -2755,17 +2755,19 @@ static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO unsigned int row, unsigned int column) { const BITMAPINFOHEADER *h = &bmi->bmiHeader; + unsigned int stride, shift, mask; const unsigned char *data; - unsigned int stride; RGBQUAD color;
- ok(h->biBitCount == 1 || h->biBitCount >= 24, "Unsupported bit count %u.\n", h->biBitCount); + ok(h->biBitCount <= 8 || h->biBitCount >= 24, "Unsupported bit count %u.\n", h->biBitCount); stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3; data = bits + row * stride + column * h->biBitCount / 8; if (h->biBitCount >= 24) return RGB(data[2], data[1], data[0]);
- color = bmi->bmiColors[!!(data[0] & (1u << (7 - (column % 8))))]; + shift = 8 - h->biBitCount - (column * h->biBitCount) % 8; + mask = ~(~0u << h->biBitCount); + color = bmi->bmiColors[(data[0] >> shift) & mask]; return RGB(color.rgbRed, color.rgbGreen, color.rgbBlue); }
@@ -2783,6 +2785,18 @@ static void test_CopyImage_StretchMode(void) 0x3f, 0xff, 0x00, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x3f, 0xff, 0x7f, 0x00, 0xff, 0x3f, 0x00, 0x00, }; + static const unsigned char test_bits_8[] = + { + 0x00, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0x55, 0x00, 0xff, + 0x00, 0xff, 0xff, 0x00, + }; + static const unsigned char expected_bits_8[] = + { + 0xff, 0xff, 0x00, 0x00, + 0x55, 0xff, 0x00, 0x00, + }; static const unsigned char test_bits_1[] = { 0x30, 0x0, 0x0, 0x0, @@ -2795,6 +2809,12 @@ static void test_CopyImage_StretchMode(void) 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, }; + static const RGBQUAD colors_bits_1[] = + { + {0, 0, 0}, + {0xff, 0xff, 0xff}, + }; + static RGBQUAD colors_bits_8[256];
static const struct { @@ -2802,19 +2822,25 @@ static void test_CopyImage_StretchMode(void) WORD bit_count; const unsigned char *test_bits, *expected_bits; size_t test_bits_size, result_bits_size; + const RGBQUAD *bmi_colors; + size_t bmi_colors_size; BOOL todo; } tests[] = { {4, 4, 2, 2, 24, test_bits_24, expected_bits_24, - sizeof(test_bits_24), sizeof(expected_bits_24), TRUE}, + sizeof(test_bits_24), sizeof(expected_bits_24), NULL, 0, TRUE}, {4, 4, 2, 2, 1, test_bits_1, expected_bits_1, - sizeof(test_bits_1), sizeof(expected_bits_1), FALSE}, + sizeof(test_bits_1), sizeof(expected_bits_1), colors_bits_1, + sizeof(colors_bits_1), FALSE}, + {4, 4, 2, 2, 8, test_bits_8, expected_bits_8, + sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8, + sizeof(colors_bits_8), TRUE}, };
HBITMAP bitmap, bitmap_copy; + unsigned int row, column, i; unsigned char *result_bits; - unsigned int row, column; unsigned int test_index; unsigned char *bits; BITMAPINFO *bmi; @@ -2825,14 +2851,19 @@ static void test_CopyImage_StretchMode(void) bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biPlanes = 1; bmi->bmiHeader.biCompression = BI_RGB; - bmi->bmiColors[1].rgbRed = 0xff; - bmi->bmiColors[1].rgbGreen = 0xff; - bmi->bmiColors[1].rgbBlue = 0xff; + + for (i = 0; i < 256; ++i) + colors_bits_8[i].rgbRed = colors_bits_8[i].rgbGreen = colors_bits_8[i].rgbBlue = i;
hdc = GetDC(NULL);
for (test_index = 0; test_index < ARRAY_SIZE(tests); ++test_index) { + if (tests[test_index].bmi_colors) + memcpy(bmi->bmiColors, tests[test_index].bmi_colors, tests[test_index].bmi_colors_size); + else + memset(bmi->bmiColors, 0, 256 * sizeof(RGBQUAD)); + bmi->bmiHeader.biWidth = tests[test_index].width; bmi->bmiHeader.biHeight = tests[test_index].height; bmi->bmiHeader.biBitCount = tests[test_index].bit_count;
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/user32/tests/cursoricon.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index f00d3f2a0c..f9821dc7bf 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -2758,13 +2758,19 @@ static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO unsigned int stride, shift, mask; const unsigned char *data; RGBQUAD color; + WORD color16;
- ok(h->biBitCount <= 8 || h->biBitCount >= 24, "Unsupported bit count %u.\n", h->biBitCount); stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3; data = bits + row * stride + column * h->biBitCount / 8; if (h->biBitCount >= 24) return RGB(data[2], data[1], data[0]);
+ if (h->biBitCount == 16) + { + color16 = ((WORD)data[1] << 8) | data[0]; + return RGB(((color16 >> 10) & 0x1f) << 3, ((color16 >> 5) & 0x1f) << 3, + (color16 & 0x1f) << 3); + } shift = 8 - h->biBitCount - (column * h->biBitCount) % 8; mask = ~(~0u << h->biBitCount); color = bmi->bmiColors[(data[0] >> shift) & mask]; @@ -2785,6 +2791,20 @@ static void test_CopyImage_StretchMode(void) 0x3f, 0xff, 0x00, 0x3f, 0xff, 0x3f, 0x00, 0x00, 0x3f, 0xff, 0x7f, 0x00, 0xff, 0x3f, 0x00, 0x00, }; + #define rgb16(r, g, b) ((WORD)(((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3))) + static const WORD test_bits_16[] = + { + rgb16(0x00, 0x20, 0x00), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00), + rgb16(0x00, 0x60, 0x00), rgb16(0xff, 0x80, 0x00), rgb16(0xff, 0x60, 0x00), rgb16(0x00, 0x80, 0x00), + rgb16(0x00, 0x20, 0xff), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00), + rgb16(0xff, 0x80, 0x00), rgb16(0x00, 0x60, 0xff), rgb16(0x00, 0x80, 0x00), rgb16(0x00, 0x60, 0x00), + }; + static const WORD expected_bits_16[] = + { + rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00), + rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00), + }; + #undef rgb16 static const unsigned char test_bits_8[] = { 0x00, 0xff, 0x00, 0xff, @@ -2836,6 +2856,8 @@ static void test_CopyImage_StretchMode(void) {4, 4, 2, 2, 8, test_bits_8, expected_bits_8, sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8, sizeof(colors_bits_8), TRUE}, + {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16, + sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, TRUE}, };
HBITMAP bitmap, bitmap_copy;
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/user32/tests/cursoricon.c | 69 ++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 28 deletions(-)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index f9821dc7bf..aa73864e63 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -2777,6 +2777,35 @@ static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO return RGB(color.rgbRed, color.rgbGreen, color.rgbBlue); }
+#define compare_bitmap_bits(a, b, c, d, e, f, g) compare_bitmap_bits_(__LINE__, a, b, c, d, e, f, g) +static void compare_bitmap_bits_(unsigned int line, HDC hdc, HBITMAP bitmap, BITMAPINFO *bmi, + size_t result_bits_size, const unsigned char *expected_bits, unsigned int test_index, BOOL todo) +{ + unsigned char *result_bits; + unsigned int row, column; + int ret; + + result_bits = HeapAlloc(GetProcessHeap(), 0, result_bits_size); + ret = GetDIBits(hdc, bitmap, 0, bmi->bmiHeader.biHeight, + result_bits, bmi, DIB_RGB_COLORS); + ok(ret == bmi->bmiHeader.biHeight, "Unexpected GetDIBits result %d, GetLastError() %u.\n", + ret, GetLastError()); + for (row = 0; row < bmi->bmiHeader.biHeight; ++row) + for (column = 0; column < bmi->bmiHeader.biWidth; ++column) + { + COLORREF result, expected; + + result = get_color_from_bits(result_bits, bmi, row, column); + expected = get_color_from_bits(expected_bits, bmi, row, column); + + todo_wine_if(todo) + ok_(__FILE__, line)(result == expected, "Colors do not match, " + "got 0x%06x, expected 0x%06x, test_index %u, row %u, column %u.\n", + result, expected, test_index, row, column); + } + HeapFree(GetProcessHeap(), 0, result_bits); +} + static void test_CopyImage_StretchMode(void) { static const unsigned char test_bits_24[] = @@ -2860,16 +2889,17 @@ static void test_CopyImage_StretchMode(void) sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, TRUE}, };
+ BITMAPINFO *bmi, *bmi_output; HBITMAP bitmap, bitmap_copy; - unsigned int row, column, i; - unsigned char *result_bits; unsigned int test_index; unsigned char *bits; - BITMAPINFO *bmi; + size_t bmi_size; + unsigned int i; HDC hdc; - int ret;
- bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); + bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size); + bmi_output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size); bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biPlanes = 1; bmi->bmiHeader.biCompression = BI_RGB; @@ -2889,6 +2919,9 @@ static void test_CopyImage_StretchMode(void) bmi->bmiHeader.biWidth = tests[test_index].width; bmi->bmiHeader.biHeight = tests[test_index].height; bmi->bmiHeader.biBitCount = tests[test_index].bit_count; + memcpy(bmi_output, bmi, bmi_size); + bmi_output->bmiHeader.biWidth = tests[test_index].output_width; + bmi_output->bmiHeader.biHeight = tests[test_index].output_height;
bitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, (void **)&bits, NULL, 0); ok(bitmap && bits, "CreateDIBSection() failed, result %u.\n", GetLastError()); @@ -2898,33 +2931,13 @@ static void test_CopyImage_StretchMode(void) tests[test_index].output_height, LR_CREATEDIBSECTION); ok(!!bitmap_copy, "CopyImage() failed, result %u.\n", GetLastError());
- result_bits = HeapAlloc(GetProcessHeap(), 0, tests[test_index].result_bits_size); - - bmi->bmiHeader.biWidth = tests[test_index].output_width; - bmi->bmiHeader.biHeight = tests[test_index].output_height; - ret = GetDIBits(hdc, bitmap_copy, 0, tests[test_index].output_height, - result_bits, bmi, DIB_RGB_COLORS); - ok(ret == tests[test_index].output_height, "Unexpected GetDIBits result %d, GetLastError() %u.\n", - ret, GetLastError()); - - for (row = 0; row < tests[test_index].output_height; ++row) - for (column = 0; column < tests[test_index].output_width; ++column) - { - COLORREF result, expected; - - result = get_color_from_bits(result_bits, bmi, row, column); - expected = get_color_from_bits(tests[test_index].expected_bits, bmi, row, column); - - todo_wine_if(tests[test_index].todo) - ok(result == expected, "Colors do not match, " - "got 0x%06x, expected 0x%06x, test_index %u, row %u, column %u.\n", - result, expected, test_index, row, column); - } + compare_bitmap_bits(hdc, bitmap_copy, bmi_output, tests[test_index].result_bits_size, + tests[test_index].expected_bits, test_index, tests[test_index].todo); DeleteObject(bitmap); DeleteObject(bitmap_copy); - HeapFree(GetProcessHeap(), 0, result_bits); } ReleaseDC(0, hdc); + HeapFree(GetProcessHeap(), 0, bmi_output); HeapFree(GetProcessHeap(), 0, bmi); }
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/user32/tests/cursoricon.c | 49 +++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index aa73864e63..e5ff215b4f 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1203,6 +1203,40 @@ static void create_ico_file(const char *filename, const test_icon_entries_t *tes HeapFree(GetProcessHeap(), 0, buf); }
+static void create_bitmap_file(const char *filename, const BITMAPINFO *bmi, const unsigned char *bits) +{ + unsigned int clr_used, bmi_size, bits_size, stride; + const BITMAPINFOHEADER *h = &bmi->bmiHeader; + BITMAPFILEHEADER hdr; + DWORD bytes_written; + HANDLE file; + BOOL ret; + + clr_used = h->biBitCount <= 8 ? 1u << h->biBitCount : 0; + stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3; + bits_size = h->biHeight * stride; + bmi_size = h->biSize + clr_used * sizeof(RGBQUAD); + + hdr.bfType = 0x4d42; + hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + bmi_size; + hdr.bfSize = hdr.bfOffBits + bits_size; + hdr.bfReserved1 = 0; + hdr.bfReserved2 = 0; + + file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed, result %u.\n", GetLastError()); + ret = WriteFile(file, &hdr, sizeof(hdr), &bytes_written, NULL); + ok(ret && bytes_written == sizeof(hdr), "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n", + ret, bytes_written); + ret = WriteFile(file, bmi, bmi_size, &bytes_written, NULL); + ok(ret && bytes_written == bmi_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n", + ret, bytes_written); + ret = WriteFile(file, bits, bits_size, &bytes_written, NULL); + ok(ret && bytes_written == bits_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n", + ret, bytes_written); + CloseHandle(file); +} + static void test_LoadImage_working_directory_run(char *path) { DWORD bytes_written; @@ -2806,7 +2840,7 @@ static void compare_bitmap_bits_(unsigned int line, HDC hdc, HBITMAP bitmap, BIT HeapFree(GetProcessHeap(), 0, result_bits); }
-static void test_CopyImage_StretchMode(void) +static void test_Image_StretchMode(void) { static const unsigned char test_bits_24[] = { @@ -2888,7 +2922,7 @@ static void test_CopyImage_StretchMode(void) {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16, sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, TRUE}, }; - + static const char filename[] = "test.bmp"; BITMAPINFO *bmi, *bmi_output; HBITMAP bitmap, bitmap_copy; unsigned int test_index; @@ -2935,6 +2969,15 @@ static void test_CopyImage_StretchMode(void) tests[test_index].expected_bits, test_index, tests[test_index].todo); DeleteObject(bitmap); DeleteObject(bitmap_copy); + + create_bitmap_file(filename, bmi, tests[test_index].test_bits); + bitmap = LoadImageA(NULL, filename, IMAGE_BITMAP, tests[test_index].output_width, + tests[test_index].output_height, LR_CREATEDIBSECTION | LR_LOADFROMFILE); + ok(!!bitmap, "LoadImageA() failed, result %u.\n", GetLastError()); + DeleteFileA(filename); + compare_bitmap_bits(hdc, bitmap, bmi_output, tests[test_index].result_bits_size, + tests[test_index].expected_bits, test_index, tests[test_index].todo); + DeleteObject(bitmap); } ReleaseDC(0, hdc); HeapFree(GetProcessHeap(), 0, bmi_output); @@ -2968,7 +3011,7 @@ START_TEST(cursoricon) test_CopyImage_Bitmap(16); test_CopyImage_Bitmap(24); test_CopyImage_Bitmap(32); - test_CopyImage_StretchMode(); + test_Image_StretchMode(); test_initial_cursor(); test_CreateIcon(); test_LoadImage();
For bug https://bugs.winehq.org/show_bug.cgi?id=46375.
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/user32/cursoricon.c | 4 ++++ dlls/user32/tests/cursoricon.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 539fc7ca54..3214746664 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -2976,6 +2976,8 @@ static HBITMAP BITMAP_Load( HINSTANCE instance, LPCWSTR name, }
orig_bm = SelectObject(screen_mem_dc, hbitmap); + if (info->bmiHeader.biBitCount > 1) + SetStretchBltMode(screen_mem_dc, HALFTONE); StretchDIBits(screen_mem_dc, 0, 0, new_width, new_height, 0, 0, width, height, bits, fix_info, DIB_RGB_COLORS, SRCCOPY); SelectObject(screen_mem_dc, orig_bm);
@@ -3217,6 +3219,8 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx, void * bits;
dc = CreateCompatibleDC(NULL); + if (ds.dsBm.bmBitsPixel > 1) + SetStretchBltMode(dc, HALFTONE);
bi->bmiHeader.biWidth = ds.dsBm.bmWidth; bi->bmiHeader.biHeight = ds.dsBm.bmHeight; diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index e5ff215b4f..bb88e2e196 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -2918,9 +2918,9 @@ static void test_Image_StretchMode(void) sizeof(colors_bits_1), FALSE}, {4, 4, 2, 2, 8, test_bits_8, expected_bits_8, sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8, - sizeof(colors_bits_8), TRUE}, + sizeof(colors_bits_8), FALSE}, {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16, - sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, TRUE}, + sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, FALSE}, }; static const char filename[] = "test.bmp"; BITMAPINFO *bmi, *bmi_output;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=46219
Your paranoid android.
=== debian9 (32 bit report) ===
user32: input.c:2566: Test failed: 200: wrong originId 1/2 input.c:2575: Test failed: 200: wrong originId 1/2 input.c:2566: Test failed: 200: wrong originId 1/2 input.c:2575: Test failed: 200: wrong originId 1/2
=== debian9 (32 bit Chinese:China report) ===
user32: msg.c:8713: Test failed: WaitForSingleObject failed 102 msg.c:8719: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8719: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8719: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
I've sent this last patch in the series mainly as request for comment. At the first place I am not sure if it should go during the code freeze, the problem it is supposed to fix is not a regression. Other than that, a complete fix would probably require a bit more than this.
My tests show that the full color images (24bpp) are downsampled using HALFTONE stretch mode, 1 bit images use BLACKONWHITE (as it works now in Wine), and anything between works like COLORONCOLOR mode. HALFTONE mode is not currently supported by gdi32 and falls back to COLORONCOLOR (STRECTH_DELETESCANS). This still makes more sense than using BLACKONWHITE for color images, but does not allow to fit the test for 24bpp bitmap. It could probably look more appropriate to set COLORONCOLOR mode for color images with less than 24bpp, but this way it won't fit any of my tests at all by now without changing gdi32 stretch code. If STRECTH_DELETESCANS mode is used, stretch_bitmapinfo() in gdi32/dibdrv/bitblt.c takes a bit different (optimized) path and drops wrong scans (not those dropped on Windows or when HALFTONE mode is used). This difference should not matter much in practice in most cases though. I see the following possible ways:
1. Use a more appropriate stretch mode in CopyImage() / LoadImage() for color images regardless of gdi32 stuff. It will eliminate major image colors distortions currently introduced when ANDing color values during stretch. 2. Leave CopyImage() / LoadImage() alone by now and start from transferring some StretchBlt tests to gdi32, fix COLORONCOLOR rows drop, maybe support HALFTONE interpolation, and come back to CopyImage / LoadImage after.
On 1/9/19 15:49, Paul Gofman wrote:
For bug https://bugs.winehq.org/show_bug.cgi?id=46375.
Signed-off-by: Paul Gofman gofmanp@gmail.com
dlls/user32/cursoricon.c | 4 ++++ dlls/user32/tests/cursoricon.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 539fc7ca54..3214746664 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -2976,6 +2976,8 @@ static HBITMAP BITMAP_Load( HINSTANCE instance, LPCWSTR name, }
orig_bm = SelectObject(screen_mem_dc, hbitmap);
- if (info->bmiHeader.biBitCount > 1)
SetStretchBltMode(screen_mem_dc, HALFTONE); StretchDIBits(screen_mem_dc, 0, 0, new_width, new_height, 0, 0, width, height, bits, fix_info, DIB_RGB_COLORS, SRCCOPY); SelectObject(screen_mem_dc, orig_bm);
@@ -3217,6 +3219,8 @@ HANDLE WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx, void * bits;
dc = CreateCompatibleDC(NULL);
if (ds.dsBm.bmBitsPixel > 1)
SetStretchBltMode(dc, HALFTONE); bi->bmiHeader.biWidth = ds.dsBm.bmWidth; bi->bmiHeader.biHeight = ds.dsBm.bmHeight;
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index e5ff215b4f..bb88e2e196 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -2918,9 +2918,9 @@ static void test_Image_StretchMode(void) sizeof(colors_bits_1), FALSE}, {4, 4, 2, 2, 8, test_bits_8, expected_bits_8, sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8,
sizeof(colors_bits_8), TRUE},
sizeof(colors_bits_8), FALSE}, {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16,
sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, TRUE},
sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, FALSE}, }; static const char filename[] = "test.bmp"; BITMAPINFO *bmi, *bmi_output;
Paul Gofman gofmanp@gmail.com writes:
My tests show that the full color images (24bpp) are downsampled using HALFTONE stretch mode, 1 bit images use BLACKONWHITE (as it works now in Wine), and anything between works like COLORONCOLOR mode. HALFTONE mode is not currently supported by gdi32 and falls back to COLORONCOLOR (STRECTH_DELETESCANS). This still makes more sense than using BLACKONWHITE for color images, but does not allow to fit the test for 24bpp bitmap. It could probably look more appropriate to set COLORONCOLOR mode for color images with less than 24bpp, but this way it won't fit any of my tests at all by now without changing gdi32 stretch code. If STRECTH_DELETESCANS mode is used, stretch_bitmapinfo() in gdi32/dibdrv/bitblt.c takes a bit different (optimized) path and drops wrong scans (not those dropped on Windows or when HALFTONE mode is used). This difference should not matter much in practice in most cases though. I see the following possible ways:
- Use a more appropriate stretch mode in CopyImage() / LoadImage()
for color images regardless of gdi32 stuff. It will eliminate major image colors distortions currently introduced when ANDing color values during stretch.
We can certainly change this first, even if gdi32 doesn't do the right thing yet. But probably not during code freeze...