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 } 853