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, 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, &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, 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, &format, WICBitmapCacheOnLoad, bitmap); 742 if (hr != S_OK) return hr; 743 744 hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); 745 if (hr == S_OK) 746 { 747 BYTE *buffer; 748 HDC hdc; 749 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)]; 750 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf; 751 752 IWICBitmapLock_GetDataPointer(lock, &size, &buffer); 753 754 hdc = CreateCompatibleDC(0); 755 756 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 757 bmi->bmiHeader.biBitCount = 0; 758 GetDIBits(hdc, hbm, 0, 0, NULL, bmi, DIB_RGB_COLORS); 759 bmi->bmiHeader.biHeight = -bm.bmHeight; 760 GetDIBits(hdc, hbm, 0, bm.bmHeight, buffer, bmi, DIB_RGB_COLORS); 761 762 DeleteDC(hdc); 763 IWICBitmapLock_Release(lock); 764 765 if (num_palette_entries) 766 { 767 IWICPalette *palette; 768 WICColor colors[256]; 769 UINT i; 770 771 hr = PaletteImpl_Create(&palette); 772 if (hr == S_OK) 773 { 774 for (i = 0; i < num_palette_entries; i++) 775 colors[i] = 0xff000000 | entry[i].peRed << 16 | 776 entry[i].peGreen << 8 | entry[i].peBlue; 777 778 hr = IWICPalette_InitializeCustom(palette, colors, num_palette_entries); 779 if (hr == S_OK) 780 hr = IWICBitmap_SetPalette(*bitmap, palette); 781 782 IWICPalette_Release(palette); 783 } 784 } 785 } 786 787 if (hr != S_OK) 788 { 789 IWICBitmap_Release(*bitmap); 790 *bitmap = NULL; 791 } 792 793 return hr; 794 } 795 796 static HRESULT WINAPI ComponentFactory_CreateBitmapFromHICON(IWICComponentFactory *iface, 797 HICON hicon, IWICBitmap **bitmap) 798 { 799 IWICBitmapLock *lock; 800 ICONINFO info; 801 BITMAP bm; 802 int width, height, x, y; 803 UINT stride, size; 804 BYTE *buffer; 805 DWORD *bits; 806 BITMAPINFO bi; 807 HDC hdc; 808 BOOL has_alpha; 809 HRESULT hr; 810 811 TRACE("(%p,%p,%p)\n", iface, hicon, bitmap); 812 813 if (!bitmap) return E_INVALIDARG; 814 815 if (!GetIconInfo(hicon, &info)) 816 return HRESULT_FROM_WIN32(GetLastError()); 817 818 GetObjectW(info.hbmColor ? info.hbmColor : info.hbmMask, sizeof(bm), &bm); 819 820 width = bm.bmWidth; 821 height = info.hbmColor ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2; 822 stride = width * 4; 823 size = stride * height; 824 825 hr = BitmapImpl_Create(width, height, stride, size, NULL, 826 &GUID_WICPixelFormat32bppBGRA, WICBitmapCacheOnLoad, bitmap); 827 if (hr != S_OK) goto failed; 828 829 hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); 830 if (hr != S_OK) 831 { 832 IWICBitmap_Release(*bitmap); 833 goto failed; 834 } 835 IWICBitmapLock_GetDataPointer(lock, &size, &buffer); 836 837 hdc = CreateCompatibleDC(0); 838 839 memset(&bi, 0, sizeof(bi)); 840 bi.bmiHeader.biSize = sizeof(bi.bmiHeader); 841 bi.bmiHeader.biWidth = width; 842 bi.bmiHeader.biHeight = info.hbmColor ? -height: -height * 2; 843 bi.bmiHeader.biPlanes = 1; 844 bi.bmiHeader.biBitCount = 32; 845 bi.bmiHeader.biCompression = BI_RGB; 846 847 has_alpha = FALSE; 848 849 if (info.hbmColor) 850 { 851 GetDIBits(hdc, info.hbmColor, 0, height, buffer, &bi, DIB_RGB_COLORS); 852 853 if (bm.bmBitsPixel == 32) 854 { 855 /* If any pixel has a non-zero alpha, ignore hbmMask */ 856 bits = (DWORD *)buffer; 857 for (x = 0; x < width && !has_alpha; x++, bits++) 858 { 859 for (y = 0; y < height; y++) 860 { 861 if (*bits & 0xff000000) 862 { 863 has_alpha = TRUE; 864 break; 865 } 866 } 867 } 868 } 869 } 870 else 871 GetDIBits(hdc, info.hbmMask, 0, height, buffer, &bi, DIB_RGB_COLORS); 872 873 if (!has_alpha) 874 { 875 DWORD *rgba; 876 877 if (info.hbmMask) 878 { 879 BYTE *mask; 880 881 mask = HeapAlloc(GetProcessHeap(), 0, size); 882 if (!mask) 883 { 884 IWICBitmapLock_Release(lock); 885 IWICBitmap_Release(*bitmap); 886 DeleteDC(hdc); 887 hr = E_OUTOFMEMORY; 888 goto failed; 889 } 890 891 /* read alpha data from the mask */ 892 GetDIBits(hdc, info.hbmMask, info.hbmColor ? 0 : height, height, mask, &bi, DIB_RGB_COLORS); 893 894 for (y = 0; y < height; y++) 895 { 896 rgba = (DWORD *)(buffer + y * stride); 897 bits = (DWORD *)(mask + y * stride); 898 899 for (x = 0; x < width; x++, rgba++, bits++) 900 { 901 if (*bits) 902 *rgba = 0; 903 else 904 *rgba |= 0xff000000; 905 } 906 } 907 908 HeapFree(GetProcessHeap(), 0, mask); 909 } 910 else 911 { 912 /* set constant alpha of 255 */ 913 for (y = 0; y < height; y++) 914 { 915 rgba = (DWORD *)(buffer + y * stride); 916 for (x = 0; x < width; x++, rgba++) 917 *rgba |= 0xff000000; 918 } 919 } 920 921 } 922 923 IWICBitmapLock_Release(lock); 924 DeleteDC(hdc); 925 926 failed: 927 DeleteObject(info.hbmColor); 928 DeleteObject(info.hbmMask); 929 930 return hr; 931 } 932 933 static HRESULT WINAPI ComponentFactory_CreateComponentEnumerator(IWICComponentFactory *iface, 934 DWORD componentTypes, DWORD options, IEnumUnknown **ppIEnumUnknown) 935 { 936 TRACE("(%p,%u,%u,%p)\n", iface, componentTypes, options, ppIEnumUnknown); 937 return CreateComponentEnumerator(componentTypes, options, ppIEnumUnknown); 938 } 939 940 static HRESULT WINAPI ComponentFactory_CreateFastMetadataEncoderFromDecoder( 941 IWICComponentFactory *iface, IWICBitmapDecoder *pIDecoder, 942 IWICFastMetadataEncoder **ppIFastEncoder) 943 { 944 FIXME("(%p,%p,%p): stub\n", iface, pIDecoder, ppIFastEncoder); 945 return E_NOTIMPL; 946 } 947 948 static HRESULT WINAPI ComponentFactory_CreateFastMetadataEncoderFromFrameDecode( 949 IWICComponentFactory *iface, IWICBitmapFrameDecode *pIFrameDecoder, 950 IWICFastMetadataEncoder **ppIFastEncoder) 951 { 952 FIXME("(%p,%p,%p): stub\n", iface, pIFrameDecoder, ppIFastEncoder); 953 return E_NOTIMPL; 954 } 955 956 static HRESULT WINAPI ComponentFactory_CreateQueryWriter(IWICComponentFactory *iface, 957 REFGUID guidMetadataFormat, const GUID *pguidVendor, 958 IWICMetadataQueryWriter **ppIQueryWriter) 959 { 960 FIXME("(%p,%s,%s,%p): stub\n", iface, debugstr_guid(guidMetadataFormat), 961 debugstr_guid(pguidVendor), ppIQueryWriter); 962 return E_NOTIMPL; 963 } 964 965 static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromReader(IWICComponentFactory *iface, 966 IWICMetadataQueryReader *pIQueryReader, const GUID *pguidVendor, 967 IWICMetadataQueryWriter **ppIQueryWriter) 968 { 969 FIXME("(%p,%p,%s,%p): stub\n", iface, pIQueryReader, debugstr_guid(pguidVendor), 970 ppIQueryWriter); 971 return E_NOTIMPL; 972 } 973 974 static HRESULT WINAPI ComponentFactory_CreateMetadataReader(IWICComponentFactory *iface, 975 REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) 976 { 977 FIXME("%p,%s,%s,%x,%p,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), 978 options, stream, reader); 979 return E_NOTIMPL; 980 } 981 982 static HRESULT WINAPI ComponentFactory_CreateMetadataReaderFromContainer(IWICComponentFactory *iface, 983 REFGUID format, const GUID *vendor, DWORD options, IStream *stream, IWICMetadataReader **reader) 984 { 985 HRESULT hr; 986 IEnumUnknown *enumreaders; 987 IUnknown *unkreaderinfo; 988 IWICMetadataReaderInfo *readerinfo; 989 IWICPersistStream *wicpersiststream; 990 ULONG num_fetched; 991 GUID decoder_vendor; 992 BOOL matches; 993 LARGE_INTEGER zero; 994 995 TRACE("%p,%s,%s,%x,%p,%p\n", iface, debugstr_guid(format), debugstr_guid(vendor), 996 options, stream, reader); 997 998 if (!format || !stream || !reader) 999 return E_INVALIDARG; 1000 1001 zero.QuadPart = 0; 1002 1003 hr = CreateComponentEnumerator(WICMetadataReader, WICComponentEnumerateDefault, &enumreaders); 1004 if (FAILED(hr)) return hr; 1005 1006 *reader = NULL; 1007 1008 start: 1009 while (!*reader) 1010 { 1011 hr = IEnumUnknown_Next(enumreaders, 1, &unkreaderinfo, &num_fetched); 1012 1013 if (hr == S_OK) 1014 { 1015 hr = IUnknown_QueryInterface(unkreaderinfo, &IID_IWICMetadataReaderInfo, (void**)&readerinfo); 1016 1017 if (SUCCEEDED(hr)) 1018 { 1019 if (vendor) 1020 { 1021 hr = IWICMetadataReaderInfo_GetVendorGUID(readerinfo, &decoder_vendor); 1022 1023 if (FAILED(hr) || !IsEqualIID(vendor, &decoder_vendor)) 1024 { 1025 IWICMetadataReaderInfo_Release(readerinfo); 1026 IUnknown_Release(unkreaderinfo); 1027 continue; 1028 } 1029 } 1030 1031 hr = IWICMetadataReaderInfo_MatchesPattern(readerinfo, format, stream, &matches); 1032 1033 if (SUCCEEDED(hr) && matches) 1034 { 1035 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); 1036 1037 if (SUCCEEDED(hr)) 1038 hr = IWICMetadataReaderInfo_CreateInstance(readerinfo, reader); 1039 1040 if (SUCCEEDED(hr)) 1041 { 1042 hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void**)&wicpersiststream); 1043 1044 if (SUCCEEDED(hr)) 1045 { 1046 hr = IWICPersistStream_LoadEx(wicpersiststream, 1047 stream, vendor, options & WICPersistOptionMask); 1048 1049 IWICPersistStream_Release(wicpersiststream); 1050 } 1051 1052 if (FAILED(hr)) 1053 { 1054 IWICMetadataReader_Release(*reader); 1055 *reader = NULL; 1056 } 1057 } 1058 } 1059 1060 IUnknown_Release(readerinfo); 1061 } 1062 1063 IUnknown_Release(unkreaderinfo); 1064 } 1065 else 1066 break; 1067 } 1068 1069 if (!*reader && vendor) 1070 { 1071 vendor = NULL; 1072 IEnumUnknown_Reset(enumreaders); 1073 goto start; 1074 } 1075 1076 IEnumUnknown_Release(enumreaders); 1077 1078 if (!*reader && !(options & WICMetadataCreationFailUnknown)) 1079 { 1080 hr = IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL); 1081 1082 if (SUCCEEDED(hr)) 1083 hr = UnknownMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void**)reader); 1084 1085 if (SUCCEEDED(hr)) 1086 { 1087 hr = IWICMetadataReader_QueryInterface(*reader, &IID_IWICPersistStream, (void**)&wicpersiststream); 1088 1089 if (SUCCEEDED(hr)) 1090 { 1091 hr = IWICPersistStream_LoadEx(wicpersiststream, stream, NULL, options & WICPersistOptionMask); 1092 1093 IWICPersistStream_Release(wicpersiststream); 1094 } 1095 1096 if (FAILED(hr)) 1097 { 1098 IWICMetadataReader_Release(*reader); 1099 *reader = NULL; 1100 } 1101 } 1102 } 1103 1104 if (*reader) 1105 return S_OK; 1106 else 1107 return WINCODEC_ERR_COMPONENTNOTFOUND; 1108 } 1109 1110 static HRESULT WINAPI ComponentFactory_CreateMetadataWriter(IWICComponentFactory *iface, 1111 REFGUID format, const GUID *vendor, DWORD options, IWICMetadataWriter **writer) 1112 { 1113 FIXME("%p,%s,%s,%x,%p: stub\n", iface, debugstr_guid(format), debugstr_guid(vendor), options, writer); 1114 return E_NOTIMPL; 1115 } 1116 1117 static HRESULT WINAPI ComponentFactory_CreateMetadataWriterFromReader(IWICComponentFactory *iface, 1118 IWICMetadataReader *reader, const GUID *vendor, IWICMetadataWriter **writer) 1119 { 1120 FIXME("%p,%p,%s,%p: stub\n", iface, reader, debugstr_guid(vendor), writer); 1121 return E_NOTIMPL; 1122 } 1123 1124 static HRESULT WINAPI ComponentFactory_CreateQueryReaderFromBlockReader(IWICComponentFactory *iface, 1125 IWICMetadataBlockReader *block_reader, IWICMetadataQueryReader **query_reader) 1126 { 1127 TRACE("%p,%p,%p\n", iface, block_reader, query_reader); 1128 1129 if (!block_reader || !query_reader) 1130 return E_INVALIDARG; 1131 1132 return MetadataQueryReader_CreateInstance(block_reader, NULL, query_reader); 1133 } 1134 1135 static HRESULT WINAPI ComponentFactory_CreateQueryWriterFromBlockWriter(IWICComponentFactory *iface, 1136 IWICMetadataBlockWriter *block_writer, IWICMetadataQueryWriter **query_writer) 1137 { 1138 FIXME("%p,%p,%p: stub\n", iface, block_writer, query_writer); 1139 return E_NOTIMPL; 1140 } 1141 1142 static HRESULT WINAPI ComponentFactory_CreateEncoderPropertyBag(IWICComponentFactory *iface, 1143 PROPBAG2 *options, UINT count, IPropertyBag2 **property) 1144 { 1145 TRACE("(%p,%p,%u,%p)\n", iface, options, count, property); 1146 return CreatePropertyBag2(options, count, property); 1147 } 1148 1149 static const IWICComponentFactoryVtbl ComponentFactory_Vtbl = { 1150 ComponentFactory_QueryInterface, 1151 ComponentFactory_AddRef, 1152 ComponentFactory_Release, 1153 ComponentFactory_CreateDecoderFromFilename, 1154 ComponentFactory_CreateDecoderFromStream, 1155 ComponentFactory_CreateDecoderFromFileHandle, 1156 ComponentFactory_CreateComponentInfo, 1157 ComponentFactory_CreateDecoder, 1158 ComponentFactory_CreateEncoder, 1159 ComponentFactory_CreatePalette, 1160 ComponentFactory_CreateFormatConverter, 1161 ComponentFactory_CreateBitmapScaler, 1162 ComponentFactory_CreateBitmapClipper, 1163 ComponentFactory_CreateBitmapFlipRotator, 1164 ComponentFactory_CreateStream, 1165 ComponentFactory_CreateColorContext, 1166 ComponentFactory_CreateColorTransformer, 1167 ComponentFactory_CreateBitmap, 1168 ComponentFactory_CreateBitmapFromSource, 1169 ComponentFactory_CreateBitmapFromSourceRect, 1170 ComponentFactory_CreateBitmapFromMemory, 1171 ComponentFactory_CreateBitmapFromHBITMAP, 1172 ComponentFactory_CreateBitmapFromHICON, 1173 ComponentFactory_CreateComponentEnumerator, 1174 ComponentFactory_CreateFastMetadataEncoderFromDecoder, 1175 ComponentFactory_CreateFastMetadataEncoderFromFrameDecode, 1176 ComponentFactory_CreateQueryWriter, 1177 ComponentFactory_CreateQueryWriterFromReader, 1178 ComponentFactory_CreateMetadataReader, 1179 ComponentFactory_CreateMetadataReaderFromContainer, 1180 ComponentFactory_CreateMetadataWriter, 1181 ComponentFactory_CreateMetadataWriterFromReader, 1182 ComponentFactory_CreateQueryReaderFromBlockReader, 1183 ComponentFactory_CreateQueryWriterFromBlockWriter, 1184 ComponentFactory_CreateEncoderPropertyBag 1185 }; 1186 1187 HRESULT ComponentFactory_CreateInstance(REFIID iid, void** ppv) 1188 { 1189 ComponentFactory *This; 1190 HRESULT ret; 1191 1192 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); 1193 1194 *ppv = NULL; 1195 1196 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ComponentFactory)); 1197 if (!This) return E_OUTOFMEMORY; 1198 1199 This->IWICComponentFactory_iface.lpVtbl = &ComponentFactory_Vtbl; 1200 This->ref = 1; 1201 1202 ret = IWICComponentFactory_QueryInterface(&This->IWICComponentFactory_iface, iid, ppv); 1203 IWICComponentFactory_Release(&This->IWICComponentFactory_iface); 1204 1205 return ret; 1206 } 1207 1208 HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, 1209 REFWICPixelFormatGUID format, HANDLE section, UINT stride, 1210 UINT offset, WICSectionAccessLevel wicaccess, IWICBitmap **bitmap) 1211 { 1212 DWORD access; 1213 void *buffer; 1214 HRESULT hr; 1215 1216 TRACE("%u,%u,%s,%p,%u,%#x,%#x,%p\n", width, height, debugstr_guid(format), 1217 section, stride, offset, wicaccess, bitmap); 1218 1219 if (!width || !height || !section || !bitmap) return E_INVALIDARG; 1220 1221 switch (wicaccess) 1222 { 1223 case WICSectionAccessLevelReadWrite: 1224 access = FILE_MAP_READ | FILE_MAP_WRITE; 1225 break; 1226 1227 case WICSectionAccessLevelRead: 1228 access = FILE_MAP_READ; 1229 break; 1230 1231 default: 1232 FIXME("unsupported access %#x\n", wicaccess); 1233 return E_INVALIDARG; 1234 } 1235 1236 buffer = MapViewOfFile(section, access, 0, offset, 0); 1237 if (!buffer) return HRESULT_FROM_WIN32(GetLastError()); 1238 1239 hr = BitmapImpl_Create(width, height, stride, 0, buffer, format, WICBitmapCacheOnLoad, bitmap); 1240 if (FAILED(hr)) UnmapViewOfFile(buffer); 1241 return hr; 1242 } 1243 1244 HRESULT WINAPI WICCreateBitmapFromSection(UINT width, UINT height, 1245 REFWICPixelFormatGUID format, HANDLE section, 1246 UINT stride, UINT offset, IWICBitmap **bitmap) 1247 { 1248 TRACE("%u,%u,%s,%p,%u,%u,%p\n", width, height, debugstr_guid(format), 1249 section, stride, offset, bitmap); 1250 1251 return WICCreateBitmapFromSectionEx(width, height, format, section, 1252 stride, offset, WICSectionAccessLevelRead, bitmap); 1253 } 1254