-- v2: windowscodecs: Implement IWICBitmapFlipRotator(WICBitmapTransformRotate90) for bitmaps with bpp >= 8. windowscodecs: Implement IWICBitmapFlipRotator(WICBitmapTransformFlipHorizontal) for bitmaps with bpp >= 8. windowscodecs/tests: Add some tests for IWICBitmapFlipRotator.
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/windowscodecs/tests/bitmap.c | 104 ++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+)
diff --git a/dlls/windowscodecs/tests/bitmap.c b/dlls/windowscodecs/tests/bitmap.c index f070eaeb47f..f5e5e53831b 100644 --- a/dlls/windowscodecs/tests/bitmap.c +++ b/dlls/windowscodecs/tests/bitmap.c @@ -1476,6 +1476,109 @@ static void test_IMILBitmap(void) IWICBitmap_Release(bitmap); }
+static void test_FlipRotator(void) +{ + static BYTE src_data[] = { 1,2,3, 4,5,6 }; + static BYTE dst_data_rotate90[] = { 4,1, 5,2, 6,3 }; + static BYTE dst_data_rotate90_flip_h[] = { 6,3, 5,2, 4,1 }; + static BYTE dst_data_rotate90_flip_v[] = { 1,4, 2,5, 3,6 }; + static BYTE dst_data_rotate90_flip_hv[] = { 3,6, 2,5, 1,4 }; + static BYTE dst_data_rotate180[] = { 6,5,4, 3,2,1 }; + static BYTE dst_data_rotate180_flip_h[] = { 4,5,6, 1,2,3 }; + static BYTE dst_data_rotate180_flip_v[] = { 3,2,1, 6,5,4 }; + static BYTE dst_data_rotate180_flip_hv[] = { 1,2,3, 4,5,6 }; + static BYTE dst_data_flip_h[] = { 3,2,1, 6,5,4 }; + static BYTE dst_data_flip_v[] = { 4,5,6, 1,2,3 }; + static BYTE dst_data_flip_hv[] = { 6,5,4, 3,2,1 }; + static const struct + { + WICBitmapTransformOptions options; + UINT dst_width, dst_height; + const BYTE *dst_data; + BOOL todo; + } td[] = + { + { WICBitmapTransformRotate0, 3, 2, src_data }, + { WICBitmapTransformRotate90, 2, 3, dst_data_rotate90, TRUE }, + { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal, 2, 3, dst_data_rotate90_flip_h, TRUE }, + { WICBitmapTransformRotate90 | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_v, TRUE }, + { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_hv, TRUE }, + { WICBitmapTransformRotate180, 3, 2, dst_data_rotate180, TRUE }, + { WICBitmapTransformRotate180 | WICBitmapTransformFlipHorizontal, 3, 2, dst_data_rotate180_flip_h }, + { WICBitmapTransformRotate180 | WICBitmapTransformFlipVertical, 3, 2, dst_data_rotate180_flip_v, TRUE }, + { WICBitmapTransformRotate180 | WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 3, 2, dst_data_rotate180_flip_hv }, + { WICBitmapTransformFlipHorizontal, 3, 2, dst_data_flip_h, TRUE }, + { WICBitmapTransformFlipVertical, 3, 2, dst_data_flip_v }, + { WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 3, 2, dst_data_flip_hv, TRUE }, + }; + HRESULT hr; + IWICBitmap *bitmap; + IWICPalette *palette; + IWICBitmapFlipRotator *fr; + WICColor colors[256]; + WICRect rc; + UINT width, height; + BYTE buf[sizeof(src_data)]; + int i, ret; + + hr = IWICImagingFactory_CreateBitmapFromMemory(factory, 3, 2, &GUID_WICPixelFormat8bppIndexed, + 3, sizeof(src_data), src_data, &bitmap); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(hr == S_OK, "got %#lx\n", hr); + + for (i = 0; i < 256; i++) + colors[i] = i; + hr = IWICPalette_InitializeCustom(palette, colors, 256); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IWICBitmap_SetPalette(bitmap, palette); + ok(hr == S_OK, "got %#lx\n", hr); + + for (i = 0; i < ARRAY_SIZE(td); i++) + { + winetest_push_context("%d", i); + + hr = IWICImagingFactory_CreateBitmapFlipRotator(factory, &fr); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IWICBitmapFlipRotator_Initialize(fr, (IWICBitmapSource *)bitmap, td[i].options); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IWICBitmapFlipRotator_GetSize(fr, &width, &height); + ok(hr == S_OK, "got %#lx\n", hr); + ok(width == td[i].dst_width, "got %u\n", td[i].dst_width); + ok(height == td[i].dst_height, "got %u\n", td[i].dst_height); + + rc.X = 0; + rc.Y = 0; + rc.Width = width; + rc.Height = height; + memset(buf, 0, sizeof(buf)); + hr = IWICBitmapFlipRotator_CopyPixels(fr, &rc, width, sizeof(buf), buf); + todo_wine_if(td[i].todo) + ok(hr == S_OK, "got %#lx\n", hr); + ret = !memcmp(buf, td[i].dst_data, sizeof(src_data)); + todo_wine_if(td[i].todo) + ok(ret, "data mismatch\n"); + if (!ret && winetest_debug > 1) + { + int k; + printf("got data:\n"); + for (k = 0; k < sizeof(buf); k++) + printf(" %u", buf[k]); + printf("\n"); + } + + IWICBitmapFlipRotator_Release(fr); + winetest_pop_context(); + } + + IWICPalette_Release(palette); + IWICBitmap_Release(bitmap); +} + START_TEST(bitmap) { HRESULT hr; @@ -1494,6 +1597,7 @@ START_TEST(bitmap) test_CreateBitmapFromHBITMAP(); test_clipper(); test_bitmap_scaler(); + test_FlipRotator();
IWICImagingFactory_Release(factory);
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/windowscodecs/fliprotate.c | 72 ++++++++++++++++++++++++++----- dlls/windowscodecs/tests/bitmap.c | 8 ++-- 2 files changed, 65 insertions(+), 15 deletions(-)
diff --git a/dlls/windowscodecs/fliprotate.c b/dlls/windowscodecs/fliprotate.c index 7fc5959eeda..9eb8b971f21 100644 --- a/dlls/windowscodecs/fliprotate.c +++ b/dlls/windowscodecs/fliprotate.c @@ -1,5 +1,6 @@ /* * Copyright 2010 Vincent Povirk for CodeWeavers + * Copyright 2024 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,6 +38,7 @@ typedef struct FlipRotator { int flip_x; int flip_y; int swap_xy; + UINT bpp; CRITICAL_SECTION lock; /* must be held when initialized */ } FlipRotator;
@@ -154,7 +156,7 @@ static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface, { FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); HRESULT hr; - UINT y; + UINT y, width, height; UINT srcy, srcwidth, srcheight; WICRect rc; WICRect rect; @@ -163,21 +165,14 @@ static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface,
if (!This->source) return WINCODEC_ERR_WRONGSTATE;
- if (This->swap_xy || This->flip_x) - { - /* This requires knowledge of the pixel format. */ - FIXME("flipping x and rotating are not implemented\n"); - return E_NOTIMPL; - } - hr = IWICBitmapSource_GetSize(This->source, &srcwidth, &srcheight); if (FAILED(hr)) return hr;
+ hr = IWICBitmapFlipRotator_GetSize(iface, &width, &height); + if (FAILED(hr)) return hr; + if (!prc) { - UINT width, height; - hr = IWICBitmapFlipRotator_GetSize(iface, &width, &height); - if (FAILED(hr)) return hr; rect.X = 0; rect.Y = 0; rect.Width = width; @@ -185,6 +180,56 @@ static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface, prc = ▭ }
+ if (This->swap_xy || This->flip_x) + { + UINT bytes_per_pixel = This->bpp / 8; + UINT srcx, x; + + if (This->bpp < 8) + { + FIXME("Flipping x and rotating are not implemented for %u bpp bitmap\n", This->bpp); + return E_NOTIMPL; + } + + if (This->swap_xy) + { + FIXME("Rotating is not implemented\n"); + return E_NOTIMPL; + } + + for (y = prc->Y; y - prc->Y < prc->Height; y++) + { + BYTE *dst = pbBuffer; + + if (This->flip_y) + srcy = srcheight - 1 - y; + else + srcy = y; + + for (x = prc->X; x - prc->X < prc->Width; x++) + { + if (This->flip_x) + srcx = srcwidth - 1 - x; + else + srcx = x; + + rc.X = srcx; + rc.Y = srcy; + rc.Width = 1; + rc.Height = 1; + + hr = IWICBitmapSource_CopyPixels(This->source, &rc, cbStride, cbStride, dst); + if (FAILED(hr)) return hr; + + dst += bytes_per_pixel; + } + + pbBuffer += cbStride; + } + + return hr; + } + for (y=prc->Y; y - prc->Y < prc->Height; y++) { if (This->flip_y) @@ -212,6 +257,7 @@ static HRESULT WINAPI FlipRotator_Initialize(IWICBitmapFlipRotator *iface, IWICBitmapSource *pISource, WICBitmapTransformOptions options) { FlipRotator *This = impl_from_IWICBitmapFlipRotator(iface); + GUID pf; HRESULT hr=S_OK;
TRACE("(%p,%p,%u)\n", iface, pISource, options); @@ -242,6 +288,10 @@ static HRESULT WINAPI FlipRotator_Initialize(IWICBitmapFlipRotator *iface, if (options&WICBitmapTransformFlipVertical) This->flip_y = !This->flip_y;
+ hr = IWICBitmapSource_GetPixelFormat(pISource, &pf); + if (SUCCEEDED(hr)) + hr = get_pixelformat_bpp(&pf, &This->bpp); + IWICBitmapSource_AddRef(pISource); This->source = pISource;
diff --git a/dlls/windowscodecs/tests/bitmap.c b/dlls/windowscodecs/tests/bitmap.c index f5e5e53831b..bc4851c13c0 100644 --- a/dlls/windowscodecs/tests/bitmap.c +++ b/dlls/windowscodecs/tests/bitmap.c @@ -1503,13 +1503,13 @@ static void test_FlipRotator(void) { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal, 2, 3, dst_data_rotate90_flip_h, TRUE }, { WICBitmapTransformRotate90 | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_v, TRUE }, { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_hv, TRUE }, - { WICBitmapTransformRotate180, 3, 2, dst_data_rotate180, TRUE }, + { WICBitmapTransformRotate180, 3, 2, dst_data_rotate180 }, { WICBitmapTransformRotate180 | WICBitmapTransformFlipHorizontal, 3, 2, dst_data_rotate180_flip_h }, - { WICBitmapTransformRotate180 | WICBitmapTransformFlipVertical, 3, 2, dst_data_rotate180_flip_v, TRUE }, + { WICBitmapTransformRotate180 | WICBitmapTransformFlipVertical, 3, 2, dst_data_rotate180_flip_v }, { WICBitmapTransformRotate180 | WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 3, 2, dst_data_rotate180_flip_hv }, - { WICBitmapTransformFlipHorizontal, 3, 2, dst_data_flip_h, TRUE }, + { WICBitmapTransformFlipHorizontal, 3, 2, dst_data_flip_h }, { WICBitmapTransformFlipVertical, 3, 2, dst_data_flip_v }, - { WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 3, 2, dst_data_flip_hv, TRUE }, + { WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 3, 2, dst_data_flip_hv }, }; HRESULT hr; IWICBitmap *bitmap;
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/windowscodecs/fliprotate.c | 31 +++++++++++++++++-------------- dlls/windowscodecs/tests/bitmap.c | 11 ++++------- 2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/dlls/windowscodecs/fliprotate.c b/dlls/windowscodecs/fliprotate.c index 9eb8b971f21..35cfde34280 100644 --- a/dlls/windowscodecs/fliprotate.c +++ b/dlls/windowscodecs/fliprotate.c @@ -191,34 +191,27 @@ static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface, return E_NOTIMPL; }
- if (This->swap_xy) - { - FIXME("Rotating is not implemented\n"); - return E_NOTIMPL; - } - for (y = prc->Y; y - prc->Y < prc->Height; y++) { BYTE *dst = pbBuffer;
if (This->flip_y) - srcy = srcheight - 1 - y; + srcy = height - 1 - y; else srcy = y;
for (x = prc->X; x - prc->X < prc->Width; x++) { if (This->flip_x) - srcx = srcwidth - 1 - x; + srcx = width - 1 - x; else srcx = x;
- rc.X = srcx; - rc.Y = srcy; + rc.X = This->swap_xy ? srcy : srcx; + rc.Y = This->swap_xy ? srcx : srcy; rc.Width = 1; rc.Height = 1; - - hr = IWICBitmapSource_CopyPixels(This->source, &rc, cbStride, cbStride, dst); + hr = IWICBitmapSource_CopyPixels(This->source, &rc, bytes_per_pixel, bytes_per_pixel, dst); if (FAILED(hr)) return hr;
dst += bytes_per_pixel; @@ -283,10 +276,20 @@ static HRESULT WINAPI FlipRotator_Initialize(IWICBitmapFlipRotator *iface, }
if (options&WICBitmapTransformFlipHorizontal) - This->flip_x = !This->flip_x; + { + if (This->swap_xy) + This->flip_y = !This->flip_y; + else + This->flip_x = !This->flip_x; + }
if (options&WICBitmapTransformFlipVertical) - This->flip_y = !This->flip_y; + { + if (This->swap_xy) + This->flip_x = !This->flip_x; + else + This->flip_y = !This->flip_y; + }
hr = IWICBitmapSource_GetPixelFormat(pISource, &pf); if (SUCCEEDED(hr)) diff --git a/dlls/windowscodecs/tests/bitmap.c b/dlls/windowscodecs/tests/bitmap.c index bc4851c13c0..b409732f022 100644 --- a/dlls/windowscodecs/tests/bitmap.c +++ b/dlls/windowscodecs/tests/bitmap.c @@ -1495,14 +1495,13 @@ static void test_FlipRotator(void) WICBitmapTransformOptions options; UINT dst_width, dst_height; const BYTE *dst_data; - BOOL todo; } td[] = { { WICBitmapTransformRotate0, 3, 2, src_data }, - { WICBitmapTransformRotate90, 2, 3, dst_data_rotate90, TRUE }, - { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal, 2, 3, dst_data_rotate90_flip_h, TRUE }, - { WICBitmapTransformRotate90 | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_v, TRUE }, - { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_hv, TRUE }, + { WICBitmapTransformRotate90, 2, 3, dst_data_rotate90 }, + { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal, 2, 3, dst_data_rotate90_flip_h }, + { WICBitmapTransformRotate90 | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_v }, + { WICBitmapTransformRotate90 | WICBitmapTransformFlipHorizontal | WICBitmapTransformFlipVertical, 2, 3, dst_data_rotate90_flip_hv }, { WICBitmapTransformRotate180, 3, 2, dst_data_rotate180 }, { WICBitmapTransformRotate180 | WICBitmapTransformFlipHorizontal, 3, 2, dst_data_rotate180_flip_h }, { WICBitmapTransformRotate180 | WICBitmapTransformFlipVertical, 3, 2, dst_data_rotate180_flip_v }, @@ -1557,10 +1556,8 @@ static void test_FlipRotator(void) rc.Height = height; memset(buf, 0, sizeof(buf)); hr = IWICBitmapFlipRotator_CopyPixels(fr, &rc, width, sizeof(buf), buf); - todo_wine_if(td[i].todo) ok(hr == S_OK, "got %#lx\n", hr); ret = !memcmp(buf, td[i].dst_data, sizeof(src_data)); - todo_wine_if(td[i].todo) ok(ret, "data mismatch\n"); if (!ret && winetest_debug > 1) {
On Mon Feb 10 12:08:52 2025 +0000, Dmitry Timoshkov wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/7211/diffs?diff_id=156682&start_sha=3bc36f52f3da5fec9e47e013d4286c223700541c#8d167020e967bd945c046f2a632d63a908db09d0_189_183)
Thanks! I like this better than what I was thinking.
This merge request was approved by Esme Povirk.