xref: /reactos/dll/win32/windowscodecs/tgaformat.c (revision 4567e13e)
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