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