wineandroid: Check that Android supports the format in IsFormatSupported.
[wine.git] / dlls / windowscodecs / bitmap.c
blob6adaab0aea183e910ada2a4911e345559a4c8f52
1 /*
2 * Copyright 2012 Vincent Povirk for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
29 #include "wincodecs_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
35 /* WARNING: .NET Media Integration Layer (MIL) directly dereferences
36 * BitmapImpl members and depends on its exact layout.
38 typedef struct BitmapImpl {
39 IMILUnknown1 IMILUnknown1_iface;
40 LONG ref;
41 IMILBitmapSource IMILBitmapSource_iface;
42 IWICBitmap IWICBitmap_iface;
43 IMILUnknown2 IMILUnknown2_iface;
44 IWICPalette *palette;
45 int palette_set;
46 LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */
47 BYTE *data;
48 UINT width, height;
49 UINT stride;
50 UINT bpp;
51 WICPixelFormatGUID pixelformat;
52 double dpix, dpiy;
53 CRITICAL_SECTION cs;
54 } BitmapImpl;
56 typedef struct BitmapLockImpl {
57 IWICBitmapLock IWICBitmapLock_iface;
58 LONG ref;
59 BitmapImpl *parent;
60 UINT width, height;
61 BYTE *data;
62 } BitmapLockImpl;
64 static inline BitmapImpl *impl_from_IWICBitmap(IWICBitmap *iface)
66 return CONTAINING_RECORD(iface, BitmapImpl, IWICBitmap_iface);
69 static inline BitmapImpl *impl_from_IMILBitmapSource(IMILBitmapSource *iface)
71 return CONTAINING_RECORD(iface, BitmapImpl, IMILBitmapSource_iface);
74 static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface)
76 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_iface);
79 static inline BitmapImpl *impl_from_IMILUnknown2(IMILUnknown2 *iface)
81 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown2_iface);
84 static inline BitmapLockImpl *impl_from_IWICBitmapLock(IWICBitmapLock *iface)
86 return CONTAINING_RECORD(iface, BitmapLockImpl, IWICBitmapLock_iface);
89 static BOOL BitmapImpl_AcquireLock(BitmapImpl *This, int write)
91 if (write)
93 return 0 == InterlockedCompareExchange(&This->lock, -1, 0);
95 else
97 while (1)
99 LONG prev_val = This->lock;
100 if (prev_val == -1)
101 return FALSE;
102 if (prev_val == InterlockedCompareExchange(&This->lock, prev_val+1, prev_val))
103 return TRUE;
108 static void BitmapImpl_ReleaseLock(BitmapImpl *This)
110 while (1)
112 LONG prev_val = This->lock, new_val;
113 if (prev_val == -1)
114 new_val = 0;
115 else
116 new_val = prev_val - 1;
117 if (prev_val == InterlockedCompareExchange(&This->lock, new_val, prev_val))
118 break;
123 static HRESULT WINAPI BitmapLockImpl_QueryInterface(IWICBitmapLock *iface, REFIID iid,
124 void **ppv)
126 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
127 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
129 if (!ppv) return E_INVALIDARG;
131 if (IsEqualIID(&IID_IUnknown, iid) ||
132 IsEqualIID(&IID_IWICBitmapLock, iid))
134 *ppv = &This->IWICBitmapLock_iface;
136 else
138 *ppv = NULL;
139 return E_NOINTERFACE;
142 IUnknown_AddRef((IUnknown*)*ppv);
143 return S_OK;
146 static ULONG WINAPI BitmapLockImpl_AddRef(IWICBitmapLock *iface)
148 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
149 ULONG ref = InterlockedIncrement(&This->ref);
151 TRACE("(%p) refcount=%u\n", iface, ref);
153 return ref;
156 static ULONG WINAPI BitmapLockImpl_Release(IWICBitmapLock *iface)
158 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
159 ULONG ref = InterlockedDecrement(&This->ref);
161 TRACE("(%p) refcount=%u\n", iface, ref);
163 if (ref == 0)
165 BitmapImpl_ReleaseLock(This->parent);
166 IWICBitmap_Release(&This->parent->IWICBitmap_iface);
167 HeapFree(GetProcessHeap(), 0, This);
170 return ref;
173 static HRESULT WINAPI BitmapLockImpl_GetSize(IWICBitmapLock *iface,
174 UINT *puiWidth, UINT *puiHeight)
176 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
177 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
179 if (!puiWidth || !puiHeight)
180 return E_INVALIDARG;
182 *puiWidth = This->width;
183 *puiHeight = This->height;
185 return S_OK;
188 static HRESULT WINAPI BitmapLockImpl_GetStride(IWICBitmapLock *iface,
189 UINT *pcbStride)
191 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
192 TRACE("(%p,%p)\n", iface, pcbStride);
194 if (!pcbStride)
195 return E_INVALIDARG;
197 *pcbStride = This->parent->stride;
199 return S_OK;
202 static HRESULT WINAPI BitmapLockImpl_GetDataPointer(IWICBitmapLock *iface,
203 UINT *pcbBufferSize, BYTE **ppbData)
205 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
206 TRACE("(%p,%p,%p)\n", iface, pcbBufferSize, ppbData);
208 if (!pcbBufferSize || !ppbData)
209 return E_INVALIDARG;
211 *pcbBufferSize = This->parent->stride * (This->height - 1) +
212 ((This->parent->bpp * This->width) + 7)/8;
213 *ppbData = This->data;
215 return S_OK;
218 static HRESULT WINAPI BitmapLockImpl_GetPixelFormat(IWICBitmapLock *iface,
219 WICPixelFormatGUID *pPixelFormat)
221 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
222 TRACE("(%p,%p)\n", iface, pPixelFormat);
224 return IWICBitmap_GetPixelFormat(&This->parent->IWICBitmap_iface, pPixelFormat);
227 static const IWICBitmapLockVtbl BitmapLockImpl_Vtbl = {
228 BitmapLockImpl_QueryInterface,
229 BitmapLockImpl_AddRef,
230 BitmapLockImpl_Release,
231 BitmapLockImpl_GetSize,
232 BitmapLockImpl_GetStride,
233 BitmapLockImpl_GetDataPointer,
234 BitmapLockImpl_GetPixelFormat
237 static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid,
238 void **ppv)
240 BitmapImpl *This = impl_from_IWICBitmap(iface);
241 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
243 if (!ppv) return E_INVALIDARG;
245 if (IsEqualIID(&IID_IUnknown, iid) ||
246 IsEqualIID(&IID_IWICBitmapSource, iid) ||
247 IsEqualIID(&IID_IWICBitmap, iid))
249 *ppv = &This->IWICBitmap_iface;
251 else if (IsEqualIID(&IID_IMILBitmapSource, iid))
253 *ppv = &This->IMILBitmapSource_iface;
255 else
257 *ppv = NULL;
258 return E_NOINTERFACE;
261 IUnknown_AddRef((IUnknown*)*ppv);
262 return S_OK;
265 static ULONG WINAPI BitmapImpl_AddRef(IWICBitmap *iface)
267 BitmapImpl *This = impl_from_IWICBitmap(iface);
268 ULONG ref = InterlockedIncrement(&This->ref);
270 TRACE("(%p) refcount=%u\n", iface, ref);
272 return ref;
275 static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface)
277 BitmapImpl *This = impl_from_IWICBitmap(iface);
278 ULONG ref = InterlockedDecrement(&This->ref);
280 TRACE("(%p) refcount=%u\n", iface, ref);
282 if (ref == 0)
284 if (This->palette) IWICPalette_Release(This->palette);
285 This->cs.DebugInfo->Spare[0] = 0;
286 DeleteCriticalSection(&This->cs);
287 HeapFree(GetProcessHeap(), 0, This->data);
288 HeapFree(GetProcessHeap(), 0, This);
291 return ref;
294 static HRESULT WINAPI BitmapImpl_GetSize(IWICBitmap *iface,
295 UINT *puiWidth, UINT *puiHeight)
297 BitmapImpl *This = impl_from_IWICBitmap(iface);
298 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
300 if (!puiWidth || !puiHeight)
301 return E_INVALIDARG;
303 *puiWidth = This->width;
304 *puiHeight = This->height;
306 return S_OK;
309 static HRESULT WINAPI BitmapImpl_GetPixelFormat(IWICBitmap *iface,
310 WICPixelFormatGUID *pPixelFormat)
312 BitmapImpl *This = impl_from_IWICBitmap(iface);
313 TRACE("(%p,%p)\n", iface, pPixelFormat);
315 if (!pPixelFormat)
316 return E_INVALIDARG;
318 memcpy(pPixelFormat, &This->pixelformat, sizeof(GUID));
320 return S_OK;
323 static HRESULT WINAPI BitmapImpl_GetResolution(IWICBitmap *iface,
324 double *pDpiX, double *pDpiY)
326 BitmapImpl *This = impl_from_IWICBitmap(iface);
327 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
329 if (!pDpiX || !pDpiY)
330 return E_INVALIDARG;
332 EnterCriticalSection(&This->cs);
333 *pDpiX = This->dpix;
334 *pDpiY = This->dpiy;
335 LeaveCriticalSection(&This->cs);
337 return S_OK;
340 static HRESULT WINAPI BitmapImpl_CopyPalette(IWICBitmap *iface,
341 IWICPalette *pIPalette)
343 BitmapImpl *This = impl_from_IWICBitmap(iface);
344 TRACE("(%p,%p)\n", iface, pIPalette);
346 if (!This->palette_set)
347 return WINCODEC_ERR_PALETTEUNAVAILABLE;
349 return IWICPalette_InitializeFromPalette(pIPalette, This->palette);
352 static HRESULT WINAPI BitmapImpl_CopyPixels(IWICBitmap *iface,
353 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
355 BitmapImpl *This = impl_from_IWICBitmap(iface);
356 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
358 return copy_pixels(This->bpp, This->data, This->width, This->height,
359 This->stride, prc, cbStride, cbBufferSize, pbBuffer);
362 static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock,
363 DWORD flags, IWICBitmapLock **ppILock)
365 BitmapImpl *This = impl_from_IWICBitmap(iface);
366 BitmapLockImpl *result;
367 WICRect rc;
369 TRACE("(%p,%p,%x,%p)\n", iface, prcLock, flags, ppILock);
371 if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock)
372 return E_INVALIDARG;
374 if (!prcLock)
376 rc.X = rc.Y = 0;
377 rc.Width = This->width;
378 rc.Height = This->height;
379 prcLock = &rc;
381 else if (prcLock->X >= This->width || prcLock->Y >= This->height ||
382 prcLock->X + prcLock->Width > This->width ||
383 prcLock->Y + prcLock->Height > This->height ||
384 prcLock->Width <= 0 || prcLock->Height <= 0)
385 return E_INVALIDARG;
386 else if (((prcLock->X * This->bpp) % 8) != 0)
388 FIXME("Cannot lock at an X coordinate not at a full byte\n");
389 return E_FAIL;
392 result = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl));
393 if (!result)
394 return E_OUTOFMEMORY;
396 if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite))
398 HeapFree(GetProcessHeap(), 0, result);
399 return WINCODEC_ERR_ALREADYLOCKED;
402 result->IWICBitmapLock_iface.lpVtbl = &BitmapLockImpl_Vtbl;
403 result->ref = 1;
404 result->parent = This;
405 result->width = prcLock->Width;
406 result->height = prcLock->Height;
407 result->data = This->data + This->stride * prcLock->Y +
408 (This->bpp * prcLock->X)/8;
410 IWICBitmap_AddRef(&This->IWICBitmap_iface);
411 *ppILock = &result->IWICBitmapLock_iface;
413 return S_OK;
416 static HRESULT WINAPI BitmapImpl_SetPalette(IWICBitmap *iface, IWICPalette *pIPalette)
418 BitmapImpl *This = impl_from_IWICBitmap(iface);
419 HRESULT hr;
421 TRACE("(%p,%p)\n", iface, pIPalette);
423 if (!This->palette)
425 IWICPalette *new_palette;
426 hr = PaletteImpl_Create(&new_palette);
428 if (FAILED(hr)) return hr;
430 if (InterlockedCompareExchangePointer((void**)&This->palette, new_palette, NULL))
432 /* someone beat us to it */
433 IWICPalette_Release(new_palette);
437 hr = IWICPalette_InitializeFromPalette(This->palette, pIPalette);
439 if (SUCCEEDED(hr))
440 This->palette_set = 1;
442 return S_OK;
445 static HRESULT WINAPI BitmapImpl_SetResolution(IWICBitmap *iface,
446 double dpiX, double dpiY)
448 BitmapImpl *This = impl_from_IWICBitmap(iface);
449 TRACE("(%p,%f,%f)\n", iface, dpiX, dpiY);
451 EnterCriticalSection(&This->cs);
452 This->dpix = dpiX;
453 This->dpiy = dpiY;
454 LeaveCriticalSection(&This->cs);
456 return S_OK;
459 static const IWICBitmapVtbl BitmapImpl_Vtbl = {
460 BitmapImpl_QueryInterface,
461 BitmapImpl_AddRef,
462 BitmapImpl_Release,
463 BitmapImpl_GetSize,
464 BitmapImpl_GetPixelFormat,
465 BitmapImpl_GetResolution,
466 BitmapImpl_CopyPalette,
467 BitmapImpl_CopyPixels,
468 BitmapImpl_Lock,
469 BitmapImpl_SetPalette,
470 BitmapImpl_SetResolution
473 static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REFIID iid,
474 void **ppv)
476 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
477 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
479 if (!ppv) return E_INVALIDARG;
481 if (IsEqualIID(&IID_IUnknown, iid) ||
482 IsEqualIID(&IID_IMILBitmapSource, iid))
484 IUnknown_AddRef(&This->IMILBitmapSource_iface);
485 *ppv = &This->IMILBitmapSource_iface;
486 return S_OK;
489 *ppv = NULL;
490 return E_NOINTERFACE;
493 static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmapSource *iface)
495 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
496 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
499 static ULONG WINAPI IMILBitmapImpl_Release(IMILBitmapSource *iface)
501 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
502 return IWICBitmap_Release(&This->IWICBitmap_iface);
505 static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface,
506 UINT *width, UINT *height)
508 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
509 return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height);
512 static const struct
514 const GUID *WIC_format;
515 int enum_format;
516 } pixel_fmt_map[] =
518 { &GUID_WICPixelFormatDontCare, 0 },
519 { &GUID_WICPixelFormat1bppIndexed, 1 },
520 { &GUID_WICPixelFormat2bppIndexed, 2 },
521 { &GUID_WICPixelFormat4bppIndexed, 3 },
522 { &GUID_WICPixelFormat8bppIndexed, 4 },
523 { &GUID_WICPixelFormatBlackWhite, 5 },
524 { &GUID_WICPixelFormat2bppGray, 6 },
525 { &GUID_WICPixelFormat4bppGray, 7 },
526 { &GUID_WICPixelFormat8bppGray, 8 },
527 { &GUID_WICPixelFormat16bppBGR555, 9 },
528 { &GUID_WICPixelFormat16bppBGR565, 0x0a },
529 { &GUID_WICPixelFormat16bppGray, 0x0b },
530 { &GUID_WICPixelFormat24bppBGR, 0x0c },
531 { &GUID_WICPixelFormat24bppRGB, 0x0d },
532 { &GUID_WICPixelFormat32bppBGR, 0x0e },
533 { &GUID_WICPixelFormat32bppBGRA, 0x0f },
534 { &GUID_WICPixelFormat32bppPBGRA, 0x10 },
535 { &GUID_WICPixelFormat48bppRGB, 0x15 },
536 { &GUID_WICPixelFormat64bppRGBA, 0x16 },
537 { &GUID_WICPixelFormat64bppPRGBA, 0x17 },
538 { &GUID_WICPixelFormat32bppCMYK, 0x1c }
541 static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface,
542 int *format)
544 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
545 int i;
547 TRACE("(%p,%p)\n", iface, format);
549 if (!format) return E_INVALIDARG;
551 *format = 0;
553 for (i = 0; i < sizeof(pixel_fmt_map)/sizeof(pixel_fmt_map[0]); i++)
555 if (IsEqualGUID(pixel_fmt_map[i].WIC_format, &This->pixelformat))
557 *format = pixel_fmt_map[i].enum_format;
558 break;
562 return S_OK;
565 static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface,
566 double *dpix, double *dpiy)
568 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
569 return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy);
572 static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface,
573 IWICPalette *palette)
575 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
576 return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette);
579 static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface,
580 const WICRect *rc, UINT stride, UINT size, BYTE *buffer)
582 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
583 return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer);
586 static HRESULT WINAPI IMILBitmapImpl_UnknownMethod1(IMILBitmapSource *iface, void **ppv)
588 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
590 TRACE("(%p,%p)\n", iface, ppv);
592 if (!ppv) return E_INVALIDARG;
594 IUnknown_AddRef(&This->IMILUnknown1_iface);
595 *ppv = &This->IMILUnknown1_iface;
597 return S_OK;
600 static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl =
602 IMILBitmapImpl_QueryInterface,
603 IMILBitmapImpl_AddRef,
604 IMILBitmapImpl_Release,
605 IMILBitmapImpl_GetSize,
606 IMILBitmapImpl_GetPixelFormat,
607 IMILBitmapImpl_GetResolution,
608 IMILBitmapImpl_CopyPalette,
609 IMILBitmapImpl_CopyPixels,
610 IMILBitmapImpl_UnknownMethod1,
613 static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid,
614 void **ppv)
616 BitmapImpl *This = impl_from_IMILUnknown1(iface);
618 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
620 if (!ppv) return E_INVALIDARG;
622 if (IsEqualIID(&IID_IUnknown, iid))
624 IUnknown_AddRef(&This->IMILUnknown1_iface);
625 *ppv = iface;
626 return S_OK;
629 return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv);
632 static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface)
634 BitmapImpl *This = impl_from_IMILUnknown1(iface);
635 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
638 static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface)
640 BitmapImpl *This = impl_from_IMILUnknown1(iface);
641 return IWICBitmap_Release(&This->IWICBitmap_iface);
644 static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl =
646 IMILUnknown1Impl_QueryInterface,
647 IMILUnknown1Impl_AddRef,
648 IMILUnknown1Impl_Release,
651 static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid,
652 void **ppv)
654 BitmapImpl *This = impl_from_IMILUnknown2(iface);
656 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
658 if (!ppv) return E_INVALIDARG;
660 if (IsEqualIID(&IID_IUnknown, iid))
662 IUnknown_AddRef(&This->IMILUnknown2_iface);
663 *ppv = iface;
664 return S_OK;
667 return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv);
670 static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface)
672 BitmapImpl *This = impl_from_IMILUnknown2(iface);
673 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
676 static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface)
678 BitmapImpl *This = impl_from_IMILUnknown2(iface);
679 return IWICBitmap_Release(&This->IWICBitmap_iface);
682 static HRESULT WINAPI IMILUnknown2Impl_UnknownMethod1(IMILUnknown2 *iface, void *arg1, void *arg2)
684 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
685 return E_NOTIMPL;
688 static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl =
690 IMILUnknown2Impl_QueryInterface,
691 IMILUnknown2Impl_AddRef,
692 IMILUnknown2Impl_Release,
693 IMILUnknown2Impl_UnknownMethod1,
696 HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight,
697 UINT stride, UINT datasize, BYTE *bits,
698 REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option,
699 IWICBitmap **ppIBitmap)
701 HRESULT hr;
702 BitmapImpl *This;
703 BYTE *data;
704 UINT bpp;
706 hr = get_pixelformat_bpp(pixelFormat, &bpp);
707 if (FAILED(hr)) return hr;
709 if (!stride) stride = (((bpp*uiWidth)+31)/32)*4;
710 if (!datasize) datasize = stride * uiHeight;
712 if (datasize < stride * uiHeight) return WINCODEC_ERR_INSUFFICIENTBUFFER;
713 if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG;
715 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl));
716 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize);
717 if (!This || !data)
719 HeapFree(GetProcessHeap(), 0, This);
720 HeapFree(GetProcessHeap(), 0, data);
721 return E_OUTOFMEMORY;
723 if (bits) memcpy(data, bits, datasize);
725 This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl;
726 This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl;
727 This->IMILUnknown1_iface.lpVtbl = &IMILUnknown1Impl_Vtbl;
728 This->IMILUnknown2_iface.lpVtbl = &IMILUnknown2Impl_Vtbl;
729 This->ref = 1;
730 This->palette = NULL;
731 This->palette_set = 0;
732 This->lock = 0;
733 This->data = data;
734 This->width = uiWidth;
735 This->height = uiHeight;
736 This->stride = stride;
737 This->bpp = bpp;
738 memcpy(&This->pixelformat, pixelFormat, sizeof(GUID));
739 This->dpix = This->dpiy = 0.0;
740 InitializeCriticalSection(&This->cs);
741 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapImpl.lock");
743 *ppIBitmap = &This->IWICBitmap_iface;
745 return S_OK;