From 6dda23f14261c202dd7f4593d5e5a77a1e6529dd Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Wed, 5 Aug 2009 21:41:38 -0500 Subject: [PATCH] windowscodecs: add tests for BMP encoder --- dlls/windowscodecs/tests/Makefile.in | 3 +- dlls/windowscodecs/tests/bmpformat.c | 14 ++ dlls/windowscodecs/tests/testsrc.c | 340 ++++++++++++++++++++++++++++++++++ dlls/windowscodecs/tests/testsrc.h | 35 ++++ 4 files changed, 391 insertions(+), 1 deletions(-) create mode 100644 dlls/windowscodecs/tests/testsrc.c create mode 100644 dlls/windowscodecs/tests/testsrc.h diff --git a/dlls/windowscodecs/tests/Makefile.in b/dlls/windowscodecs/tests/Makefile.in index 2bb8c01..a8e123e 100644 --- a/dlls/windowscodecs/tests/Makefile.in +++ b/dlls/windowscodecs/tests/Makefile.in @@ -7,7 +7,8 @@ IMPORTS = kernel32 ole32 CTESTS = \ bmpformat.c \ - palette.c + palette.c \ + testsrc.c @MAKE_TEST_RULES@ diff --git a/dlls/windowscodecs/tests/bmpformat.c b/dlls/windowscodecs/tests/bmpformat.c index 39bb3b4..4bd6e87 100644 --- a/dlls/windowscodecs/tests/bmpformat.c +++ b/dlls/windowscodecs/tests/bmpformat.c @@ -27,6 +27,8 @@ #include "wincodec.h" #include "wine/test.h" +#include "testsrc.h" + static const char testbmp_24bpp[] = { /* BITMAPFILEHEADER */ 66,77, /* "BM" */ @@ -45,6 +47,16 @@ static const char testbmp_24bpp[] = { 255,0,255, 255,255,255, 0,0 }; +static const BYTE testbits_24bpp[] = { + 0,0,0, 0,255,0, 0,0, + 255,0,0, 255,255,0, 0,0, + 255,0,255, 255,255,255, 0,0 +}; + +static const struct bitmap_data testdata_24bpp = { + &GUID_WICPixelFormat24bppBGR, 24, testbits_24bpp, 2, 3, 96.0, 96.0 +}; + static void test_decode_24bpp(void) { IWICBitmapDecoder *decoder, *decoder2; @@ -1039,6 +1051,8 @@ START_TEST(bmpformat) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); test_decode_24bpp(); + test_encode_decode(&testdata_24bpp, &testdata_24bpp, &CLSID_WICBmpEncoder, &CLSID_WICBmpDecoder, 0, "24bpp source encode"); + test_encode_decode(&testdata_24bpp, &testdata_24bpp, &CLSID_WICBmpEncoder, &CLSID_WICBmpDecoder, 1, "24bpp pixel encode"); test_decode_1bpp(); test_decode_4bpp(); test_decode_rle8(); diff --git a/dlls/windowscodecs/tests/testsrc.c b/dlls/windowscodecs/tests/testsrc.c new file mode 100644 index 0000000..9b401e4 --- /dev/null +++ b/dlls/windowscodecs/tests/testsrc.c @@ -0,0 +1,340 @@ +/* + * Copyright 2009 Vincent Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "objbase.h" +#include "wincodec.h" +#include "wine/test.h" + +#include "testsrc.h" + +typedef struct BitmapTestSrc { + const IWICBitmapSourceVtbl *lpVtbl; + LONG ref; + const bitmap_data *data; +} BitmapTestSrc; + +static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid, + void **ppv) +{ + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapSource, iid)) + *ppv = iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface) +{ + BitmapTestSrc *This = (BitmapTestSrc*)iface; + ULONG ref = InterlockedIncrement(&This->ref); + return ref; +} + +static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface) +{ + BitmapTestSrc *This = (BitmapTestSrc*)iface; + ULONG ref = InterlockedDecrement(&This->ref); + return ref; +} + +static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface, + UINT *puiWidth, UINT *puiHeight) +{ + BitmapTestSrc *This = (BitmapTestSrc*)iface; + *puiWidth = This->data->width; + *puiHeight = This->data->height; + return S_OK; +} + +static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface, + WICPixelFormatGUID *pPixelFormat) +{ + BitmapTestSrc *This = (BitmapTestSrc*)iface; + memcpy(pPixelFormat, This->data->format, sizeof(GUID)); + return S_OK; +} + +static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface, + double *pDpiX, double *pDpiY) +{ + BitmapTestSrc *This = (BitmapTestSrc*)iface; + *pDpiX = This->data->xres; + *pDpiY = This->data->yres; + return S_OK; +} + +static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface, + IWICPalette *pIPalette) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface, + const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) +{ + BitmapTestSrc *This = (BitmapTestSrc*)iface; + UINT bytesperrow; + UINT srcstride; + UINT row_offset; + + if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->data->width || prc->Y+prc->Height > This->data->height) + return E_INVALIDARG; + + bytesperrow = ((This->data->bpp * prc->Width)+7)/8; + srcstride = ((This->data->bpp * This->data->width)+7)/8; + + if (cbStride < bytesperrow) + return E_INVALIDARG; + + if ((cbStride * prc->Height) > cbBufferSize) + return E_INVALIDARG; + + row_offset = prc->X * This->data->bpp; + + if (row_offset % 8 == 0) + { + UINT row; + const BYTE *src; + BYTE *dst; + + src = This->data->bits + (row_offset / 8) + prc->Y * srcstride; + dst = pbBuffer; + for (row=0; row < prc->Height; row++) + { + memcpy(dst, src, bytesperrow); + src += srcstride; + dst += cbStride; + } + return S_OK; + } + else + { + ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface); + return E_FAIL; + } +} + +static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl = { + BitmapTestSrc_QueryInterface, + BitmapTestSrc_AddRef, + BitmapTestSrc_Release, + BitmapTestSrc_GetSize, + BitmapTestSrc_GetPixelFormat, + BitmapTestSrc_GetResolution, + BitmapTestSrc_CopyPalette, + BitmapTestSrc_CopyPixels +}; + +void CreateTestBitmap(const bitmap_data *data, IWICBitmapSource **bitmap) +{ + BitmapTestSrc *This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapTestSrc)); + + if (This) + { + This->lpVtbl = &BitmapTestSrc_Vtbl; + This->ref = 1; + This->data = data; + *bitmap = (IWICBitmapSource*)This; + } + else + *bitmap = NULL; +} + +void DeleteTestBitmap(IWICBitmapSource *bitmap) +{ + BitmapTestSrc *This = (BitmapTestSrc*)bitmap; + ok(This->lpVtbl == &BitmapTestSrc_Vtbl, "test bitmap %p deleted with incorrect vtable\n", bitmap); + ok(This->ref == 1, "test bitmap %p deleted with %i references instead of 1\n", bitmap, This->ref); + HeapFree(GetProcessHeap(), 0, This); +} + +void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name) +{ + BYTE *converted_bits; + UINT width, height; + double xres, yres; + WICRect prc; + UINT stride, buffersize; + GUID dst_pixelformat; + HRESULT hr; + + hr = IWICBitmapSource_GetSize(source, &width, &height); + ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr); + ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name); + ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name); + + hr = IWICBitmapSource_GetResolution(source, &xres, &yres); + ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr); + ok(fabs(xres - expect->xres) < 0.05, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name); + ok(fabs(yres - expect->yres) < 0.05, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name); + + hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat); + ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr); + ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format (%s)\n", name); + + prc.X = 0; + prc.Y = 0; + prc.Width = expect->width; + prc.Height = expect->height; + + stride = (expect->bpp * expect->width + 7) / 8; + buffersize = stride * expect->height; + + converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize); + hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits); + ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr); + if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR)) + { + /* ignore the padding byte when comparing data */ + UINT i; + BOOL equal=TRUE; + const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits; + for (i=0; i<(buffersize/4); i++) + if ((a[i]&0xffffff) != (b[i]&0xffffff)) + { + equal = FALSE; + break; + } + ok(equal, "unexpected pixel data (%s)\n", name); + } + else + ok(memcmp(expect->bits, converted_bits, buffersize) == 0, "unexpected pixel data (%s)\n", name); + HeapFree(GetProcessHeap(), 0, converted_bits); +} + +void test_encode_decode(const struct bitmap_data *input, const struct bitmap_data *output, const CLSID *encoderclsid, const CLSID *decoderclsid, BOOL bypixels, const char *name) +{ + IWICBitmapDecoder *decoder; + IWICBitmapFrameDecode *framedecode; + IWICBitmapEncoder *encoder; + IWICBitmapFrameEncode *frameencode; + IWICBitmapSource *testsource; + IPropertyBag2 *options=NULL; + HRESULT hr; + HGLOBAL hdata; + IStream *stream; + WICPixelFormatGUID pixelformat; + + hr = CoCreateInstance(encoderclsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapEncoder, (void**)&encoder); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + if (!SUCCEEDED(hr)) return; + + hdata = GlobalAlloc(GMEM_MOVEABLE, 0); + ok(hdata != 0, "GlobalAlloc failed\n"); + if (hdata) + { + hr = CreateStreamOnHGlobal(hdata, FALSE, &stream); + ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache); + ok(hr == S_OK, "Initialize failed, hr=%x\n", hr); + + hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options); + ok(hr == S_OK, "CreateNewFrame failed, hr=%x\n", hr); + + if (SUCCEEDED(hr)) + { + hr = IWICBitmapFrameEncode_Initialize(frameencode, options); + ok(hr == S_OK, "Initialize failed, hr=%x\n", hr); + + hr = IWICBitmapFrameEncode_SetSize(frameencode, input->width, input->height); + ok(hr == S_OK, "SetSize failed, hr=%x\n", hr); + + memcpy(&pixelformat, input->format, sizeof(GUID)); + hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat); + ok(hr == S_OK, "SetPixelFormat failed, hr=%x\n", hr); + ok(memcmp(&pixelformat, output->format, sizeof(GUID)) == 0, "got unexpected pixel format\n"); + + if (bypixels) + { + UINT stride = (input->width * input->bpp+7)/8; + + hr = IWICBitmapFrameEncode_SetResolution(frameencode, input->xres, input->yres); + ok(hr == S_OK, "SetResolution failed, hr=%x\n", hr); + + hr = IWICBitmapFrameEncode_WritePixels(frameencode, input->height, stride, stride*input->height, (BYTE*)input->bits); + ok(hr == S_OK, "WritePixels failed, hr=%x\n", hr); + } + else + { + CreateTestBitmap(input, &testsource); + + hr = IWICBitmapFrameEncode_WriteSource(frameencode, testsource, NULL); + ok(hr == S_OK, "WriteSource failed, hr=%x\n", hr); + + DeleteTestBitmap(testsource); + } + + hr = IWICBitmapFrameEncode_Commit(frameencode); + ok(hr == S_OK, "Commit failed, hr=%x\n", hr); + + IWICBitmapFrameEncode_Release(frameencode); + + IPropertyBag2_Release(options); + } + + hr = IWICBitmapEncoder_Commit(encoder); + ok(hr == S_OK, "Commit failed, hr=%x\n", hr); + + IWICBitmapEncoder_Release(encoder); + + hr = CoCreateInstance(decoderclsid, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICBitmapDecoder, (void**)&decoder); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + if (SUCCEEDED(hr)) + { + hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnLoad); + ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr); + + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &framedecode); + ok(SUCCEEDED(hr), "GetFrame failed, hr=%x\n", hr); + if (SUCCEEDED(hr)) + { + compare_bitmap_data(output, (IWICBitmapSource*)framedecode, name); + + IWICBitmapFrameDecode_Release(framedecode); + } + + IWICBitmapDecoder_Release(decoder); + } + + IStream_Release(stream); + } + + GlobalFree(hdata); + } +} + + +START_TEST(testsrc) +{ +} + diff --git a/dlls/windowscodecs/tests/testsrc.h b/dlls/windowscodecs/tests/testsrc.h new file mode 100644 index 0000000..0a75be5 --- /dev/null +++ b/dlls/windowscodecs/tests/testsrc.h @@ -0,0 +1,35 @@ +/* + * Copyright 2009 Vincent Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +typedef struct bitmap_data { + const WICPixelFormatGUID *format; + UINT bpp; + const BYTE *bits; + UINT width; + UINT height; + double xres; + double yres; +} bitmap_data; + +extern void CreateTestBitmap(const bitmap_data *data, IWICBitmapSource **bitmap); +extern void DeleteTestBitmap(IWICBitmapSource *bitmap); + +void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name); + +void test_encode_decode(const struct bitmap_data *input, const struct bitmap_data *output, const CLSID *encoderclsid, const CLSID *decoderclsid, BOOL bypixels, const char *name); + -- 1.5.4.3