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