jscript: Return double from to_integer.
[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     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     *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_NOTINITIALIZED;
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 IUnknown_AddRef((IUnknown*)This);
472 }
473
474 static ULONG WINAPI TgaDecoder_Frame_Release(IWICBitmapFrameDecode *iface)
475 {
476     TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
477     return IUnknown_Release((IUnknown*)This);
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(IUnknown *pUnkOuter, REFIID iid, void** ppv)
943 {
944     TgaDecoder *This;
945     HRESULT ret;
946
947     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
948
949     *ppv = NULL;
950
951     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
952
953     This = HeapAlloc(GetProcessHeap(), 0, sizeof(TgaDecoder));
954     if (!This) return E_OUTOFMEMORY;
955
956     This->IWICBitmapDecoder_iface.lpVtbl = &TgaDecoder_Vtbl;
957     This->IWICBitmapFrameDecode_iface.lpVtbl = &TgaDecoder_Frame_Vtbl;
958     This->ref = 1;
959     This->initialized = FALSE;
960     This->stream = NULL;
961     This->imagebits = NULL;
962     InitializeCriticalSection(&This->lock);
963     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TgaDecoder.lock");
964
965     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
966     IUnknown_Release((IUnknown*)This);
967
968     return ret;
969 }