include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / windowscodecs / bitmap.c
blobe7d8b27d94ada009a70ed47ba5e1b626bd868974
1 /*
2 * Copyright 2012 Vincent Povirk for CodeWeavers
3 * Copyright 2016 Dmitry Timoshkov
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.
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.
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
20 #include <stdarg.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
28 #include "wincodecs_private.h"
30 #include "wine/asm.h"
31 #include "wine/debug.h"
33 #include "initguid.h"
34 DEFINE_GUID(IID_CMetaBitmapRenderTarget, 0x0ccd7824,0xdc16,0x4d09,0xbc,0xa8,0x6b,0x09,0xc4,0xef,0x55,0x35);
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
38 /* WARNING: .NET Media Integration Layer (MIL) directly dereferences
39 * BitmapImpl members and depends on its exact layout.
41 typedef struct BitmapImpl {
42 IMILUnknown1 IMILUnknown1_iface;
43 LONG ref;
44 IMILBitmap IMILBitmap_iface;
45 IWICBitmap IWICBitmap_iface;
46 IMILUnknown2 IMILUnknown2_iface;
47 IWICPalette *palette;
48 int palette_set;
49 LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */
50 BYTE *data;
51 void *view; /* used if data is a section created by an application */
52 UINT offset; /* offset into view */
53 UINT width, height;
54 UINT stride;
55 UINT bpp;
56 WICPixelFormatGUID pixelformat;
57 double dpix, dpiy;
58 CRITICAL_SECTION cs;
59 } BitmapImpl;
61 typedef struct BitmapLockImpl {
62 IWICBitmapLock IWICBitmapLock_iface;
63 LONG ref;
64 BitmapImpl *parent;
65 UINT width, height;
66 BYTE *data;
67 } BitmapLockImpl;
69 static inline BitmapImpl *impl_from_IWICBitmap(IWICBitmap *iface)
71 return CONTAINING_RECORD(iface, BitmapImpl, IWICBitmap_iface);
74 static inline BitmapImpl *impl_from_IMILBitmap(IMILBitmap *iface)
76 return CONTAINING_RECORD(iface, BitmapImpl, IMILBitmap_iface);
79 static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface)
81 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_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 FIXME("unknown interface %s\n", debugstr_guid(iid));
139 *ppv = NULL;
140 return E_NOINTERFACE;
143 IUnknown_AddRef((IUnknown*)*ppv);
144 return S_OK;
147 static ULONG WINAPI BitmapLockImpl_AddRef(IWICBitmapLock *iface)
149 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
150 ULONG ref = InterlockedIncrement(&This->ref);
152 TRACE("(%p) refcount=%lu\n", iface, ref);
154 return ref;
157 static ULONG WINAPI BitmapLockImpl_Release(IWICBitmapLock *iface)
159 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
160 ULONG ref = InterlockedDecrement(&This->ref);
162 TRACE("(%p) refcount=%lu\n", iface, ref);
164 if (ref == 0)
166 BitmapImpl_ReleaseLock(This->parent);
167 IWICBitmap_Release(&This->parent->IWICBitmap_iface);
168 free(This);
171 return ref;
174 static HRESULT WINAPI BitmapLockImpl_GetSize(IWICBitmapLock *iface,
175 UINT *puiWidth, UINT *puiHeight)
177 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
178 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
180 if (!puiWidth || !puiHeight)
181 return E_INVALIDARG;
183 *puiWidth = This->width;
184 *puiHeight = This->height;
186 return S_OK;
189 static HRESULT WINAPI BitmapLockImpl_GetStride(IWICBitmapLock *iface,
190 UINT *pcbStride)
192 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
193 TRACE("(%p,%p)\n", iface, pcbStride);
195 if (!pcbStride)
196 return E_INVALIDARG;
198 *pcbStride = This->parent->stride;
200 return S_OK;
203 static HRESULT WINAPI BitmapLockImpl_GetDataPointer(IWICBitmapLock *iface,
204 UINT *pcbBufferSize, BYTE **ppbData)
206 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
207 TRACE("(%p,%p,%p)\n", iface, pcbBufferSize, ppbData);
209 if (!pcbBufferSize || !ppbData)
210 return E_INVALIDARG;
212 *pcbBufferSize = This->parent->stride * (This->height - 1) +
213 ((This->parent->bpp * This->width) + 7)/8;
214 *ppbData = This->data;
216 return S_OK;
219 static HRESULT WINAPI BitmapLockImpl_GetPixelFormat(IWICBitmapLock *iface,
220 WICPixelFormatGUID *pPixelFormat)
222 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
223 TRACE("(%p,%p)\n", iface, pPixelFormat);
225 return IWICBitmap_GetPixelFormat(&This->parent->IWICBitmap_iface, pPixelFormat);
228 static const IWICBitmapLockVtbl BitmapLockImpl_Vtbl = {
229 BitmapLockImpl_QueryInterface,
230 BitmapLockImpl_AddRef,
231 BitmapLockImpl_Release,
232 BitmapLockImpl_GetSize,
233 BitmapLockImpl_GetStride,
234 BitmapLockImpl_GetDataPointer,
235 BitmapLockImpl_GetPixelFormat
238 static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid,
239 void **ppv)
241 BitmapImpl *This = impl_from_IWICBitmap(iface);
242 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
244 if (!ppv) return E_INVALIDARG;
246 if (IsEqualIID(&IID_IUnknown, iid) ||
247 IsEqualIID(&IID_IWICBitmapSource, iid) ||
248 IsEqualIID(&IID_IWICBitmap, iid))
250 *ppv = &This->IWICBitmap_iface;
252 else if (IsEqualIID(&IID_IMILBitmap, iid) ||
253 IsEqualIID(&IID_IMILBitmapSource, iid))
255 *ppv = &This->IMILBitmap_iface;
257 else
259 if (IsEqualIID(&IID_CMetaBitmapRenderTarget, iid))
260 WARN("Ignoring interface %s\n", debugstr_guid(iid));
261 else
262 FIXME("unknown interface %s\n", debugstr_guid(iid));
263 *ppv = NULL;
264 return E_NOINTERFACE;
267 IUnknown_AddRef((IUnknown*)*ppv);
268 return S_OK;
271 static ULONG WINAPI BitmapImpl_AddRef(IWICBitmap *iface)
273 BitmapImpl *This = impl_from_IWICBitmap(iface);
274 ULONG ref = InterlockedIncrement(&This->ref);
276 TRACE("(%p) refcount=%lu\n", iface, ref);
278 return ref;
281 static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface)
283 BitmapImpl *This = impl_from_IWICBitmap(iface);
284 ULONG ref = InterlockedDecrement(&This->ref);
286 TRACE("(%p) refcount=%lu\n", iface, ref);
288 if (ref == 0)
290 if (This->palette) IWICPalette_Release(This->palette);
291 This->cs.DebugInfo->Spare[0] = 0;
292 DeleteCriticalSection(&This->cs);
293 if (This->view)
294 UnmapViewOfFile(This->view);
295 else
296 free(This->data);
297 free(This);
300 return ref;
303 static HRESULT WINAPI BitmapImpl_GetSize(IWICBitmap *iface,
304 UINT *puiWidth, UINT *puiHeight)
306 BitmapImpl *This = impl_from_IWICBitmap(iface);
307 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
309 if (!puiWidth || !puiHeight)
310 return E_INVALIDARG;
312 *puiWidth = This->width;
313 *puiHeight = This->height;
315 return S_OK;
318 static HRESULT WINAPI BitmapImpl_GetPixelFormat(IWICBitmap *iface,
319 WICPixelFormatGUID *pPixelFormat)
321 BitmapImpl *This = impl_from_IWICBitmap(iface);
322 TRACE("(%p,%p)\n", iface, pPixelFormat);
324 if (!pPixelFormat)
325 return E_INVALIDARG;
327 memcpy(pPixelFormat, &This->pixelformat, sizeof(GUID));
329 return S_OK;
332 static HRESULT WINAPI BitmapImpl_GetResolution(IWICBitmap *iface,
333 double *pDpiX, double *pDpiY)
335 BitmapImpl *This = impl_from_IWICBitmap(iface);
336 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
338 if (!pDpiX || !pDpiY)
339 return E_INVALIDARG;
341 EnterCriticalSection(&This->cs);
342 *pDpiX = This->dpix;
343 *pDpiY = This->dpiy;
344 LeaveCriticalSection(&This->cs);
346 return S_OK;
349 static HRESULT WINAPI BitmapImpl_CopyPalette(IWICBitmap *iface,
350 IWICPalette *pIPalette)
352 BitmapImpl *This = impl_from_IWICBitmap(iface);
353 TRACE("(%p,%p)\n", iface, pIPalette);
355 if (!This->palette_set)
356 return WINCODEC_ERR_PALETTEUNAVAILABLE;
358 return IWICPalette_InitializeFromPalette(pIPalette, This->palette);
361 static HRESULT WINAPI BitmapImpl_CopyPixels(IWICBitmap *iface,
362 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
364 BitmapImpl *This = impl_from_IWICBitmap(iface);
365 TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
367 return copy_pixels(This->bpp, This->data, This->width, This->height,
368 This->stride, prc, cbStride, cbBufferSize, pbBuffer);
371 static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock,
372 DWORD flags, IWICBitmapLock **ppILock)
374 BitmapImpl *This = impl_from_IWICBitmap(iface);
375 BitmapLockImpl *result;
376 WICRect rc;
378 TRACE("(%p,%s,%lx,%p)\n", iface, debug_wic_rect(prcLock), flags, ppILock);
380 if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock)
381 return E_INVALIDARG;
383 if (!prcLock)
385 rc.X = rc.Y = 0;
386 rc.Width = This->width;
387 rc.Height = This->height;
388 prcLock = &rc;
390 else if (prcLock->X >= This->width || prcLock->Y >= This->height ||
391 prcLock->X + prcLock->Width > This->width ||
392 prcLock->Y + prcLock->Height > This->height ||
393 prcLock->Width <= 0 || prcLock->Height <= 0)
394 return E_INVALIDARG;
395 else if (((prcLock->X * This->bpp) % 8) != 0)
397 FIXME("Cannot lock at an X coordinate not at a full byte\n");
398 return E_FAIL;
401 result = malloc(sizeof(BitmapLockImpl));
402 if (!result)
403 return E_OUTOFMEMORY;
405 if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite))
407 free(result);
408 return WINCODEC_ERR_ALREADYLOCKED;
411 result->IWICBitmapLock_iface.lpVtbl = &BitmapLockImpl_Vtbl;
412 result->ref = 1;
413 result->parent = This;
414 result->width = prcLock->Width;
415 result->height = prcLock->Height;
416 result->data = This->data + This->stride * prcLock->Y +
417 (This->bpp * prcLock->X)/8;
419 IWICBitmap_AddRef(&This->IWICBitmap_iface);
420 *ppILock = &result->IWICBitmapLock_iface;
422 return S_OK;
425 static HRESULT WINAPI BitmapImpl_SetPalette(IWICBitmap *iface, IWICPalette *pIPalette)
427 BitmapImpl *This = impl_from_IWICBitmap(iface);
428 HRESULT hr;
430 TRACE("(%p,%p)\n", iface, pIPalette);
432 if (!This->palette)
434 IWICPalette *new_palette;
435 hr = PaletteImpl_Create(&new_palette);
437 if (FAILED(hr)) return hr;
439 if (InterlockedCompareExchangePointer((void**)&This->palette, new_palette, NULL))
441 /* someone beat us to it */
442 IWICPalette_Release(new_palette);
446 hr = IWICPalette_InitializeFromPalette(This->palette, pIPalette);
448 if (SUCCEEDED(hr))
449 This->palette_set = 1;
451 return S_OK;
454 static HRESULT WINAPI BitmapImpl_SetResolution(IWICBitmap *iface,
455 double dpiX, double dpiY)
457 BitmapImpl *This = impl_from_IWICBitmap(iface);
458 TRACE("(%p,%f,%f)\n", iface, dpiX, dpiY);
460 EnterCriticalSection(&This->cs);
461 This->dpix = dpiX;
462 This->dpiy = dpiY;
463 LeaveCriticalSection(&This->cs);
465 return S_OK;
468 static const IWICBitmapVtbl BitmapImpl_Vtbl = {
469 BitmapImpl_QueryInterface,
470 BitmapImpl_AddRef,
471 BitmapImpl_Release,
472 BitmapImpl_GetSize,
473 BitmapImpl_GetPixelFormat,
474 BitmapImpl_GetResolution,
475 BitmapImpl_CopyPalette,
476 BitmapImpl_CopyPixels,
477 BitmapImpl_Lock,
478 BitmapImpl_SetPalette,
479 BitmapImpl_SetResolution
482 static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmap *iface, REFIID iid,
483 void **ppv)
485 BitmapImpl *This = impl_from_IMILBitmap(iface);
486 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
487 return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv);
490 static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmap *iface)
492 BitmapImpl *This = impl_from_IMILBitmap(iface);
493 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
496 static ULONG WINAPI IMILBitmapImpl_Release(IMILBitmap *iface)
498 BitmapImpl *This = impl_from_IMILBitmap(iface);
499 return IWICBitmap_Release(&This->IWICBitmap_iface);
502 static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmap *iface,
503 UINT *width, UINT *height)
505 BitmapImpl *This = impl_from_IMILBitmap(iface);
506 TRACE("(%p,%p,%p)\n", iface, width, height);
507 return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height);
510 static const struct
512 const GUID *WIC_format;
513 int enum_format;
514 } pixel_fmt_map[] =
516 { &GUID_WICPixelFormatDontCare, 0 },
517 { &GUID_WICPixelFormat1bppIndexed, 1 },
518 { &GUID_WICPixelFormat2bppIndexed, 2 },
519 { &GUID_WICPixelFormat4bppIndexed, 3 },
520 { &GUID_WICPixelFormat8bppIndexed, 4 },
521 { &GUID_WICPixelFormatBlackWhite, 5 },
522 { &GUID_WICPixelFormat2bppGray, 6 },
523 { &GUID_WICPixelFormat4bppGray, 7 },
524 { &GUID_WICPixelFormat8bppGray, 8 },
525 { &GUID_WICPixelFormat16bppBGR555, 9 },
526 { &GUID_WICPixelFormat16bppBGR565, 0x0a },
527 { &GUID_WICPixelFormat16bppGray, 0x0b },
528 { &GUID_WICPixelFormat24bppBGR, 0x0c },
529 { &GUID_WICPixelFormat24bppRGB, 0x0d },
530 { &GUID_WICPixelFormat32bppBGR, 0x0e },
531 { &GUID_WICPixelFormat32bppBGRA, 0x0f },
532 { &GUID_WICPixelFormat32bppPBGRA, 0x10 },
533 { &GUID_WICPixelFormat48bppRGB, 0x15 },
534 { &GUID_WICPixelFormat64bppRGBA, 0x16 },
535 { &GUID_WICPixelFormat64bppPRGBA, 0x17 },
536 { &GUID_WICPixelFormat32bppCMYK, 0x1c }
539 static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmap *iface,
540 int *format)
542 BitmapImpl *This = impl_from_IMILBitmap(iface);
543 int i;
545 TRACE("(%p,%p)\n", iface, format);
547 if (!format) return E_INVALIDARG;
549 *format = 0;
551 for (i = 0; i < ARRAY_SIZE(pixel_fmt_map); i++)
553 if (IsEqualGUID(pixel_fmt_map[i].WIC_format, &This->pixelformat))
555 *format = pixel_fmt_map[i].enum_format;
556 break;
560 TRACE("=> %u\n", *format);
561 return S_OK;
564 static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmap *iface,
565 double *dpix, double *dpiy)
567 BitmapImpl *This = impl_from_IMILBitmap(iface);
568 TRACE("(%p,%p,%p)\n", iface, dpix, dpiy);
569 return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy);
572 static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmap *iface,
573 IWICPalette *palette)
575 BitmapImpl *This = impl_from_IMILBitmap(iface);
576 TRACE("(%p,%p)\n", iface, palette);
577 return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette);
580 static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmap *iface,
581 const WICRect *rc, UINT stride, UINT size, BYTE *buffer)
583 BitmapImpl *This = impl_from_IMILBitmap(iface);
584 TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer);
585 return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer);
588 static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmap *iface, void **ppv)
590 BitmapImpl *This = impl_from_IMILBitmap(iface);
592 TRACE("(%p,%p)\n", iface, ppv);
594 if (!ppv) return E_INVALIDARG;
596 /* reference count is not incremented here */
597 *ppv = &This->IMILUnknown1_iface;
599 return S_OK;
602 static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmap *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock)
604 BitmapImpl *This = impl_from_IMILBitmap(iface);
605 TRACE("(%p,%p,%08lx,%p)\n", iface, rc, flags, lock);
606 return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock);
609 static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmap *iface, IWICBitmapLock *lock)
611 TRACE("(%p,%p)\n", iface, lock);
612 IWICBitmapLock_Release(lock);
613 return S_OK;
616 static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmap *iface, IWICPalette *palette)
618 BitmapImpl *This = impl_from_IMILBitmap(iface);
619 TRACE("(%p,%p)\n", iface, palette);
620 return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette);
623 static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmap *iface, double dpix, double dpiy)
625 BitmapImpl *This = impl_from_IMILBitmap(iface);
626 TRACE("(%p,%f,%f)\n", iface, dpix, dpiy);
627 return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy);
630 static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmap *iface, const WICRect *rc)
632 FIXME("(%p,%p): stub\n", iface, rc);
633 return E_NOTIMPL;
636 static const IMILBitmapVtbl IMILBitmapImpl_Vtbl =
638 IMILBitmapImpl_QueryInterface,
639 IMILBitmapImpl_AddRef,
640 IMILBitmapImpl_Release,
641 IMILBitmapImpl_GetSize,
642 IMILBitmapImpl_GetPixelFormat,
643 IMILBitmapImpl_GetResolution,
644 IMILBitmapImpl_CopyPalette,
645 IMILBitmapImpl_CopyPixels,
646 IMILBitmapImpl_unknown1,
647 IMILBitmapImpl_Lock,
648 IMILBitmapImpl_Unlock,
649 IMILBitmapImpl_SetPalette,
650 IMILBitmapImpl_SetResolution,
651 IMILBitmapImpl_AddDirtyRect
654 static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid,
655 void **ppv)
657 /* It's not clear what interface should be returned here */
658 FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv);
659 *ppv = NULL;
660 return E_NOINTERFACE;
663 static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface)
665 BitmapImpl *This = impl_from_IMILUnknown1(iface);
666 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
669 static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface)
671 BitmapImpl *This = impl_from_IMILUnknown1(iface);
672 return IWICBitmap_Release(&This->IWICBitmap_iface);
675 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8)
676 void __thiscall IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg)
678 FIXME("(%p,%p): stub\n", iface, arg);
681 static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, void *arg2)
683 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
684 return E_NOTIMPL;
687 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8)
688 HRESULT __thiscall IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg)
690 FIXME("(%p,%p): stub\n", iface, arg);
691 return E_NOTIMPL;
694 static HRESULT WINAPI IMILUnknown1Impl_unknown4(IMILUnknown1 *iface, void *arg)
696 FIXME("(%p,%p): stub\n", iface, arg);
697 return E_NOTIMPL;
700 static HRESULT WINAPI IMILUnknown1Impl_unknown5(IMILUnknown1 *iface, void *arg)
702 FIXME("(%p,%p): stub\n", iface, arg);
703 return E_NOTIMPL;
706 static HRESULT WINAPI IMILUnknown1Impl_unknown6(IMILUnknown1 *iface, DWORD64 arg)
708 FIXME("(%p,%s): stub\n", iface, wine_dbgstr_longlong(arg));
709 return E_NOTIMPL;
712 static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg)
714 FIXME("(%p,%p): stub\n", iface, arg);
715 return E_NOTIMPL;
718 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4)
719 HRESULT __thiscall IMILUnknown1Impl_unknown8(IMILUnknown1 *iface)
721 FIXME("(%p): stub\n", iface);
722 return E_NOTIMPL;
725 static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl =
727 IMILUnknown1Impl_QueryInterface,
728 IMILUnknown1Impl_AddRef,
729 IMILUnknown1Impl_Release,
730 THISCALL(IMILUnknown1Impl_unknown1),
731 IMILUnknown1Impl_unknown2,
732 THISCALL(IMILUnknown1Impl_unknown3),
733 IMILUnknown1Impl_unknown4,
734 IMILUnknown1Impl_unknown5,
735 IMILUnknown1Impl_unknown6,
736 IMILUnknown1Impl_unknown7,
737 THISCALL(IMILUnknown1Impl_unknown8)
740 static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid,
741 void **ppv)
743 FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv);
744 *ppv = NULL;
745 return E_NOINTERFACE;
748 static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface)
750 FIXME("(%p): stub\n", iface);
751 return 0;
754 static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface)
756 FIXME("(%p): stub\n", iface);
757 return 0;
760 static HRESULT WINAPI IMILUnknown2Impl_unknown1(IMILUnknown2 *iface, void *arg1, void **arg2)
762 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
763 if (arg2) *arg2 = NULL;
764 return E_NOTIMPL;
767 static HRESULT WINAPI IMILUnknown2Impl_unknown2(IMILUnknown2 *iface, void *arg1, void *arg2)
769 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
770 return E_NOTIMPL;
773 static HRESULT WINAPI IMILUnknown2Impl_unknown3(IMILUnknown2 *iface, void *arg1)
775 FIXME("(%p,%p): stub\n", iface, arg1);
776 return E_NOTIMPL;
779 static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl =
781 IMILUnknown2Impl_QueryInterface,
782 IMILUnknown2Impl_AddRef,
783 IMILUnknown2Impl_Release,
784 IMILUnknown2Impl_unknown1,
785 IMILUnknown2Impl_unknown2,
786 IMILUnknown2Impl_unknown3
789 HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride, UINT datasize, void *view,
790 UINT offset, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option,
791 IWICBitmap **ppIBitmap)
793 HRESULT hr;
794 BitmapImpl *This;
795 BYTE *data;
796 UINT bpp;
798 hr = get_pixelformat_bpp(pixelFormat, &bpp);
799 if (FAILED(hr)) return hr;
801 if (!stride) stride = (((bpp*uiWidth)+31)/32)*4;
802 if (!datasize) datasize = stride * uiHeight;
804 if (datasize < stride * uiHeight) return WINCODEC_ERR_INSUFFICIENTBUFFER;
805 if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG;
807 This = malloc(sizeof(BitmapImpl));
808 if (!This) return E_OUTOFMEMORY;
810 if (view) data = (BYTE *)view + offset;
811 else if (!(data = calloc(1, datasize)))
813 free(This);
814 return E_OUTOFMEMORY;
817 This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl;
818 This->IMILBitmap_iface.lpVtbl = &IMILBitmapImpl_Vtbl;
819 This->IMILUnknown1_iface.lpVtbl = &IMILUnknown1Impl_Vtbl;
820 This->IMILUnknown2_iface.lpVtbl = &IMILUnknown2Impl_Vtbl;
821 This->ref = 1;
822 This->palette = NULL;
823 This->palette_set = 0;
824 This->lock = 0;
825 This->data = data;
826 This->view = view;
827 This->offset = offset;
828 This->width = uiWidth;
829 This->height = uiHeight;
830 This->stride = stride;
831 This->bpp = bpp;
832 memcpy(&This->pixelformat, pixelFormat, sizeof(GUID));
833 This->dpix = This->dpiy = 0.0;
834 InitializeCriticalSectionEx(&This->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO);
835 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapImpl.lock");
837 *ppIBitmap = &This->IWICBitmap_iface;
839 return S_OK;