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