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