Vincent Povirk : windowscodecs: Implement CopyPixels for 8-bit ICO icons.
Alexandre Julliard
julliard at winehq.org
Fri Aug 21 09:32:32 CDT 2009
Module: wine
Branch: master
Commit: 1c25ee8ce7b8d506a606d2313cd66843b6d631d3
URL: http://source.winehq.org/git/wine.git/?a=commit;h=1c25ee8ce7b8d506a606d2313cd66843b6d631d3
Author: Vincent Povirk <vincent at codeweavers.com>
Date: Thu Aug 20 11:58:49 2009 -0500
windowscodecs: Implement CopyPixels for 8-bit ICO icons.
---
dlls/windowscodecs/icoformat.c | 185 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 183 insertions(+), 2 deletions(-)
diff --git a/dlls/windowscodecs/icoformat.c b/dlls/windowscodecs/icoformat.c
index dfdf94b..cb545a1 100644
--- a/dlls/windowscodecs/icoformat.c
+++ b/dlls/windowscodecs/icoformat.c
@@ -24,6 +24,7 @@
#include "windef.h"
#include "winbase.h"
+#include "wingdi.h"
#include "objbase.h"
#include "wincodec.h"
@@ -68,6 +69,7 @@ typedef struct {
LONG ref;
ICONDIRENTRY entry;
IcoDecoder *parent;
+ BYTE *bits;
} IcoFrameDecode;
static HRESULT WINAPI IcoFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
@@ -114,6 +116,7 @@ static ULONG WINAPI IcoFrameDecode_Release(IWICBitmapFrameDecode *iface)
if (ref == 0)
{
IUnknown_Release((IUnknown*)This->parent);
+ HeapFree(GetProcessHeap(), 0, This->bits);
HeapFree(GetProcessHeap(), 0, This);
}
@@ -154,11 +157,188 @@ static HRESULT WINAPI IcoFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
return WINCODEC_ERR_PALETTEUNAVAILABLE;
}
+static inline void pixel_set_trans(DWORD* pixel, BOOL transparent)
+{
+ if (transparent) *pixel = 0;
+ else *pixel |= 0xff000000;
+}
+
+static HRESULT IcoFrameDecode_ReadPixels(IcoFrameDecode *This)
+{
+ BITMAPINFOHEADER bih;
+ DWORD colors[256];
+ UINT colorcount=0;
+ LARGE_INTEGER seek;
+ ULONG bytesread;
+ HRESULT hr;
+ BYTE *tempdata = NULL;
+ BYTE *bits = NULL;
+ UINT bitsStride;
+ UINT bitsSize;
+ UINT width, height;
+
+ width = This->entry.bWidth ? This->entry.bWidth : 256;
+ height = This->entry.bHeight ? This->entry.bHeight : 256;
+
+ /* read the BITMAPINFOHEADER */
+ seek.QuadPart = This->entry.dwDIBOffset;
+ hr = IStream_Seek(This->parent->stream, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr)) goto fail;
+
+ hr = IStream_Read(This->parent->stream, &bih, sizeof(BITMAPINFOHEADER), &bytesread);
+ if (FAILED(hr) || bytesread != sizeof(BITMAPINFOHEADER)) goto fail;
+
+ if (This->entry.wBitCount <= 8)
+ {
+ /* read the palette */
+ colorcount = This->entry.bColorCount ? This->entry.bColorCount : 256;
+
+ hr = IStream_Read(This->parent->stream, colors, sizeof(RGBQUAD)*colorcount, &bytesread);
+ if (FAILED(hr) || bytesread != sizeof(RGBQUAD)*colorcount) goto fail;
+ }
+
+ bitsStride = width * 4;
+ bitsSize = bitsStride * height;
+
+ /* read the XOR data */
+ switch (This->entry.wBitCount)
+ {
+ case 8:
+ {
+ UINT xorBytesPerRow = (width+3)/4*4;
+ UINT xorBytes = xorBytesPerRow * height;
+ INT xorStride;
+ BYTE *xorRow;
+ BYTE *bitsRow;
+ UINT x, y;
+
+ tempdata = HeapAlloc(GetProcessHeap(), 0, xorBytes);
+ if (!tempdata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hr = IStream_Read(This->parent->stream, tempdata, xorBytes, &bytesread);
+ if (FAILED(hr) || bytesread != xorBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ xorStride = -xorBytesPerRow;
+ xorRow = tempdata + (height-1)*xorBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ xorStride = xorBytesPerRow;
+ xorRow = tempdata;
+ }
+
+ bits = HeapAlloc(GetProcessHeap(), 0, bitsSize);
+
+ /* palette-map the 8-bit data */
+ bitsRow = bits;
+ for (y=0; y<height; y++) {
+ BYTE *xorByte=xorRow;
+ DWORD *bitsPixel=(DWORD*)bitsRow;
+ for (x=0; x<width; x++)
+ *bitsPixel++ = colors[*xorByte++];
+ xorRow += xorStride;
+ bitsRow += bitsStride;
+ }
+
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ break;
+ }
+ default:
+ FIXME("unsupported bitcount: %u\n", This->entry.wBitCount);
+ goto fail;
+ }
+
+ if (This->entry.wBitCount < 32)
+ {
+ /* set alpha data based on the AND mask */
+ UINT andBytesPerRow = (width+31)/32*4;
+ UINT andBytes = andBytesPerRow * height;
+ INT andStride;
+ BYTE *andRow;
+ BYTE *bitsRow;
+ UINT x, y;
+
+ tempdata = HeapAlloc(GetProcessHeap(), 0, andBytes);
+ if (!tempdata)
+ {
+ hr = E_OUTOFMEMORY;
+ goto fail;
+ }
+
+ hr = IStream_Read(This->parent->stream, tempdata, andBytes, &bytesread);
+ if (FAILED(hr) || bytesread != andBytes) goto fail;
+
+ if (bih.biHeight > 0) /* bottom-up DIB */
+ {
+ andStride = -andBytesPerRow;
+ andRow = tempdata + (height-1)*andBytesPerRow;
+ }
+ else /* top-down DIB */
+ {
+ andStride = andBytesPerRow;
+ andRow = tempdata;
+ }
+
+ bitsRow = bits;
+ for (y=0; y<height; y++) {
+ BYTE *andByte=andRow;
+ DWORD *bitsPixel=(DWORD*)bitsRow;
+ for (x=0; x<width; x+=8) {
+ BYTE andVal=*andByte++;
+ pixel_set_trans(bitsPixel++, andVal>>7&1);
+ if (x+1 < width) pixel_set_trans(bitsPixel++, andVal>>6&1);
+ if (x+2 < width) pixel_set_trans(bitsPixel++, andVal>>5&1);
+ if (x+3 < width) pixel_set_trans(bitsPixel++, andVal>>4&1);
+ if (x+4 < width) pixel_set_trans(bitsPixel++, andVal>>3&1);
+ if (x+5 < width) pixel_set_trans(bitsPixel++, andVal>>2&1);
+ if (x+6 < width) pixel_set_trans(bitsPixel++, andVal>>1&1);
+ if (x+7 < width) pixel_set_trans(bitsPixel++, andVal&1);
+ }
+ andRow += andStride;
+ bitsRow += bitsStride;
+ }
+
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ }
+
+ This->bits = bits;
+
+ return S_OK;
+
+fail:
+ HeapFree(GetProcessHeap(), 0, tempdata);
+ HeapFree(GetProcessHeap(), 0, bits);
+ if (SUCCEEDED(hr)) hr = E_FAIL;
+ TRACE("<-- %x\n", hr);
+ return hr;
+}
+
static HRESULT WINAPI IcoFrameDecode_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;
+ IcoFrameDecode *This = (IcoFrameDecode*)iface;
+ HRESULT hr;
+ UINT width, height, stride;
+ TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
+
+ if (!This->bits)
+ {
+ hr = IcoFrameDecode_ReadPixels(This);
+ if (FAILED(hr)) return hr;
+ }
+
+ width = This->entry.bWidth ? This->entry.bWidth : 256;
+ height = This->entry.bHeight ? This->entry.bHeight : 256;
+ stride = width * 4;
+
+ return copy_pixels(32, This->bits, width, height, stride,
+ prc, cbStride, cbBufferSize, pbBuffer);
}
static HRESULT WINAPI IcoFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
@@ -362,6 +542,7 @@ static HRESULT WINAPI IcoDecoder_GetFrame(IWICBitmapDecoder *iface,
result->lpVtbl = &IcoFrameDecode_Vtbl;
result->ref = 1;
result->parent = This;
+ result->bits = NULL;
/* read the icon entry */
seek.QuadPart = sizeof(ICONHEADER) + sizeof(ICONDIRENTRY) * index;
More information about the wine-cvs
mailing list