1 /* 2 * Copyright 2009 Vincent Povirk 3 * Copyright 2016 Dmitry Timoshkov 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "precomp.h" 21 22 static IWICImagingFactory *factory; 23 24 typedef struct bitmap_data { 25 const WICPixelFormatGUID *format; 26 UINT bpp; 27 const BYTE *bits; 28 UINT width; 29 UINT height; 30 double xres; 31 double yres; 32 const struct bitmap_data *alt_data; 33 } bitmap_data; 34 35 typedef struct BitmapTestSrc { 36 IWICBitmapSource IWICBitmapSource_iface; 37 LONG ref; 38 const bitmap_data *data; 39 } BitmapTestSrc; 40 41 extern HRESULT STDMETHODCALLTYPE IWICBitmapFrameEncode_WriteSource_Proxy(IWICBitmapFrameEncode* This, 42 IWICBitmapSource *pIBitmapSource, WICRect *prc); 43 44 static BOOL near_equal(float a, float b) 45 { 46 return fabsf(a - b) < 0.001; 47 } 48 49 static inline BitmapTestSrc *impl_from_IWICBitmapSource(IWICBitmapSource *iface) 50 { 51 return CONTAINING_RECORD(iface, BitmapTestSrc, IWICBitmapSource_iface); 52 } 53 54 static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid, 55 void **ppv) 56 { 57 if (!ppv) return E_INVALIDARG; 58 59 if (IsEqualIID(&IID_IUnknown, iid) || 60 IsEqualIID(&IID_IWICBitmapSource, iid)) 61 *ppv = iface; 62 else 63 return E_NOINTERFACE; 64 65 IUnknown_AddRef((IUnknown*)*ppv); 66 return S_OK; 67 } 68 69 static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface) 70 { 71 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); 72 ULONG ref = InterlockedIncrement(&This->ref); 73 return ref; 74 } 75 76 static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface) 77 { 78 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); 79 ULONG ref = InterlockedDecrement(&This->ref); 80 return ref; 81 } 82 83 static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface, 84 UINT *puiWidth, UINT *puiHeight) 85 { 86 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); 87 *puiWidth = This->data->width; 88 *puiHeight = This->data->height; 89 return S_OK; 90 } 91 92 static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface, 93 WICPixelFormatGUID *pPixelFormat) 94 { 95 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); 96 memcpy(pPixelFormat, This->data->format, sizeof(GUID)); 97 return S_OK; 98 } 99 100 static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface, 101 double *pDpiX, double *pDpiY) 102 { 103 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); 104 *pDpiX = This->data->xres; 105 *pDpiY = This->data->yres; 106 return S_OK; 107 } 108 109 static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface, 110 IWICPalette *pIPalette) 111 { 112 return E_NOTIMPL; 113 } 114 115 static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface, 116 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) 117 { 118 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); 119 UINT bytesperrow; 120 UINT srcstride; 121 UINT row_offset; 122 WICRect rc; 123 124 if (!prc) 125 { 126 rc.X = 0; 127 rc.Y = 0; 128 rc.Width = This->data->width; 129 rc.Height = This->data->height; 130 prc = &rc; 131 } 132 else 133 { 134 if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->data->width || prc->Y+prc->Height > This->data->height) 135 return E_INVALIDARG; 136 } 137 138 bytesperrow = ((This->data->bpp * prc->Width)+7)/8; 139 srcstride = ((This->data->bpp * This->data->width)+7)/8; 140 141 if (cbStride < bytesperrow) 142 return E_INVALIDARG; 143 144 if ((cbStride * prc->Height) > cbBufferSize) 145 return E_INVALIDARG; 146 147 row_offset = prc->X * This->data->bpp; 148 149 if (row_offset % 8 == 0) 150 { 151 UINT row; 152 const BYTE *src; 153 BYTE *dst; 154 155 src = This->data->bits + (row_offset / 8) + prc->Y * srcstride; 156 dst = pbBuffer; 157 for (row=0; row < prc->Height; row++) 158 { 159 memcpy(dst, src, bytesperrow); 160 src += srcstride; 161 dst += cbStride; 162 } 163 return S_OK; 164 } 165 else 166 { 167 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface); 168 return E_FAIL; 169 } 170 } 171 172 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl = { 173 BitmapTestSrc_QueryInterface, 174 BitmapTestSrc_AddRef, 175 BitmapTestSrc_Release, 176 BitmapTestSrc_GetSize, 177 BitmapTestSrc_GetPixelFormat, 178 BitmapTestSrc_GetResolution, 179 BitmapTestSrc_CopyPalette, 180 BitmapTestSrc_CopyPixels 181 }; 182 183 static void CreateTestBitmap(const bitmap_data *data, BitmapTestSrc **This) 184 { 185 *This = HeapAlloc(GetProcessHeap(), 0, sizeof(**This)); 186 187 if (*This) 188 { 189 (*This)->IWICBitmapSource_iface.lpVtbl = &BitmapTestSrc_Vtbl; 190 (*This)->ref = 1; 191 (*This)->data = data; 192 } 193 } 194 195 static void DeleteTestBitmap(BitmapTestSrc *This) 196 { 197 ok(This->IWICBitmapSource_iface.lpVtbl == &BitmapTestSrc_Vtbl, "test bitmap %p deleted with incorrect vtable\n", This); 198 ok(This->ref == 1, "test bitmap %p deleted with %i references instead of 1\n", This, This->ref); 199 HeapFree(GetProcessHeap(), 0, This); 200 } 201 202 static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, const BYTE *converted_bits) 203 { 204 BOOL equal; 205 206 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR)) 207 { 208 /* ignore the padding byte when comparing data */ 209 UINT i; 210 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits; 211 equal=TRUE; 212 for (i=0; i<(buffersize/4); i++) 213 if ((a[i]&0xffffff) != (b[i]&0xffffff)) 214 { 215 equal = FALSE; 216 break; 217 } 218 } 219 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppGrayFloat)) 220 { 221 UINT i; 222 const float *a=(const float*)expect->bits, *b=(const float*)converted_bits; 223 equal=TRUE; 224 for (i=0; i<(buffersize/4); i++) 225 if (!near_equal(a[i], b[i])) 226 { 227 equal = FALSE; 228 break; 229 } 230 } 231 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormatBlackWhite) || 232 IsEqualGUID(expect->format, &GUID_WICPixelFormat1bppIndexed)) 233 { 234 UINT i; 235 const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits; 236 equal=TRUE; 237 for (i=0; i<buffersize; i++) 238 if (a[i] != b[i] && b[i] != 0xff /* BMP encoder B&W */) 239 { 240 equal = FALSE; 241 break; 242 } 243 } 244 else 245 equal = (memcmp(expect->bits, converted_bits, buffersize) == 0); 246 247 if (!equal && expect->alt_data) 248 equal = compare_bits(expect->alt_data, buffersize, converted_bits); 249 250 return equal; 251 } 252 253 static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name) 254 { 255 BYTE *converted_bits; 256 UINT width, height; 257 double xres, yres; 258 WICRect prc; 259 UINT stride, buffersize; 260 GUID dst_pixelformat; 261 HRESULT hr; 262 263 hr = IWICBitmapSource_GetSize(source, &width, &height); 264 ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr); 265 ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name); 266 ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name); 267 268 hr = IWICBitmapSource_GetResolution(source, &xres, &yres); 269 ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr); 270 ok(fabs(xres - expect->xres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name); 271 ok(fabs(yres - expect->yres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name); 272 273 hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat); 274 ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr); 275 ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format %s (%s)\n", wine_dbgstr_guid(&dst_pixelformat), name); 276 277 prc.X = 0; 278 prc.Y = 0; 279 prc.Width = expect->width; 280 prc.Height = expect->height; 281 282 stride = (expect->bpp * expect->width + 7) / 8; 283 buffersize = stride * expect->height; 284 285 converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize); 286 hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits); 287 ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr); 288 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); 289 290 /* Test with NULL rectangle - should copy the whole bitmap */ 291 memset(converted_bits, 0xaa, buffersize); 292 hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits); 293 ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr); 294 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); 295 296 HeapFree(GetProcessHeap(), 0, converted_bits); 297 } 298 299 /* some encoders (like BMP) require data to be 4-bytes aligned */ 300 static const BYTE bits_1bpp[] = { 301 0x55,0x55,0x55,0x55, /*01010101*/ 302 0xaa,0xaa,0xaa,0xaa}; /*10101010*/ 303 static const struct bitmap_data testdata_BlackWhite = { 304 &GUID_WICPixelFormatBlackWhite, 1, bits_1bpp, 32, 2, 96.0, 96.0}; 305 static const struct bitmap_data testdata_1bppIndexed = { 306 &GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0}; 307 308 static const BYTE bits_8bpp[] = { 309 0,1,2,3, 310 4,5,6,7}; 311 static const struct bitmap_data testdata_8bppIndexed = { 312 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 4, 2, 96.0, 96.0}; 313 314 static const BYTE bits_24bppBGR[] = { 315 255,0,0, 0,255,0, 0,0,255, 0,0,0, 316 0,255,255, 255,0,255, 255,255,0, 255,255,255}; 317 static const struct bitmap_data testdata_24bppBGR = { 318 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 4, 2, 96.0, 96.0}; 319 320 static const BYTE bits_24bppRGB[] = { 321 0,0,255, 0,255,0, 255,0,0, 0,0,0, 322 255,255,0, 255,0,255, 0,255,255, 255,255,255}; 323 static const struct bitmap_data testdata_24bppRGB = { 324 &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 4, 2, 96.0, 96.0}; 325 326 static const BYTE bits_32bppBGR[] = { 327 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 328 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80}; 329 static const struct bitmap_data testdata_32bppBGR = { 330 &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 4, 2, 96.0, 96.0}; 331 332 static const BYTE bits_32bppBGRA[] = { 333 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 334 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255}; 335 static const struct bitmap_data testdata_32bppBGRA = { 336 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 4, 2, 96.0, 96.0}; 337 338 /* XP and 2003 use linear color conversion, later versions use sRGB gamma */ 339 static const float bits_32bppGrayFloat_xp[] = { 340 0.114000f,0.587000f,0.299000f,0.000000f, 341 0.886000f,0.413000f,0.701000f,1.000000f}; 342 static const struct bitmap_data testdata_32bppGrayFloat_xp = { 343 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat_xp, 4, 2, 96.0, 96.0}; 344 345 static const float bits_32bppGrayFloat[] = { 346 0.072200f,0.715200f,0.212600f,0.000000f, 347 0.927800f,0.284800f,0.787400f,1.000000f}; 348 static const struct bitmap_data testdata_32bppGrayFloat = { 349 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 4, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp}; 350 351 static const BYTE bits_8bppGray_xp[] = { 352 29,150,76,0, 353 226,105,179,255}; 354 static const struct bitmap_data testdata_8bppGray_xp = { 355 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray_xp, 4, 2, 96.0, 96.0}; 356 357 static const BYTE bits_8bppGray[] = { 358 76,220,127,0, 359 247,145,230,255}; 360 static const struct bitmap_data testdata_8bppGray = { 361 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray, 4, 2, 96.0, 96.0, &testdata_8bppGray_xp}; 362 363 static const BYTE bits_24bppBGR_gray[] = { 364 76,76,76, 220,220,220, 127,127,127, 0,0,0, 365 247,247,247, 145,145,145, 230,230,230, 255,255,255}; 366 static const struct bitmap_data testdata_24bppBGR_gray = { 367 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_gray, 4, 2, 96.0, 96.0}; 368 369 static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo) 370 { 371 BitmapTestSrc *src_obj; 372 IWICBitmapSource *dst_bitmap; 373 HRESULT hr; 374 375 CreateTestBitmap(src, &src_obj); 376 377 hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap); 378 todo_wine_if (todo) 379 ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr); 380 381 if (SUCCEEDED(hr)) 382 { 383 compare_bitmap_data(dst, dst_bitmap, name); 384 385 IWICBitmapSource_Release(dst_bitmap); 386 } 387 388 DeleteTestBitmap(src_obj); 389 } 390 391 static void test_invalid_conversion(void) 392 { 393 BitmapTestSrc *src_obj; 394 IWICBitmapSource *dst_bitmap; 395 HRESULT hr; 396 397 CreateTestBitmap(&testdata_32bppBGRA, &src_obj); 398 399 /* convert to a non-pixel-format GUID */ 400 hr = WICConvertBitmapSource(&GUID_VendorMicrosoft, &src_obj->IWICBitmapSource_iface, &dst_bitmap); 401 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "WICConvertBitmapSource returned %x\n", hr); 402 403 DeleteTestBitmap(src_obj); 404 } 405 406 static void test_default_converter(void) 407 { 408 BitmapTestSrc *src_obj; 409 IWICFormatConverter *converter; 410 BOOL can_convert = TRUE; 411 HRESULT hr; 412 413 CreateTestBitmap(&testdata_32bppBGRA, &src_obj); 414 415 hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER, 416 &IID_IWICFormatConverter, (void**)&converter); 417 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); 418 if (SUCCEEDED(hr)) 419 { 420 hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA, 421 &GUID_WICPixelFormat32bppBGR, &can_convert); 422 ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr); 423 ok(can_convert, "expected TRUE, got %i\n", can_convert); 424 425 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, 426 &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.0, 427 WICBitmapPaletteTypeCustom); 428 ok(SUCCEEDED(hr), "Initialize returned %x\n", hr); 429 430 if (SUCCEEDED(hr)) 431 compare_bitmap_data(&testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter"); 432 433 IWICFormatConverter_Release(converter); 434 } 435 436 DeleteTestBitmap(src_obj); 437 } 438 439 typedef struct property_opt_test_data 440 { 441 LPCOLESTR name; 442 VARTYPE var_type; 443 VARTYPE initial_var_type; 444 int i_init_val; 445 float f_init_val; 446 BOOL skippable; 447 } property_opt_test_data; 448 449 static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0}; 450 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0}; 451 static const WCHAR wszInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0}; 452 static const WCHAR wszFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0}; 453 static const WCHAR wszImageQuality[] = {'I','m','a','g','e','Q','u','a','l','i','t','y',0}; 454 static const WCHAR wszBitmapTransform[] = {'B','i','t','m','a','p','T','r','a','n','s','f','o','r','m',0}; 455 static const WCHAR wszLuminance[] = {'L','u','m','i','n','a','n','c','e',0}; 456 static const WCHAR wszChrominance[] = {'C','h','r','o','m','i','n','a','n','c','e',0}; 457 static const WCHAR wszJpegYCrCbSubsampling[] = {'J','p','e','g','Y','C','r','C','b','S','u','b','s','a','m','p','l','i','n','g',0}; 458 static const WCHAR wszSuppressApp0[] = {'S','u','p','p','r','e','s','s','A','p','p','0',0}; 459 460 static const struct property_opt_test_data testdata_tiff_props[] = { 461 { wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare }, 462 { wszCompressionQuality, VT_R4, VT_EMPTY }, 463 { NULL } 464 }; 465 466 static const struct property_opt_test_data testdata_png_props[] = { 467 { wszInterlaceOption, VT_BOOL, VT_BOOL, 0 }, 468 { wszFilterOption, VT_UI1, VT_UI1, WICPngFilterUnspecified, 0.0f, TRUE /* not supported on XP/2k3 */}, 469 { NULL } 470 }; 471 472 static const struct property_opt_test_data testdata_jpeg_props[] = { 473 { wszImageQuality, VT_R4, VT_EMPTY }, 474 { wszBitmapTransform, VT_UI1, VT_UI1, WICBitmapTransformRotate0 }, 475 { wszLuminance, VT_I4|VT_ARRAY, VT_EMPTY }, 476 { wszChrominance, VT_I4|VT_ARRAY, VT_EMPTY }, 477 { wszJpegYCrCbSubsampling, VT_UI1, VT_UI1, WICJpegYCrCbSubsamplingDefault, 0.0f, TRUE }, /* not supported on XP/2k3 */ 478 { wszSuppressApp0, VT_BOOL, VT_BOOL, FALSE }, 479 { NULL } 480 }; 481 482 static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt) 483 { 484 int i; 485 for (i=0; i < all_prop_cnt; i++) 486 { 487 if (lstrcmpW(name, all_props[i].pstrName) == 0) 488 return i; 489 } 490 return -1; 491 } 492 493 static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt) 494 { 495 HRESULT hr; 496 int i = 0; 497 VARIANT pvarValue; 498 HRESULT phrError = S_OK; 499 500 while (data[i].name) 501 { 502 int idx = find_property_index(data[i].name, all_props, all_prop_cnt); 503 PROPBAG2 pb = {0}; 504 pb.pstrName = (LPOLESTR)data[i].name; 505 506 hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError); 507 508 if (data[i].skippable && idx == -1) 509 { 510 win_skip("Property %s is not supported on this machine.\n", wine_dbgstr_w(data[i].name)); 511 i++; 512 continue; 513 } 514 515 ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n", 516 wine_dbgstr_w(data[i].name)); 517 if (idx >= 0) 518 { 519 ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n", 520 wine_dbgstr_w(data[i].name), all_props[idx].vt); 521 ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n", 522 wine_dbgstr_w(data[i].name), all_props[idx].dwType); 523 ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n", 524 wine_dbgstr_w(data[i].name), all_props[idx].cfType); 525 } 526 527 ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n", 528 wine_dbgstr_w(data[i].name), hr); 529 530 if (SUCCEEDED(hr)) 531 { 532 /* On XP the initial type is always VT_EMPTY */ 533 ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY, 534 "Property %s has unexpected initial type, V_VT=%i\n", 535 wine_dbgstr_w(data[i].name), V_VT(&pvarValue)); 536 537 if(V_VT(&pvarValue) == data[i].initial_var_type) 538 { 539 switch (data[i].initial_var_type) 540 { 541 case VT_BOOL: 542 case VT_UI1: 543 ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n", 544 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal)); 545 break; 546 case VT_R4: 547 ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n", 548 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal)); 549 break; 550 default: 551 break; 552 } 553 } 554 555 VariantClear(&pvarValue); 556 } 557 558 i++; 559 } 560 } 561 562 static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *options) 563 { 564 HRESULT hr; 565 ULONG cProperties = 0; 566 ULONG cProperties2 = 0; 567 PROPBAG2 all_props[64] = {{0}}; /* Should be enough for every encoder out there */ 568 int i; 569 570 /* CountProperties */ 571 { 572 hr = IPropertyBag2_CountProperties(options, &cProperties); 573 ok(SUCCEEDED(hr), "Reading property count, hr=%x\n", hr); 574 } 575 576 /* GetPropertyInfo */ 577 { 578 hr = IPropertyBag2_GetPropertyInfo(options, cProperties, 1, all_props, &cProperties2); 579 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - iProperty out of bounce handled wrong, hr=%x\n", hr); 580 581 hr = IPropertyBag2_GetPropertyInfo(options, 0, cProperties+1, all_props, &cProperties2); 582 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - cProperty out of bounce handled wrong, hr=%x\n", hr); 583 584 if (cProperties == 0) /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */ 585 { 586 cProperties2 = cProperties; 587 hr = S_OK; 588 } 589 else 590 { 591 hr = IPropertyBag2_GetPropertyInfo(options, 0, min(64, cProperties), all_props, &cProperties2); 592 ok(SUCCEEDED(hr), "Reading infos from property bag failed, hr=%x\n", hr); 593 } 594 595 if (FAILED(hr)) 596 return; 597 598 ok(cProperties == cProperties2, "Mismatch of property count (IPropertyBag2::CountProperties=%i, IPropertyBag2::GetPropertyInfo=%i)\n", 599 (int)cProperties, (int)cProperties2); 600 } 601 602 if (IsEqualCLSID(clsid_encoder, &CLSID_WICTiffEncoder)) 603 test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2); 604 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICPngEncoder)) 605 test_specific_encoder_properties(options, testdata_png_props, all_props, cProperties2); 606 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICJpegEncoder)) 607 test_specific_encoder_properties(options, testdata_jpeg_props, all_props, cProperties2); 608 609 for (i=0; i < cProperties2; i++) 610 { 611 ok(all_props[i].pstrName != NULL, "Unset property name in output of IPropertyBag2::GetPropertyInfo\n"); 612 CoTaskMemFree(all_props[i].pstrName); 613 } 614 } 615 616 static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format) 617 { 618 /* FIXME */ 619 } 620 621 static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format) 622 { 623 /* FIXME */ 624 } 625 626 static unsigned be_uint(unsigned val) 627 { 628 union 629 { 630 unsigned val; 631 char c[4]; 632 } u; 633 634 u.val = val; 635 return (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3]; 636 } 637 638 static void check_png_format(IStream *stream, const WICPixelFormatGUID *format) 639 { 640 static const char png_sig[8] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a}; 641 static const char png_IHDR[8] = {0,0,0,0x0d,'I','H','D','R'}; 642 HRESULT hr; 643 struct 644 { 645 char png_sig[8]; 646 char ihdr_sig[8]; 647 unsigned width, height; 648 char bit_depth, color_type, compression, filter, interlace; 649 } png; 650 651 memset(&png, 0, sizeof(png)); 652 hr = IStream_Read(stream, &png, sizeof(png), NULL); 653 ok(hr == S_OK, "IStream_Read error %#x\n", hr); 654 655 ok(!memcmp(png.png_sig, png_sig, sizeof(png_sig)), "expected PNG signature\n"); 656 ok(!memcmp(png.ihdr_sig, png_IHDR, sizeof(png_IHDR)), "expected PNG IHDR\n"); 657 658 if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite)) 659 { 660 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width)); 661 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); 662 663 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth); 664 ok(png.color_type == 0, "wrong color_type %d\n", png.color_type); 665 ok(png.compression == 0, "wrong compression %d\n", png.compression); 666 ok(png.filter == 0, "wrong filter %d\n", png.filter); 667 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace); 668 } 669 else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed)) 670 { 671 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width)); 672 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); 673 674 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth); 675 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type); 676 ok(png.compression == 0, "wrong compression %d\n", png.compression); 677 ok(png.filter == 0, "wrong filter %d\n", png.filter); 678 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace); 679 } 680 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed)) 681 { 682 ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width)); 683 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); 684 685 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth); 686 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type); 687 ok(png.compression == 0, "wrong compression %d\n", png.compression); 688 ok(png.filter == 0, "wrong filter %d\n", png.filter); 689 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace); 690 } 691 else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR)) 692 { 693 ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width)); 694 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); 695 696 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth); 697 ok(png.color_type == 2, "wrong color_type %d\n", png.color_type); 698 ok(png.compression == 0, "wrong compression %d\n", png.compression); 699 ok(png.filter == 0, "wrong filter %d\n", png.filter); 700 ok(png.interlace == 0 || png.interlace == 1, "wrong interlace %d\n", png.interlace); 701 } 702 else 703 ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format)); 704 } 705 706 static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format) 707 { 708 HRESULT hr; 709 LARGE_INTEGER pos; 710 711 pos.QuadPart = 0; 712 hr = IStream_Seek(stream, pos, SEEK_SET, (ULARGE_INTEGER *)&pos); 713 ok(hr == S_OK, "IStream_Seek error %#x\n", hr); 714 715 if (IsEqualGUID(encoder, &CLSID_WICPngEncoder)) 716 check_png_format(stream, format); 717 else if (IsEqualGUID(encoder, &CLSID_WICBmpEncoder)) 718 check_bmp_format(stream, format); 719 else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder)) 720 check_tiff_format(stream, format); 721 else 722 ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder)); 723 724 hr = IStream_Seek(stream, pos, SEEK_SET, NULL); 725 ok(hr == S_OK, "IStream_Seek error %#x\n", hr); 726 } 727 728 struct setting { 729 const WCHAR *name; 730 PROPBAG2_TYPE type; 731 VARTYPE vt; 732 void *value; 733 }; 734 735 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__) 736 static void _expect_ref(IUnknown* obj, ULONG ref, int line) 737 { 738 ULONG rc; 739 IUnknown_AddRef(obj); 740 rc = IUnknown_Release(obj); 741 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc); 742 } 743 744 static void test_set_frame_palette(IWICBitmapFrameEncode *frameencode) 745 { 746 IWICComponentFactory *factory; 747 IWICPalette *palette; 748 HRESULT hr; 749 750 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 751 &IID_IWICComponentFactory, (void **)&factory); 752 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); 753 754 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL); 755 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr); 756 757 hr = IWICComponentFactory_CreatePalette(factory, &palette); 758 ok(hr == S_OK, "CreatePalette failed, hr=%x\n", hr); 759 760 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette); 761 todo_wine 762 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr=%x\n", hr); 763 764 hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedHalftone256, FALSE); 765 ok(hr == S_OK, "InitializePredefined failed, hr=%x\n", hr); 766 767 EXPECT_REF(palette, 1); 768 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette); 769 ok(hr == S_OK, "SetPalette failed, hr=%x\n", hr); 770 EXPECT_REF(palette, 1); 771 772 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL); 773 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr); 774 775 IWICPalette_Release(palette); 776 IWICComponentFactory_Release(factory); 777 } 778 779 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder, 780 const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc, 781 const struct setting *settings, const char *name, IWICPalette *palette) 782 { 783 HRESULT hr; 784 IWICBitmapEncoder *encoder; 785 BitmapTestSrc *src_obj; 786 HGLOBAL hglobal; 787 IStream *stream; 788 IWICBitmapFrameEncode *frameencode; 789 IPropertyBag2 *options=NULL; 790 IWICBitmapDecoder *decoder; 791 IWICBitmapFrameDecode *framedecode; 792 WICPixelFormatGUID pixelformat; 793 int i; 794 795 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER, 796 &IID_IWICBitmapEncoder, (void**)&encoder); 797 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); 798 if (SUCCEEDED(hr)) 799 { 800 hglobal = GlobalAlloc(GMEM_MOVEABLE, 0); 801 ok(hglobal != NULL, "GlobalAlloc failed\n"); 802 if (hglobal) 803 { 804 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream); 805 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr); 806 } 807 808 if (hglobal && SUCCEEDED(hr)) 809 { 810 if (palette) 811 { 812 hr = IWICBitmapEncoder_SetPalette(encoder, palette); 813 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x (%s)\n", hr, name); 814 } 815 816 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache); 817 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr); 818 819 if (palette) 820 { 821 hr = IWICBitmapEncoder_SetPalette(encoder, palette); 822 ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr); 823 hr = S_OK; 824 } 825 826 i=0; 827 while (SUCCEEDED(hr) && srcs[i]) 828 { 829 CreateTestBitmap(srcs[i], &src_obj); 830 831 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options); 832 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr); 833 if (SUCCEEDED(hr)) 834 { 835 ok(options != NULL, "Encoder initialization has not created an property bag\n"); 836 if(options) 837 test_encoder_properties(clsid_encoder, options); 838 839 if (settings) 840 { 841 int j; 842 for (j=0; settings[j].name; j++) 843 { 844 PROPBAG2 propbag; 845 VARIANT var; 846 847 memset(&propbag, 0, sizeof(propbag)); 848 memset(&var, 0, sizeof(var)); 849 propbag.pstrName = (LPOLESTR)settings[j].name; 850 propbag.dwType = settings[j].type; 851 V_VT(&var) = settings[j].vt; 852 V_UNKNOWN(&var) = settings[j].value; 853 854 hr = IPropertyBag2_Write(options, 1, &propbag, &var); 855 ok(SUCCEEDED(hr), "Writing property %s failed, hr=%x\n", wine_dbgstr_w(settings[j].name), hr); 856 } 857 } 858 859 if (palette) 860 { 861 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette); 862 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x\n", hr); 863 } 864 865 hr = IWICBitmapFrameEncode_Initialize(frameencode, options); 866 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr); 867 868 memcpy(&pixelformat, srcs[i]->format, sizeof(GUID)); 869 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat); 870 ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr); 871 ok(IsEqualGUID(&pixelformat, dsts[i]->format), "SetPixelFormat changed the format to %s (%s)\n", 872 wine_dbgstr_guid(&pixelformat), name); 873 874 hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height); 875 ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr); 876 877 if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder)) 878 test_set_frame_palette(frameencode); 879 880 if (palette) 881 { 882 WICColor colors[256]; 883 884 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette); 885 ok(SUCCEEDED(hr), "SetPalette failed, hr=%x (%s)\n", hr, name); 886 887 /* trash the assigned palette */ 888 memset(colors, 0, sizeof(colors)); 889 hr = IWICPalette_InitializeCustom(palette, colors, 256); 890 ok(hr == S_OK, "InitializeCustom error %#x\n", hr); 891 } 892 893 hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, rc); 894 if (rc && (rc->Width <= 0 || rc->Height <= 0)) 895 { 896 /* WriteSource fails but WriteSource_Proxy succeeds. */ 897 ok(hr == E_INVALIDARG, "WriteSource should fail, hr=%x (%s)\n", hr, name); 898 hr = IWICBitmapFrameEncode_WriteSource_Proxy(frameencode, &src_obj->IWICBitmapSource_iface, rc); 899 ok(SUCCEEDED(hr), "WriteSource_Proxy failed, %dx%d, hr=%x (%s)\n", rc->Width, rc->Height, hr, name); 900 } 901 else 902 { 903 if (rc) 904 ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name); 905 else 906 ok(hr == S_OK || 907 broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */, 908 "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name); 909 } 910 911 if (SUCCEEDED(hr)) 912 { 913 hr = IWICBitmapFrameEncode_Commit(frameencode); 914 ok(SUCCEEDED(hr), "Commit failed, hr=%x (%s)\n", hr, name); 915 } 916 917 IWICBitmapFrameEncode_Release(frameencode); 918 IPropertyBag2_Release(options); 919 } 920 921 DeleteTestBitmap(src_obj); 922 923 i++; 924 } 925 926 if (clsid_decoder == NULL) 927 { 928 IStream_Release(stream); 929 IWICBitmapEncoder_Release(encoder); 930 return; 931 } 932 933 if (SUCCEEDED(hr)) 934 { 935 hr = IWICBitmapEncoder_Commit(encoder); 936 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr); 937 938 check_bitmap_format(stream, clsid_encoder, dsts[0]->format); 939 } 940 941 if (SUCCEEDED(hr)) 942 { 943 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER, 944 &IID_IWICBitmapDecoder, (void**)&decoder); 945 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); 946 } 947 948 if (SUCCEEDED(hr)) 949 { 950 IWICPalette *frame_palette; 951 952 hr = IWICImagingFactory_CreatePalette(factory, &frame_palette); 953 ok(hr == S_OK, "CreatePalette error %#x\n", hr); 954 955 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette); 956 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); 957 958 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand); 959 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr); 960 961 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette); 962 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); 963 964 hr = S_OK; 965 i=0; 966 while (SUCCEEDED(hr) && dsts[i]) 967 { 968 hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode); 969 ok(SUCCEEDED(hr), "GetFrame failed, hr=%x (%s)\n", hr, name); 970 971 if (SUCCEEDED(hr)) 972 { 973 compare_bitmap_data(dsts[i], (IWICBitmapSource*)framedecode, name); 974 975 hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette); 976 if (winetest_debug > 1) 977 trace("%s, bpp %d, %s, hr %#x\n", name, dsts[i]->bpp, wine_dbgstr_guid(dsts[i]->format), hr); 978 if (dsts[i]->bpp > 8 || IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite)) 979 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); 980 else 981 { 982 UINT count, ret; 983 WICColor colors[256]; 984 985 ok(hr == S_OK, "CopyPalette error %#x (%s)\n", hr, name); 986 987 count = 0; 988 hr = IWICPalette_GetColorCount(frame_palette, &count); 989 ok(hr == S_OK, "GetColorCount error %#x\n", hr); 990 991 memset(colors, 0, sizeof(colors)); 992 ret = 0; 993 hr = IWICPalette_GetColors(frame_palette, count, colors, &ret); 994 ok(hr == S_OK, "GetColors error %#x\n", hr); 995 ok(ret == count, "expected %u, got %u\n", count, ret); 996 if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder)) 997 { 998 ok(count == 256 || count == 2 /* newer libpng versions */, "expected 256, got %u (%s)\n", count, name); 999 1000 ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name); 1001 ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name); 1002 if (count > 2) 1003 { 1004 ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name); 1005 ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name); 1006 ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name); 1007 ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name); 1008 } 1009 } 1010 else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) || 1011 IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder)) 1012 { 1013 if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite) || 1014 IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat8bppIndexed)) 1015 { 1016 ok(count == 256, "expected 256, got %u (%s)\n", count, name); 1017 1018 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name); 1019 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name); 1020 ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name); 1021 ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name); 1022 ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name); 1023 ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name); 1024 } 1025 else 1026 { 1027 ok(count == 2, "expected 2, got %u (%s)\n", count, name); 1028 1029 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name); 1030 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name); 1031 } 1032 } 1033 else 1034 { 1035 ok(count == 2, "expected 2, got %u (%s)\n", count, name); 1036 1037 ok(colors[0] == 0xff111111, "got %08x\n", colors[0]); 1038 ok(colors[1] == 0xff222222, "got %08x\n", colors[1]); 1039 } 1040 } 1041 1042 IWICBitmapFrameDecode_Release(framedecode); 1043 } 1044 1045 i++; 1046 } 1047 1048 IWICPalette_Release(frame_palette); 1049 IWICBitmapDecoder_Release(decoder); 1050 } 1051 1052 IStream_Release(stream); 1053 } 1054 1055 IWICBitmapEncoder_Release(encoder); 1056 } 1057 } 1058 1059 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder, 1060 const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name) 1061 { 1062 const struct bitmap_data *srcs[2]; 1063 const struct bitmap_data *dsts[2]; 1064 WICColor colors[256]; 1065 IWICPalette *palette; 1066 HRESULT hr; 1067 1068 hr = IWICImagingFactory_CreatePalette(factory, &palette); 1069 ok(hr == S_OK, "CreatePalette error %#x\n", hr); 1070 1071 memset(colors, 0, sizeof(colors)); 1072 colors[0] = 0x11111111; 1073 colors[1] = 0x22222222; 1074 colors[2] = 0x33333333; 1075 colors[3] = 0x44444444; 1076 colors[4] = 0x55555555; 1077 /* TIFF decoder fails to decode a 8bpp frame if palette has less than 256 colors */ 1078 hr = IWICPalette_InitializeCustom(palette, colors, 256); 1079 ok(hr == S_OK, "InitializeCustom error %#x\n", hr); 1080 1081 srcs[0] = src; 1082 srcs[1] = NULL; 1083 dsts[0] = dst; 1084 dsts[1] = NULL; 1085 1086 test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name, palette); 1087 1088 IWICPalette_Release(palette); 1089 } 1090 1091 static void test_encoder_rects(void) 1092 { 1093 const struct bitmap_data *srcs[2]; 1094 const struct bitmap_data *dsts[2]; 1095 WICRect rc; 1096 1097 srcs[0] = &testdata_24bppBGR; 1098 srcs[1] = NULL; 1099 dsts[0] = &testdata_24bppBGR; 1100 dsts[1] = NULL; 1101 1102 rc.X = 0; 1103 rc.Y = 0; 1104 rc.Width = 4; 1105 rc.Height = 2; 1106 1107 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL); 1108 1109 rc.Width = 0; 1110 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0", NULL); 1111 1112 rc.Width = -1; 1113 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL); 1114 1115 rc.Width = 4; 1116 rc.Height = 0; 1117 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL); 1118 1119 rc.Height = -1; 1120 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1", NULL); 1121 } 1122 1123 static const struct bitmap_data *multiple_frames[3] = { 1124 &testdata_24bppBGR, 1125 &testdata_24bppBGR, 1126 NULL}; 1127 1128 static const struct bitmap_data *single_frame[2] = { 1129 &testdata_24bppBGR, 1130 NULL}; 1131 1132 static const struct setting png_interlace_settings[] = { 1133 {wszInterlaceOption, PROPBAG2_TYPE_DATA, VT_BOOL, (void*)VARIANT_TRUE}, 1134 {NULL} 1135 }; 1136 1137 START_TEST(converter) 1138 { 1139 HRESULT hr; 1140 1141 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1142 1143 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 1144 &IID_IWICImagingFactory, (void **)&factory); 1145 ok(hr == S_OK, "failed to create factory: %#x\n", hr); 1146 1147 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE); 1148 test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE); 1149 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE); 1150 1151 test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE); 1152 test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE); 1153 1154 test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", FALSE); 1155 test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", FALSE); 1156 1157 test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", FALSE); 1158 test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", FALSE); 1159 test_conversion(&testdata_32bppBGRA, &testdata_24bppRGB, "32bppBGRA -> 24bppRGB", FALSE); 1160 1161 test_conversion(&testdata_24bppRGB, &testdata_32bppGrayFloat, "24bppRGB -> 32bppGrayFloat", FALSE); 1162 test_conversion(&testdata_32bppBGR, &testdata_32bppGrayFloat, "32bppBGR -> 32bppGrayFloat", FALSE); 1163 1164 test_conversion(&testdata_24bppBGR, &testdata_8bppGray, "24bppBGR -> 8bppGray", FALSE); 1165 test_conversion(&testdata_32bppBGR, &testdata_8bppGray, "32bppBGR -> 8bppGray", FALSE); 1166 test_conversion(&testdata_32bppGrayFloat, &testdata_24bppBGR_gray, "32bppGrayFloat -> 24bppBGR gray", FALSE); 1167 test_conversion(&testdata_32bppGrayFloat, &testdata_8bppGray, "32bppGrayFloat -> 8bppGray", FALSE); 1168 1169 test_invalid_conversion(); 1170 test_default_converter(); 1171 1172 test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder, 1173 &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite"); 1174 test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder, 1175 &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed"); 1176 test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder, 1177 &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed"); 1178 test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder, 1179 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR"); 1180 1181 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */ 1182 { 1183 test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder, 1184 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite"); 1185 test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder, 1186 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed"); 1187 test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder, 1188 &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed"); 1189 } 1190 test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder, 1191 &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR"); 1192 1193 test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder, 1194 &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite"); 1195 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */ 1196 { 1197 test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder, 1198 &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed"); 1199 test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder, 1200 &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed"); 1201 } 1202 test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder, 1203 &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR"); 1204 1205 test_encoder(&testdata_24bppBGR, &CLSID_WICJpegEncoder, 1206 &testdata_24bppBGR, NULL, "JPEG encoder 24bppBGR"); 1207 1208 test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder, 1209 multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame", NULL); 1210 1211 test_encoder_rects(); 1212 1213 test_multi_encoder(single_frame, &CLSID_WICPngEncoder, 1214 single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced", NULL); 1215 1216 IWICImagingFactory_Release(factory); 1217 1218 CoUninitialize(); 1219 } 1220