/*
 * 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)
{
    HRESULT hr;
    IWICComponentInfo *compinfo;

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

    hr = CreateComponentInfo(&CLSID_WineTgaDecoder, &compinfo);
    if (FAILED(hr)) return hr;

    hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
        (void**)ppIDecoderInfo);

    IWICComponentInfo_Release(compinfo);

    return hr;
}

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;
}
