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