2 * Copyright 2009 Vincent Povirk
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
29 typedef struct bitmap_data
{
30 const WICPixelFormatGUID
*format
;
39 typedef struct BitmapTestSrc
{
40 const IWICBitmapSourceVtbl
*lpVtbl
;
42 const bitmap_data
*data
;
45 static HRESULT WINAPI
BitmapTestSrc_QueryInterface(IWICBitmapSource
*iface
, REFIID iid
,
48 if (!ppv
) return E_INVALIDARG
;
50 if (IsEqualIID(&IID_IUnknown
, iid
) ||
51 IsEqualIID(&IID_IWICBitmapSource
, iid
))
56 IUnknown_AddRef((IUnknown
*)*ppv
);
60 static ULONG WINAPI
BitmapTestSrc_AddRef(IWICBitmapSource
*iface
)
62 BitmapTestSrc
*This
= (BitmapTestSrc
*)iface
;
63 ULONG ref
= InterlockedIncrement(&This
->ref
);
67 static ULONG WINAPI
BitmapTestSrc_Release(IWICBitmapSource
*iface
)
69 BitmapTestSrc
*This
= (BitmapTestSrc
*)iface
;
70 ULONG ref
= InterlockedDecrement(&This
->ref
);
74 static HRESULT WINAPI
BitmapTestSrc_GetSize(IWICBitmapSource
*iface
,
75 UINT
*puiWidth
, UINT
*puiHeight
)
77 BitmapTestSrc
*This
= (BitmapTestSrc
*)iface
;
78 *puiWidth
= This
->data
->width
;
79 *puiHeight
= This
->data
->height
;
83 static HRESULT WINAPI
BitmapTestSrc_GetPixelFormat(IWICBitmapSource
*iface
,
84 WICPixelFormatGUID
*pPixelFormat
)
86 BitmapTestSrc
*This
= (BitmapTestSrc
*)iface
;
87 memcpy(pPixelFormat
, This
->data
->format
, sizeof(GUID
));
91 static HRESULT WINAPI
BitmapTestSrc_GetResolution(IWICBitmapSource
*iface
,
92 double *pDpiX
, double *pDpiY
)
94 BitmapTestSrc
*This
= (BitmapTestSrc
*)iface
;
95 *pDpiX
= This
->data
->xres
;
96 *pDpiY
= This
->data
->yres
;
100 static HRESULT WINAPI
BitmapTestSrc_CopyPalette(IWICBitmapSource
*iface
,
101 IWICPalette
*pIPalette
)
106 static HRESULT WINAPI
BitmapTestSrc_CopyPixels(IWICBitmapSource
*iface
,
107 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
109 BitmapTestSrc
*This
= (BitmapTestSrc
*)iface
;
119 rc
.Width
= This
->data
->width
;
120 rc
.Height
= This
->data
->height
;
125 if (prc
->X
< 0 || prc
->Y
< 0 || prc
->X
+prc
->Width
> This
->data
->width
|| prc
->Y
+prc
->Height
> This
->data
->height
)
129 bytesperrow
= ((This
->data
->bpp
* prc
->Width
)+7)/8;
130 srcstride
= ((This
->data
->bpp
* This
->data
->width
)+7)/8;
132 if (cbStride
< bytesperrow
)
135 if ((cbStride
* prc
->Height
) > cbBufferSize
)
138 row_offset
= prc
->X
* This
->data
->bpp
;
140 if (row_offset
% 8 == 0)
146 src
= This
->data
->bits
+ (row_offset
/ 8) + prc
->Y
* srcstride
;
148 for (row
=0; row
< prc
->Height
; row
++)
150 memcpy(dst
, src
, bytesperrow
);
158 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface
);
163 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl
= {
164 BitmapTestSrc_QueryInterface
,
165 BitmapTestSrc_AddRef
,
166 BitmapTestSrc_Release
,
167 BitmapTestSrc_GetSize
,
168 BitmapTestSrc_GetPixelFormat
,
169 BitmapTestSrc_GetResolution
,
170 BitmapTestSrc_CopyPalette
,
171 BitmapTestSrc_CopyPixels
174 static void CreateTestBitmap(const bitmap_data
*data
, IWICBitmapSource
**bitmap
)
176 BitmapTestSrc
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapTestSrc
));
180 This
->lpVtbl
= &BitmapTestSrc_Vtbl
;
183 *bitmap
= (IWICBitmapSource
*)This
;
189 static void DeleteTestBitmap(IWICBitmapSource
*bitmap
)
191 BitmapTestSrc
*This
= (BitmapTestSrc
*)bitmap
;
192 ok(This
->lpVtbl
== &BitmapTestSrc_Vtbl
, "test bitmap %p deleted with incorrect vtable\n", bitmap
);
193 ok(This
->ref
== 1, "test bitmap %p deleted with %i references instead of 1\n", bitmap
, This
->ref
);
194 HeapFree(GetProcessHeap(), 0, This
);
197 static void compare_bitmap_data(const struct bitmap_data
*expect
, IWICBitmapSource
*source
, const char *name
)
199 BYTE
*converted_bits
;
203 UINT stride
, buffersize
;
204 GUID dst_pixelformat
;
207 hr
= IWICBitmapSource_GetSize(source
, &width
, &height
);
208 ok(SUCCEEDED(hr
), "GetSize(%s) failed, hr=%x\n", name
, hr
);
209 ok(width
== expect
->width
, "expecting %u, got %u (%s)\n", expect
->width
, width
, name
);
210 ok(height
== expect
->height
, "expecting %u, got %u (%s)\n", expect
->height
, height
, name
);
212 hr
= IWICBitmapSource_GetResolution(source
, &xres
, &yres
);
213 ok(SUCCEEDED(hr
), "GetResolution(%s) failed, hr=%x\n", name
, hr
);
214 ok(fabs(xres
- expect
->xres
) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect
->xres
, xres
, name
);
215 ok(fabs(yres
- expect
->yres
) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect
->yres
, yres
, name
);
217 hr
= IWICBitmapSource_GetPixelFormat(source
, &dst_pixelformat
);
218 ok(SUCCEEDED(hr
), "GetPixelFormat(%s) failed, hr=%x\n", name
, hr
);
219 ok(IsEqualGUID(&dst_pixelformat
, expect
->format
), "got unexpected pixel format (%s)\n", name
);
223 prc
.Width
= expect
->width
;
224 prc
.Height
= expect
->height
;
226 stride
= (expect
->bpp
* expect
->width
+ 7) / 8;
227 buffersize
= stride
* expect
->height
;
229 converted_bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
230 hr
= IWICBitmapSource_CopyPixels(source
, &prc
, stride
, buffersize
, converted_bits
);
231 ok(SUCCEEDED(hr
), "CopyPixels(%s) failed, hr=%x\n", name
, hr
);
232 if (IsEqualGUID(expect
->format
, &GUID_WICPixelFormat32bppBGR
))
234 /* ignore the padding byte when comparing data */
237 const DWORD
*a
=(const DWORD
*)expect
->bits
, *b
=(const DWORD
*)converted_bits
;
238 for (i
=0; i
<(buffersize
/4); i
++)
239 if ((a
[i
]&0xffffff) != (b
[i
]&0xffffff))
244 ok(equal
, "unexpected pixel data (%s)\n", name
);
247 ok(memcmp(expect
->bits
, converted_bits
, buffersize
) == 0, "unexpected pixel data (%s)\n", name
);
249 /* Test with NULL rectangle - should copy the whole bitmap */
250 hr
= IWICBitmapSource_CopyPixels(source
, NULL
, stride
, buffersize
, converted_bits
);
251 ok(SUCCEEDED(hr
), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name
, hr
);
252 if (IsEqualGUID(expect
->format
, &GUID_WICPixelFormat32bppBGR
))
254 /* ignore the padding byte when comparing data */
257 const DWORD
*a
=(const DWORD
*)expect
->bits
, *b
=(const DWORD
*)converted_bits
;
258 for (i
=0; i
<(buffersize
/4); i
++)
259 if ((a
[i
]&0xffffff) != (b
[i
]&0xffffff))
264 ok(equal
, "unexpected pixel data with rc=NULL (%s)\n", name
);
267 ok(memcmp(expect
->bits
, converted_bits
, buffersize
) == 0, "unexpected pixel data with rc=NULL (%s)\n", name
);
269 HeapFree(GetProcessHeap(), 0, converted_bits
);
272 static const BYTE bits_24bppBGR
[] = {
273 255,0,0, 0,255,0, 0,0,255, 0,0,0,
274 0,255,255, 255,0,255, 255,255,0, 255,255,255};
275 static const struct bitmap_data testdata_24bppBGR
= {
276 &GUID_WICPixelFormat24bppBGR
, 24, bits_24bppBGR
, 4, 2, 96.0, 96.0};
278 static const BYTE bits_32bppBGR
[] = {
279 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
280 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
281 static const struct bitmap_data testdata_32bppBGR
= {
282 &GUID_WICPixelFormat32bppBGR
, 32, bits_32bppBGR
, 4, 2, 96.0, 96.0};
284 static const BYTE bits_32bppBGRA
[] = {
285 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
286 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
287 static const struct bitmap_data testdata_32bppBGRA
= {
288 &GUID_WICPixelFormat32bppBGRA
, 32, bits_32bppBGRA
, 4, 2, 96.0, 96.0};
290 static void test_conversion(const struct bitmap_data
*src
, const struct bitmap_data
*dst
, const char *name
, BOOL todo
)
292 IWICBitmapSource
*src_bitmap
, *dst_bitmap
;
295 CreateTestBitmap(src
, &src_bitmap
);
297 hr
= WICConvertBitmapSource(dst
->format
, src_bitmap
, &dst_bitmap
);
299 todo_wine
ok(SUCCEEDED(hr
), "WICConvertBitmapSource(%s) failed, hr=%x\n", name
, hr
);
301 ok(SUCCEEDED(hr
), "WICConvertBitmapSource(%s) failed, hr=%x\n", name
, hr
);
305 compare_bitmap_data(dst
, dst_bitmap
, name
);
307 IWICBitmapSource_Release(dst_bitmap
);
310 DeleteTestBitmap(src_bitmap
);
313 static void test_invalid_conversion(void)
315 IWICBitmapSource
*src_bitmap
, *dst_bitmap
;
318 CreateTestBitmap(&testdata_32bppBGRA
, &src_bitmap
);
320 /* convert to a non-pixel-format GUID */
321 hr
= WICConvertBitmapSource(&GUID_VendorMicrosoft
, src_bitmap
, &dst_bitmap
);
322 ok(hr
== WINCODEC_ERR_COMPONENTNOTFOUND
, "WICConvertBitmapSource returned %x\n", hr
);
324 DeleteTestBitmap(src_bitmap
);
327 static void test_default_converter(void)
329 IWICBitmapSource
*src_bitmap
;
330 IWICFormatConverter
*converter
;
334 CreateTestBitmap(&testdata_32bppBGRA
, &src_bitmap
);
336 hr
= CoCreateInstance(&CLSID_WICDefaultFormatConverter
, NULL
, CLSCTX_INPROC_SERVER
,
337 &IID_IWICFormatConverter
, (void**)&converter
);
338 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
341 hr
= IWICFormatConverter_CanConvert(converter
, &GUID_WICPixelFormat32bppBGRA
,
342 &GUID_WICPixelFormat32bppBGR
, &can_convert
);
343 ok(SUCCEEDED(hr
), "CanConvert returned %x\n", hr
);
344 ok(can_convert
, "expected TRUE, got %i\n", can_convert
);
346 hr
= IWICFormatConverter_Initialize(converter
, src_bitmap
,
347 &GUID_WICPixelFormat32bppBGR
, WICBitmapDitherTypeNone
, NULL
, 0.0,
348 WICBitmapPaletteTypeCustom
);
349 ok(SUCCEEDED(hr
), "Initialize returned %x\n", hr
);
352 compare_bitmap_data(&testdata_32bppBGR
, (IWICBitmapSource
*)converter
, "default converter");
354 IWICFormatConverter_Release(converter
);
357 DeleteTestBitmap(src_bitmap
);
360 static void test_encoder(const struct bitmap_data
*src
, const CLSID
* clsid_encoder
,
361 const struct bitmap_data
*dst
, const CLSID
*clsid_decoder
, const char *name
)
364 IWICBitmapEncoder
*encoder
;
365 IWICBitmapSource
*src_bitmap
;
368 IWICBitmapFrameEncode
*frameencode
;
369 IPropertyBag2
*options
=NULL
;
370 IWICBitmapDecoder
*decoder
;
371 IWICBitmapFrameDecode
*framedecode
;
372 WICPixelFormatGUID pixelformat
;
374 CreateTestBitmap(src
, &src_bitmap
);
376 hr
= CoCreateInstance(clsid_encoder
, NULL
, CLSCTX_INPROC_SERVER
,
377 &IID_IWICBitmapEncoder
, (void**)&encoder
);
378 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
381 hglobal
= GlobalAlloc(GMEM_MOVEABLE
, 0);
382 ok(hglobal
!= NULL
, "GlobalAlloc failed\n");
385 hr
= CreateStreamOnHGlobal(hglobal
, TRUE
, &stream
);
386 ok(SUCCEEDED(hr
), "CreateStreamOnHGlobal failed, hr=%x\n", hr
);
389 if (hglobal
&& SUCCEEDED(hr
))
391 hr
= IWICBitmapEncoder_Initialize(encoder
, stream
, WICBitmapEncoderNoCache
);
392 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
394 hr
= IWICBitmapEncoder_CreateNewFrame(encoder
, &frameencode
, &options
);
395 ok(SUCCEEDED(hr
), "CreateFrame failed, hr=%x\n", hr
);
398 hr
= IWICBitmapFrameEncode_Initialize(frameencode
, options
);
399 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
401 memcpy(&pixelformat
, src
->format
, sizeof(GUID
));
402 hr
= IWICBitmapFrameEncode_SetPixelFormat(frameencode
, &pixelformat
);
403 ok(SUCCEEDED(hr
), "SetPixelFormat failed, hr=%x\n", hr
);
404 ok(IsEqualGUID(&pixelformat
, src
->format
), "SetPixelFormat changed the format\n");
406 hr
= IWICBitmapFrameEncode_SetSize(frameencode
, src
->width
, src
->height
);
407 ok(SUCCEEDED(hr
), "SetSize failed, hr=%x\n", hr
);
409 hr
= IWICBitmapFrameEncode_WriteSource(frameencode
, src_bitmap
, NULL
);
410 ok(SUCCEEDED(hr
), "WriteSource failed, hr=%x\n", hr
);
412 hr
= IWICBitmapFrameEncode_Commit(frameencode
);
413 ok(SUCCEEDED(hr
), "Commit failed, hr=%x\n", hr
);
415 hr
= IWICBitmapEncoder_Commit(encoder
);
416 ok(SUCCEEDED(hr
), "Commit failed, hr=%x\n", hr
);
418 IWICBitmapFrameEncode_Release(frameencode
);
419 IPropertyBag2_Release(options
);
424 hr
= CoCreateInstance(clsid_decoder
, NULL
, CLSCTX_INPROC_SERVER
,
425 &IID_IWICBitmapDecoder
, (void**)&decoder
);
426 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
431 hr
= IWICBitmapDecoder_Initialize(decoder
, stream
, WICDecodeMetadataCacheOnDemand
);
432 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
434 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
435 ok(SUCCEEDED(hr
), "GetFrame failed, hr=%x\n", hr
);
439 compare_bitmap_data(dst
, (IWICBitmapSource
*)framedecode
, name
);
441 IWICBitmapFrameDecode_Release(framedecode
);
444 IWICBitmapDecoder_Release(decoder
);
447 IStream_Release(stream
);
450 IWICBitmapEncoder_Release(encoder
);
453 DeleteTestBitmap(src_bitmap
);
456 START_TEST(converter
)
458 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
460 test_conversion(&testdata_32bppBGRA
, &testdata_32bppBGR
, "BGRA -> BGR", 0);
461 test_conversion(&testdata_32bppBGR
, &testdata_32bppBGRA
, "BGR -> BGRA", 0);
462 test_conversion(&testdata_32bppBGRA
, &testdata_32bppBGRA
, "BGRA -> BGRA", 0);
463 test_invalid_conversion();
464 test_default_converter();
466 test_encoder(&testdata_32bppBGR
, &CLSID_WICBmpEncoder
,
467 &testdata_32bppBGR
, &CLSID_WICBmpDecoder
, "BMP encoder 32bppBGR");
469 test_encoder(&testdata_24bppBGR
, &CLSID_WICPngEncoder
,
470 &testdata_24bppBGR
, &CLSID_WICPngDecoder
, "PNG encoder 24bppBGR");