1 /* 2 * Copyright 2009 Vincent Povirk for CodeWeavers 3 * Copyright 2012 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 "config.h" 21 22 #include <stdarg.h> 23 24 #define COBJMACROS 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winreg.h" 29 #include "objbase.h" 30 #include "shellapi.h" 31 32 #include "wincodecs_private.h" 33 34 #include "wine/debug.h" 35 36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 37 38 typedef struct { 39 IWICComponentFactory IWICComponentFactory_iface; 40 LONG ref; 41 } ComponentFactory; 42 43 static inline ComponentFactory *impl_from_IWICComponentFactory(IWICComponentFactory *iface) 44 { 45 return CONTAINING_RECORD(iface, ComponentFactory, IWICComponentFactory_iface); 46 } 47 48 static HRESULT WINAPI ComponentFactory_QueryInterface(IWICComponentFactory *iface, REFIID iid, 49 void **ppv) 50 { 51 ComponentFactory *This = impl_from_IWICComponentFactory(iface); 52 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 53 54 if (!ppv) return E_INVALIDARG; 55 56 if (IsEqualIID(&IID_IUnknown, iid) || 57 IsEqualIID(&IID_IWICImagingFactory, iid) || 58 IsEqualIID(&IID_IWICComponentFactory, iid)) 59 { 60 *ppv = &This->IWICComponentFactory_iface; 61 } 62 else 63 { 64 *ppv = NULL; 65 return E_NOINTERFACE; 66 } 67 68 IUnknown_AddRef((IUnknown*)*ppv); 69 return S_OK; 70 } 71 72 static ULONG WINAPI ComponentFactory_AddRef(IWICComponentFactory *iface) 73 { 74 ComponentFactory *This = impl_from_IWICComponentFactory(iface); 75 ULONG ref = InterlockedIncrement(&This->ref); 76 77 TRACE("(%p) refcount=%u\n", iface, ref); 78 79 return ref; 80 } 81 82 static ULONG WINAPI ComponentFactory_Release(IWICComponentFactory *iface) 83 { 84 ComponentFactory *This = impl_from_IWICComponentFactory(iface); 85 ULONG ref = InterlockedDecrement(&This->ref); 86 87 TRACE("(%p) refcount=%u\n", iface, ref); 88 89 if (ref == 0) 90 HeapFree(GetProcessHeap(), 0, This); 91 92 return ref; 93 } 94 95 static HRESULT WINAPI ComponentFactory_CreateDecoderFromFilename( 96 IWICComponentFactory *iface, LPCWSTR wzFilename, const GUID *pguidVendor, 97 DWORD dwDesiredAccess, WICDecodeOptions metadataOptions, 98 IWICBitmapDecoder **ppIDecoder) 99 { 100 IWICStream *stream; 101 HRESULT hr; 102 103 TRACE("(%p,%s,%s,%u,%u,%p)\n", iface, debugstr_w(wzFilename), 104 debugstr_guid(pguidVendor), dwDesiredAccess, metadataOptions, ppIDecoder); 105 106 hr = StreamImpl_Create(&stream); 107 if (SUCCEEDED(hr)) 108 { 109 hr = IWICStream_InitializeFromFilename(stream, wzFilename, dwDesiredAccess); 110 111 if (SUCCEEDED(hr)) 112 { 113 hr = IWICComponentFactory_CreateDecoderFromStream(iface, (IStream*)stream, 114 pguidVendor, metadataOptions, ppIDecoder); 115 } 116 117 IWICStream_Release(stream); 118 } 119 120 return hr; 121 } 122 123 static HRESULT find_decoder(IStream *pIStream, const GUID *pguidVendor, 124 WICDecodeOptions metadataOptions, IWICBitmapDecoder **decoder) 125 { 126 IEnumUnknown *enumdecoders; 127 IUnknown *unkdecoderinfo; 128 IWICBitmapDecoderInfo *decoderinfo; 129 GUID vendor; 130 HRESULT res; 131 ULONG num_fetched; 132 BOOL matches; 133 134 *decoder = NULL; 135 136 res = CreateComponentEnumerator(WICDecoder, WICComponentEnumerateDefault, &enumdecoders); 137 if (FAILED(res)) return res; 138 139 while (!*decoder) 140 { 141 res = IEnumUnknown_Next(enumdecoders, 1, &unkdecoderinfo, &num_fetched); 142 143 if (res == S_OK) 144 { 145 res = IUnknown_QueryInterface(unkdecoderinfo, &IID_IWICBitmapDecoderInfo, (void**)&decoderinfo); 146 147 if (SUCCEEDED(res)) 148 { 149 if (pguidVendor) 150 { 151 res = IWICBitmapDecoderInfo_GetVendorGUID(decoderinfo, &vendor); 152 if (FAILED(res) || !IsEqualIID(&vendor, pguidVendor)) 153 { 154 IWICBitmapDecoderInfo_Release(decoderinfo); 155 IUnknown_Release(unkdecoderinfo); 156 continue; 157 } 158 } 159 160 res = IWICBitmapDecoderInfo_MatchesPattern(decoderinfo, pIStream, &matches); 161 162 if (SUCCEEDED(res) && matches) 163 { 164 res = IWICBitmapDecoderInfo_CreateInstance(decoderinfo, decoder); 165 166 /* FIXME: should use QueryCapability to choose a decoder */ 167 168 if (SUCCEEDED(res)) 169 { 170 res = IWICBitmapDecoder_Initialize(*decoder, pIStream, metadataOptions); 171 172 if (FAILED(res)) 173 { 174 IWICBitmapDecoder_Release(*decoder); 175 IWICBitmapDecoderInfo_Release(decoderinfo); 176 IUnknown_Release(unkdecoderinfo); 177 *decoder = NULL; 178 return res; 179 } 180 } 181 } 182 183 IWICBitmapDecoderInfo_Release(decoderinfo); 184 } 185 186 IUnknown_Release(unkdecoderinfo); 187 } 188 else 189 break; 190 } 191 192 IEnumUnknown_Release(enumdecoders); 193 194 return WINCODEC_ERR_COMPONENTNOTFOUND; 195 } 196 197 static HRESULT WINAPI ComponentFactory_CreateDecoderFromStream( 198 IWICComponentFactory *iface, IStream *pIStream, const GUID *pguidVendor, 199 WICDecodeOptions metadataOptions, IWICBitmapDecoder **ppIDecoder) 200 { 201 HRESULT res; 202 IWICBitmapDecoder *decoder = NULL; 203 204 TRACE("(%p,%p,%s,%u,%p)\n", iface, pIStream, debugstr_guid(pguidVendor), 205 metadataOptions, ppIDecoder); 206 207 if (pguidVendor) 208 res = find_decoder(pIStream, pguidVendor, metadataOptions, &decoder); 209 if (!decoder) 210 res = find_decoder(pIStream, NULL, metadataOptions, &decoder); 211 212 if (decoder) 213 { 214 *ppIDecoder = decoder; 215 return S_OK; 216 } 217 else 218 { 219 if (WARN_ON(wincodecs)) 220 { 221 LARGE_INTEGER seek; 222 BYTE data[4]; 223 ULONG bytesread; 224 225 WARN("failed to load from a stream %#x\n", res); 226 227 seek.QuadPart = 0; 228 if (IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL) == S_OK) 229 { 230 if (IStream_Read(pIStream, data, 4, &bytesread) == S_OK) 231 WARN("first %i bytes of stream=%x %x %x %x\n", bytesread, data[0], data[1], data[2], data[3]); 232 } 233 } 234 *ppIDecoder = NULL; 235 return res; 236 } 237 } 238 239 static HRESULT WINAPI ComponentFactory_CreateDecoderFromFileHandle( 240 IWICComponentFactory *iface, ULONG_PTR hFile, const GUID *pguidVendor, 241 WICDecodeOptions metadataOptions, IWICBitmapDecoder **ppIDecoder) 242 { 243 IWICStream *stream; 244 HRESULT hr; 245 246 TRACE("(%p,%lx,%s,%u,%p)\n", iface, hFile, debugstr_guid(pguidVendor), 247 metadataOptions, ppIDecoder); 248 249 hr = StreamImpl_Create(&stream); 250 if (SUCCEEDED(hr)) 251 { 252 hr = stream_initialize_from_filehandle(stream, (HANDLE)hFile); 253 if (SUCCEEDED(hr)) 254 { 255 hr = IWICComponentFactory_CreateDecoderFromStream(iface, (IStream*)stream, 256 pguidVendor, metadataOptions, ppIDecoder); 257 } 258 IWICStream_Release(stream); 259 } 260 return hr; 261 } 262 263 static HRESULT WINAPI ComponentFactory_CreateComponentInfo(IWICComponentFactory *iface, 264 REFCLSID clsidComponent, IWICComponentInfo **ppIInfo) 265 { 266 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(clsidComponent), ppIInfo); 267 return CreateComponentInfo(clsidComponent, ppIInfo); 268 } 269 270 static HRESULT WINAPI ComponentFactory_CreateDecoder(IWICComponentFactory *iface, 271 REFGUID guidContainerFormat, const GUID *pguidVendor, 272 IWICBitmapDecoder **ppIDecoder) 273 { 274 IEnumUnknown *enumdecoders; 275 IUnknown *unkdecoderinfo; 276 IWICBitmapDecoderInfo *decoderinfo; 277 IWICBitmapDecoder *decoder = NULL, *preferred_decoder = NULL; 278 GUID vendor; 279 HRESULT res; 280 ULONG num_fetched; 281 282 TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(guidContainerFormat), 283 debugstr_guid(pguidVendor), ppIDecoder); 284 285 if (!guidContainerFormat || !ppIDecoder) return E_INVALIDARG; 286 287 res = CreateComponentEnumerator(WICDecoder, WICComponentEnumerateDefault, &enumdecoders); 288 if (FAILED(res)) return res; 289 290 while (!preferred_decoder) 291 { 292 res = IEnumUnknown_Next(enumdecoders, 1, &unkdecoderinfo, &num_fetched); 293 if (res != S_OK) break; 294 295 res = IUnknown_QueryInterface(unkdecoderinfo, &IID_IWICBitmapDecoderInfo, (void **)&decoderinfo); 296 if (SUCCEEDED(res)) 297 { 298 GUID container_guid; 299 300 res = IWICBitmapDecoderInfo_GetContainerFormat(decoderinfo, &container_guid); 301 if (SUCCEEDED(res) && IsEqualIID(&container_guid, guidContainerFormat)) 302 { 303 IWICBitmapDecoder *new_decoder; 304 305 res = IWICBitmapDecoderInfo_CreateInstance(decoderinfo, &new_decoder); 306 if (SUCCEEDED(res)) 307 { 308 if (pguidVendor) 309 { 310 res = IWICBitmapDecoderInfo_GetVendorGUID(decoderinfo, &vendor); 311 if (SUCCEEDED(res) && IsEqualIID(&vendor, pguidVendor)) 312 { 313 preferred_decoder = new_decoder; 314 new_decoder = NULL; 315 } 316 } 317 318 if (new_decoder && !decoder) 319 { 320 decoder = new_decoder; 321 new_decoder = NULL; 322 } 323 324 if (new_decoder) IWICBitmapDecoder_Release(new_decoder); 325 } 326 } 327 328 IWICBitmapDecoderInfo_Release(decoderinfo); 329 } 330 331 IUnknown_Release(unkdecoderinfo); 332 } 333 334 IEnumUnknown_Release(enumdecoders); 335 336 if (preferred_decoder) 337 { 338 *ppIDecoder = preferred_decoder; 339 if (decoder) IWICBitmapDecoder_Release(decoder); 340 return S_OK; 341 } 342 343 if (decoder) 344 { 345 *ppIDecoder = decoder; 346 return S_OK; 347 } 348 349 *ppIDecoder = NULL; 350 return WINCODEC_ERR_COMPONENTNOTFOUND; 351 } 352 353 static HRESULT WINAPI ComponentFactory_CreateEncoder(IWICComponentFactory *iface, 354 REFGUID guidContainerFormat, const GUID *pguidVendor, 355 IWICBitmapEncoder **ppIEncoder) 356 { 357 static int fixme=0; 358 IEnumUnknown *enumencoders; 359 IUnknown *unkencoderinfo; 360 IWICBitmapEncoderInfo *encoderinfo; 361 IWICBitmapEncoder *encoder=NULL; 362 HRESULT res=S_OK; 363 ULONG num_fetched; 364 GUID actual_containerformat; 365 366 TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(guidContainerFormat), 367 debugstr_guid(pguidVendor), ppIEncoder); 368 369 if (pguidVendor && !fixme++) 370 FIXME("ignoring vendor GUID\n"); 371 372 res = CreateComponentEnumerator(WICEncoder, WICComponentEnumerateDefault, &enumencoders); 373 if (FAILED(res)) return res; 374 375 while (!encoder) 376 { 377 res = IEnumUnknown_Next(enumencoders, 1, &unkencoderinfo, &num_fetched); 378 379 if (res == S_OK) 380 { 381 res = IUnknown_QueryInterface(unkencoderinfo, &IID_IWICBitmapEncoderInfo, (void**)&encoderinfo); 382 383 if (SUCCEEDED(res)) 384 { 385 res = IWICBitmapEncoderInfo_GetContainerFormat(encoderinfo, &actual_containerformat); 386 387 if (SUCCEEDED(res) && IsEqualGUID(guidContainerFormat, &actual_containerformat)) 388 { 389 res = IWICBitmapEncoderInfo_CreateInstance(encoderinfo, &encoder); 390 if (FAILED(res)) 391 encoder = NULL; 392 } 393 394 IWICBitmapEncoderInfo_Release(encoderinfo); 395 } 396 397 IUnknown_Release(unkencoderinfo); 398 } 399 else 400 break; 401 } 402 403 IEnumUnknown_Release(enumencoders); 404 405 if (encoder) 406 { 407 *ppIEncoder = encoder; 408 return S_OK; 409 } 410 else 411 { 412 WARN("failed to create encoder\n"); 413 *ppIEncoder = NULL; 414 return WINCODEC_ERR_COMPONENTNOTFOUND; 415 } 416 } 417 418 static HRESULT WINAPI ComponentFactory_CreatePalette(IWICComponentFactory *iface, 419 IWICPalette **ppIPalette) 420 { 421 TRACE("(%p,%p)\n", iface, ppIPalette); 422 return PaletteImpl_Create(ppIPalette); 423 } 424 425 static HRESULT WINAPI ComponentFactory_CreateFormatConverter(IWICComponentFactory *iface, 426 IWICFormatConverter **ppIFormatConverter) 427 { 428 return FormatConverter_CreateInstance(&IID_IWICFormatConverter, (void**)ppIFormatConverter); 429 } 430 431 static HRESULT WINAPI ComponentFactory_CreateBitmapScaler(IWICComponentFactory *iface, 432 IWICBitmapScaler **ppIBitmapScaler) 433 { 434 TRACE("(%p,%p)\n", iface, ppIBitmapScaler); 435 436 return BitmapScaler_Create(ppIBitmapScaler); 437 } 438 439 static HRESULT WINAPI ComponentFactory_CreateBitmapClipper(IWICComponentFactory *iface, 440 IWICBitmapClipper **ppIBitmapClipper) 441 { 442 TRACE("(%p,%p)\n", iface, ppIBitmapClipper); 443 return BitmapClipper_Create(ppIBitmapClipper); 444 } 445 446 static HRESULT WINAPI ComponentFactory_CreateBitmapFlipRotator(IWICComponentFactory *iface, 447 IWICBitmapFlipRotator **ppIBitmapFlipRotator) 448 { 449 TRACE("(%p,%p)\n", iface, ppIBitmapFlipRotator); 450 return FlipRotator_Create(ppIBitmapFlipRotator); 451 } 452 453 static HRESULT WINAPI ComponentFactory_CreateStream(IWICComponentFactory *iface, 454 IWICStream **ppIWICStream) 455 { 456 TRACE("(%p,%p)\n", iface, ppIWICStream); 457 return StreamImpl_Create(ppIWICStream); 458 } 459 460 static HRESULT WINAPI ComponentFactory_CreateColorContext(IWICComponentFactory *iface, 461 IWICColorContext **ppIColorContext) 462 { 463 TRACE("(%p,%p)\n", iface, ppIColorContext); 464 return ColorContext_Create(ppIColorContext); 465 } 466 467 static HRESULT WINAPI ComponentFactory_CreateColorTransformer(IWICComponentFactory *iface, 468 IWICColorTransform **ppIColorTransform) 469 { 470 TRACE("(%p,%p)\n", iface, ppIColorTransform); 471 return ColorTransform_Create(ppIColorTransform); 472 } 473 474 static HRESULT WINAPI ComponentFactory_CreateBitmap(IWICComponentFactory *iface, 475 UINT uiWidth, UINT uiHeight, REFWICPixelFormatGUID pixelFormat, 476 WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap) 477 { 478 TRACE("(%p,%u,%u,%s,%u,%p)\n", iface, uiWidth, uiHeight, 479 debugstr_guid(pixelFormat), option, ppIBitmap); 480 return BitmapImpl_Create(uiWidth, uiHeight, 0, 0, NULL, 0, pixelFormat, option, ppIBitmap); 481 } 482 483 static HRESULT WINAPI ComponentFactory_CreateBitmapFromSource(IWICComponentFactory *iface, 484 IWICBitmapSource *piBitmapSource, WICBitmapCreateCacheOption option, 485 IWICBitmap **ppIBitmap) 486 { 487 IWICBitmap *result; 488 IWICBitmapLock *lock; 489 IWICPalette *palette; 490 UINT width, height; 491 WICPixelFormatGUID pixelformat = {0}; 492 HRESULT hr; 493 WICRect rc; 494 double dpix, dpiy; 495 IWICComponentInfo *info; 496 IWICPixelFormatInfo2 *formatinfo; 497 WICPixelFormatNumericRepresentation format_type; 498 499 TRACE("(%p,%p,%u,%p)\n", iface, piBitmapSource, option, ppIBitmap); 500 501 if (!piBitmapSource || !ppIBitmap) 502 return E_INVALIDARG; 503 504 hr = IWICBitmapSource_GetSize(piBitmapSource, &width, &height); 505 506 if (SUCCEEDED(hr)) 507 hr = IWICBitmapSource_GetPixelFormat(piBitmapSource, &pixelformat); 508 509 if (SUCCEEDED(hr)) 510 hr = CreateComponentInfo(&pixelformat, &info); 511 512 if (SUCCEEDED(hr)) 513 { 514 hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo2, (void**)&formatinfo); 515 516 if (SUCCEEDED(hr)) 517 { 518 hr = IWICPixelFormatInfo2_GetNumericRepresentation(formatinfo, &format_type); 519 520 IWICPixelFormatInfo2_Release(formatinfo); 521 } 522 523 IWICComponentInfo_Release(info); 524 } 525 526 if (SUCCEEDED(hr)) 527 hr = BitmapImpl_Create(width, height, 0, 0, NULL, 0, &pixelformat, option, &result); 528 529 if (SUCCEEDED(hr)) 530 { 531 hr = IWICBitmap_Lock(result, NULL, WICBitmapLockWrite, &lock); 532 if (SUCCEEDED(hr)) 533 { 534 UINT stride, buffersize; 535 BYTE *buffer; 536 rc.X = rc.Y = 0; 537 rc.Width = width; 538 rc.Height = height; 539 540 hr = IWICBitmapLock_GetStride(lock, &stride); 541 542 if (SUCCEEDED(hr)) 543 hr = IWICBitmapLock_GetDataPointer(lock, &buffersize, &buffer); 544 545 if (SUCCEEDED(hr)) 546 hr = IWICBitmapSource_CopyPixels(piBitmapSource, &rc, stride, 547 buffersize, buffer); 548 549 IWICBitmapLock_Release(lock); 550 } 551 552 if (SUCCEEDED(hr) && (format_type == WICPixelFormatNumericRepresentationUnspecified || 553 format_type == WICPixelFormatNumericRepresentationIndexed)) 554 { 555 hr = PaletteImpl_Create(&palette); 556 557 if (SUCCEEDED(hr)) 558 { 559 hr = IWICBitmapSource_CopyPalette(piBitmapSource, palette); 560 561 if (SUCCEEDED(hr)) 562 hr = IWICBitmap_SetPalette(result, palette); 563 else 564 hr = S_OK; 565 566 IWICPalette_Release(palette); 567 } 568 } 569 570 if (SUCCEEDED(hr)) 571 { 572 hr = IWICBitmapSource_GetResolution(piBitmapSource, &dpix, &dpiy); 573 574 if (SUCCEEDED(hr)) 575 hr = IWICBitmap_SetResolution(result, dpix, dpiy); 576 else 577 hr = S_OK; 578 } 579 580 if (SUCCEEDED(hr)) 581 *ppIBitmap = result; 582 else 583 IWICBitmap_Release(result); 584 } 585 586 return hr; 587 } 588 589 static HRESULT WINAPI ComponentFactory_CreateBitmapFromSourceRect(IWICComponentFactory *iface, 590 IWICBitmapSource *piBitmapSource, UINT x, UINT y, UINT width, UINT height, 591 IWICBitmap **ppIBitmap) 592 { 593 FIXME("(%p,%p,%u,%u,%u,%u,%p): stub\n", iface, piBitmapSource, x, y, width, 594 height, ppIBitmap); 595 return E_NOTIMPL; 596 } 597 598 static HRESULT WINAPI ComponentFactory_CreateBitmapFromMemory(IWICComponentFactory *iface, 599 UINT width, UINT height, REFWICPixelFormatGUID format, UINT stride, 600 UINT size, BYTE *buffer, IWICBitmap **bitmap) 601 { 602 HRESULT hr; 603 604 TRACE("(%p,%u,%u,%s,%u,%u,%p,%p\n", iface, width, height, 605 debugstr_guid(format), stride, size, buffer, bitmap); 606 607 if (!stride || !size || !buffer || !bitmap) return E_INVALIDARG; 608 609 hr = BitmapImpl_Create(width, height, stride, size, NULL, 0, format, WICBitmapCacheOnLoad, bitmap); 610 if (SUCCEEDED(hr)) 611 { 612 IWICBitmapLock *lock; 613 614 hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); 615 if (SUCCEEDED(hr)) 616 { 617 UINT buffersize; 618 BYTE *data; 619 620 IWICBitmapLock_GetDataPointer(lock, &buffersize, &data); 621 memcpy(data, buffer, buffersize); 622 623 IWICBitmapLock_Release(lock); 624 } 625 else 626 { 627 IWICBitmap_Release(*bitmap); 628 *bitmap = NULL; 629 } 630 } 631 return hr; 632 } 633 634 static BOOL get_16bpp_format(HBITMAP hbm, WICPixelFormatGUID *format) 635 { 636 BOOL ret = TRUE; 637 BITMAPV4HEADER bmh; 638 HDC hdc; 639 640 hdc = CreateCompatibleDC(0); 641 642 memset(&bmh, 0, sizeof(bmh)); 643 bmh.bV4Size = sizeof(bmh); 644 bmh.bV4Width = 1; 645 bmh.bV4Height = 1; 646 bmh.bV4V4Compression = BI_BITFIELDS; 647 bmh.bV4BitCount = 16; 648 649 GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO *)&bmh, DIB_RGB_COLORS); 650 651 if (bmh.bV4RedMask == 0x7c00 && 652 bmh.bV4GreenMask == 0x3e0 && 653 bmh.bV4BlueMask == 0x1f) 654 { 655 *format = GUID_WICPixelFormat16bppBGR555; 656 } 657 else if (bmh.bV4RedMask == 0xf800 && 658 bmh.bV4GreenMask == 0x7e0 && 659 bmh.bV4BlueMask == 0x1f) 660 { 661 *format = GUID_WICPixelFormat16bppBGR565; 662 } 663 else 664 { 665 FIXME("unrecognized bitfields %x,%x,%x\n", bmh.bV4RedMask, 666 bmh.bV4GreenMask, bmh.bV4BlueMask); 667 ret = FALSE; 668 } 669 670 DeleteDC(hdc); 671 return ret; 672 } 673 674 static HRESULT WINAPI ComponentFactory_CreateBitmapFromHBITMAP(IWICComponentFactory *iface, 675 HBITMAP hbm, HPALETTE hpal, WICBitmapAlphaChannelOption option, IWICBitmap **bitmap) 676 { 677 BITMAP bm; 678 HRESULT hr; 679 WICPixelFormatGUID format; 680 IWICBitmapLock *lock; 681 UINT size, num_palette_entries = 0; 682 PALETTEENTRY entry[256]; 683 684 TRACE("(%p,%p,%p,%u,%p)\n", iface, hbm, hpal, option, bitmap); 685 686 if (!bitmap) return E_INVALIDARG; 687 688 if (GetObjectW(hbm, sizeof(bm), &bm) != sizeof(bm)) 689 return WINCODEC_ERR_WIN32ERROR; 690 691 if (hpal) 692 { 693 num_palette_entries = GetPaletteEntries(hpal, 0, 256, entry); 694 if (!num_palette_entries) 695 return WINCODEC_ERR_WIN32ERROR; 696 } 697 698 /* TODO: Figure out the correct format for 16, 32, 64 bpp */ 699 switch(bm.bmBitsPixel) 700 { 701 case 1: 702 format = GUID_WICPixelFormat1bppIndexed; 703 break; 704 case 4: 705 format = GUID_WICPixelFormat4bppIndexed; 706 break; 707 case 8: 708 format = GUID_WICPixelFormat8bppIndexed; 709 break; 710 case 16: 711 if (!get_16bpp_format(hbm, &format)) 712 return E_INVALIDARG; 713 break; 714 case 24: 715 format = GUID_WICPixelFormat24bppBGR; 716 break; 717 case 32: 718 switch (option) 719 { 720 case WICBitmapUseAlpha: 721 format = GUID_WICPixelFormat32bppBGRA; 722 break; 723 case WICBitmapUsePremultipliedAlpha: 724 format = GUID_WICPixelFormat32bppPBGRA; 725 break; 726 case WICBitmapIgnoreAlpha: 727 format = GUID_WICPixelFormat32bppBGR; 728 break; 729 default: 730 return E_INVALIDARG; 731 } 732 break; 733 case 48: 734 format = GUID_WICPixelFormat48bppRGB; 735 break; 736 default: 737 FIXME("unsupported %d bpp\n", bm.bmBitsPixel); 738 return E_INVALIDARG; 739 } 740 741 hr = BitmapImpl_Create(bm.bmWidth, bm.bmHeight, bm.bmWidthBytes, 0, NULL, 0, &format, 742 WICBitmapCacheOnLoad, bitmap); 743 if (hr != S_OK) return hr; 744 745 hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); 746 if (hr == S_OK) 747 { 748 BYTE *buffer; 749 HDC hdc; 750 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)]; 751 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf; 752 753 IWICBitmapLock_GetDataPointer(lock, &size, &buffer); 754 755 hdc = CreateCompatibleDC(0); 756 757 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 758 bmi->bmiHeader.biBitCount = 0; 759 GetDIBits(hdc, hbm, 0, 0, NULL, bmi, DIB_RGB_COLORS); 760 bmi->bmiHeader.biHeight = -bm.bmHeight; 761 GetDIBits(hdc, hbm, 0, bm.bmHeight, buffer, bmi, DIB_RGB_COLORS); 762 763 DeleteDC(hdc); 764 IWICBitmapLock_Release(lock); 765 766 if (num_palette_entries) 767 { 768 IWICPalette *palette; 769 WICColor colors[256]; 770 UINT i; 771 772 hr = PaletteImpl_Create(&palette); 773 if (hr == S_OK) 774 { 775 for (i = 0; i < num_palette_entries; i++) 776 colors[i] = 0xff000000 | entry[i].peRed << 16 | 777 entry[i].peGreen << 8 | entry[i].peBlue; 778 779 hr = IWICPalette_InitializeCustom(palette, colors, num_palette_entries); 780 if (hr == S_OK) 781 hr = IWICBitmap_SetPalette(*bitmap, palette); 782 783 IWICPalette_Release(palette); 784 } 785 } 786 } 787 788 if (hr != S_OK) 789 { 790 IWICBitmap_Release(*bitmap); 791 *bitmap = NULL; 792 } 793 794 return hr; 795 } 796 797 static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactory *iface, 798 HICON hicon, IWICBitmap **bitmap) 799 { 800 IWICBitmapLock *lock; 801 ICONINFO info; 802 BITMAP bm; 803 int width, height, x, y; 804 UINT stride, size; 805 BYTE *buffer; 806 DWORD *bits; 807 BITMAPINFO bi; 808 HDC hdc; 809 BOOL has_alpha; 810 HRESULT hr; 811 812 TRACE("(%p,%p,%p)\n", iface, hicon, bitmap); 813 814 if (!bitmap) return E_INVALIDARG; 815 816 if (!GetIconInfo(hicon, &info)) 817 return HRESULT_FROM_WIN32(GetLastError()); 818 819 GetObjectW(info.hbmColor ? info.hbmColor : info.hbmMask, sizeof(bm), &bm); 820 821 width = bm.bmWidth; 822 height = info.hbmColor ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2; 823 stride = width * 4; 824 size = stride * height; 825 826 hr = BitmapImpl_Create(width, height, stride, size, NULL, 0, 827 &GUID_WICPixelFormat32bppBGRA, WICBitmapCacheOnLoad, bitmap); 828 if (hr != S_OK) goto failed; 829 830 hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); 831 if (hr != S_OK) 832 { 833 IWICBitmap_Release(*bitmap); 834 goto failed; 835 } 836 IWICBitmapLock_GetDataPointer(lock, &size, &buffer); 837 838 hdc = CreateCompatibleDC(0); 839 840 memset(&bi, 0, sizeof(bi)); 841 bi.bmiHeader.biSize = sizeof(bi.bmiHeader); 842 bi.bmiHeader.biWidth = width; 843 bi.bmiHeader.biHeight = info.hbmColor ? -height: -height * 2; 844 bi.bmiHeader.biPlanes = 1; 845 bi.bmiHeader.biBitCount = 32; 846 bi.bmiHeader.biCompression = BI_RGB; 847 848 has_alpha = FALSE; 849 850 if (info.hbmColor) 851 { 852 GetDIBits(hdc, info.hbmColor, 0, height, buffer, &bi, DIB_RGB_COLORS); 853 854 if (bm.bmBitsPixel == 32) 855 { 856 /* If any pixel has a non-zero alpha, ignore hbmMask */ 857 bits = (DWORD *)buffer; 858 for (x = 0; x < width && !has_alpha; x++, bits++) 859 { 860 for (y = 0; y < height; y++) 861 { 862 if (*bits & 0xff000000) 863 { 864 has_alpha = TRUE; 865 break; 866 } 867 } 868 } 869 } 870 } 871 else 872 GetDIBits(hdc, info.hbmMask, 0, height, buffer, &bi, DIB_RGB_COLORS); 873 874 if (!has_alpha) 875 { 876 DWORD *rgba; 877 878 if (info.hbmMask) 879 { 880 BYTE *mask; 881 882 mask = HeapAlloc(GetProcessHeap(), 0, size); 883 if (!mask) 884 { 885 IWICBitmapLock_Release(lock); 886 IWICBitmap_Release(*bitmap); 887 DeleteDC(hdc); 888 hr = E_OUTOFMEMORY; 889 goto failed; 890 } 891 892 /* read alpha data from the mask */ 893 GetDIBits(hdc, info.hbmMask, info.hbmColor ? 0 : height, height, mask, &bi, DIB_RGB_COLORS); 894 895 for (y = 0; y < height; y++) 896 { 897 rgba = (DWORD *)(buffer + y * stride); 898 bits = (DWORD *)(mask + y * stride); 899 900 for (x = 0; x < width; x++, rgba++, bits++) 901 { 902 if (*bits) 903 *rgba = 0; 904 else 905 *rgba |= 0xff000000; 906 } 907 } 908 909 HeapFree(GetProcessHeap(), 0, mask); 910 } 911 else 912 { 913 /* set constant alpha of 255 */ 914 for (y = 0; y < height; y++) 915 { 916 rgba = (DWORD *)(buffer + y * stride); 917 for (x = 0; x < width; x++, rgba++) 918 *rgba |= 0xff000000; 919 } 920 } 921 922 } 923 924 IWICBitmapLock_Release(lock); 925 DeleteDC(hdc); 926 927 failed: 928 DeleteObject(info.hbmColor); 929 DeleteObject(info.hbmMask); 930 931 return hr; 932 } 933 934 static HRESULT WINAPI ComponentFactory_CreateComponentEnumerator(IWICComponentFactory *iface, 935 DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) 936 { 937 TRACE("(%p,%u,%u,%p)\n", iface, componentTypes, options, ppIEnumUnknown); 938 return CreateComponentEnumerator(componentTypes, options, ppIEnumUnknown); 939 } 940 941 static HRESULT WINAPI ComponentFactory_CreateFastMetadataEncoderFromDecoder( 942 IWICComponentFactory *iface, IWICBitmapDecoder *pIDecoder, 943 IWICFastMetadataEncoder **ppIFastEncoder) 944 { 945 FIXME("(%p,%p,%p): stub\n", iface, pIDecoder, ppIFastEncoder); 946 return E_NOTIMPL; 947 } 948 949 static HRESULT WINAPI ComponentFactory_CreateFastMetadataEncoderFromFrameDecode( 950 IWICComponentFactory *iface, IWICBitmapFrameDecode *pIFrameDecoder, 951 IWICFastMetadataEncoder **ppIFastEncoder) 952 { 953 FIXME("(%p,%p,%p): stub\n", iface, pIFrameDecoder, ppIFastEncoder); 954 return E_NOTIMPL; 955 } 956 957 static HRESULT WINAPI ComponentFactory_CreateQueryWriter(IWICComponentFactory *iface, 958 REFGUID guidMetadataFormat, const GUID *pguidVendor, 959 IWICMetadataQueryWriter **ppIQueryWriter) 960 { 961 FIXME("(%p,%s,%s,%p): stub\n", iface, debugstr_guid(guidMetadataFormat), 962 debugstr_guid(pguidVendor), ppIQueryWriter); 963 return E_NOTIMPL; 964 } 965 966 static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromReader(IWICComponentFactory *iface, 967 IWICMetadataQueryReader *pIQueryReader, const GUID *pguidVendor, 968 IWICMetadataQueryWriter **ppIQueryWriter) 969 { 970 FIXME("(%p,%p,%s,%p): stub\n", iface, pIQueryReader, debugstr_guid(pguidVendor), 971 ppIQueryWriter); 972 return E_NOTIMPL; 973 } 974 975 static HRESULT WINAPI ComponentFactory_CreateMetadataReader(IWICComponentFactory *iface, 976 REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) 977 { 978 FIXME("%p,%s,%s,%x,%p,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), 979 options, stream, reader); 980 return E_NOTIMPL; 981 } 982 983 static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICComponentFactory *iface, 984 REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) 985 { 986 HRESULT hr; 987 IEnumUnknown *enumreaders; 988 IUnknown *unkreaderinfo; 989 IWICMetadataReaderInfo *readerinfo; 990 IWICPersistStream *wicpersiststream; 991 ULONG num_fetched; 992 GUID decoder_vendor; 993 BOOL matches; 994 LARGE_INTEGER zero; 995 996 TRACE("%p,%s,%s,%x,%p,%p\n", iface, debugstr_guid(format), debugstr_guid(vendor), 997 options, stream, reader); 998 999 if (!format || !stream || !reader) 1000 return E_INVALIDARG; 1001 1002 zero.QuadPart = 0; 1003 1004 hr = CreateComponentEnumerator(WICMetadataReader, WICComponentEnumerateDefault, &enumreaders); 1005 if (FAILED(hr)) return hr; 1006 1007 *reader = NULL; 1008 1009 start: 1010 while (!*reader) 1011 { 1012 hr = IEnumUnknown_Next(enumreaders, 1, &unkreaderinfo, &num_fetched); 1013 1014 if (hr == S_OK) 1015 { 1016 hr = IUnknown_QueryInterface(unkreaderinfo, &IID_IWICMetadataReaderInfo, (void**)&readerinfo); 1017 1018 if (SUCCEEDED(hr)) 1019 { 1020 if (vendor) 1021 { 1022 hr = IWICMetadataReaderInfo_GetVendorGUID(readerinfo, &decoder_vendor); 1023 1024 if (FAILED(hr) || !IsEqualIID(vendor, &decoder_vendor)) 1025 { 1026 IWICMetadataReaderInfo_Release(readerinfo); 1027 IUnknown_Release(unkreaderinfo); 1028 continue; 1029 } 1030 } 1031 1032 hr = IWICMetadataReaderInfo_MatchesPattern(readerinfo, format, stream, &matches); 1033 1034 if (SUCCEEDED(hr) && matches) 1035 { 1036 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); 1037 1038 if (SUCCEEDED(hr)) 1039 hr = IWICMetadataReaderInfo_CreateInstance(readerinfo, reader); 1040 1041 if (SUCCEEDED(hr)) 1042 { 1043 hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void**)&wicpersiststream); 1044 1045 if (SUCCEEDED(hr)) 1046 { 1047 hr = IWICPersistStream_LoadEx(wicpersiststream, 1048 stream, vendor, options & WICPersistOptionMask); 1049 1050 IWICPersistStream_Release(wicpersiststream); 1051 } 1052 1053 if (FAILED(hr)) 1054 { 1055 IWICMetadataReader_Release(*reader); 1056 *reader = NULL; 1057 } 1058 } 1059 } 1060 1061 IUnknown_Release(readerinfo); 1062 } 1063 1064 IUnknown_Release(unkreaderinfo); 1065 } 1066 else 1067 break; 1068 } 1069 1070 if (!*reader && vendor) 1071 { 1072 vendor = NULL; 1073 IEnumUnknown_Reset(enumreaders); 1074 goto start; 1075 } 1076 1077 IEnumUnknown_Release(enumreaders); 1078 1079 if (!*reader && !(options & WICMetadataCreationFailUnknown)) 1080 { 1081 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); 1082 1083 if (SUCCEEDED(hr)) 1084 hr = UnknownMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void**)reader); 1085 1086 if (SUCCEEDED(hr)) 1087 { 1088 hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void**)&wicpersiststream); 1089 1090 if (SUCCEEDED(hr)) 1091 { 1092 hr = IWICPersistStream_LoadEx(wicpersiststream, stream, NULL, options & WICPersistOptionMask); 1093 1094 IWICPersistStream_Release(wicpersiststream); 1095 } 1096 1097 if (FAILED(hr)) 1098 { 1099 IWICMetadataReader_Release(*reader); 1100 *reader = NULL; 1101 } 1102 } 1103 } 1104 1105 if (*reader) 1106 return S_OK; 1107 else 1108 return WINCODEC_ERR_COMPONENTNOTFOUND; 1109 } 1110 1111 static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory *iface, 1112 REFGUID format, const GUID *vendor, DWORD options, IWICMetadataWriter **writer) 1113 { 1114 FIXME("%p,%s,%s,%x,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), options, writer); 1115 return E_NOTIMPL; 1116 } 1117 1118 static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, 1119 IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **writer) 1120 { 1121 FIXME("%p,%p,%s,%p: stub\n", iface, reader, debugstr_guid(vendor), writer); 1122 return E_NOTIMPL; 1123 } 1124 1125 static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComponentFactory *iface, 1126 IWICMetadataBlockReader *block_reader, IWICMetadataQueryReader **query_reader) 1127 { 1128 TRACE("%p,%p,%p\n", iface, block_reader, query_reader); 1129 1130 if (!block_reader || !query_reader) 1131 return E_INVALIDARG; 1132 1133 return MetadataQueryReader_CreateInstance(block_reader, NULL, query_reader); 1134 } 1135 1136 static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromBlockWriter(IWICComponentFactory *iface, 1137 IWICMetadataBlockWriter *block_writer, IWICMetadataQueryWriter **query_writer) 1138 { 1139 FIXME("%p,%p,%p: stub\n", iface, block_writer, query_writer); 1140 return E_NOTIMPL; 1141 } 1142 1143 static HRESULT WINAPI ComponentFactory_CreateEncoderPropertyBag(IWICComponentFactory *iface, 1144 PROPBAG2 *options, UINT count, IPropertyBag2 **property) 1145 { 1146 TRACE("(%p,%p,%u,%p)\n", iface, options, count, property); 1147 return CreatePropertyBag2(options, count, property); 1148 } 1149 1150 static const IWICComponentFactoryVtbl ComponentFactory_Vtbl = { 1151 ComponentFactory_QueryInterface, 1152 ComponentFactory_AddRef, 1153 ComponentFactory_Release, 1154 ComponentFactory_CreateDecoderFromFilename, 1155 ComponentFactory_CreateDecoderFromStream, 1156 ComponentFactory_CreateDecoderFromFileHandle, 1157 ComponentFactory_CreateComponentInfo, 1158 ComponentFactory_CreateDecoder, 1159 ComponentFactory_CreateEncoder, 1160 ComponentFactory_CreatePalette, 1161 ComponentFactory_CreateFormatConverter, 1162 ComponentFactory_CreateBitmapScaler, 1163 ComponentFactory_CreateBitmapClipper, 1164 ComponentFactory_CreateBitmapFlipRotator, 1165 ComponentFactory_CreateStream, 1166 ComponentFactory_CreateColorContext, 1167 ComponentFactory_CreateColorTransformer, 1168 ComponentFactory_CreateBitmap, 1169 ComponentFactory_CreateBitmapFromSource, 1170 ComponentFactory_CreateBitmapFromSourceRect, 1171 ComponentFactory_CreateBitmapFromMemory, 1172 ComponentFactory_CreateBitmapFromHBITMAP, 1173 ComponentFactory_CreateBitmapFromHICON, 1174 ComponentFactory_CreateComponentEnumerator, 1175 ComponentFactory_CreateFastMetadataEncoderFromDecoder, 1176 ComponentFactory_CreateFastMetadataEncoderFromFrameDecode, 1177 ComponentFactory_CreateQueryWriter, 1178 ComponentFactory_CreateQueryWriterFromReader, 1179 ComponentFactory_CreateMetadataReader, 1180 ComponentFactory_CreateMetadataReaderFromContainer, 1181 ComponentFactory_CreateMetadataWriter, 1182 ComponentFactory_CreateMetadataWriterFromReader, 1183 ComponentFactory_CreateQueryReaderFromBlockReader, 1184 ComponentFactory_CreateQueryWriterFromBlockWriter, 1185 ComponentFactory_CreateEncoderPropertyBag 1186 }; 1187 1188 HRESULT ComponentFactory_CreateInstance(REFIID iid, void** ppv) 1189 { 1190 ComponentFactory *This; 1191 HRESULT ret; 1192 1193 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); 1194 1195 *ppv = NULL; 1196 1197 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentFactory)); 1198 if (!This) return E_OUTOFMEMORY; 1199 1200 This->IWICComponentFactory_iface.lpVtbl = &ComponentFactory_Vtbl; 1201 This->ref = 1; 1202 1203 ret = IWICComponentFactory_QueryInterface(&This->IWICComponentFactory_iface, iid, ppv); 1204 IWICComponentFactory_Release(&This->IWICComponentFactory_iface); 1205 1206 return ret; 1207 } 1208 1209 HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, 1210 REFWICPixelFormatGUID format, HANDLE section, UINT stride, 1211 UINT offset, WICSectionAccessLevel wicaccess, IWICBitmap **bitmap) 1212 { 1213 SYSTEM_INFO sysinfo; 1214 UINT bpp, access, size, view_offset, view_size; 1215 void *view; 1216 HRESULT hr; 1217 1218 TRACE("%u,%u,%s,%p,%u,%u,%#x,%p\n", width, height, debugstr_guid(format), 1219 section, stride, offset, wicaccess, bitmap); 1220 1221 if (!width || !height || !section || !bitmap) return E_INVALIDARG; 1222 1223 hr = get_pixelformat_bpp(format, &bpp); 1224 if (FAILED(hr)) return hr; 1225 1226 switch (wicaccess) 1227 { 1228 case WICSectionAccessLevelReadWrite: 1229 access = FILE_MAP_READ | FILE_MAP_WRITE; 1230 break; 1231 1232 case WICSectionAccessLevelRead: 1233 access = FILE_MAP_READ; 1234 break; 1235 1236 default: 1237 FIXME("unsupported access %#x\n", wicaccess); 1238 return E_INVALIDARG; 1239 } 1240 1241 if (!stride) stride = (((bpp * width) + 31) / 32) * 4; 1242 size = stride * height; 1243 if (size / height != stride) return E_INVALIDARG; 1244 1245 GetSystemInfo(&sysinfo); 1246 view_offset = offset - (offset % sysinfo.dwAllocationGranularity); 1247 view_size = size + (offset - view_offset); 1248 1249 view = MapViewOfFile(section, access, 0, view_offset, view_size); 1250 if (!view) return HRESULT_FROM_WIN32(GetLastError()); 1251 1252 offset -= view_offset; 1253 hr = BitmapImpl_Create(width, height, stride, 0, view, offset, format, WICBitmapCacheOnLoad, bitmap); 1254 if (FAILED(hr)) UnmapViewOfFile(view); 1255 return hr; 1256 } 1257 1258 HRESULT WINAPI WICCreateBitmapFromSection(UINT width, UINT height, 1259 REFWICPixelFormatGUID format, HANDLE section, 1260 UINT stride, UINT offset, IWICBitmap **bitmap) 1261 { 1262 TRACE("%u,%u,%s,%p,%u,%u,%p\n", width, height, debugstr_guid(format), 1263 section, stride, offset, bitmap); 1264 1265 return WICCreateBitmapFromSectionEx(width, height, format, section, 1266 stride, offset, WICSectionAccessLevelRead, bitmap); 1267 } 1268