xref: /reactos/dll/win32/windowscodecs/tgaformat.c (revision 48cc7814)
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     HRESULT hr;
364     IWICComponentInfo *compinfo;
365 
366     TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
367 
368     hr = CreateComponentInfo(&CLSID_WineTgaDecoder, &compinfo);
369     if (FAILED(hr)) return hr;
370 
371     hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
372         (void**)ppIDecoderInfo);
373 
374     IWICComponentInfo_Release(compinfo);
375 
376     return hr;
377 }
378 
379 static HRESULT WINAPI TgaDecoder_CopyPalette(IWICBitmapDecoder *iface,
380     IWICPalette *pIPalette)
381 {
382     FIXME("(%p,%p): stub\n", iface, pIPalette);
383     return E_NOTIMPL;
384 }
385 
386 static HRESULT WINAPI TgaDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
387     IWICMetadataQueryReader **ppIMetadataQueryReader)
388 {
389     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
390     return E_NOTIMPL;
391 }
392 
393 static HRESULT WINAPI TgaDecoder_GetPreview(IWICBitmapDecoder *iface,
394     IWICBitmapSource **ppIBitmapSource)
395 {
396     FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
397     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
398 }
399 
400 static HRESULT WINAPI TgaDecoder_GetColorContexts(IWICBitmapDecoder *iface,
401     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
402 {
403     FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
404     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
405 }
406 
407 static HRESULT WINAPI TgaDecoder_GetThumbnail(IWICBitmapDecoder *iface,
408     IWICBitmapSource **ppIThumbnail)
409 {
410     FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
411     return WINCODEC_ERR_CODECNOTHUMBNAIL;
412 }
413 
414 static HRESULT WINAPI TgaDecoder_GetFrameCount(IWICBitmapDecoder *iface,
415     UINT *pCount)
416 {
417     if (!pCount) return E_INVALIDARG;
418 
419     *pCount = 1;
420     return S_OK;
421 }
422 
423 static HRESULT WINAPI TgaDecoder_GetFrame(IWICBitmapDecoder *iface,
424     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
425 {
426     TgaDecoder *This = impl_from_IWICBitmapDecoder(iface);
427     TRACE("(%p,%p)\n", iface, ppIBitmapFrame);
428 
429     if (!This->initialized) return WINCODEC_ERR_FRAMEMISSING;
430 
431     if (index != 0) return E_INVALIDARG;
432 
433     IWICBitmapDecoder_AddRef(iface);
434     *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface;
435 
436     return S_OK;
437 }
438 
439 static const IWICBitmapDecoderVtbl TgaDecoder_Vtbl = {
440     TgaDecoder_QueryInterface,
441     TgaDecoder_AddRef,
442     TgaDecoder_Release,
443     TgaDecoder_QueryCapability,
444     TgaDecoder_Initialize,
445     TgaDecoder_GetContainerFormat,
446     TgaDecoder_GetDecoderInfo,
447     TgaDecoder_CopyPalette,
448     TgaDecoder_GetMetadataQueryReader,
449     TgaDecoder_GetPreview,
450     TgaDecoder_GetColorContexts,
451     TgaDecoder_GetThumbnail,
452     TgaDecoder_GetFrameCount,
453     TgaDecoder_GetFrame
454 };
455 
456 static HRESULT WINAPI TgaDecoder_Frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
457     void **ppv)
458 {
459     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
460 
461     if (!ppv) return E_INVALIDARG;
462 
463     if (IsEqualIID(&IID_IUnknown, iid) ||
464         IsEqualIID(&IID_IWICBitmapSource, iid) ||
465         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
466     {
467         *ppv = iface;
468     }
469     else
470     {
471         *ppv = NULL;
472         return E_NOINTERFACE;
473     }
474 
475     IUnknown_AddRef((IUnknown*)*ppv);
476     return S_OK;
477 }
478 
479 static ULONG WINAPI TgaDecoder_Frame_AddRef(IWICBitmapFrameDecode *iface)
480 {
481     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
482     return IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface);
483 }
484 
485 static ULONG WINAPI TgaDecoder_Frame_Release(IWICBitmapFrameDecode *iface)
486 {
487     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
488     return IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
489 }
490 
491 static HRESULT WINAPI TgaDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface,
492     UINT *puiWidth, UINT *puiHeight)
493 {
494     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
495 
496     *puiWidth = This->header.width;
497     *puiHeight = This->header.height;
498 
499     TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);
500 
501     return S_OK;
502 }
503 
504 static HRESULT WINAPI TgaDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *iface,
505     WICPixelFormatGUID *pPixelFormat)
506 {
507     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
508     int attribute_bitcount;
509     byte attribute_type;
510 
511     TRACE("(%p,%p)\n", iface, pPixelFormat);
512 
513     attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
514 
515     if (attribute_bitcount && This->extension_area_offset)
516         attribute_type = This->extension_area.attributes_type;
517     else if (attribute_bitcount)
518         attribute_type = ATTRIBUTE_ALPHA;
519     else
520         attribute_type = ATTRIBUTE_NO_ALPHA;
521 
522     switch (This->header.image_type & ~IMAGETYPE_RLE)
523     {
524     case IMAGETYPE_COLORMAPPED:
525         switch (This->header.depth)
526         {
527         case 8:
528             memcpy(pPixelFormat, &GUID_WICPixelFormat8bppIndexed, sizeof(GUID));
529             break;
530         default:
531             FIXME("Unhandled indexed color depth %u\n", This->header.depth);
532             return E_NOTIMPL;
533         }
534         break;
535     case IMAGETYPE_TRUECOLOR:
536         switch (This->header.depth)
537         {
538         case 16:
539             switch (attribute_type)
540             {
541             case ATTRIBUTE_NO_ALPHA:
542             case ATTRIBUTE_UNDEFINED:
543             case ATTRIBUTE_UNDEFINED_PRESERVE:
544                 memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGR555, sizeof(GUID));
545                 break;
546             case ATTRIBUTE_ALPHA:
547             case ATTRIBUTE_PALPHA:
548                 memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGRA5551, sizeof(GUID));
549                 break;
550             default:
551                 FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
552                 return E_NOTIMPL;
553             }
554             break;
555         case 24:
556             memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID));
557             break;
558         case 32:
559             switch (attribute_type)
560             {
561             case ATTRIBUTE_NO_ALPHA:
562             case ATTRIBUTE_UNDEFINED:
563             case ATTRIBUTE_UNDEFINED_PRESERVE:
564                 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGR, sizeof(GUID));
565                 break;
566             case ATTRIBUTE_ALPHA:
567                 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
568                 break;
569             case ATTRIBUTE_PALPHA:
570                 memcpy(pPixelFormat, &GUID_WICPixelFormat32bppPBGRA, sizeof(GUID));
571                 break;
572             default:
573                 FIXME("Unhandled 32-bit attribute type %u\n", attribute_type);
574                 return E_NOTIMPL;
575             }
576             break;
577         default:
578             FIXME("Unhandled truecolor depth %u\n", This->header.depth);
579             return E_NOTIMPL;
580         }
581         break;
582     case IMAGETYPE_GRAYSCALE:
583         switch (This->header.depth)
584         {
585         case 8:
586             memcpy(pPixelFormat, &GUID_WICPixelFormat8bppGray, sizeof(GUID));
587             break;
588         case 16:
589             memcpy(pPixelFormat, &GUID_WICPixelFormat16bppGray, sizeof(GUID));
590             break;
591         default:
592             FIXME("Unhandled grayscale depth %u\n", This->header.depth);
593             return E_NOTIMPL;
594         }
595         break;
596     default:
597         ERR("Unknown image type %u\n", This->header.image_type);
598         return E_FAIL;
599     }
600 
601     return S_OK;
602 }
603 
604 static HRESULT WINAPI TgaDecoder_Frame_GetResolution(IWICBitmapFrameDecode *iface,
605     double *pDpiX, double *pDpiY)
606 {
607     FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
608     return E_NOTIMPL;
609 }
610 
611 static HRESULT WINAPI TgaDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
612     IWICPalette *pIPalette)
613 {
614     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
615     HRESULT hr=S_OK;
616     WICColor colors[256], *color;
617     BYTE *colormap_data;
618     WORD *wcolormap_data;
619     DWORD *dwcolormap_data;
620     LARGE_INTEGER seek;
621     ULONG bytesread;
622     int depth, attribute_bitcount, attribute_type;
623     int i;
624 
625     TRACE("(%p,%p)\n", iface, pIPalette);
626 
627     if (!This->colormap_length)
628     {
629         WARN("no colormap present in this file\n");
630         return WINCODEC_ERR_PALETTEUNAVAILABLE;
631     }
632 
633     if (This->header.colormap_firstentry + This->header.colormap_length > 256)
634     {
635         FIXME("cannot read colormap with %i entries starting at %i\n",
636             This->header.colormap_firstentry + This->header.colormap_length,
637             This->header.colormap_firstentry);
638         return E_FAIL;
639     }
640 
641     colormap_data = HeapAlloc(GetProcessHeap(), 0, This->colormap_length);
642     if (!colormap_data) return E_OUTOFMEMORY;
643 
644     wcolormap_data = (WORD*)colormap_data;
645     dwcolormap_data = (DWORD*)colormap_data;
646 
647     EnterCriticalSection(&This->lock);
648 
649     seek.QuadPart = This->colormap_offset;
650     hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);
651 
652     if (SUCCEEDED(hr))
653     {
654         hr = IStream_Read(This->stream, colormap_data, This->colormap_length, &bytesread);
655         if (SUCCEEDED(hr) && bytesread != This->colormap_length)
656         {
657             WARN("expected %i bytes in colormap, got %i\n", This->colormap_length, bytesread);
658             hr = E_FAIL;
659         }
660     }
661 
662     LeaveCriticalSection(&This->lock);
663 
664     if (SUCCEEDED(hr))
665     {
666         attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
667 
668         if (attribute_bitcount && This->extension_area_offset)
669             attribute_type = This->extension_area.attributes_type;
670         else if (attribute_bitcount)
671             attribute_type = ATTRIBUTE_ALPHA;
672         else
673             attribute_type = ATTRIBUTE_NO_ALPHA;
674 
675         depth = This->header.colormap_entrysize;
676         if (depth == 15)
677         {
678             depth = 16;
679             attribute_type = ATTRIBUTE_NO_ALPHA;
680         }
681 
682         memset(colors, 0, sizeof(colors));
683 
684         color = &colors[This->header.colormap_firstentry];
685 
686         /* Colormap entries can be in any truecolor format, and we have to convert them. */
687         switch (depth)
688         {
689         case 16:
690             switch (attribute_type)
691             {
692             case ATTRIBUTE_NO_ALPHA:
693             case ATTRIBUTE_UNDEFINED:
694             case ATTRIBUTE_UNDEFINED_PRESERVE:
695                 for (i=0; i<This->header.colormap_length; i++)
696                 {
697                     WORD srcval = wcolormap_data[i];
698                     *color++=0xff000000 | /* constant 255 alpha */
699                              ((srcval << 9) & 0xf80000) | /* r */
700                              ((srcval << 4) & 0x070000) | /* r - 3 bits */
701                              ((srcval << 6) & 0x00f800) | /* g */
702                              ((srcval << 1) & 0x000700) | /* g - 3 bits */
703                              ((srcval << 3) & 0x0000f8) | /* b */
704                              ((srcval >> 2) & 0x000007);  /* b - 3 bits */
705                 }
706                 break;
707             case ATTRIBUTE_ALPHA:
708             case ATTRIBUTE_PALPHA:
709                 for (i=0; i<This->header.colormap_length; i++)
710                 {
711                     WORD srcval = wcolormap_data[i];
712                     *color++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
713                              ((srcval << 9) & 0xf80000) | /* r */
714                              ((srcval << 4) & 0x070000) | /* r - 3 bits */
715                              ((srcval << 6) & 0x00f800) | /* g */
716                              ((srcval << 1) & 0x000700) | /* g - 3 bits */
717                              ((srcval << 3) & 0x0000f8) | /* b */
718                              ((srcval >> 2) & 0x000007);  /* b - 3 bits */
719                 }
720                 break;
721             default:
722                 FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
723                 hr = E_NOTIMPL;
724             }
725             break;
726         case 24:
727             for (i=0; i<This->header.colormap_length; i++)
728             {
729                 *color++=0xff000000 | /* alpha */
730                          colormap_data[i*3+2] | /* red */
731                          colormap_data[i*3+1] | /* green */
732                          colormap_data[i*3]; /* blue */
733             }
734             break;
735         case 32:
736             switch (attribute_type)
737             {
738             case ATTRIBUTE_NO_ALPHA:
739             case ATTRIBUTE_UNDEFINED:
740             case ATTRIBUTE_UNDEFINED_PRESERVE:
741                 for (i=0; i<This->header.colormap_length; i++)
742                     *color++=dwcolormap_data[i]|0xff000000;
743                 break;
744             case ATTRIBUTE_ALPHA:
745                 for (i=0; i<This->header.colormap_length; i++)
746                     *color++=dwcolormap_data[i];
747                 break;
748             case ATTRIBUTE_PALPHA:
749                 /* FIXME: Unpremultiply alpha */
750             default:
751                 FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
752                 hr = E_NOTIMPL;
753             }
754             break;
755         default:
756             FIXME("Unhandled truecolor depth %u\n", This->header.depth);
757             hr = E_NOTIMPL;
758         }
759     }
760 
761     HeapFree(GetProcessHeap(), 0, colormap_data);
762 
763     if (SUCCEEDED(hr))
764         hr = IWICPalette_InitializeCustom(pIPalette, colors, 256);
765 
766     return hr;
767 }
768 
769 static HRESULT TgaDecoder_ReadRLE(TgaDecoder *This, BYTE *imagebits, int datasize)
770 {
771     int i=0, j, bytesperpixel;
772     ULONG bytesread;
773     HRESULT hr=S_OK;
774 
775     bytesperpixel = This->header.depth / 8;
776 
777     while (i<datasize)
778     {
779         BYTE rc;
780         int count, size;
781         BYTE pixeldata[4];
782 
783         hr = IStream_Read(This->stream, &rc, 1, &bytesread);
784         if (bytesread != 1) hr = E_FAIL;
785         if (FAILED(hr)) break;
786 
787         count = (rc&0x7f)+1;
788         size = count * bytesperpixel;
789 
790         if (size + i > datasize)
791         {
792             WARN("RLE packet too large\n");
793             hr = E_FAIL;
794             break;
795         }
796 
797         if (rc&0x80)
798         {
799             /* Run-length packet */
800             hr = IStream_Read(This->stream, pixeldata, bytesperpixel, &bytesread);
801             if (bytesread != bytesperpixel) hr = E_FAIL;
802             if (FAILED(hr)) break;
803 
804             if (bytesperpixel == 1)
805                 memset(&imagebits[i], pixeldata[0], count);
806             else
807             {
808                 for (j=0; j<count; j++)
809                     memcpy(&imagebits[i+j*bytesperpixel], pixeldata, bytesperpixel);
810             }
811         }
812         else
813         {
814             /* Raw packet */
815             hr = IStream_Read(This->stream, &imagebits[i], size, &bytesread);
816             if (bytesread != size) hr = E_FAIL;
817             if (FAILED(hr)) break;
818         }
819 
820         i += size;
821     }
822 
823     return hr;
824 }
825 
826 static HRESULT TgaDecoder_ReadImage(TgaDecoder *This)
827 {
828     HRESULT hr=S_OK;
829     int datasize;
830     LARGE_INTEGER seek;
831     ULONG bytesread;
832 
833     if (This->imagebits)
834         return S_OK;
835 
836     EnterCriticalSection(&This->lock);
837 
838     if (!This->imagebits)
839     {
840         if (This->header.image_descriptor & IMAGE_RIGHTTOLEFT)
841         {
842             FIXME("Right to left image reading not implemented\n");
843             hr = E_NOTIMPL;
844         }
845 
846         if (SUCCEEDED(hr))
847         {
848             datasize = This->header.width * This->header.height * (This->header.depth / 8);
849             This->imagebits = HeapAlloc(GetProcessHeap(), 0, datasize);
850             if (!This->imagebits) hr = E_OUTOFMEMORY;
851         }
852 
853         if (SUCCEEDED(hr))
854         {
855             seek.QuadPart = This->image_offset;
856             hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);
857         }
858 
859         if (SUCCEEDED(hr))
860         {
861             if (This->header.image_type & IMAGETYPE_RLE)
862             {
863                 hr = TgaDecoder_ReadRLE(This, This->imagebits, datasize);
864             }
865             else
866             {
867                 hr = IStream_Read(This->stream, This->imagebits, datasize, &bytesread);
868                 if (SUCCEEDED(hr) && bytesread != datasize)
869                     hr = E_FAIL;
870             }
871         }
872 
873         if (SUCCEEDED(hr))
874         {
875             if (This->header.image_descriptor & IMAGE_TOPTOBOTTOM)
876             {
877                 This->origin = This->imagebits;
878                 This->stride = This->header.width * (This->header.depth / 8);
879             }
880             else
881             {
882                 This->stride = -This->header.width * (This->header.depth / 8);
883                 This->origin = This->imagebits + This->header.width * (This->header.height - 1) * (This->header.depth / 8);
884             }
885         }
886         else
887         {
888             HeapFree(GetProcessHeap(), 0, This->imagebits);
889             This->imagebits = NULL;
890         }
891     }
892 
893     LeaveCriticalSection(&This->lock);
894 
895     return hr;
896 }
897 
898 static HRESULT WINAPI TgaDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
899     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
900 {
901     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
902     HRESULT hr;
903 
904     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
905 
906     hr = TgaDecoder_ReadImage(This);
907 
908     if (SUCCEEDED(hr))
909     {
910         hr = copy_pixels(This->header.depth, This->origin,
911             This->header.width, This->header.height, This->stride,
912             prc, cbStride, cbBufferSize, pbBuffer);
913     }
914 
915     return hr;
916 }
917 
918 static HRESULT WINAPI TgaDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
919     IWICMetadataQueryReader **ppIMetadataQueryReader)
920 {
921     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
922     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
923 }
924 
925 static HRESULT WINAPI TgaDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface,
926     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
927 {
928     FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
929     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
930 }
931 
932 static HRESULT WINAPI TgaDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface,
933     IWICBitmapSource **ppIThumbnail)
934 {
935     FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
936     return WINCODEC_ERR_CODECNOTHUMBNAIL;
937 }
938 
939 static const IWICBitmapFrameDecodeVtbl TgaDecoder_Frame_Vtbl = {
940     TgaDecoder_Frame_QueryInterface,
941     TgaDecoder_Frame_AddRef,
942     TgaDecoder_Frame_Release,
943     TgaDecoder_Frame_GetSize,
944     TgaDecoder_Frame_GetPixelFormat,
945     TgaDecoder_Frame_GetResolution,
946     TgaDecoder_Frame_CopyPalette,
947     TgaDecoder_Frame_CopyPixels,
948     TgaDecoder_Frame_GetMetadataQueryReader,
949     TgaDecoder_Frame_GetColorContexts,
950     TgaDecoder_Frame_GetThumbnail
951 };
952 
953 HRESULT TgaDecoder_CreateInstance(REFIID iid, void** ppv)
954 {
955     TgaDecoder *This;
956     HRESULT ret;
957 
958     TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
959 
960     *ppv = NULL;
961 
962     This = HeapAlloc(GetProcessHeap(), 0, sizeof(TgaDecoder));
963     if (!This) return E_OUTOFMEMORY;
964 
965     This->IWICBitmapDecoder_iface.lpVtbl = &TgaDecoder_Vtbl;
966     This->IWICBitmapFrameDecode_iface.lpVtbl = &TgaDecoder_Frame_Vtbl;
967     This->ref = 1;
968     This->initialized = FALSE;
969     This->stream = NULL;
970     This->imagebits = NULL;
971     InitializeCriticalSection(&This->lock);
972     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TgaDecoder.lock");
973 
974     ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
975     IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
976 
977     return ret;
978 }
979