From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/windowscodecs/fliprotate.c | 56 +++++++++++++++++++++++++++---- dlls/windowscodecs/tests/bitmap.c | 2 -- 2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/dlls/windowscodecs/fliprotate.c b/dlls/windowscodecs/fliprotate.c index 7fc5959eeda..c880e10ea33 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 x, y, width, height; UINT srcy, srcwidth, srcheight; WICRect rc; WICRect rect; @@ -163,21 +165,20 @@ static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface,
if (!This->source) return WINCODEC_ERR_WRONGSTATE;
- if (This->swap_xy || This->flip_x) + if ((This->swap_xy || This->flip_x) && This->bpp < 8) { /* This requires knowledge of the pixel format. */ - FIXME("flipping x and rotating are not implemented\n"); + FIXME("flipping x and rotating are not implemented for %u bpp bitmap\n", This->bpp); 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 +186,44 @@ static HRESULT WINAPI FlipRotator_CopyPixels(IWICBitmapFlipRotator *iface, prc = ▭ }
+ if (This->swap_xy && This->flip_x) /* Rotate90 */ + { + UINT bytes_per_pixel = This->bpp / 8, stride = srcwidth * bytes_per_pixel; + BYTE *bits; + + bits = malloc(srcheight * stride); + if (!bits) return E_OUTOFMEMORY; + + rc.X = 0; + rc.Y = 0; + rc.Width = srcwidth; + rc.Height = srcheight; + hr = IWICBitmapSource_CopyPixels(This->source, &rc, stride, srcheight * stride, bits); + if (FAILED(hr)) + { + free(bits); + return hr; + } + + for (y = prc->Y; y - prc->Y < prc->Height; y++) + { + for (x = prc->X; x - prc->X < prc->Width; x++) + { + BYTE *src = bits + (width - x - 1) * stride + y * bytes_per_pixel; + BYTE *dst = pbBuffer + y * cbStride + x * bytes_per_pixel; + memcpy(dst, src, bytes_per_pixel); + } + } + + free(bits); + return S_OK; + } + else if (This->swap_xy || This->flip_x) + { + FIXME("flipping x and rotating are not implemented for %u bpp bitmap\n", This->bpp); + return E_NOTIMPL; + } + for (y=prc->Y; y - prc->Y < prc->Height; y++) { if (This->flip_y) @@ -212,6 +251,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 +282,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 85e4ebaa04d..f89e89d7459 100644 --- a/dlls/windowscodecs/tests/bitmap.c +++ b/dlls/windowscodecs/tests/bitmap.c @@ -1522,10 +1522,8 @@ static void test_FlipRotator(void) rc.Height = height; memset(buf, 0, sizeof(buf)); hr = IWICBitmapFlipRotator_CopyPixels(fr, &rc, 2, sizeof(buf), buf); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); ret = !memcmp(buf, data_rotate90, sizeof(data_rotate90)); - todo_wine ok(ret, "data mismatch\n"); if (!ret && winetest_debug > 1) {