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
;
114 if (prc
->X
< 0 || prc
->Y
< 0 || prc
->X
+prc
->Width
> This
->data
->width
|| prc
->Y
+prc
->Height
> This
->data
->height
)
117 bytesperrow
= ((This
->data
->bpp
* prc
->Width
)+7)/8;
118 srcstride
= ((This
->data
->bpp
* This
->data
->width
)+7)/8;
120 if (cbStride
< bytesperrow
)
123 if ((cbStride
* prc
->Height
) > cbBufferSize
)
126 row_offset
= prc
->X
* This
->data
->bpp
;
128 if (row_offset
% 8 == 0)
134 src
= This
->data
->bits
+ (row_offset
/ 8) + prc
->Y
* srcstride
;
136 for (row
=0; row
< prc
->Height
; row
++)
138 memcpy(dst
, src
, bytesperrow
);
146 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface
);
151 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl
= {
152 BitmapTestSrc_QueryInterface
,
153 BitmapTestSrc_AddRef
,
154 BitmapTestSrc_Release
,
155 BitmapTestSrc_GetSize
,
156 BitmapTestSrc_GetPixelFormat
,
157 BitmapTestSrc_GetResolution
,
158 BitmapTestSrc_CopyPalette
,
159 BitmapTestSrc_CopyPixels
162 static void CreateTestBitmap(const bitmap_data
*data
, IWICBitmapSource
**bitmap
)
164 BitmapTestSrc
*This
= HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapTestSrc
));
168 This
->lpVtbl
= &BitmapTestSrc_Vtbl
;
171 *bitmap
= (IWICBitmapSource
*)This
;
177 static void DeleteTestBitmap(IWICBitmapSource
*bitmap
)
179 BitmapTestSrc
*This
= (BitmapTestSrc
*)bitmap
;
180 ok(This
->lpVtbl
== &BitmapTestSrc_Vtbl
, "test bitmap %p deleted with incorrect vtable\n", bitmap
);
181 ok(This
->ref
== 1, "test bitmap %p deleted with %i references instead of 1\n", bitmap
, This
->ref
);
182 HeapFree(GetProcessHeap(), 0, This
);
185 static void compare_bitmap_data(const struct bitmap_data
*expect
, IWICBitmapSource
*source
, const char *name
)
187 BYTE
*converted_bits
;
191 UINT stride
, buffersize
;
192 GUID dst_pixelformat
;
195 hr
= IWICBitmapSource_GetSize(source
, &width
, &height
);
196 ok(SUCCEEDED(hr
), "GetSize(%s) failed, hr=%x\n", name
, hr
);
197 ok(width
== expect
->width
, "expecting %u, got %u (%s)\n", expect
->width
, width
, name
);
198 ok(height
== expect
->height
, "expecting %u, got %u (%s)\n", expect
->height
, height
, name
);
200 hr
= IWICBitmapSource_GetResolution(source
, &xres
, &yres
);
201 ok(SUCCEEDED(hr
), "GetResolution(%s) failed, hr=%x\n", name
, hr
);
202 ok(fabs(xres
- expect
->xres
) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect
->xres
, xres
, name
);
203 ok(fabs(yres
- expect
->yres
) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect
->yres
, yres
, name
);
205 hr
= IWICBitmapSource_GetPixelFormat(source
, &dst_pixelformat
);
206 ok(SUCCEEDED(hr
), "GetPixelFormat(%s) failed, hr=%x\n", name
, hr
);
207 ok(IsEqualGUID(&dst_pixelformat
, expect
->format
), "got unexpected pixel format (%s)\n", name
);
211 prc
.Width
= expect
->width
;
212 prc
.Height
= expect
->height
;
214 stride
= (expect
->bpp
* expect
->width
+ 7) / 8;
215 buffersize
= stride
* expect
->height
;
217 converted_bits
= HeapAlloc(GetProcessHeap(), 0, buffersize
);
218 hr
= IWICBitmapSource_CopyPixels(source
, &prc
, stride
, buffersize
, converted_bits
);
219 ok(SUCCEEDED(hr
), "CopyPixels(%s) failed, hr=%x\n", name
, hr
);
220 if (IsEqualGUID(expect
->format
, &GUID_WICPixelFormat32bppBGR
))
222 /* ignore the padding byte when comparing data */
225 const DWORD
*a
=(const DWORD
*)expect
->bits
, *b
=(const DWORD
*)converted_bits
;
226 for (i
=0; i
<(buffersize
/4); i
++)
227 if ((a
[i
]&0xffffff) != (b
[i
]&0xffffff))
232 ok(equal
, "unexpected pixel data (%s)\n", name
);
235 ok(memcmp(expect
->bits
, converted_bits
, buffersize
) == 0, "unexpected pixel data (%s)\n", name
);
236 HeapFree(GetProcessHeap(), 0, converted_bits
);
239 static const BYTE bits_32bppBGR
[] = {
240 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
241 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
242 static const struct bitmap_data testdata_32bppBGR
= {
243 &GUID_WICPixelFormat32bppBGR
, 32, bits_32bppBGR
, 4, 2, 96.0, 96.0};
245 static const BYTE bits_32bppBGRA
[] = {
246 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
247 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
248 static const struct bitmap_data testdata_32bppBGRA
= {
249 &GUID_WICPixelFormat32bppBGRA
, 32, bits_32bppBGRA
, 4, 2, 96.0, 96.0};
251 static void test_conversion(const struct bitmap_data
*src
, const struct bitmap_data
*dst
, const char *name
, BOOL todo
)
253 IWICBitmapSource
*src_bitmap
, *dst_bitmap
;
256 CreateTestBitmap(src
, &src_bitmap
);
258 hr
= WICConvertBitmapSource(dst
->format
, src_bitmap
, &dst_bitmap
);
260 todo_wine
ok(SUCCEEDED(hr
), "WICConvertBitmapSource(%s) failed, hr=%x\n", name
, hr
);
262 ok(SUCCEEDED(hr
), "WICConvertBitmapSource(%s) failed, hr=%x\n", name
, hr
);
266 compare_bitmap_data(dst
, dst_bitmap
, name
);
268 IWICBitmapSource_Release(dst_bitmap
);
271 DeleteTestBitmap(src_bitmap
);
274 static void test_invalid_conversion(void)
276 IWICBitmapSource
*src_bitmap
, *dst_bitmap
;
279 CreateTestBitmap(&testdata_32bppBGRA
, &src_bitmap
);
281 /* convert to a non-pixel-format GUID */
282 hr
= WICConvertBitmapSource(&GUID_VendorMicrosoft
, src_bitmap
, &dst_bitmap
);
283 ok(hr
== WINCODEC_ERR_COMPONENTNOTFOUND
, "WICConvertBitmapSource returned %x\n", hr
);
285 DeleteTestBitmap(src_bitmap
);
288 static void test_default_converter(void)
290 IWICBitmapSource
*src_bitmap
;
291 IWICFormatConverter
*converter
;
295 CreateTestBitmap(&testdata_32bppBGRA
, &src_bitmap
);
297 hr
= CoCreateInstance(&CLSID_WICDefaultFormatConverter
, NULL
, CLSCTX_INPROC_SERVER
,
298 &IID_IWICFormatConverter
, (void**)&converter
);
299 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
302 hr
= IWICFormatConverter_CanConvert(converter
, &GUID_WICPixelFormat32bppBGRA
,
303 &GUID_WICPixelFormat32bppBGR
, &can_convert
);
304 ok(SUCCEEDED(hr
), "CanConvert returned %x\n", hr
);
305 ok(can_convert
, "expected TRUE, got %i\n", can_convert
);
307 hr
= IWICFormatConverter_Initialize(converter
, src_bitmap
,
308 &GUID_WICPixelFormat32bppBGR
, WICBitmapDitherTypeNone
, NULL
, 0.0,
309 WICBitmapPaletteTypeCustom
);
310 ok(SUCCEEDED(hr
), "Initialize returned %x\n", hr
);
313 compare_bitmap_data(&testdata_32bppBGR
, (IWICBitmapSource
*)converter
, "default converter");
315 IWICFormatConverter_Release(converter
);
318 DeleteTestBitmap(src_bitmap
);
321 static void test_encoder(const struct bitmap_data
*src
, const CLSID
* clsid_encoder
,
322 const struct bitmap_data
*dst
, const CLSID
*clsid_decoder
, const char *name
)
325 IWICBitmapEncoder
*encoder
;
326 IWICBitmapSource
*src_bitmap
;
329 IWICBitmapFrameEncode
*frameencode
;
330 IPropertyBag2
*options
=NULL
;
331 IWICBitmapDecoder
*decoder
;
332 IWICBitmapFrameDecode
*framedecode
;
333 WICPixelFormatGUID pixelformat
;
335 CreateTestBitmap(src
, &src_bitmap
);
337 hr
= CoCreateInstance(clsid_encoder
, NULL
, CLSCTX_INPROC_SERVER
,
338 &IID_IWICBitmapEncoder
, (void**)&encoder
);
339 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
342 hglobal
= GlobalAlloc(GMEM_MOVEABLE
, 0);
343 ok(hglobal
!= NULL
, "GlobalAlloc failed\n");
346 hr
= CreateStreamOnHGlobal(hglobal
, TRUE
, &stream
);
347 ok(SUCCEEDED(hr
), "CreateStreamOnHGlobal failed, hr=%x\n", hr
);
350 if (hglobal
&& SUCCEEDED(hr
))
352 hr
= IWICBitmapEncoder_Initialize(encoder
, stream
, WICBitmapEncoderNoCache
);
353 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
355 hr
= IWICBitmapEncoder_CreateNewFrame(encoder
, &frameencode
, &options
);
356 ok(SUCCEEDED(hr
), "CreateFrame failed, hr=%x\n", hr
);
359 hr
= IWICBitmapFrameEncode_Initialize(frameencode
, options
);
360 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
362 memcpy(&pixelformat
, src
->format
, sizeof(GUID
));
363 hr
= IWICBitmapFrameEncode_SetPixelFormat(frameencode
, &pixelformat
);
364 ok(SUCCEEDED(hr
), "SetPixelFormat failed, hr=%x\n", hr
);
365 ok(IsEqualGUID(&pixelformat
, src
->format
), "SetPixelFormat changed the format\n");
367 hr
= IWICBitmapFrameEncode_SetSize(frameencode
, src
->width
, src
->height
);
368 ok(SUCCEEDED(hr
), "SetSize failed, hr=%x\n", hr
);
370 hr
= IWICBitmapFrameEncode_WriteSource(frameencode
, src_bitmap
, NULL
);
371 ok(SUCCEEDED(hr
), "WriteSource failed, hr=%x\n", hr
);
373 hr
= IWICBitmapFrameEncode_Commit(frameencode
);
374 ok(SUCCEEDED(hr
), "Commit failed, hr=%x\n", hr
);
376 hr
= IWICBitmapEncoder_Commit(encoder
);
377 ok(SUCCEEDED(hr
), "Commit failed, hr=%x\n", hr
);
379 IWICBitmapFrameEncode_Release(frameencode
);
380 IPropertyBag2_Release(options
);
385 hr
= CoCreateInstance(clsid_decoder
, NULL
, CLSCTX_INPROC_SERVER
,
386 &IID_IWICBitmapDecoder
, (void**)&decoder
);
387 ok(SUCCEEDED(hr
), "CoCreateInstance failed, hr=%x\n", hr
);
392 hr
= IWICBitmapDecoder_Initialize(decoder
, stream
, WICDecodeMetadataCacheOnDemand
);
393 ok(SUCCEEDED(hr
), "Initialize failed, hr=%x\n", hr
);
395 hr
= IWICBitmapDecoder_GetFrame(decoder
, 0, &framedecode
);
396 ok(SUCCEEDED(hr
), "GetFrame failed, hr=%x\n", hr
);
400 compare_bitmap_data(dst
, (IWICBitmapSource
*)framedecode
, name
);
402 IWICBitmapFrameDecode_Release(framedecode
);
405 IWICBitmapDecoder_Release(decoder
);
408 IStream_Release(stream
);
412 DeleteTestBitmap(src_bitmap
);
415 START_TEST(converter
)
417 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
419 test_conversion(&testdata_32bppBGRA
, &testdata_32bppBGR
, "BGRA -> BGR", 0);
420 test_conversion(&testdata_32bppBGR
, &testdata_32bppBGRA
, "BGR -> BGRA", 0);
421 test_conversion(&testdata_32bppBGRA
, &testdata_32bppBGRA
, "BGRA -> BGRA", 0);
422 test_invalid_conversion();
423 test_default_converter();
425 test_encoder(&testdata_32bppBGR
, &CLSID_WICBmpEncoder
,
426 &testdata_32bppBGR
, &CLSID_WICBmpDecoder
, "BMP encoder 32bppBGR");