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