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
28 #include "wine/test.h"
30 typedef struct bitmap_data
{
31 const WICPixelFormatGUID
*format
;
40 typedef struct BitmapTestSrc
{
41 IWICBitmapSource IWICBitmapSource_iface
;
43 const bitmap_data
*data
;
46 static inline BitmapTestSrc
*impl_from_IWICBitmapSource(IWICBitmapSource
*iface
)
48 return CONTAINING_RECORD(iface
, BitmapTestSrc
, IWICBitmapSource_iface
);
51 static HRESULT WINAPI
BitmapTestSrc_QueryInterface(IWICBitmapSource
*iface
, REFIID iid
,
54 if (!ppv
) return E_INVALIDARG
;
56 if (IsEqualIID(&IID_IUnknown
, iid
) ||
57 IsEqualIID(&IID_IWICBitmapSource
, iid
))
62 IUnknown_AddRef((IUnknown
*)*ppv
);
66 static ULONG WINAPI
BitmapTestSrc_AddRef(IWICBitmapSource
*iface
)
68 BitmapTestSrc
*This
= impl_from_IWICBitmapSource(iface
);
69 ULONG ref
= InterlockedIncrement(&This
->ref
);
73 static ULONG WINAPI
BitmapTestSrc_Release(IWICBitmapSource
*iface
)
75 BitmapTestSrc
*This
= impl_from_IWICBitmapSource(iface
);
76 ULONG ref
= InterlockedDecrement(&This
->ref
);
80 static HRESULT WINAPI
BitmapTestSrc_GetSize(IWICBitmapSource
*iface
,
81 UINT
*puiWidth
, UINT
*puiHeight
)
83 BitmapTestSrc
*This
= impl_from_IWICBitmapSource(iface
);
84 *puiWidth
= This
->data
->width
;
85 *puiHeight
= This
->data
->height
;
89 static HRESULT WINAPI
BitmapTestSrc_GetPixelFormat(IWICBitmapSource
*iface
,
90 WICPixelFormatGUID
*pPixelFormat
)
92 BitmapTestSrc
*This
= impl_from_IWICBitmapSource(iface
);
93 memcpy(pPixelFormat
, This
->data
->format
, sizeof(GUID
));
97 static HRESULT WINAPI
BitmapTestSrc_GetResolution(IWICBitmapSource
*iface
,
98 double *pDpiX
, double *pDpiY
)
100 BitmapTestSrc
*This
= impl_from_IWICBitmapSource(iface
);
101 *pDpiX
= This
->data
->xres
;
102 *pDpiY
= This
->data
->yres
;
106 static HRESULT WINAPI
BitmapTestSrc_CopyPalette(IWICBitmapSource
*iface
,
107 IWICPalette
*pIPalette
)
112 static HRESULT WINAPI
BitmapTestSrc_CopyPixels(IWICBitmapSource
*iface
,
113 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
115 BitmapTestSrc
*This
= impl_from_IWICBitmapSource(iface
);
125 rc
.Width
= This
->data
->width
;
126 rc
.Height
= This
->data
->height
;
131 if (prc
->X
< 0 || prc
->Y
< 0 || prc
->X
+prc
->Width
> This
->data
->width
|| prc
->Y
+prc
->Height
> This
->data
->height
)
135 bytesperrow
= ((This
->data
->bpp
* prc
->Width
)+7)/8;
136 srcstride
= ((This
->data
->bpp
* This
->data
->width
)+7)/8;
138 if (cbStride
< bytesperrow
)
141 if ((cbStride
* prc
->Height
) > cbBufferSize
)
144 row_offset
= prc
->X
* This
->data
->bpp
;
146 if (row_offset
% 8 == 0)
152 src
= This
->data
->bits
+ (row_offset
/ 8) + prc
->Y
* srcstride
;
154 for (row
=0; row
< prc
->Height
; row
++)
156 memcpy(dst
, src
, bytesperrow
);
164 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface
);
169 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl
= {
170 BitmapTestSrc_QueryInterface
,
171 BitmapTestSrc_AddRef
,
172 BitmapTestSrc_Release
,
173 BitmapTestSrc_GetSize
,
174 BitmapTestSrc_GetPixelFormat
,
175 BitmapTestSrc_GetResolution
,
176 BitmapTestSrc_CopyPalette
,
177 BitmapTestSrc_CopyPixels
180 static void CreateTestBitmap(const bitmap_data
*data
, BitmapTestSrc
**This
)
182 *This
= HeapAlloc(GetProcessHeap(), 0, sizeof(**This
));
186 (*This
)->IWICBitmapSource_iface
.lpVtbl
= &BitmapTestSrc_Vtbl
;
188 (*This
)->data
= data
;
192 static void DeleteTestBitmap(BitmapTestSrc
*This
)
194 ok(This
->IWICBitmapSource_iface
.lpVtbl
== &BitmapTestSrc_Vtbl
, "test bitmap %p deleted with incorrect vtable\n", This
);
195 ok(This
->ref
== 1, "test bitmap %p deleted with %i references instead of 1\n", This
, This
->ref
);
196 HeapFree(GetProcessHeap(), 0, This
);
199 static void compare_bitmap_data(const struct bitmap_data
*expect
, IWICBitmapSource
*source
, const char *name
)
201 BYTE
*converted_bits
;
205 UINT stride
, buffersize
;
206 GUID dst_pixelformat
;
209 hr
= IWICBitmapSource_GetSize(source
, &width
, &height
);
210 ok(SUCCEEDED(hr
), "GetSize(%s) failed, hr=%x\n", name
, hr
);
211 ok(width
== expect
->width
, "expecting %u, got %u (%s)\n", expect
->width
, width
, name
);
212 ok(height
== expect
->height
, "expecting %u, got %u (%s)\n", expect
->height
, height
, name
);
214 hr
= IWICBitmapSource_GetResolution(source
, &xres
, &yres
);
215 ok(SUCCEEDED(hr
), "GetResolution(%s) failed, hr=%x\n", name
, hr
);
216 ok(fabs(xres
- expect
->xres
) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect
->xres
, xres
, name
);
217 ok(fabs(yres
- expect
->yres
) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect
->yres
, yres
, name
);
219 hr
= IWICBitmapSource_GetPixelFormat(source
, &dst_pixelformat
);
220 ok(SUCCEEDED(hr
), "GetPixelFormat(%s) failed, hr=%x\n", name
, hr
);
221 ok(IsEqualGUID(&dst_pixelformat
, expect
->format
), "got unexpected pixel format (%s)\n", name
);
225 prc
.Width
= expect
->width
;
226 prc
.Height
= expect
->height
;
228 stride
= (expect
->bpp
* expect
->width
+ 7) / 8;
229 buffersize
= stride
* expect
->height
;
231 converted_bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
232 hr
= IWICBitmapSource_CopyPixels(source
, &prc
, stride
, buffersize
, converted_bits
);
233 ok(SUCCEEDED(hr
), "CopyPixels(%s) failed, hr=%x\n", name
, hr
);
234 if (IsEqualGUID(expect
->format
, &GUID_WICPixelFormat32bppBGR
))
236 /* ignore the padding byte when comparing data */
239 const DWORD
*a
=(const DWORD
*)expect
->bits
, *b
=(const DWORD
*)converted_bits
;
240 for (i
=0; i
<(buffersize
/4); i
++)
241 if ((a
[i
]&0xffffff) != (b
[i
]&0xffffff))
246 ok(equal
, "unexpected pixel data (%s)\n", name
);
249 ok(memcmp(expect
->bits
, converted_bits
, buffersize
) == 0, "unexpected pixel data (%s)\n", name
);
251 /* Test with NULL rectangle - should copy the whole bitmap */
252 hr
= IWICBitmapSource_CopyPixels(source
, NULL
, stride
, buffersize
, converted_bits
);
253 ok(SUCCEEDED(hr
), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name
, hr
);
254 if (IsEqualGUID(expect
->format
, &GUID_WICPixelFormat32bppBGR
))
256 /* ignore the padding byte when comparing data */
259 const DWORD
*a
=(const DWORD
*)expect
->bits
, *b
=(const DWORD
*)converted_bits
;
260 for (i
=0; i
<(buffersize
/4); i
++)
261 if ((a
[i
]&0xffffff) != (b
[i
]&0xffffff))
266 ok(equal
, "unexpected pixel data with rc=NULL (%s)\n", name
);
269 ok(memcmp(expect
->bits
, converted_bits
, buffersize
) == 0, "unexpected pixel data with rc=NULL (%s)\n", name
);
271 HeapFree(GetProcessHeap(), 0, converted_bits
);
274 static const BYTE bits_24bppBGR
[] = {
275 255,0,0, 0,255,0, 0,0,255, 0,0,0,
276 0,255,255, 255,0,255, 255,255,0, 255,255,255};
277 static const struct bitmap_data testdata_24bppBGR
= {
278 &GUID_WICPixelFormat24bppBGR
, 24, bits_24bppBGR
, 4, 2, 96.0, 96.0};
280 static const BYTE bits_32bppBGR
[] = {
281 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
282 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
283 static const struct bitmap_data testdata_32bppBGR
= {
284 &GUID_WICPixelFormat32bppBGR
, 32, bits_32bppBGR
, 4, 2, 96.0, 96.0};
286 static const BYTE bits_32bppBGRA
[] = {
287 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
288 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
289 static const struct bitmap_data testdata_32bppBGRA
= {
290 &GUID_WICPixelFormat32bppBGRA
, 32, bits_32bppBGRA
, 4, 2, 96.0, 96.0};
292 static void test_conversion(const struct bitmap_data
*src
, const struct bitmap_data
*dst
, const char *name
, BOOL todo
)
294 BitmapTestSrc
*src_obj
;
295 IWICBitmapSource
*dst_bitmap
;
298 CreateTestBitmap(src
, &src_obj
);
300 hr
= WICConvertBitmapSource(dst
->format
, &src_obj
->IWICBitmapSource_iface
, &dst_bitmap
);
302 todo_wine
ok(SUCCEEDED(hr
), "WICConvertBitmapSource(%s) failed, hr=%x\n", name
, hr
);
304 ok(SUCCEEDED(hr
), "WICConvertBitmapSource(%s) failed, hr=%x\n", name
, hr
);
308 compare_bitmap_data(dst
, dst_bitmap
, name
);
310 IWICBitmapSource_Release(dst_bitmap
);
313 DeleteTestBitmap(src_obj
);
316 static void test_invalid_conversion(void)
318 BitmapTestSrc
*src_obj
;
319 IWICBitmapSource
*dst_bitmap
;
322 CreateTestBitmap(&testdata_32bppBGRA
, &src_obj
);
324 /* convert to a non-pixel-format GUID */
325 hr
= WICConvertBitmapSource(&GUID_VendorMicrosoft
, &src_obj
->IWICBitmapSource_iface
, &dst_bitmap
);
326 ok(hr
== WINCODEC_ERR_COMPONENTNOTFOUND
, "WICConvertBitmapSource returned %x\n", hr
);
328 DeleteTestBitmap(src_obj
);
331 static void test_default_converter(void)
333 BitmapTestSrc
*src_obj
;
334 IWICFormatConverter
*converter
;
338 CreateTestBitmap(&testdata_32bppBGRA
, &src_obj
);
340 hr
= CoCreateInstance(&CLSID_WICDefaultFormatConverter
, NULL
, CLSCTX_INPROC_SERVER
,
341 &IID_IWICFormatConverter
, (void**)&converter
);
342 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
345 hr
= IWICFormatConverter_CanConvert(converter
, &GUID_WICPixelFormat32bppBGRA
,
346 &GUID_WICPixelFormat32bppBGR
, &can_convert
);
347 ok(SUCCEEDED(hr
), "CanConvert returned %x\n", hr
);
348 ok(can_convert
, "expected TRUE, got %i\n", can_convert
);
350 hr
= IWICFormatConverter_Initialize(converter
, &src_obj
->IWICBitmapSource_iface
,
351 &GUID_WICPixelFormat32bppBGR
, WICBitmapDitherTypeNone
, NULL
, 0.0,
352 WICBitmapPaletteTypeCustom
);
353 ok(SUCCEEDED(hr
), "Initialize returned %x\n", hr
);
356 compare_bitmap_data(&testdata_32bppBGR
, (IWICBitmapSource
*)converter
, "default converter");
358 IWICFormatConverter_Release(converter
);
361 DeleteTestBitmap(src_obj
);
364 static void test_multi_encoder(const struct bitmap_data
**srcs
, const CLSID
* clsid_encoder
,
365 const struct bitmap_data
**dsts
, const CLSID
*clsid_decoder
, const char *name
)
368 IWICBitmapEncoder
*encoder
;
369 BitmapTestSrc
*src_obj
;
372 IWICBitmapFrameEncode
*frameencode
;
373 IPropertyBag2
*options
=NULL
;
374 IWICBitmapDecoder
*decoder
;
375 IWICBitmapFrameDecode
*framedecode
;
376 WICPixelFormatGUID pixelformat
;
379 hr
= CoCreateInstance(clsid_encoder
, NULL
, CLSCTX_INPROC_SERVER
,
380 &IID_IWICBitmapEncoder
, (void**)&encoder
);
381 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
384 hglobal
= GlobalAlloc(GMEM_MOVEABLE
, 0);
385 ok(hglobal
!= NULL
, "GlobalAlloc failed\n");
388 hr
= CreateStreamOnHGlobal(hglobal
, TRUE
, &stream
);
389 ok(SUCCEEDED(hr
), "CreateStreamOnHGlobal failed, hr=%x\n", hr
);
392 if (hglobal
&& SUCCEEDED(hr
))
394 hr
= IWICBitmapEncoder_Initialize(encoder
, stream
, WICBitmapEncoderNoCache
);
395 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
398 while (SUCCEEDED(hr
) && srcs
[i
])
400 CreateTestBitmap(srcs
[i
], &src_obj
);
402 hr
= IWICBitmapEncoder_CreateNewFrame(encoder
, &frameencode
, &options
);
403 ok(SUCCEEDED(hr
), "CreateFrame failed, hr=%x\n", hr
);
406 hr
= IWICBitmapFrameEncode_Initialize(frameencode
, options
);
407 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
409 memcpy(&pixelformat
, srcs
[i
]->format
, sizeof(GUID
));
410 hr
= IWICBitmapFrameEncode_SetPixelFormat(frameencode
, &pixelformat
);
411 ok(SUCCEEDED(hr
), "SetPixelFormat failed, hr=%x\n", hr
);
412 ok(IsEqualGUID(&pixelformat
, srcs
[i
]->format
), "SetPixelFormat changed the format\n");
414 hr
= IWICBitmapFrameEncode_SetSize(frameencode
, srcs
[i
]->width
, srcs
[i
]->height
);
415 ok(SUCCEEDED(hr
), "SetSize failed, hr=%x\n", hr
);
417 hr
= IWICBitmapFrameEncode_WriteSource(frameencode
, &src_obj
->IWICBitmapSource_iface
, NULL
);
418 ok(SUCCEEDED(hr
), "WriteSource failed, hr=%x\n", hr
);
420 hr
= IWICBitmapFrameEncode_Commit(frameencode
);
421 ok(SUCCEEDED(hr
), "Commit failed, hr=%x\n", hr
);
423 IWICBitmapFrameEncode_Release(frameencode
);
424 IPropertyBag2_Release(options
);
427 DeleteTestBitmap(src_obj
);
434 hr
= IWICBitmapEncoder_Commit(encoder
);
435 ok(SUCCEEDED(hr
), "Commit failed, hr=%x\n", hr
);
440 hr
= CoCreateInstance(clsid_decoder
, NULL
, CLSCTX_INPROC_SERVER
,
441 &IID_IWICBitmapDecoder
, (void**)&decoder
);
442 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
447 hr
= IWICBitmapDecoder_Initialize(decoder
, stream
, WICDecodeMetadataCacheOnDemand
);
448 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
451 while (SUCCEEDED(hr
) && dsts
[i
])
453 hr
= IWICBitmapDecoder_GetFrame(decoder
, i
, &framedecode
);
454 ok(SUCCEEDED(hr
), "GetFrame failed, hr=%x\n", hr
);
458 compare_bitmap_data(dsts
[i
], (IWICBitmapSource
*)framedecode
, name
);
460 IWICBitmapFrameDecode_Release(framedecode
);
466 IWICBitmapDecoder_Release(decoder
);
469 IStream_Release(stream
);
472 IWICBitmapEncoder_Release(encoder
);
476 static void test_encoder(const struct bitmap_data
*src
, const CLSID
* clsid_encoder
,
477 const struct bitmap_data
*dst
, const CLSID
*clsid_decoder
, const char *name
)
479 const struct bitmap_data
*srcs
[2];
480 const struct bitmap_data
*dsts
[2];
487 test_multi_encoder(srcs
, clsid_encoder
, dsts
, clsid_decoder
, name
);
490 static const struct bitmap_data
*multiple_frames
[3] = {
495 START_TEST(converter
)
497 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
499 test_conversion(&testdata_32bppBGRA
, &testdata_32bppBGR
, "BGRA -> BGR", 0);
500 test_conversion(&testdata_32bppBGR
, &testdata_32bppBGRA
, "BGR -> BGRA", 0);
501 test_conversion(&testdata_32bppBGRA
, &testdata_32bppBGRA
, "BGRA -> BGRA", 0);
502 test_invalid_conversion();
503 test_default_converter();
505 test_encoder(&testdata_32bppBGR
, &CLSID_WICBmpEncoder
,
506 &testdata_32bppBGR
, &CLSID_WICBmpDecoder
, "BMP encoder 32bppBGR");
508 test_encoder(&testdata_24bppBGR
, &CLSID_WICPngEncoder
,
509 &testdata_24bppBGR
, &CLSID_WICPngDecoder
, "PNG encoder 24bppBGR");
511 test_encoder(&testdata_24bppBGR
, &CLSID_WICTiffEncoder
,
512 &testdata_24bppBGR
, &CLSID_WICTiffDecoder
, "TIFF encoder 24bppBGR");
514 test_multi_encoder(multiple_frames
, &CLSID_WICTiffEncoder
,
515 multiple_frames
, &CLSID_WICTiffDecoder
, "TIFF encoder multi-frame");