Vincent Povirk : windowscodecs: Implement CopyPixels for the TGA decoder.

Alexandre Julliard julliard at winehq.org
Fri Oct 22 12:30:43 CDT 2010


Module: wine
Branch: master
Commit: c2533f36913b7af66383ebeb772ad9abcb423bd1
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c2533f36913b7af66383ebeb772ad9abcb423bd1

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Mon Jun  7 17:13:56 2010 -0500

windowscodecs: Implement CopyPixels for the TGA decoder.

---

 dlls/windowscodecs/tgaformat.c |  108 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 106 insertions(+), 2 deletions(-)

diff --git a/dlls/windowscodecs/tgaformat.c b/dlls/windowscodecs/tgaformat.c
index f778cd4..57dca7d 100644
--- a/dlls/windowscodecs/tgaformat.c
+++ b/dlls/windowscodecs/tgaformat.c
@@ -72,6 +72,13 @@ typedef struct {
     BOOL initialized;
     IStream *stream;
     tga_header header;
+    BYTE *imagebits;
+    BYTE *origin;
+    int stride;
+    ULONG id_offset;
+    ULONG colormap_length;
+    ULONG colormap_offset;
+    ULONG image_offset;
     CRITICAL_SECTION lock;
 } TgaDecoder;
 
@@ -125,6 +132,7 @@ static ULONG WINAPI TgaDecoder_Release(IWICBitmapDecoder *iface)
         DeleteCriticalSection(&This->lock);
         if (This->stream)
             IStream_Release(This->stream);
+        HeapFree(GetProcessHeap(), 0, This->imagebits);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -209,6 +217,15 @@ static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
         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;
+
     /* FIXME: Read footer if there is one. */
 
     IStream_AddRef(pIStream);
@@ -436,11 +453,97 @@ static HRESULT WINAPI TgaDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface,
     return E_NOTIMPL;
 }
 
+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)
+            {
+                FIXME("RLE decoding not implemented\n");
+                hr = E_NOTIMPL;
+            }
+            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)
 {
-    FIXME("(%p,%p,%u,%u,%p):stub\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
-    return E_NOTIMPL;
+    TgaDecoder *This = decoder_from_frame(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,
@@ -497,6 +600,7 @@ HRESULT TgaDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
     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");
 




More information about the wine-cvs mailing list