[ADVAPI32_APITEST][NTDLL_APITEST][WINDOWSCODECS] Comment out some unused functions...
[reactos.git] / dll / win32 / windowscodecs / bitmap.c
1 /*
2 * Copyright 2012 Vincent Povirk for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include "wincodecs_private.h"
20
21 /* WARNING: .NET Media Integration Layer (MIL) directly dereferences
22 * BitmapImpl members and depends on its exact layout.
23 */
24 typedef struct BitmapImpl {
25 IMILUnknown1 IMILUnknown1_iface;
26 LONG ref;
27 IMILBitmapSource IMILBitmapSource_iface;
28 IWICBitmap IWICBitmap_iface;
29 IMILUnknown2 IMILUnknown2_iface;
30 IWICPalette *palette;
31 int palette_set;
32 LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */
33 BYTE *data;
34 BOOL is_section; /* TRUE if data is a section created by an application */
35 UINT width, height;
36 UINT stride;
37 UINT bpp;
38 WICPixelFormatGUID pixelformat;
39 double dpix, dpiy;
40 CRITICAL_SECTION cs;
41 } BitmapImpl;
42
43 typedef struct BitmapLockImpl {
44 IWICBitmapLock IWICBitmapLock_iface;
45 LONG ref;
46 BitmapImpl *parent;
47 UINT width, height;
48 BYTE *data;
49 } BitmapLockImpl;
50
51 static inline BitmapImpl *impl_from_IWICBitmap(IWICBitmap *iface)
52 {
53 return CONTAINING_RECORD(iface, BitmapImpl, IWICBitmap_iface);
54 }
55
56 static inline BitmapImpl *impl_from_IMILBitmapSource(IMILBitmapSource *iface)
57 {
58 return CONTAINING_RECORD(iface, BitmapImpl, IMILBitmapSource_iface);
59 }
60
61 static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface)
62 {
63 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_iface);
64 }
65
66 #ifndef __REACTOS__
67 /* This is currently unused */
68 static inline BitmapImpl *impl_from_IMILUnknown2(IMILUnknown2 *iface)
69 {
70 return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown2_iface);
71 }
72 #endif
73
74 static inline BitmapLockImpl *impl_from_IWICBitmapLock(IWICBitmapLock *iface)
75 {
76 return CONTAINING_RECORD(iface, BitmapLockImpl, IWICBitmapLock_iface);
77 }
78
79 static BOOL BitmapImpl_AcquireLock(BitmapImpl *This, int write)
80 {
81 if (write)
82 {
83 return 0 == InterlockedCompareExchange(&This->lock, -1, 0);
84 }
85 else
86 {
87 while (1)
88 {
89 LONG prev_val = This->lock;
90 if (prev_val == -1)
91 return FALSE;
92 if (prev_val == InterlockedCompareExchange(&This->lock, prev_val+1, prev_val))
93 return TRUE;
94 }
95 }
96 }
97
98 static void BitmapImpl_ReleaseLock(BitmapImpl *This)
99 {
100 while (1)
101 {
102 LONG prev_val = This->lock, new_val;
103 if (prev_val == -1)
104 new_val = 0;
105 else
106 new_val = prev_val - 1;
107 if (prev_val == InterlockedCompareExchange(&This->lock, new_val, prev_val))
108 break;
109 }
110 }
111
112
113 static HRESULT WINAPI BitmapLockImpl_QueryInterface(IWICBitmapLock *iface, REFIID iid,
114 void **ppv)
115 {
116 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
117 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
118
119 if (!ppv) return E_INVALIDARG;
120
121 if (IsEqualIID(&IID_IUnknown, iid) ||
122 IsEqualIID(&IID_IWICBitmapLock, iid))
123 {
124 *ppv = &This->IWICBitmapLock_iface;
125 }
126 else
127 {
128 FIXME("unknown interface %s\n", debugstr_guid(iid));
129 *ppv = NULL;
130 return E_NOINTERFACE;
131 }
132
133 IUnknown_AddRef((IUnknown*)*ppv);
134 return S_OK;
135 }
136
137 static ULONG WINAPI BitmapLockImpl_AddRef(IWICBitmapLock *iface)
138 {
139 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
140 ULONG ref = InterlockedIncrement(&This->ref);
141
142 TRACE("(%p) refcount=%u\n", iface, ref);
143
144 return ref;
145 }
146
147 static ULONG WINAPI BitmapLockImpl_Release(IWICBitmapLock *iface)
148 {
149 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
150 ULONG ref = InterlockedDecrement(&This->ref);
151
152 TRACE("(%p) refcount=%u\n", iface, ref);
153
154 if (ref == 0)
155 {
156 BitmapImpl_ReleaseLock(This->parent);
157 IWICBitmap_Release(&This->parent->IWICBitmap_iface);
158 HeapFree(GetProcessHeap(), 0, This);
159 }
160
161 return ref;
162 }
163
164 static HRESULT WINAPI BitmapLockImpl_GetSize(IWICBitmapLock *iface,
165 UINT *puiWidth, UINT *puiHeight)
166 {
167 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
168 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
169
170 if (!puiWidth || !puiHeight)
171 return E_INVALIDARG;
172
173 *puiWidth = This->width;
174 *puiHeight = This->height;
175
176 return S_OK;
177 }
178
179 static HRESULT WINAPI BitmapLockImpl_GetStride(IWICBitmapLock *iface,
180 UINT *pcbStride)
181 {
182 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
183 TRACE("(%p,%p)\n", iface, pcbStride);
184
185 if (!pcbStride)
186 return E_INVALIDARG;
187
188 *pcbStride = This->parent->stride;
189
190 return S_OK;
191 }
192
193 static HRESULT WINAPI BitmapLockImpl_GetDataPointer(IWICBitmapLock *iface,
194 UINT *pcbBufferSize, BYTE **ppbData)
195 {
196 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
197 TRACE("(%p,%p,%p)\n", iface, pcbBufferSize, ppbData);
198
199 if (!pcbBufferSize || !ppbData)
200 return E_INVALIDARG;
201
202 *pcbBufferSize = This->parent->stride * (This->height - 1) +
203 ((This->parent->bpp * This->width) + 7)/8;
204 *ppbData = This->data;
205
206 return S_OK;
207 }
208
209 static HRESULT WINAPI BitmapLockImpl_GetPixelFormat(IWICBitmapLock *iface,
210 WICPixelFormatGUID *pPixelFormat)
211 {
212 BitmapLockImpl *This = impl_from_IWICBitmapLock(iface);
213 TRACE("(%p,%p)\n", iface, pPixelFormat);
214
215 return IWICBitmap_GetPixelFormat(&This->parent->IWICBitmap_iface, pPixelFormat);
216 }
217
218 static const IWICBitmapLockVtbl BitmapLockImpl_Vtbl = {
219 BitmapLockImpl_QueryInterface,
220 BitmapLockImpl_AddRef,
221 BitmapLockImpl_Release,
222 BitmapLockImpl_GetSize,
223 BitmapLockImpl_GetStride,
224 BitmapLockImpl_GetDataPointer,
225 BitmapLockImpl_GetPixelFormat
226 };
227
228 static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid,
229 void **ppv)
230 {
231 BitmapImpl *This = impl_from_IWICBitmap(iface);
232 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
233
234 if (!ppv) return E_INVALIDARG;
235
236 if (IsEqualIID(&IID_IUnknown, iid) ||
237 IsEqualIID(&IID_IWICBitmapSource, iid) ||
238 IsEqualIID(&IID_IWICBitmap, iid))
239 {
240 *ppv = &This->IWICBitmap_iface;
241 }
242 else if (IsEqualIID(&IID_IMILBitmap, iid) ||
243 IsEqualIID(&IID_IMILBitmapSource, iid))
244 {
245 *ppv = &This->IMILBitmapSource_iface;
246 }
247 else
248 {
249 FIXME("unknown interface %s\n", debugstr_guid(iid));
250 *ppv = NULL;
251 return E_NOINTERFACE;
252 }
253
254 IUnknown_AddRef((IUnknown*)*ppv);
255 return S_OK;
256 }
257
258 static ULONG WINAPI BitmapImpl_AddRef(IWICBitmap *iface)
259 {
260 BitmapImpl *This = impl_from_IWICBitmap(iface);
261 ULONG ref = InterlockedIncrement(&This->ref);
262
263 TRACE("(%p) refcount=%u\n", iface, ref);
264
265 return ref;
266 }
267
268 static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface)
269 {
270 BitmapImpl *This = impl_from_IWICBitmap(iface);
271 ULONG ref = InterlockedDecrement(&This->ref);
272
273 TRACE("(%p) refcount=%u\n", iface, ref);
274
275 if (ref == 0)
276 {
277 if (This->palette) IWICPalette_Release(This->palette);
278 This->cs.DebugInfo->Spare[0] = 0;
279 DeleteCriticalSection(&This->cs);
280 if (This->is_section)
281 UnmapViewOfFile(This->data);
282 else
283 HeapFree(GetProcessHeap(), 0, This->data);
284 HeapFree(GetProcessHeap(), 0, This);
285 }
286
287 return ref;
288 }
289
290 static HRESULT WINAPI BitmapImpl_GetSize(IWICBitmap *iface,
291 UINT *puiWidth, UINT *puiHeight)
292 {
293 BitmapImpl *This = impl_from_IWICBitmap(iface);
294 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
295
296 if (!puiWidth || !puiHeight)
297 return E_INVALIDARG;
298
299 *puiWidth = This->width;
300 *puiHeight = This->height;
301
302 return S_OK;
303 }
304
305 static HRESULT WINAPI BitmapImpl_GetPixelFormat(IWICBitmap *iface,
306 WICPixelFormatGUID *pPixelFormat)
307 {
308 BitmapImpl *This = impl_from_IWICBitmap(iface);
309 TRACE("(%p,%p)\n", iface, pPixelFormat);
310
311 if (!pPixelFormat)
312 return E_INVALIDARG;
313
314 memcpy(pPixelFormat, &This->pixelformat, sizeof(GUID));
315
316 return S_OK;
317 }
318
319 static HRESULT WINAPI BitmapImpl_GetResolution(IWICBitmap *iface,
320 double *pDpiX, double *pDpiY)
321 {
322 BitmapImpl *This = impl_from_IWICBitmap(iface);
323 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
324
325 if (!pDpiX || !pDpiY)
326 return E_INVALIDARG;
327
328 EnterCriticalSection(&This->cs);
329 *pDpiX = This->dpix;
330 *pDpiY = This->dpiy;
331 LeaveCriticalSection(&This->cs);
332
333 return S_OK;
334 }
335
336 static HRESULT WINAPI BitmapImpl_CopyPalette(IWICBitmap *iface,
337 IWICPalette *pIPalette)
338 {
339 BitmapImpl *This = impl_from_IWICBitmap(iface);
340 TRACE("(%p,%p)\n", iface, pIPalette);
341
342 if (!This->palette_set)
343 return WINCODEC_ERR_PALETTEUNAVAILABLE;
344
345 return IWICPalette_InitializeFromPalette(pIPalette, This->palette);
346 }
347
348 static HRESULT WINAPI BitmapImpl_CopyPixels(IWICBitmap *iface,
349 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
350 {
351 BitmapImpl *This = impl_from_IWICBitmap(iface);
352 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
353
354 return copy_pixels(This->bpp, This->data, This->width, This->height,
355 This->stride, prc, cbStride, cbBufferSize, pbBuffer);
356 }
357
358 static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock,
359 DWORD flags, IWICBitmapLock **ppILock)
360 {
361 BitmapImpl *This = impl_from_IWICBitmap(iface);
362 BitmapLockImpl *result;
363 WICRect rc;
364
365 TRACE("(%p,%p,%x,%p)\n", iface, prcLock, flags, ppILock);
366
367 if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock)
368 return E_INVALIDARG;
369
370 if (!prcLock)
371 {
372 rc.X = rc.Y = 0;
373 rc.Width = This->width;
374 rc.Height = This->height;
375 prcLock = &rc;
376 }
377 else if (prcLock->X >= This->width || prcLock->Y >= This->height ||
378 prcLock->X + prcLock->Width > This->width ||
379 prcLock->Y + prcLock->Height > This->height ||
380 prcLock->Width <= 0 || prcLock->Height <= 0)
381 return E_INVALIDARG;
382 else if (((prcLock->X * This->bpp) % 8) != 0)
383 {
384 FIXME("Cannot lock at an X coordinate not at a full byte\n");
385 return E_FAIL;
386 }
387
388 result = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl));
389 if (!result)
390 return E_OUTOFMEMORY;
391
392 if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite))
393 {
394 HeapFree(GetProcessHeap(), 0, result);
395 return WINCODEC_ERR_ALREADYLOCKED;
396 }
397
398 result->IWICBitmapLock_iface.lpVtbl = &BitmapLockImpl_Vtbl;
399 result->ref = 1;
400 result->parent = This;
401 result->width = prcLock->Width;
402 result->height = prcLock->Height;
403 result->data = This->data + This->stride * prcLock->Y +
404 (This->bpp * prcLock->X)/8;
405
406 IWICBitmap_AddRef(&This->IWICBitmap_iface);
407 *ppILock = &result->IWICBitmapLock_iface;
408
409 return S_OK;
410 }
411
412 static HRESULT WINAPI BitmapImpl_SetPalette(IWICBitmap *iface, IWICPalette *pIPalette)
413 {
414 BitmapImpl *This = impl_from_IWICBitmap(iface);
415 HRESULT hr;
416
417 TRACE("(%p,%p)\n", iface, pIPalette);
418
419 if (!This->palette)
420 {
421 IWICPalette *new_palette;
422 hr = PaletteImpl_Create(&new_palette);
423
424 if (FAILED(hr)) return hr;
425
426 if (InterlockedCompareExchangePointer((void**)&This->palette, new_palette, NULL))
427 {
428 /* someone beat us to it */
429 IWICPalette_Release(new_palette);
430 }
431 }
432
433 hr = IWICPalette_InitializeFromPalette(This->palette, pIPalette);
434
435 if (SUCCEEDED(hr))
436 This->palette_set = 1;
437
438 return S_OK;
439 }
440
441 static HRESULT WINAPI BitmapImpl_SetResolution(IWICBitmap *iface,
442 double dpiX, double dpiY)
443 {
444 BitmapImpl *This = impl_from_IWICBitmap(iface);
445 TRACE("(%p,%f,%f)\n", iface, dpiX, dpiY);
446
447 EnterCriticalSection(&This->cs);
448 This->dpix = dpiX;
449 This->dpiy = dpiY;
450 LeaveCriticalSection(&This->cs);
451
452 return S_OK;
453 }
454
455 static const IWICBitmapVtbl BitmapImpl_Vtbl = {
456 BitmapImpl_QueryInterface,
457 BitmapImpl_AddRef,
458 BitmapImpl_Release,
459 BitmapImpl_GetSize,
460 BitmapImpl_GetPixelFormat,
461 BitmapImpl_GetResolution,
462 BitmapImpl_CopyPalette,
463 BitmapImpl_CopyPixels,
464 BitmapImpl_Lock,
465 BitmapImpl_SetPalette,
466 BitmapImpl_SetResolution
467 };
468
469 static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REFIID iid,
470 void **ppv)
471 {
472 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
473 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
474
475 if (!ppv) return E_INVALIDARG;
476
477 if (IsEqualIID(&IID_IUnknown, iid) ||
478 IsEqualIID(&IID_IMILBitmap, iid) ||
479 IsEqualIID(&IID_IMILBitmapSource, iid))
480 {
481 IUnknown_AddRef(&This->IMILBitmapSource_iface);
482 *ppv = &This->IMILBitmapSource_iface;
483 return S_OK;
484 }
485 else if (IsEqualIID(&IID_IWICBitmap, iid) ||
486 IsEqualIID(&IID_IWICBitmapSource, iid))
487 {
488 IUnknown_AddRef(&This->IWICBitmap_iface);
489 *ppv = &This->IWICBitmap_iface;
490 return S_OK;
491 }
492
493 FIXME("unknown interface %s\n", debugstr_guid(iid));
494 *ppv = NULL;
495 return E_NOINTERFACE;
496 }
497
498 static ULONG WINAPI IMILBitmapImpl_AddRef(IMILBitmapSource *iface)
499 {
500 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
501 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
502 }
503
504 static ULONG WINAPI IMILBitmapImpl_Release(IMILBitmapSource *iface)
505 {
506 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
507 return IWICBitmap_Release(&This->IWICBitmap_iface);
508 }
509
510 static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface,
511 UINT *width, UINT *height)
512 {
513 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
514 TRACE("(%p,%p,%p)\n", iface, width, height);
515 return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height);
516 }
517
518 static const struct
519 {
520 const GUID *WIC_format;
521 int enum_format;
522 } pixel_fmt_map[] =
523 {
524 { &GUID_WICPixelFormatDontCare, 0 },
525 { &GUID_WICPixelFormat1bppIndexed, 1 },
526 { &GUID_WICPixelFormat2bppIndexed, 2 },
527 { &GUID_WICPixelFormat4bppIndexed, 3 },
528 { &GUID_WICPixelFormat8bppIndexed, 4 },
529 { &GUID_WICPixelFormatBlackWhite, 5 },
530 { &GUID_WICPixelFormat2bppGray, 6 },
531 { &GUID_WICPixelFormat4bppGray, 7 },
532 { &GUID_WICPixelFormat8bppGray, 8 },
533 { &GUID_WICPixelFormat16bppBGR555, 9 },
534 { &GUID_WICPixelFormat16bppBGR565, 0x0a },
535 { &GUID_WICPixelFormat16bppGray, 0x0b },
536 { &GUID_WICPixelFormat24bppBGR, 0x0c },
537 { &GUID_WICPixelFormat24bppRGB, 0x0d },
538 { &GUID_WICPixelFormat32bppBGR, 0x0e },
539 { &GUID_WICPixelFormat32bppBGRA, 0x0f },
540 { &GUID_WICPixelFormat32bppPBGRA, 0x10 },
541 { &GUID_WICPixelFormat48bppRGB, 0x15 },
542 { &GUID_WICPixelFormat64bppRGBA, 0x16 },
543 { &GUID_WICPixelFormat64bppPRGBA, 0x17 },
544 { &GUID_WICPixelFormat32bppCMYK, 0x1c }
545 };
546
547 static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface,
548 int *format)
549 {
550 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
551 int i;
552
553 TRACE("(%p,%p)\n", iface, format);
554
555 if (!format) return E_INVALIDARG;
556
557 *format = 0;
558
559 for (i = 0; i < sizeof(pixel_fmt_map)/sizeof(pixel_fmt_map[0]); i++)
560 {
561 if (IsEqualGUID(pixel_fmt_map[i].WIC_format, &This->pixelformat))
562 {
563 *format = pixel_fmt_map[i].enum_format;
564 break;
565 }
566 }
567
568 TRACE("=> %u\n", *format);
569 return S_OK;
570 }
571
572 static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface,
573 double *dpix, double *dpiy)
574 {
575 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
576 TRACE("(%p,%p,%p)\n", iface, dpix, dpiy);
577 return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy);
578 }
579
580 static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface,
581 IWICPalette *palette)
582 {
583 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
584 TRACE("(%p,%p)\n", iface, palette);
585 return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette);
586 }
587
588 static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface,
589 const WICRect *rc, UINT stride, UINT size, BYTE *buffer)
590 {
591 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
592 TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer);
593 return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer);
594 }
595
596 static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **ppv)
597 {
598 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
599
600 TRACE("(%p,%p)\n", iface, ppv);
601
602 if (!ppv) return E_INVALIDARG;
603
604 /* reference count is not incremented here */
605 *ppv = &This->IMILUnknown1_iface;
606
607 return S_OK;
608 }
609
610 static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmapSource *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock)
611 {
612 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
613 TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock);
614 return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock);
615 }
616
617 static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmapSource *iface, IWICBitmapLock *lock)
618 {
619 TRACE("(%p,%p)\n", iface, lock);
620 IWICBitmapLock_Release(lock);
621 return S_OK;
622 }
623
624 static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmapSource *iface, IWICPalette *palette)
625 {
626 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
627 TRACE("(%p,%p)\n", iface, palette);
628 return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette);
629 }
630
631 static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmapSource *iface, double dpix, double dpiy)
632 {
633 BitmapImpl *This = impl_from_IMILBitmapSource(iface);
634 TRACE("(%p,%f,%f)\n", iface, dpix, dpiy);
635 return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy);
636 }
637
638 static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmapSource *iface, const WICRect *rc)
639 {
640 FIXME("(%p,%p): stub\n", iface, rc);
641 return E_NOTIMPL;
642 }
643
644 static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl =
645 {
646 IMILBitmapImpl_QueryInterface,
647 IMILBitmapImpl_AddRef,
648 IMILBitmapImpl_Release,
649 IMILBitmapImpl_GetSize,
650 IMILBitmapImpl_GetPixelFormat,
651 IMILBitmapImpl_GetResolution,
652 IMILBitmapImpl_CopyPalette,
653 IMILBitmapImpl_CopyPixels,
654 IMILBitmapImpl_unknown1,
655 IMILBitmapImpl_Lock,
656 IMILBitmapImpl_Unlock,
657 IMILBitmapImpl_SetPalette,
658 IMILBitmapImpl_SetResolution,
659 IMILBitmapImpl_AddDirtyRect
660 };
661
662 static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid,
663 void **ppv)
664 {
665 FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv);
666 *ppv = NULL;
667 return E_NOINTERFACE;
668 }
669
670 static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface)
671 {
672 BitmapImpl *This = impl_from_IMILUnknown1(iface);
673 return IWICBitmap_AddRef(&This->IWICBitmap_iface);
674 }
675
676 static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface)
677 {
678 BitmapImpl *This = impl_from_IMILUnknown1(iface);
679 return IWICBitmap_Release(&This->IWICBitmap_iface);
680 }
681
682 DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg)
683 {
684 FIXME("(%p,%p): stub\n", iface, arg);
685 }
686
687 static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, void *arg2)
688 {
689 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
690 return E_NOTIMPL;
691 }
692
693 DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg)
694 {
695 FIXME("(%p,%p): stub\n", iface, arg);
696 return E_NOTIMPL;
697 }
698
699 static HRESULT WINAPI IMILUnknown1Impl_unknown4(IMILUnknown1 *iface, void *arg)
700 {
701 FIXME("(%p,%p): stub\n", iface, arg);
702 return E_NOTIMPL;
703 }
704
705 static HRESULT WINAPI IMILUnknown1Impl_unknown5(IMILUnknown1 *iface, void *arg)
706 {
707 FIXME("(%p,%p): stub\n", iface, arg);
708 return E_NOTIMPL;
709 }
710
711 static HRESULT WINAPI IMILUnknown1Impl_unknown6(IMILUnknown1 *iface, DWORD64 arg)
712 {
713 FIXME("(%p,%s): stub\n", iface, wine_dbgstr_longlong(arg));
714 return E_NOTIMPL;
715 }
716
717 static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg)
718 {
719 FIXME("(%p,%p): stub\n", iface, arg);
720 return E_NOTIMPL;
721 }
722
723 DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface)
724 {
725 FIXME("(%p): stub\n", iface);
726 return E_NOTIMPL;
727 }
728
729 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8)
730 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8)
731 DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4)
732
733 static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl =
734 {
735 IMILUnknown1Impl_QueryInterface,
736 IMILUnknown1Impl_AddRef,
737 IMILUnknown1Impl_Release,
738 THISCALL(IMILUnknown1Impl_unknown1),
739 IMILUnknown1Impl_unknown2,
740 THISCALL(IMILUnknown1Impl_unknown3),
741 IMILUnknown1Impl_unknown4,
742 IMILUnknown1Impl_unknown5,
743 IMILUnknown1Impl_unknown6,
744 IMILUnknown1Impl_unknown7,
745 THISCALL(IMILUnknown1Impl_unknown8)
746 };
747
748 static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid,
749 void **ppv)
750 {
751 FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv);
752 *ppv = NULL;
753 return E_NOINTERFACE;
754 }
755
756 static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface)
757 {
758 FIXME("(%p): stub\n", iface);
759 return 0;
760 }
761
762 static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface)
763 {
764 FIXME("(%p): stub\n", iface);
765 return 0;
766 }
767
768 static HRESULT WINAPI IMILUnknown2Impl_unknown1(IMILUnknown2 *iface, void *arg1, void **arg2)
769 {
770 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
771 if (arg2) *arg2 = NULL;
772 return E_NOTIMPL;
773 }
774
775 static HRESULT WINAPI IMILUnknown2Impl_unknown2(IMILUnknown2 *iface, void *arg1, void *arg2)
776 {
777 FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
778 return E_NOTIMPL;
779 }
780
781 static HRESULT WINAPI IMILUnknown2Impl_unknown3(IMILUnknown2 *iface, void *arg1)
782 {
783 FIXME("(%p,%p): stub\n", iface, arg1);
784 return E_NOTIMPL;
785 }
786
787 static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl =
788 {
789 IMILUnknown2Impl_QueryInterface,
790 IMILUnknown2Impl_AddRef,
791 IMILUnknown2Impl_Release,
792 IMILUnknown2Impl_unknown1,
793 IMILUnknown2Impl_unknown2,
794 IMILUnknown2Impl_unknown3
795 };
796
797 HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight,
798 UINT stride, UINT datasize, BYTE *data,
799 REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option,
800 IWICBitmap **ppIBitmap)
801 {
802 HRESULT hr;
803 BitmapImpl *This;
804 UINT bpp;
805
806 hr = get_pixelformat_bpp(pixelFormat, &bpp);
807 if (FAILED(hr)) return hr;
808
809 if (!stride) stride = (((bpp*uiWidth)+31)/32)*4;
810 if (!datasize) datasize = stride * uiHeight;
811
812 if (datasize < stride * uiHeight) return WINCODEC_ERR_INSUFFICIENTBUFFER;
813 if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG;
814
815 This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl));
816 if (!This) return E_OUTOFMEMORY;
817
818 if (!data)
819 {
820 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize);
821 if (!data)
822 {
823 HeapFree(GetProcessHeap(), 0, This);
824 return E_OUTOFMEMORY;
825 }
826 This->is_section = FALSE;
827 }
828 else
829 This->is_section = TRUE;
830
831 This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl;
832 This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl;
833 This->IMILUnknown1_iface.lpVtbl = &IMILUnknown1Impl_Vtbl;
834 This->IMILUnknown2_iface.lpVtbl = &IMILUnknown2Impl_Vtbl;
835 This->ref = 1;
836 This->palette = NULL;
837 This->palette_set = 0;
838 This->lock = 0;
839 This->data = data;
840 This->width = uiWidth;
841 This->height = uiHeight;
842 This->stride = stride;
843 This->bpp = bpp;
844 memcpy(&This->pixelformat, pixelFormat, sizeof(GUID));
845 This->dpix = This->dpiy = 0.0;
846 InitializeCriticalSection(&This->cs);
847 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapImpl.lock");
848
849 *ppIBitmap = &This->IWICBitmap_iface;
850
851 return S_OK;
852 }