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