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
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
;
41 IMILBitmapSource IMILBitmapSource_iface
;
42 IWICBitmap IWICBitmap_iface
;
43 IMILUnknown2 IMILUnknown2_iface
;
46 LONG lock
; /* 0 if not locked, -1 if locked for writing, count if locked for reading */
51 WICPixelFormatGUID pixelformat
;
56 typedef struct BitmapLockImpl
{
57 IWICBitmapLock IWICBitmapLock_iface
;
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
)
93 return 0 == InterlockedCompareExchange(&This
->lock
, -1, 0);
99 LONG prev_val
= This
->lock
;
102 if (prev_val
== InterlockedCompareExchange(&This
->lock
, prev_val
+1, prev_val
))
108 static void BitmapImpl_ReleaseLock(BitmapImpl
*This
)
112 LONG prev_val
= This
->lock
, new_val
;
116 new_val
= prev_val
- 1;
117 if (prev_val
== InterlockedCompareExchange(&This
->lock
, new_val
, prev_val
))
123 static HRESULT WINAPI
BitmapLockImpl_QueryInterface(IWICBitmapLock
*iface
, REFIID iid
,
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
;
139 return E_NOINTERFACE
;
142 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
165 BitmapImpl_ReleaseLock(This
->parent
);
166 IWICBitmap_Release(&This
->parent
->IWICBitmap_iface
);
167 HeapFree(GetProcessHeap(), 0, This
);
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
)
182 *puiWidth
= This
->width
;
183 *puiHeight
= This
->height
;
188 static HRESULT WINAPI
BitmapLockImpl_GetStride(IWICBitmapLock
*iface
,
191 BitmapLockImpl
*This
= impl_from_IWICBitmapLock(iface
);
192 TRACE("(%p,%p)\n", iface
, pcbStride
);
197 *pcbStride
= This
->parent
->stride
;
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
)
211 *pcbBufferSize
= This
->parent
->stride
* (This
->height
- 1) +
212 ((This
->parent
->bpp
* This
->width
) + 7)/8;
213 *ppbData
= This
->data
;
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
,
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
;
258 return E_NOINTERFACE
;
261 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
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
);
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
)
303 *puiWidth
= This
->width
;
304 *puiHeight
= This
->height
;
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
);
318 memcpy(pPixelFormat
, &This
->pixelformat
, sizeof(GUID
));
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
)
332 EnterCriticalSection(&This
->cs
);
335 LeaveCriticalSection(&This
->cs
);
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
;
369 TRACE("(%p,%p,%x,%p)\n", iface
, prcLock
, flags
, ppILock
);
371 if (!(flags
& (WICBitmapLockRead
|WICBitmapLockWrite
)) || !ppILock
)
377 rc
.Width
= This
->width
;
378 rc
.Height
= This
->height
;
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)
386 else if (((prcLock
->X
* This
->bpp
) % 8) != 0)
388 FIXME("Cannot lock at an X coordinate not at a full byte\n");
392 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl
));
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
;
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
;
416 static HRESULT WINAPI
BitmapImpl_SetPalette(IWICBitmap
*iface
, IWICPalette
*pIPalette
)
418 BitmapImpl
*This
= impl_from_IWICBitmap(iface
);
421 TRACE("(%p,%p)\n", iface
, pIPalette
);
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
);
440 This
->palette_set
= 1;
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
);
454 LeaveCriticalSection(&This
->cs
);
459 static const IWICBitmapVtbl BitmapImpl_Vtbl
= {
460 BitmapImpl_QueryInterface
,
464 BitmapImpl_GetPixelFormat
,
465 BitmapImpl_GetResolution
,
466 BitmapImpl_CopyPalette
,
467 BitmapImpl_CopyPixels
,
469 BitmapImpl_SetPalette
,
470 BitmapImpl_SetResolution
473 static HRESULT WINAPI
IMILBitmapImpl_QueryInterface(IMILBitmapSource
*iface
, REFIID iid
,
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
;
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
);
514 const GUID
*WIC_format
;
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
,
544 BitmapImpl
*This
= impl_from_IMILBitmapSource(iface
);
547 TRACE("(%p,%p)\n", iface
, format
);
549 if (!format
) return E_INVALIDARG
;
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
;
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
;
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
,
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
);
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
,
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
);
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
);
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
)
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
);
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
;
730 This
->palette
= NULL
;
731 This
->palette_set
= 0;
734 This
->width
= uiWidth
;
735 This
->height
= uiHeight
;
736 This
->stride
= stride
;
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
;