/*
 * Copyright 2010 Vincent Povirk for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
#include "wine/port.h"

#include <stdarg.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wincodec.h"

#include "wincodecs_private.h"

#include "wine/debug.h"
#include "wine/library.h"

WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);

#include "pshpack1.h"

typedef struct {
    BYTE id_length;
    BYTE colormap_type;
    BYTE image_type;
    /* Colormap Specification */
    WORD colormap_firstentry;
    WORD colormap_length;
    BYTE colormap_entrysize;
    /* Image Specification */
    WORD xorigin;
    WORD yorigin;
    WORD width;
    WORD height;
    BYTE depth;
    BYTE image_descriptor;
} tga_header;

#define IMAGETYPE_COLORMAPPED 1
#define IMAGETYPE_TRUECOLOR 2
#define IMAGETYPE_GRAYSCALE 3
#define IMAGETYPE_RLE 8

#define IMAGE_ATTRIBUTE_BITCOUNT_MASK 0xf
#define IMAGE_RIGHTTOLEFT 0x10
#define IMAGE_TOPTOBOTTOM 0x20

typedef struct {
    DWORD extension_area_offset;
    DWORD developer_directory_offset;
    char magic[18];
} tga_footer;

static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";

typedef struct {
    WORD size;
    char author_name[41];
    char author_comments[324];
    WORD timestamp[6];
    char job_name[41];
    WORD job_timestamp[6];
    char software_id[41];
    WORD software_version;
    char software_version_letter;
    DWORD key_color;
    WORD pixel_width;
    WORD pixel_height;
    WORD gamma_numerator;
    WORD gamma_denominator;
    DWORD color_correction_offset;
    DWORD thumbnail_offset;
    DWORD scanline_offset;
    BYTE attributes_type;
} tga_extension_area;

#define ATTRIBUTE_NO_ALPHA 0
#define ATTRIBUTE_UNDEFINED 1
#define ATTRIBUTE_UNDEFINED_PRESERVE 2
#define ATTRIBUTE_ALPHA 3
#define ATTRIBUTE_PALPHA 4

#include "poppack.h"

typedef struct {
    IWICBitmapDecoder IWICBitmapDecoder_iface;
    IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
    LONG ref;
    BOOL initialized;
    IStream *stream;
    tga_header header;
    tga_extension_area extension_area;
    BYTE *imagebits;
    BYTE *origin;
    int stride;
    ULONG id_offset;
    ULONG colormap_length;
    ULONG colormap_offset;
    ULONG image_offset;
    ULONG extension_area_offset;
    ULONG developer_directory_offset;
    CRITICAL_SECTION lock;
} TgaDecoder;

static inline TgaDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
{
    return CONTAINING_RECORD(iface, TgaDecoder, IWICBitmapDecoder_iface);
}

static inline TgaDecoder *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
{
    return CONTAINING_RECORD(iface, TgaDecoder, IWICBitmapFrameDecode_iface);
}

static HRESULT WINAPI TgaDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
    void **ppv)
{
    TgaDecoder *This = impl_from_IWICBitmapDecoder(iface);
    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);

    if (!ppv) return E_INVALIDARG;

    if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
    {
        *ppv = This;
    }
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}

static ULONG WINAPI TgaDecoder_AddRef(IWICBitmapDecoder *iface)
{
    TgaDecoder *This = impl_from_IWICBitmapDecoder(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p) refcount=%u\n", iface, ref);

    return ref;
}

static ULONG WINAPI TgaDecoder_Release(IWICBitmapDecoder *iface)
{
    TgaDecoder *This = impl_from_IWICBitmapDecoder(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p) refcount=%u\n", iface, ref);

    if (ref == 0)
    {
        This->lock.DebugInfo->Spare[0] = 0;
        DeleteCriticalSection(&This->lock);
        if (This->stream)
            IStream_Release(This->stream);
        HeapFree(GetProcessHeap(), 0, This->imagebits);
        HeapFree(GetProcessHeap(), 0, This);
    }

    return ref;
}

static HRESULT WINAPI TgaDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
    DWORD *pdwCapability)
{
    FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
    return E_NOTIMPL;
}

static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
    WICDecodeOptions cacheOptions)
{
    TgaDecoder *This = impl_from_IWICBitmapDecoder(iface);
    HRESULT hr=S_OK;
    DWORD bytesread;
    LARGE_INTEGER seek;
    tga_footer footer;
    int attribute_bitcount;
    int mapped_depth=0;

    TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);

    EnterCriticalSection(&This->lock);

    if (This->initialized)
    {
        hr = WINCODEC_ERR_WRONGSTATE;
        goto end;
    }

    seek.QuadPart = 0;
    hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
    if (FAILED(hr)) goto end;

    hr = IStream_Read(pIStream, &This->header, sizeof(tga_header), &bytesread);
    if (SUCCEEDED(hr) && bytesread != sizeof(tga_header))
    {
        TRACE("got only %u bytes\n", bytesread);
        hr = E_FAIL;
    }
    if (FAILED(hr)) goto end;

    TRACE("imagetype=%u, colormap type=%u, depth=%u, image descriptor=0x%x\n",
        This->header.image_type, This->header.colormap_type,
        This->header.depth, This->header.image_descriptor);

    /* Sanity checking. Since TGA has no clear identifying markers, we need
     * to be careful to not load a non-TGA image. */
    switch (This->header.image_type)
    {
    case IMAGETYPE_COLORMAPPED:
    case IMAGETYPE_COLORMAPPED|IMAGETYPE_RLE:
        if (This->header.colormap_type != 1)
            hr = E_FAIL;
        mapped_depth = This->header.colormap_entrysize;
        break;
    case IMAGETYPE_TRUECOLOR:
    case IMAGETYPE_TRUECOLOR|IMAGETYPE_RLE:
        if (This->header.colormap_type != 0 && This->header.colormap_type != 1)
            hr = E_FAIL;
        mapped_depth = This->header.depth;
        break;
    case IMAGETYPE_GRAYSCALE:
    case IMAGETYPE_GRAYSCALE|IMAGETYPE_RLE:
        if (This->header.colormap_type != 0)
            hr = E_FAIL;
        mapped_depth = 0;
        break;
    default:
        hr = E_FAIL;
    }

    if (This->header.depth != 8 && This->header.depth != 16 &&
        This->header.depth != 24 && This->header.depth != 32)
        hr = E_FAIL;

    if ((This->header.image_descriptor & 0xc0) != 0)
        hr = E_FAIL;

    attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;

    if (attribute_bitcount &&
        !((mapped_depth == 32 && attribute_bitcount == 8) ||
          (mapped_depth == 16 && attribute_bitcount == 1)))
        hr = E_FAIL;

    if (FAILED(hr))
    {
        WARN("bad tga header\n");
        goto end;
    }

    /* Locate data in the file based on the header. */
    This->id_offset = sizeof(tga_header);
    This->colormap_offset = This->id_offset + This->header.id_length;
    if (This->header.colormap_type == 1)
        This->colormap_length = ((This->header.colormap_entrysize+7)/8) * This->header.colormap_length;
    else
        This->colormap_length = 0;
    This->image_offset = This->colormap_offset + This->colormap_length;

    /* Read footer if there is one */
    seek.QuadPart = -sizeof(tga_footer);
    hr = IStream_Seek(pIStream, seek, STREAM_SEEK_END, NULL);

    if (SUCCEEDED(hr)) {
        hr = IStream_Read(pIStream, &footer, sizeof(tga_footer), &bytesread);
        if (SUCCEEDED(hr) && bytesread != sizeof(tga_footer))
        {
            TRACE("got only %u footer bytes\n", bytesread);
            hr = E_FAIL;
        }

        if (memcmp(footer.magic, tga_footer_magic, sizeof(tga_footer_magic)) == 0)
        {
            This->extension_area_offset = footer.extension_area_offset;
            This->developer_directory_offset = footer.developer_directory_offset;
        }
        else
        {
            This->extension_area_offset = 0;
            This->developer_directory_offset = 0;
        }
    }
    else
    {
        /* File is too small to have a footer. */
        This->extension_area_offset = 0;
        This->developer_directory_offset = 0;
        hr = S_OK;
    }

    if (This->extension_area_offset)
    {
        seek.QuadPart = This->extension_area_offset;
        hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
        if (FAILED(hr)) goto end;

        hr = IStream_Read(pIStream, &This->extension_area, sizeof(tga_extension_area), &bytesread);
        if (SUCCEEDED(hr) && bytesread != sizeof(tga_extension_area))
        {
            TRACE("got only %u extension area bytes\n", bytesread);
            hr = E_FAIL;
        }
        if (SUCCEEDED(hr) && This->extension_area.size < 495)
        {
            TRACE("extension area is only %u bytes long\n", This->extension_area.size);
            hr = E_FAIL;
        }
        if (FAILED(hr)) goto end;
    }

    IStream_AddRef(pIStream);
    This->stream = pIStream;
    This->initialized = TRUE;

end:
    LeaveCriticalSection(&This->lock);
    return hr;
}

static HRESULT WINAPI TgaDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
    GUID *pguidContainerFormat)
{
    memcpy(pguidContainerFormat, &GUID_WineContainerFormatTga, sizeof(GUID));
    return S_OK;
}

static HRESULT WINAPI TgaDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
    IWICBitmapDecoderInfo **ppIDecoderInfo)
{
    FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
    return E_NOTIMPL;
}

static HRESULT WINAPI TgaDecoder_CopyPalette(IWICBitmapDecoder *iface,
    IWICPalette *pIPalette)
{
    FIXME("(%p,%p): stub\n", iface, pIPalette);
    return E_NOTIMPL;
}

static HRESULT WINAPI TgaDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
    IWICMetadataQueryReader **ppIMetadataQueryReader)
{
    FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
    return E_NOTIMPL;
}

static HRESULT WINAPI TgaDecoder_GetPreview(IWICBitmapDecoder *iface,
    IWICBitmapSource **ppIBitmapSource)
{
    FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
    return WINCODEC_ERR_UNSUPPORTEDOPERATION;
}

static HRESULT WINAPI TgaDecoder_GetColorContexts(IWICBitmapDecoder *iface,
    UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
{
    FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
    return WINCODEC_ERR_UNSUPPORTEDOPERATION;
}

static HRESULT WINAPI TgaDecoder_GetThumbnail(IWICBitmapDecoder *iface,
    IWICBitmapSource **ppIThumbnail)
{
    FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
    return WINCODEC_ERR_CODECNOTHUMBNAIL;
}

static HRESULT WINAPI TgaDecoder_GetFrameCount(IWICBitmapDecoder *iface,
    UINT *pCount)
{
    *pCount = 1;
    return S_OK;
}

static HRESULT WINAPI TgaDecoder_GetFrame(IWICBitmapDecoder *iface,
    UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
{
    TgaDecoder *This = impl_from_IWICBitmapDecoder(iface);
    TRACE("(%p,%p)\n", iface, ppIBitmapFrame);

    if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED;

    if (index != 0) return E_INVALIDARG;

    IWICBitmapDecoder_AddRef(iface);
    *ppIBitmapFrame = &This->IWICBitmapFrameDecode_iface;

    return S_OK;
}

static const IWICBitmapDecoderVtbl TgaDecoder_Vtbl = {
    TgaDecoder_QueryInterface,
    TgaDecoder_AddRef,
    TgaDecoder_Release,
    TgaDecoder_QueryCapability,
    TgaDecoder_Initialize,
    TgaDecoder_GetContainerFormat,
    TgaDecoder_GetDecoderInfo,
    TgaDecoder_CopyPalette,
    TgaDecoder_GetMetadataQueryReader,
    TgaDecoder_GetPreview,
    TgaDecoder_GetColorContexts,
    TgaDecoder_GetThumbnail,
    TgaDecoder_GetFrameCount,
    TgaDecoder_GetFrame
};

static HRESULT WINAPI TgaDecoder_Frame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
    void **ppv)
{
    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);

    if (!ppv) return E_INVALIDARG;

    if (IsEqualIID(&IID_IUnknown, iid) ||
        IsEqualIID(&IID_IWICBitmapSource, iid) ||
        IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
    {
        *ppv = iface;
    }
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}

static ULONG WINAPI TgaDecoder_Frame_AddRef(IWICBitmapFrameDecode *iface)
{
    TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
    return IUnknown_AddRef((IUnknown*)This);
}

static ULONG WINAPI TgaDecoder_Frame_Release(IWICBitmapFrameDecode *iface)
{
    TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
    return IUnknown_Release((IUnknown*)This);
}

static HRESULT WINAPI TgaDecoder_Frame_GetSize(IWICBitmapFrameDecode *iface,
    UINT *puiWidth, UINT *puiHeight)
{
    TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);

    *puiWidth = This->header.width;
    *puiHeight = This->header.height;

    TRACE("(%p)->(%u,%u)\n", iface, *puiWidth, *puiHeight);

    return S_OK;
}

static HRESULT WINAPI TgaDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *iface,
    WICPixelFormatGUID *pPixelFormat)
{
    TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
    int attribute_bitcount;
    byte attribute_type;

    TRACE("(%p,%p)\n", iface, pPixelFormat);

    attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;

    if (attribute_bitcount && This->extension_area_offset)
        attribute_type = This->extension_area.attributes_type;
    else if (attribute_bitcount)
        attribute_type = ATTRIBUTE_ALPHA;
    else
        attribute_type = ATTRIBUTE_NO_ALPHA;

    switch (This->header.image_type & ~IMAGETYPE_RLE)
    {
    case IMAGETYPE_COLORMAPPED:
        switch (This->header.depth)
        {
        case 8:
            memcpy(pPixelFormat, &GUID_WICPixelFormat8bppIndexed, sizeof(GUID));
            break;
        default:
            FIXME("Unhandled indexed color depth %u\n", This->header.depth);
            return E_NOTIMPL;
        }
        break;
    case IMAGETYPE_TRUECOLOR:
        switch (This->header.depth)
        {
        case 16:
            switch (attribute_type)
            {
            case ATTRIBUTE_NO_ALPHA:
            case ATTRIBUTE_UNDEFINED:
            case ATTRIBUTE_UNDEFINED_PRESERVE:
                memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGR555, sizeof(GUID));
                break;
            case ATTRIBUTE_ALPHA:
            case ATTRIBUTE_PALPHA:
                memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGRA5551, sizeof(GUID));
                break;
            default:
                FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
                return E_NOTIMPL;
            }
            break;
        case 24:
            memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID));
            break;
        case 32:
            switch (attribute_type)
            {
            case ATTRIBUTE_NO_ALPHA:
            case ATTRIBUTE_UNDEFINED:
            case ATTRIBUTE_UNDEFINED_PRESERVE:
                memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGR, sizeof(GUID));
                break;
            case ATTRIBUTE_ALPHA:
                memcpy(pPixelFormat, &GUID_WICPixelFormat32bppBGRA, sizeof(GUID));
                break;
            case ATTRIBUTE_PALPHA:
                memcpy(pPixelFormat, &GUID_WICPixelFormat32bppPBGRA, sizeof(GUID));
                break;
            default:
                FIXME("Unhandled 32-bit attribute type %u\n", attribute_type);
                return E_NOTIMPL;
            }
            break;
        default:
            FIXME("Unhandled truecolor depth %u\n", This->header.depth);
            return E_NOTIMPL;
        }
        break;
    case IMAGETYPE_GRAYSCALE:
        switch (This->header.depth)
        {
        case 8:
            memcpy(pPixelFormat, &GUID_WICPixelFormat8bppGray, sizeof(GUID));
            break;
        case 16:
            memcpy(pPixelFormat, &GUID_WICPixelFormat16bppGray, sizeof(GUID));
            break;
        default:
            FIXME("Unhandled grayscale depth %u\n", This->header.depth);
            return E_NOTIMPL;
        }
        break;
    default:
        ERR("Unknown image type %u\n", This->header.image_type);
        return E_FAIL;
    }

    return S_OK;
}

static HRESULT WINAPI TgaDecoder_Frame_GetResolution(IWICBitmapFrameDecode *iface,
    double *pDpiX, double *pDpiY)
{
    FIXME("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
    return E_NOTIMPL;
}

static HRESULT WINAPI TgaDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
    IWICPalette *pIPalette)
{
    TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
    HRESULT hr=S_OK;
    WICColor colors[256], *color;
    BYTE *colormap_data;
    WORD *wcolormap_data;
    DWORD *dwcolormap_data;
    LARGE_INTEGER seek;
    ULONG bytesread;
    int depth, attribute_bitcount, attribute_type;
    int i;

    TRACE("(%p,%p)\n", iface, pIPalette);

    if (!This->colormap_length)
    {
        WARN("no colormap present in this file\n");
        return WINCODEC_ERR_PALETTEUNAVAILABLE;
    }

    if (This->header.colormap_firstentry + This->header.colormap_length > 256)
    {
        FIXME("cannot read colormap with %i entries starting at %i\n",
            This->header.colormap_firstentry + This->header.colormap_length,
            This->header.colormap_firstentry);
        return E_FAIL;
    }

    colormap_data = HeapAlloc(GetProcessHeap(), 0, This->colormap_length);
    if (!colormap_data) return E_OUTOFMEMORY;

    wcolormap_data = (WORD*)colormap_data;
    dwcolormap_data = (DWORD*)colormap_data;

    EnterCriticalSection(&This->lock);

    seek.QuadPart = This->colormap_offset;
    hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);

    if (SUCCEEDED(hr))
    {
        hr = IStream_Read(This->stream, colormap_data, This->colormap_length, &bytesread);
        if (SUCCEEDED(hr) && bytesread != This->colormap_length)
        {
            WARN("expected %i bytes in colormap, got %i\n", This->colormap_length, bytesread);
            hr = E_FAIL;
        }
    }

    LeaveCriticalSection(&This->lock);

    if (SUCCEEDED(hr))
    {
        attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;

        if (attribute_bitcount && This->extension_area_offset)
            attribute_type = This->extension_area.attributes_type;
        else if (attribute_bitcount)
            attribute_type = ATTRIBUTE_ALPHA;
        else
            attribute_type = ATTRIBUTE_NO_ALPHA;

        depth = This->header.colormap_entrysize;
        if (depth == 15)
        {
            depth = 16;
            attribute_type = ATTRIBUTE_NO_ALPHA;
        }

        memset(colors, 0, sizeof(colors));

        color = &colors[This->header.colormap_firstentry];

        /* Colormap entries can be in any truecolor format, and we have to convert them. */
        switch (depth)
        {
        case 16:
            switch (attribute_type)
            {
            case ATTRIBUTE_NO_ALPHA:
            case ATTRIBUTE_UNDEFINED:
            case ATTRIBUTE_UNDEFINED_PRESERVE:
                for (i=0; i<This->header.colormap_length; i++)
                {
                    WORD srcval = wcolormap_data[i];
                    *color++=0xff000000 | /* constant 255 alpha */
                             ((srcval << 9) & 0xf80000) | /* r */
                             ((srcval << 4) & 0x070000) | /* r - 3 bits */
                             ((srcval << 6) & 0x00f800) | /* g */
                             ((srcval << 1) & 0x000700) | /* g - 3 bits */
                             ((srcval << 3) & 0x0000f8) | /* b */
                             ((srcval >> 2) & 0x000007);  /* b - 3 bits */
                }
                break;
            case ATTRIBUTE_ALPHA:
            case ATTRIBUTE_PALPHA:
                for (i=0; i<This->header.colormap_length; i++)
                {
                    WORD srcval = wcolormap_data[i];
                    *color++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
                             ((srcval << 9) & 0xf80000) | /* r */
                             ((srcval << 4) & 0x070000) | /* r - 3 bits */
                             ((srcval << 6) & 0x00f800) | /* g */
                             ((srcval << 1) & 0x000700) | /* g - 3 bits */
                             ((srcval << 3) & 0x0000f8) | /* b */
                             ((srcval >> 2) & 0x000007);  /* b - 3 bits */
                }
                break;
            default:
                FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
                hr = E_NOTIMPL;
            }
            break;
        case 24:
            for (i=0; i<This->header.colormap_length; i++)
            {
                *color++=0xff000000 | /* alpha */
                         colormap_data[i*3+2] | /* red */
                         colormap_data[i*3+1] | /* green */
                         colormap_data[i*3]; /* blue */
            }
            break;
        case 32:
            switch (attribute_type)
            {
            case ATTRIBUTE_NO_ALPHA:
            case ATTRIBUTE_UNDEFINED:
            case ATTRIBUTE_UNDEFINED_PRESERVE:
                for (i=0; i<This->header.colormap_length; i++)
                    *color++=dwcolormap_data[i]|0xff000000;
                break;
            case ATTRIBUTE_ALPHA:
                for (i=0; i<This->header.colormap_length; i++)
                    *color++=dwcolormap_data[i];
                break;
            case ATTRIBUTE_PALPHA:
                /* FIXME: Unpremultiply alpha */
            default:
                FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
                hr = E_NOTIMPL;
            }
            break;
        default:
            FIXME("Unhandled truecolor depth %u\n", This->header.depth);
            hr = E_NOTIMPL;
        }
    }

    HeapFree(GetProcessHeap(), 0, colormap_data);

    if (SUCCEEDED(hr))
        hr = IWICPalette_InitializeCustom(pIPalette, colors, 256);

    return hr;
}

static HRESULT TgaDecoder_ReadRLE(TgaDecoder *This, BYTE *imagebits, int datasize)
{
    int i=0, j, bytesperpixel;
    ULONG bytesread;
    HRESULT hr=S_OK;

    bytesperpixel = This->header.depth / 8;

    while (i<datasize)
    {
        BYTE rc;
        int count, size;
        BYTE pixeldata[4];

        hr = IStream_Read(This->stream, &rc, 1, &bytesread);
        if (bytesread != 1) hr = E_FAIL;
        if (FAILED(hr)) break;

        count = (rc&0x7f)+1;
        size = count * bytesperpixel;

        if (size + i > datasize)
        {
            WARN("RLE packet too large\n");
            hr = E_FAIL;
            break;
        }

        if (rc&0x80)
        {
            /* Run-length packet */
            hr = IStream_Read(This->stream, pixeldata, bytesperpixel, &bytesread);
            if (bytesread != bytesperpixel) hr = E_FAIL;
            if (FAILED(hr)) break;

            if (bytesperpixel == 1)
                memset(&imagebits[i], pixeldata[0], count);
            else
            {
                for (j=0; j<count; j++)
                    memcpy(&imagebits[i+j*bytesperpixel], pixeldata, bytesperpixel);
            }
        }
        else
        {
            /* Raw packet */
            hr = IStream_Read(This->stream, &imagebits[i], size, &bytesread);
            if (bytesread != size) hr = E_FAIL;
            if (FAILED(hr)) break;
        }

        i += size;
    }

    return hr;
}

static HRESULT TgaDecoder_ReadImage(TgaDecoder *This)
{
    HRESULT hr=S_OK;
    int datasize;
    LARGE_INTEGER seek;
    ULONG bytesread;

    if (This->imagebits)
        return S_OK;

    EnterCriticalSection(&This->lock);

    if (!This->imagebits)
    {
        if (This->header.image_descriptor & IMAGE_RIGHTTOLEFT)
        {
            FIXME("Right to left image reading not implemented\n");
            hr = E_NOTIMPL;
        }

        if (SUCCEEDED(hr))
        {
            datasize = This->header.width * This->header.height * (This->header.depth / 8);
            This->imagebits = HeapAlloc(GetProcessHeap(), 0, datasize);
            if (!This->imagebits) hr = E_OUTOFMEMORY;
        }

        if (SUCCEEDED(hr))
        {
            seek.QuadPart = This->image_offset;
            hr = IStream_Seek(This->stream, seek, STREAM_SEEK_SET, NULL);
        }

        if (SUCCEEDED(hr))
        {
            if (This->header.image_type & IMAGETYPE_RLE)
            {
                hr = TgaDecoder_ReadRLE(This, This->imagebits, datasize);
            }
            else
            {
                hr = IStream_Read(This->stream, This->imagebits, datasize, &bytesread);
                if (SUCCEEDED(hr) && bytesread != datasize)
                    hr = E_FAIL;
            }
        }

        if (SUCCEEDED(hr))
        {
            if (This->header.image_descriptor & IMAGE_TOPTOBOTTOM)
            {
                This->origin = This->imagebits;
                This->stride = This->header.width * (This->header.depth / 8);
            }
            else
            {
                This->stride = -This->header.width * (This->header.depth / 8);
                This->origin = This->imagebits + This->header.width * (This->header.height - 1) * (This->header.depth / 8);
            }
        }
        else
        {
            HeapFree(GetProcessHeap(), 0, This->imagebits);
            This->imagebits = NULL;
        }
    }

    LeaveCriticalSection(&This->lock);

    return hr;
}

static HRESULT WINAPI TgaDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface,
    const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
{
    TgaDecoder *This = impl_from_IWICBitmapFrameDecode(iface);
    HRESULT hr;

    TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);

    hr = TgaDecoder_ReadImage(This);

    if (SUCCEEDED(hr))
    {
        hr = copy_pixels(This->header.depth, This->origin,
            This->header.width, This->header.height, This->stride,
            prc, cbStride, cbBufferSize, pbBuffer);
    }

    return hr;
}

static HRESULT WINAPI TgaDecoder_Frame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
    IWICMetadataQueryReader **ppIMetadataQueryReader)
{
    FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
    return WINCODEC_ERR_UNSUPPORTEDOPERATION;
}

static HRESULT WINAPI TgaDecoder_Frame_GetColorContexts(IWICBitmapFrameDecode *iface,
    UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
{
    FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
    return WINCODEC_ERR_UNSUPPORTEDOPERATION;
}

static HRESULT WINAPI TgaDecoder_Frame_GetThumbnail(IWICBitmapFrameDecode *iface,
    IWICBitmapSource **ppIThumbnail)
{
    FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
    return WINCODEC_ERR_CODECNOTHUMBNAIL;
}

static const IWICBitmapFrameDecodeVtbl TgaDecoder_Frame_Vtbl = {
    TgaDecoder_Frame_QueryInterface,
    TgaDecoder_Frame_AddRef,
    TgaDecoder_Frame_Release,
    TgaDecoder_Frame_GetSize,
    TgaDecoder_Frame_GetPixelFormat,
    TgaDecoder_Frame_GetResolution,
    TgaDecoder_Frame_CopyPalette,
    TgaDecoder_Frame_CopyPixels,
    TgaDecoder_Frame_GetMetadataQueryReader,
    TgaDecoder_Frame_GetColorContexts,
    TgaDecoder_Frame_GetThumbnail
};

HRESULT TgaDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
{
    TgaDecoder *This;
    HRESULT ret;

    TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);

    *ppv = NULL;

    if (pUnkOuter) return CLASS_E_NOAGGREGATION;

    This = HeapAlloc(GetProcessHeap(), 0, sizeof(TgaDecoder));
    if (!This) return E_OUTOFMEMORY;

    This->IWICBitmapDecoder_iface.lpVtbl = &TgaDecoder_Vtbl;
    This->IWICBitmapFrameDecode_iface.lpVtbl = &TgaDecoder_Frame_Vtbl;
    This->ref = 1;
    This->initialized = FALSE;
    This->stream = NULL;
    This->imagebits = NULL;
    InitializeCriticalSection(&This->lock);
    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TgaDecoder.lock");

    ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
    IUnknown_Release((IUnknown*)This);

    return ret;
}
