1 /* 2 * Copyright 2010 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 #include "wine/port.h" 21 22 #include <stdarg.h> 23 24 #define COBJMACROS 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "objbase.h" 29 30 #include "wincodecs_private.h" 31 32 #include "wine/debug.h" 33 #include "wine/library.h" 34 35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); 36 37 #include "pshpack1.h" 38 39 typedef struct { 40 BYTE id_length; 41 BYTE colormap_type; 42 BYTE image_type; 43 /* Colormap Specification */ 44 WORD colormap_firstentry; 45 WORD colormap_length; 46 BYTE colormap_entrysize; 47 /* Image Specification */ 48 WORD xorigin; 49 WORD yorigin; 50 WORD width; 51 WORD height; 52 BYTE depth; 53 BYTE image_descriptor; 54 } tga_header; 55 56 #define IMAGETYPE_COLORMAPPED 1 57 #define IMAGETYPE_TRUECOLOR 2 58 #define IMAGETYPE_GRAYSCALE 3 59 #define IMAGETYPE_RLE 8 60 61 #define IMAGE_ATTRIBUTE_BITCOUNT_MASK 0xf 62 #define IMAGE_RIGHTTOLEFT 0x10 63 #define IMAGE_TOPTOBOTTOM 0x20 64 65 typedef struct { 66 DWORD extension_area_offset; 67 DWORD developer_directory_offset; 68 char magic[18]; 69 } tga_footer; 70 71 static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE."; 72 73 typedef struct { 74 WORD size; 75 char author_name[41]; 76 char author_comments[324]; 77 WORD timestamp[6]; 78 char job_name[41]; 79 WORD job_timestamp[6]; 80 char software_id[41]; 81 WORD software_version; 82 char software_version_letter; 83 DWORD key_color; 84 WORD pixel_width; 85 WORD pixel_height; 86 WORD gamma_numerator; 87 WORD gamma_denominator; 88 DWORD color_correction_offset; 89 DWORD thumbnail_offset; 90 DWORD scanline_offset; 91 BYTE attributes_type; 92 } tga_extension_area; 93 94 #define ATTRIBUTE_NO_ALPHA 0 95 #define ATTRIBUTE_UNDEFINED 1 96 #define ATTRIBUTE_UNDEFINED_PRESERVE 2 97 #define ATTRIBUTE_ALPHA 3 98 #define ATTRIBUTE_PALPHA 4 99 100 #include "poppack.h" 101 102 typedef struct { 103 IWICBitmapDecoder IWICBitmapDecoder_iface; 104 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; 105 LONG ref; 106 BOOL initialized; 107 IStream *stream; 108 tga_header header; 109 tga_extension_area extension_area; 110 BYTE *imagebits; 111 BYTE *origin; 112 int stride; 113 ULONG id_offset; 114 ULONG colormap_length; 115 ULONG colormap_offset; 116 ULONG image_offset; 117 ULONG extension_area_offset; 118 ULONG developer_directory_offset; 119 CRITICAL_SECTION lock; 120 } TgaDecoder; 121 122 static inline TgaDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) 123 { 124 return CONTAINING_RECORD(iface, TgaDecoder, IWICBitmapDecoder_iface); 125 } 126 127 static inline TgaDecoder *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface) 128 { 129 return CONTAINING_RECORD(iface, TgaDecoder, IWICBitmapFrameDecode_iface); 130 } 131 132 static HRESULT WINAPI TgaDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, 133 void **ppv) 134 { 135 TgaDecoder *This = impl_from_IWICBitmapDecoder(iface); 136 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 137 138 if (!ppv) return E_INVALIDARG; 139 140 if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid)) 141 { 142 *ppv = &This->IWICBitmapDecoder_iface; 143 } 144 else 145 { 146 *ppv = NULL; 147 return E_NOINTERFACE; 148 } 149 150 IUnknown_AddRef((IUnknown*)*ppv); 151 return S_OK; 152 } 153 154 static ULONG WINAPI TgaDecoder_AddRef(IWICBitmapDecoder *iface) 155 { 156 TgaDecoder *This = impl_from_IWICBitmapDecoder(iface); 157 ULONG ref = InterlockedIncrement(&This->ref); 158 159 TRACE("(%p) refcount=%u\n", iface, ref); 160 161 return ref; 162 } 163 164 static ULONG WINAPI TgaDecoder_Release(IWICBitmapDecoder *iface) 165 { 166 TgaDecoder *This = impl_from_IWICBitmapDecoder(iface); 167 ULONG ref = InterlockedDecrement(&This->ref); 168 169 TRACE("(%p) refcount=%u\n", iface, ref); 170 171 if (ref == 0) 172 { 173 This->lock.DebugInfo->Spare[0] = 0; 174 DeleteCriticalSection(&This->lock); 175 if (This->stream) 176 IStream_Release(This->stream); 177 HeapFree(GetProcessHeap(), 0, This->imagebits); 178 HeapFree(GetProcessHeap(), 0, This); 179 } 180 181 return ref; 182 } 183 184 static HRESULT WINAPI TgaDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream, 185 DWORD *capability) 186 { 187 HRESULT hr; 188 189 TRACE("(%p,%p,%p)\n", iface, stream, capability); 190 191 if (!stream || !capability) return E_INVALIDARG; 192 193 hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand); 194 if (hr != S_OK) return hr; 195 196 *capability = WICBitmapDecoderCapabilityCanDecodeAllImages | 197 WICBitmapDecoderCapabilityCanDecodeSomeImages; 198 return S_OK; 199 } 200 201 static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, 202 WICDecodeOptions cacheOptions) 203 { 204 TgaDecoder *This = impl_from_IWICBitmapDecoder(iface); 205 HRESULT hr=S_OK; 206 DWORD bytesread; 207 LARGE_INTEGER seek; 208 tga_footer footer; 209 int attribute_bitcount; 210 int mapped_depth=0; 211 212 TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions); 213 214 EnterCriticalSection(&This->lock); 215 216 if (This->initialized) 217 { 218 hr = WINCODEC_ERR_WRONGSTATE; 219 goto end; 220 } 221 222 seek.QuadPart = 0; 223 hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); 224 if (FAILED(hr)) goto end; 225 226 hr = IStream_Read(pIStream, &This->header, sizeof(tga_header), &bytesread); 227 if (SUCCEEDED(hr) && bytesread != sizeof(tga_header)) 228 { 229 TRACE("got only %u bytes\n", bytesread); 230 hr = E_FAIL; 231 } 232 if (FAILED(hr)) goto end; 233 234 TRACE("imagetype=%u, colormap type=%u, depth=%u, image descriptor=0x%x\n", 235 This->header.image_type, This->header.colormap_type, 236 This->header.depth, This->header.image_descriptor); 237 238 /* Sanity checking. Since TGA has no clear identifying markers, we need 239 * to be careful to not load a non-TGA image. */ 240 switch (This->header.image_type) 241 { 242 case IMAGETYPE_COLORMAPPED: 243 case IMAGETYPE_COLORMAPPED|IMAGETYPE_RLE: 244 if (This->header.colormap_type != 1) 245 hr = E_FAIL; 246 mapped_depth = This->header.colormap_entrysize; 247 break; 248 case IMAGETYPE_TRUECOLOR: 249 case IMAGETYPE_TRUECOLOR|IMAGETYPE_RLE: 250 if (This->header.colormap_type != 0 && This->header.colormap_type != 1) 251 hr = E_FAIL; 252 mapped_depth = This->header.depth; 253 break; 254 case IMAGETYPE_GRAYSCALE: 255 case IMAGETYPE_GRAYSCALE|IMAGETYPE_RLE: 256 if (This->header.colormap_type != 0) 257 hr = E_FAIL; 258 mapped_depth = 0; 259 break; 260 default: 261 hr = E_FAIL; 262 } 263 264 if (This->header.depth != 8 && This->header.depth != 16 && 265 This->header.depth != 24 && This->header.depth != 32) 266 hr = E_FAIL; 267 268 if ((This->header.image_descriptor & 0xc0) != 0) 269 hr = E_FAIL; 270 271 attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK; 272 273 if (attribute_bitcount && 274 !((mapped_depth == 32 && attribute_bitcount == 8) || 275 (mapped_depth == 16 && attribute_bitcount == 1))) 276 hr = E_FAIL; 277 278 if (FAILED(hr)) 279 { 280 WARN("bad tga header\n"); 281 goto end; 282 } 283 284 /* Locate data in the file based on the header. */ 285 This->id_offset = sizeof(tga_header); 286 This->colormap_offset = This->id_offset + This->header.id_length; 287 if (This->header.colormap_type == 1) 288 This->colormap_length = ((This->header.colormap_entrysize+7)/8) * This->header.colormap_length; 289 else 290 This->colormap_length = 0; 291 This->image_offset = This->colormap_offset + This->colormap_length; 292 293 /* Read footer if there is one */ 294 seek.QuadPart = -(LONGLONG)sizeof(tga_footer); 295 hr = IStream_Seek(pIStream, seek, STREAM_SEEK_END, NULL); 296 297 if (SUCCEEDED(hr)) { 298 hr = IStream_Read(pIStream, &footer, sizeof(tga_footer), &bytesread); 299 if (SUCCEEDED(hr) && bytesread != sizeof(tga_footer)) 300 { 301 TRACE("got only %u footer bytes\n", bytesread); 302 hr = E_FAIL; 303 } 304 305 if (memcmp(footer.magic, tga_footer_magic, sizeof(tga_footer_magic)) == 0) 306 { 307 This->extension_area_offset = footer.extension_area_offset; 308 This->developer_directory_offset = footer.developer_directory_offset; 309 } 310 else 311 { 312 This->extension_area_offset = 0; 313 This->developer_directory_offset = 0; 314 } 315 } 316 else 317 { 318 /* File is too small to have a footer. */ 319 This->extension_area_offset = 0; 320 This->developer_directory_offset = 0; 321 hr = S_OK; 322 } 323 324 if (This->extension_area_offset) 325 { 326 seek.QuadPart = This->extension_area_offset; 327 hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); 328 if (FAILED(hr)) goto end; 329 330 hr = IStream_Read(pIStream, &This->extension_area, sizeof(tga_extension_area), &bytesread); 331 if (SUCCEEDED(hr) && bytesread != sizeof(tga_extension_area)) 332 { 333 TRACE("got only %u extension area bytes\n", bytesread); 334 hr = E_FAIL; 335 } 336 if (SUCCEEDED(hr) && This->extension_area.size < 495) 337 { 338 TRACE("extension area is only %u bytes long\n", This->extension_area.size); 339 hr = E_FAIL; 340 } 341 if (FAILED(hr)) goto end; 342 } 343 344 IStream_AddRef(pIStream); 345 This->stream = pIStream; 346 This->initialized = TRUE; 347 348 end: 349 LeaveCriticalSection(&This->lock); 350 return hr; 351 } 352 353 static HRESULT WINAPI TgaDecoder_GetContainerFormat(IWICBitmapDecoder *iface, 354 GUID *pguidContainerFormat) 355 { 356 memcpy(pguidContainerFormat, &GUID_WineContainerFormatTga, sizeof(GUID)); 357 return S_OK; 358 } 359 360 static HRESULT WINAPI TgaDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, 361 IWICBitmapDecoderInfo **ppIDecoderInfo) 362 { 363 TRACE("(%p,%p)\n", iface, ppIDecoderInfo); 364 365 return get_decoder_info(&CLSID_WineTgaDecoder, ppIDecoderInfo); 366 } 367 368 static HRESULT WINAPI TgaDecoder_CopyPalette(IWICBitmapDecoder *iface, 369 IWICPalette *pIPalette) 370 { 371 FIXME("(%p,%p): stub\n", iface, pIPalette); 372 return E_NOTIMPL; 373 } 374 375 static HRESULT WINAPI TgaDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, 376 IWICMetadataQueryReader **ppIMetadataQueryReader) 377 { 378 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); 379 return E_NOTIMPL; 380 } 381 382 static HRESULT WINAPI TgaDecoder_GetPreview(IWICBitmapDecoder *iface, 383 IWICBitmapSource **ppIBitmapSource) 384 { 385 FIXME("(%p,%p): stub\n", iface, ppIBitmapSource); 386 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 387 } 388 389 static HRESULT WINAPI TgaDecoder_GetColorContexts(IWICBitmapDecoder *iface, 390 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) 391 { 392 FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount); 393 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 394 } 395 396 static HRESULT WINAPI TgaDecoder_GetThumbnail(IWICBitmapDecoder *iface, 397 IWICBitmapSource **ppIThumbnail) 398 { 399 FIXME("(%p,%p): stub\n", iface, ppIThumbnail); 400 return WINCODEC_ERR_CODECNOTHUMBNAIL; 401 } 402 403 static HRESULT WINAPI TgaDecoder_GetFrameCount(IWICBitmapDecoder *iface, 404 UINT *pCount) 405 { 406 if (!pCount) return E_INVALIDARG; 407 408 *pCount = 1; 409 return S_OK; 410 } 411 412 static HRESULT WINAPI TgaDecoder_GetFrame(IWICBitmapDecoder *iface, 413 UINT index, IWICBitmapFrameDecode **ppIBitmapFrame) 414 { 415 TgaDecoder *This = impl_from_IWICBitmapDecoder(iface); 416 TRACE("(%p,%p)\n", iface, ppIBitmapFrame); 417 418 if (!This->initialized) return WINCODEC_ERR_FRAMEMISSING; 419 420 if (index != 0) return E_INVALIDARG; 421 422 IWICBitmapDecoder_AddRef(iface); 423 *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface; 424 425 return S_OK; 426 } 427 428 static const IWICBitmapDecoderVtbl TgaDecoder_Vtbl = { 429 TgaDecoder_QueryInterface, 430 TgaDecoder_AddRef, 431 TgaDecoder_Release, 432 TgaDecoder_QueryCapability, 433 TgaDecoder_Initialize, 434 TgaDecoder_GetContainerFormat, 435 TgaDecoder_GetDecoderInfo, 436 TgaDecoder_CopyPalette, 437 TgaDecoder_GetMetadataQueryReader, 438 TgaDecoder_GetPreview, 439 TgaDecoder_GetColorContexts, 440 TgaDecoder_GetThumbnail, 441 TgaDecoder_GetFrameCount, 442 TgaDecoder_GetFrame 443 }; 444 445 static HRESULT WINAPI TgaDecoder_Frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, 446 void **ppv) 447 { 448 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 449 450 if (!ppv) return E_INVALIDARG; 451 452 if (IsEqualIID(&IID_IUnknown, iid) || 453 IsEqualIID(&IID_IWICBitmapSource, iid) || 454 IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) 455 { 456 *ppv = iface; 457 } 458 else 459 { 460 *ppv = NULL; 461 return E_NOINTERFACE; 462 } 463 464 IUnknown_AddRef((IUnknown*)*ppv); 465 return S_OK; 466 } 467 468 static ULONG WINAPI TgaDecoder_Frame_AddRef(IWICBitmapFrameDecode *iface) 469 { 470 TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface); 471 return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface); 472 } 473 474 static ULONG WINAPI TgaDecoder_Frame_Release(IWICBitmapFrameDecode *iface) 475 { 476 TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface); 477 return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); 478 } 479 480 static HRESULT WINAPI TgaDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface, 481 UINT *puiWidth, UINT *puiHeight) 482 { 483 TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface); 484 485 *puiWidth = This->header.width; 486 *puiHeight = This->header.height; 487 488 TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight); 489 490 return S_OK; 491 } 492 493 static HRESULT WINAPI TgaDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *iface, 494 WICPixelFormatGUID *pPixelFormat) 495 { 496 TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface); 497 int attribute_bitcount; 498 byte attribute_type; 499 500 TRACE("(%p,%p)\n", iface, pPixelFormat); 501 502 attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK; 503 504 if (attribute_bitcount && This->extension_area_offset) 505 attribute_type = This->extension_area.attributes_type; 506 else if (attribute_bitcount) 507 attribute_type = ATTRIBUTE_ALPHA; 508 else 509 attribute_type = ATTRIBUTE_NO_ALPHA; 510 511 switch (This->header.image_type & ~IMAGETYPE_RLE) 512 { 513 case IMAGETYPE_COLORMAPPED: 514 switch (This->header.depth) 515 { 516 case 8: 517 memcpy(pPixelFormat, &GUID_WICPixelFormat8bppIndexed, sizeof(GUID)); 518 break; 519 default: 520 FIXME("Unhandled indexed color depth %u\n", This->header.depth); 521 return E_NOTIMPL; 522 } 523 break; 524 case IMAGETYPE_TRUECOLOR: 525 switch (This->header.depth) 526 { 527 case 16: 528 switch (attribute_type) 529 { 530 case ATTRIBUTE_NO_ALPHA: 531 case ATTRIBUTE_UNDEFINED: 532 case ATTRIBUTE_UNDEFINED_PRESERVE: 533 memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGR555, sizeof(GUID)); 534 break; 535 case ATTRIBUTE_ALPHA: 536 case ATTRIBUTE_PALPHA: 537 memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGRA5551, sizeof(GUID)); 538 break; 539 default: 540 FIXME("Unhandled 16-bit attribute type %u\n", attribute_type); 541 return E_NOTIMPL; 542 } 543 break; 544 case 24: 545 memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID)); 546 break; 547 case 32: 548 switch (attribute_type) 549 { 550 case ATTRIBUTE_NO_ALPHA: 551 case ATTRIBUTE_UNDEFINED: 552 case ATTRIBUTE_UNDEFINED_PRESERVE: 553 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGR, sizeof(GUID)); 554 break; 555 case ATTRIBUTE_ALPHA: 556 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID)); 557 break; 558 case ATTRIBUTE_PALPHA: 559 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppPBGRA, sizeof(GUID)); 560 break; 561 default: 562 FIXME("Unhandled 32-bit attribute type %u\n", attribute_type); 563 return E_NOTIMPL; 564 } 565 break; 566 default: 567 FIXME("Unhandled truecolor depth %u\n", This->header.depth); 568 return E_NOTIMPL; 569 } 570 break; 571 case IMAGETYPE_GRAYSCALE: 572 switch (This->header.depth) 573 { 574 case 8: 575 memcpy(pPixelFormat, &GUID_WICPixelFormat8bppGray, sizeof(GUID)); 576 break; 577 case 16: 578 memcpy(pPixelFormat, &GUID_WICPixelFormat16bppGray, sizeof(GUID)); 579 break; 580 default: 581 FIXME("Unhandled grayscale depth %u\n", This->header.depth); 582 return E_NOTIMPL; 583 } 584 break; 585 default: 586 ERR("Unknown image type %u\n", This->header.image_type); 587 return E_FAIL; 588 } 589 590 return S_OK; 591 } 592 593 static HRESULT WINAPI TgaDecoder_Frame_GetResolution(IWICBitmapFrameDecode *iface, 594 double *pDpiX, double *pDpiY) 595 { 596 FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY); 597 return E_NOTIMPL; 598 } 599 600 static HRESULT WINAPI TgaDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface, 601 IWICPalette *pIPalette) 602 { 603 TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface); 604 HRESULT hr=S_OK; 605 WICColor colors[256], *color; 606 BYTE *colormap_data; 607 WORD *wcolormap_data; 608 DWORD *dwcolormap_data; 609 LARGE_INTEGER seek; 610 ULONG bytesread; 611 int depth, attribute_bitcount, attribute_type; 612 int i; 613 614 TRACE("(%p,%p)\n", iface, pIPalette); 615 616 if (!This->colormap_length) 617 { 618 WARN("no colormap present in this file\n"); 619 return WINCODEC_ERR_PALETTEUNAVAILABLE; 620 } 621 622 if (This->header.colormap_firstentry + This->header.colormap_length > 256) 623 { 624 FIXME("cannot read colormap with %i entries starting at %i\n", 625 This->header.colormap_firstentry + This->header.colormap_length, 626 This->header.colormap_firstentry); 627 return E_FAIL; 628 } 629 630 colormap_data = HeapAlloc(GetProcessHeap(), 0, This->colormap_length); 631 if (!colormap_data) return E_OUTOFMEMORY; 632 633 wcolormap_data = (WORD*)colormap_data; 634 dwcolormap_data = (DWORD*)colormap_data; 635 636 EnterCriticalSection(&This->lock); 637 638 seek.QuadPart = This->colormap_offset; 639 hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL); 640 641 if (SUCCEEDED(hr)) 642 { 643 hr = IStream_Read(This->stream, colormap_data, This->colormap_length, &bytesread); 644 if (SUCCEEDED(hr) && bytesread != This->colormap_length) 645 { 646 WARN("expected %i bytes in colormap, got %i\n", This->colormap_length, bytesread); 647 hr = E_FAIL; 648 } 649 } 650 651 LeaveCriticalSection(&This->lock); 652 653 if (SUCCEEDED(hr)) 654 { 655 attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK; 656 657 if (attribute_bitcount && This->extension_area_offset) 658 attribute_type = This->extension_area.attributes_type; 659 else if (attribute_bitcount) 660 attribute_type = ATTRIBUTE_ALPHA; 661 else 662 attribute_type = ATTRIBUTE_NO_ALPHA; 663 664 depth = This->header.colormap_entrysize; 665 if (depth == 15) 666 { 667 depth = 16; 668 attribute_type = ATTRIBUTE_NO_ALPHA; 669 } 670 671 memset(colors, 0, sizeof(colors)); 672 673 color = &colors[This->header.colormap_firstentry]; 674 675 /* Colormap entries can be in any truecolor format, and we have to convert them. */ 676 switch (depth) 677 { 678 case 16: 679 switch (attribute_type) 680 { 681 case ATTRIBUTE_NO_ALPHA: 682 case ATTRIBUTE_UNDEFINED: 683 case ATTRIBUTE_UNDEFINED_PRESERVE: 684 for (i=0; i<This->header.colormap_length; i++) 685 { 686 WORD srcval = wcolormap_data[i]; 687 *color++=0xff000000 | /* constant 255 alpha */ 688 ((srcval << 9) & 0xf80000) | /* r */ 689 ((srcval << 4) & 0x070000) | /* r - 3 bits */ 690 ((srcval << 6) & 0x00f800) | /* g */ 691 ((srcval << 1) & 0x000700) | /* g - 3 bits */ 692 ((srcval << 3) & 0x0000f8) | /* b */ 693 ((srcval >> 2) & 0x000007); /* b - 3 bits */ 694 } 695 break; 696 case ATTRIBUTE_ALPHA: 697 case ATTRIBUTE_PALPHA: 698 for (i=0; i<This->header.colormap_length; i++) 699 { 700 WORD srcval = wcolormap_data[i]; 701 *color++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */ 702 ((srcval << 9) & 0xf80000) | /* r */ 703 ((srcval << 4) & 0x070000) | /* r - 3 bits */ 704 ((srcval << 6) & 0x00f800) | /* g */ 705 ((srcval << 1) & 0x000700) | /* g - 3 bits */ 706 ((srcval << 3) & 0x0000f8) | /* b */ 707 ((srcval >> 2) & 0x000007); /* b - 3 bits */ 708 } 709 break; 710 default: 711 FIXME("Unhandled 16-bit attribute type %u\n", attribute_type); 712 hr = E_NOTIMPL; 713 } 714 break; 715 case 24: 716 for (i=0; i<This->header.colormap_length; i++) 717 { 718 *color++=0xff000000 | /* alpha */ 719 colormap_data[i*3+2] | /* red */ 720 colormap_data[i*3+1] | /* green */ 721 colormap_data[i*3]; /* blue */ 722 } 723 break; 724 case 32: 725 switch (attribute_type) 726 { 727 case ATTRIBUTE_NO_ALPHA: 728 case ATTRIBUTE_UNDEFINED: 729 case ATTRIBUTE_UNDEFINED_PRESERVE: 730 for (i=0; i<This->header.colormap_length; i++) 731 *color++=dwcolormap_data[i]|0xff000000; 732 break; 733 case ATTRIBUTE_ALPHA: 734 for (i=0; i<This->header.colormap_length; i++) 735 *color++=dwcolormap_data[i]; 736 break; 737 case ATTRIBUTE_PALPHA: 738 /* FIXME: Unpremultiply alpha */ 739 default: 740 FIXME("Unhandled 16-bit attribute type %u\n", attribute_type); 741 hr = E_NOTIMPL; 742 } 743 break; 744 default: 745 FIXME("Unhandled truecolor depth %u\n", This->header.depth); 746 hr = E_NOTIMPL; 747 } 748 } 749 750 HeapFree(GetProcessHeap(), 0, colormap_data); 751 752 if (SUCCEEDED(hr)) 753 hr = IWICPalette_InitializeCustom(pIPalette, colors, 256); 754 755 return hr; 756 } 757 758 static HRESULT TgaDecoder_ReadRLE(TgaDecoder *This, BYTE *imagebits, int datasize) 759 { 760 int i=0, j, bytesperpixel; 761 ULONG bytesread; 762 HRESULT hr=S_OK; 763 764 bytesperpixel = This->header.depth / 8; 765 766 while (i<datasize) 767 { 768 BYTE rc; 769 int count, size; 770 BYTE pixeldata[4]; 771 772 hr = IStream_Read(This->stream, &rc, 1, &bytesread); 773 if (bytesread != 1) hr = E_FAIL; 774 if (FAILED(hr)) break; 775 776 count = (rc&0x7f)+1; 777 size = count * bytesperpixel; 778 779 if (size + i > datasize) 780 { 781 WARN("RLE packet too large\n"); 782 hr = E_FAIL; 783 break; 784 } 785 786 if (rc&0x80) 787 { 788 /* Run-length packet */ 789 hr = IStream_Read(This->stream, pixeldata, bytesperpixel, &bytesread); 790 if (bytesread != bytesperpixel) hr = E_FAIL; 791 if (FAILED(hr)) break; 792 793 if (bytesperpixel == 1) 794 memset(&imagebits[i], pixeldata[0], count); 795 else 796 { 797 for (j=0; j<count; j++) 798 memcpy(&imagebits[i+j*bytesperpixel], pixeldata, bytesperpixel); 799 } 800 } 801 else 802 { 803 /* Raw packet */ 804 hr = IStream_Read(This->stream, &imagebits[i], size, &bytesread); 805 if (bytesread != size) hr = E_FAIL; 806 if (FAILED(hr)) break; 807 } 808 809 i += size; 810 } 811 812 return hr; 813 } 814 815 static HRESULT TgaDecoder_ReadImage(TgaDecoder *This) 816 { 817 HRESULT hr=S_OK; 818 int datasize; 819 LARGE_INTEGER seek; 820 ULONG bytesread; 821 822 if (This->imagebits) 823 return S_OK; 824 825 EnterCriticalSection(&This->lock); 826 827 if (!This->imagebits) 828 { 829 if (This->header.image_descriptor & IMAGE_RIGHTTOLEFT) 830 { 831 FIXME("Right to left image reading not implemented\n"); 832 hr = E_NOTIMPL; 833 } 834 835 if (SUCCEEDED(hr)) 836 { 837 datasize = This->header.width * This->header.height * (This->header.depth / 8); 838 This->imagebits = HeapAlloc(GetProcessHeap(), 0, datasize); 839 if (!This->imagebits) hr = E_OUTOFMEMORY; 840 } 841 842 if (SUCCEEDED(hr)) 843 { 844 seek.QuadPart = This->image_offset; 845 hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL); 846 } 847 848 if (SUCCEEDED(hr)) 849 { 850 if (This->header.image_type & IMAGETYPE_RLE) 851 { 852 hr = TgaDecoder_ReadRLE(This, This->imagebits, datasize); 853 } 854 else 855 { 856 hr = IStream_Read(This->stream, This->imagebits, datasize, &bytesread); 857 if (SUCCEEDED(hr) && bytesread != datasize) 858 hr = E_FAIL; 859 } 860 } 861 862 if (SUCCEEDED(hr)) 863 { 864 if (This->header.image_descriptor & IMAGE_TOPTOBOTTOM) 865 { 866 This->origin = This->imagebits; 867 This->stride = This->header.width * (This->header.depth / 8); 868 } 869 else 870 { 871 This->stride = -This->header.width * (This->header.depth / 8); 872 This->origin = This->imagebits + This->header.width * (This->header.height - 1) * (This->header.depth / 8); 873 } 874 } 875 else 876 { 877 HeapFree(GetProcessHeap(), 0, This->imagebits); 878 This->imagebits = NULL; 879 } 880 } 881 882 LeaveCriticalSection(&This->lock); 883 884 return hr; 885 } 886 887 static HRESULT WINAPI TgaDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface, 888 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) 889 { 890 TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface); 891 HRESULT hr; 892 893 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); 894 895 hr = TgaDecoder_ReadImage(This); 896 897 if (SUCCEEDED(hr)) 898 { 899 hr = copy_pixels(This->header.depth, This->origin, 900 This->header.width, This->header.height, This->stride, 901 prc, cbStride, cbBufferSize, pbBuffer); 902 } 903 904 return hr; 905 } 906 907 static HRESULT WINAPI TgaDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, 908 IWICMetadataQueryReader **ppIMetadataQueryReader) 909 { 910 FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); 911 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 912 } 913 914 static HRESULT WINAPI TgaDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface, 915 UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) 916 { 917 FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount); 918 return WINCODEC_ERR_UNSUPPORTEDOPERATION; 919 } 920 921 static HRESULT WINAPI TgaDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface, 922 IWICBitmapSource **ppIThumbnail) 923 { 924 FIXME("(%p,%p): stub\n", iface, ppIThumbnail); 925 return WINCODEC_ERR_CODECNOTHUMBNAIL; 926 } 927 928 static const IWICBitmapFrameDecodeVtbl TgaDecoder_Frame_Vtbl = { 929 TgaDecoder_Frame_QueryInterface, 930 TgaDecoder_Frame_AddRef, 931 TgaDecoder_Frame_Release, 932 TgaDecoder_Frame_GetSize, 933 TgaDecoder_Frame_GetPixelFormat, 934 TgaDecoder_Frame_GetResolution, 935 TgaDecoder_Frame_CopyPalette, 936 TgaDecoder_Frame_CopyPixels, 937 TgaDecoder_Frame_GetMetadataQueryReader, 938 TgaDecoder_Frame_GetColorContexts, 939 TgaDecoder_Frame_GetThumbnail 940 }; 941 942 HRESULT TgaDecoder_CreateInstance(REFIID iid, void** ppv) 943 { 944 TgaDecoder *This; 945 HRESULT ret; 946 947 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); 948 949 *ppv = NULL; 950 951 This = HeapAlloc(GetProcessHeap(), 0, sizeof(TgaDecoder)); 952 if (!This) return E_OUTOFMEMORY; 953 954 This->IWICBitmapDecoder_iface.lpVtbl = &TgaDecoder_Vtbl; 955 This->IWICBitmapFrameDecode_iface.lpVtbl = &TgaDecoder_Frame_Vtbl; 956 This->ref = 1; 957 This->initialized = FALSE; 958 This->stream = NULL; 959 This->imagebits = NULL; 960 InitializeCriticalSection(&This->lock); 961 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TgaDecoder.lock"); 962 963 ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); 964 IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); 965 966 return ret; 967 } 968