PATCH: gif support for OLE pictures
Marcus Meissner
marcus at jet.franken.de
Sun Jan 5 13:21:39 CST 2003
Hi,
This fixes a report from some weeks ago, where an app called OleLoadPicture
on a GIF resource (http://www.myhexin.com/tw2002/rjxz/download.asp?rjxz=exe1).
Please rerun autoconf and autoheader.
The application uses shdocvw.dll right after that, which does not work here,
since I lack the native setup on this machine.
So I was not able to 'see' the GIF images. But it should be correct I hope,
at least the CreateDIBSection and later GetObject does not crash.
Ciao, Marcus
Changelog:
Implemented loading of GIF pictures for the OLE Automation IPicture
interface using libungif/libgif.
Sometimes the persistant stream does not have a header.
Index: configure.ac
===================================================================
RCS file: /home/wine/wine/configure.ac,v
retrieving revision 1.116
diff -u -u -r1.116 configure.ac
--- configure.ac 4 Jan 2003 02:52:05 -0000 1.116
+++ configure.ac 5 Jan 2003 19:09:46 -0000
@@ -146,6 +146,21 @@
)
)
+GIFLIB=""
+AC_SUBST(GIFLIB)
+AC_CHECK_HEADERS(gif_lib.h,
+ AC_CHECK_LIB(ungif,DGifOpen,
+ AC_DEFINE(HAVE_LIBGIF,1,[Define if you have libgif/libungif including devel headers])
+ GIFLIB="-lungif",
+ [
+ AC_CHECK_LIB(gif,DGifOpen,
+ AC_DEFINE(HAVE_LIBGIF,1,[Define if you have libgif/libungif including devel headers])
+ JPEGLIB="-lgif"
+ )
+ ]
+ )
+)
+
AC_SUBST(XLIB)
AC_SUBST(XFILES)
Index: dlls/oleaut32/olepicture.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/olepicture.c,v
retrieving revision 1.21
diff -u -u -r1.21 olepicture.c
--- dlls/oleaut32/olepicture.c 2 Jan 2003 17:54:57 -0000 1.21
+++ dlls/oleaut32/olepicture.c 5 Jan 2003 19:09:47 -0000
@@ -42,6 +42,14 @@
#endif
#include <stdio.h>
#include <string.h>
+
+/* Must be before wine includes, the header has things conflicting with
+ * WINE headers.
+ */
+#ifdef HAVE_LIBGIF
+# include <gif_lib.h>
+#endif
+
#include "winerror.h"
#include "winbase.h"
#include "wingdi.h"
@@ -810,6 +818,26 @@
static void _jpeg_term_source(j_decompress_ptr cinfo) { }
#endif /* HAVE_LIBJPEG */
+#ifdef HAVE_LIBGIF
+struct gifdata {
+ unsigned char *data;
+ unsigned int curoff;
+ unsigned int len;
+};
+
+static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
+ struct gifdata *gd = (struct gifdata*)gif->UserData;
+
+ if (len+gd->curoff > gd->len) {
+ FIXME("Trying to read %d bytes, but only %d available.\n",len, gd->len-gd->curoff);
+ len = gd->len - gd->curoff;
+ }
+ memcpy(data, gd->data+gd->curoff, len);
+ gd->curoff += len;
+ return len;
+}
+#endif
+
/************************************************************************
* OLEPictureImpl_IPersistStream_Load (IUnknown)
*
@@ -826,30 +854,134 @@
BYTE *xbuf;
DWORD header[2];
WORD magic;
+ STATSTG statstg;
ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface);
-
+
TRACE("(%p,%p)\n",This,pStm);
+ /* Sometimes we have a header, sometimes we don't. Apply some guesses to find
+ * out whether we do.
+ */
+ hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
+ if (hr)
+ FIXME("Stat failed with hres %lx\n",hr);
hr=IStream_Read(pStm,header,8,&xread);
if (hr || xread!=8) {
FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
return hr;
}
- xread = 0;
- xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
- This->datalen = header[1];
- while (xread < header[1]) {
- ULONG nread;
- hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
- xread+=nread;
- if (hr || !nread)
- break;
+ if (header[1] > statstg.cbSize.QuadPart) {/* Incorrect header, assume none. */
+ xread = 8;
+ xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,statstg.cbSize.QuadPart);
+ memcpy(xbuf,&header,8);
+ This->datalen = statstg.cbSize.QuadPart;
+ while (xread < This->datalen) {
+ ULONG nread;
+ hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
+ xread+=nread;
+ if (hr || !nread)
+ break;
+ }
+ if (xread != This->datalen)
+ FIXME("Could only read %ld of %d bytes in no-header case?\n",xread,This->datalen);
+ } else {
+ xread = 0;
+ xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
+ This->datalen = header[1];
+ while (xread < header[1]) {
+ ULONG nread;
+ hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
+ xread+=nread;
+ if (hr || !nread)
+ break;
+ }
+ if (xread != header[1])
+ FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
}
- if (xread != header[1])
- FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
-
magic = xbuf[0] + (xbuf[1]<<8);
switch (magic) {
+ case 0x4947: { /* GIF */
+#ifdef HAVE_LIBGIF
+ struct gifdata gd;
+ GifFileType *gif;
+ BITMAPINFO *bmi;
+ HDC hdcref;
+ LPBYTE bytes;
+ int i,j,ret;
+ GifImageDesc *gid;
+ SavedImage *si;
+ ColorMapObject *cm;
+
+ gd.data = xbuf;
+ gd.curoff = 0;
+ gd.len = xread;
+ gif = DGifOpen((void*)&gd, _gif_inputfunc);
+ ret = DGifSlurp(gif);
+ if (ret == GIF_ERROR) {
+ FIXME("Failed reading GIF using libgif.\n");
+ return E_FAIL;
+ }
+ TRACE("screen height %d, width %d\n", gif->SWidth, gif->SHeight);
+ TRACE("color res %d, backgcolor %d\n", gif->SColorResolution, gif->SBackGroundColor);
+ TRACE("imgcnt %d\n", gif->ImageCount);
+ if (gif->ImageCount<1) {
+ FIXME("GIF stream does not have images inside?\n");
+ return E_FAIL;
+ }
+ TRACE("curimage: %d x %d, on %dx%d, interlace %d\n",
+ gif->Image.Width, gif->Image.Height,
+ gif->Image.Left, gif->Image.Top,
+ gif->Image.Interlace
+ );
+ /* */
+ bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
+ bytes= HeapAlloc(GetProcessHeap(),0,gif->SWidth*gif->SHeight);
+ si = gif->SavedImages+0;
+ gid = &(si->ImageDesc);
+ cm = gid->ColorMap;
+ if (!cm) cm = gif->SColorMap;
+ for (i=0;i<(1<<gif->SColorResolution);i++) {
+ bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
+ bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
+ bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
+ }
+ /* Map to in picture coordinates */
+ for (i=0;i<gid->Height;i++)
+ for (j=0;j<gid->Width;j++)
+ bytes[(gid->Top+i)*gif->SWidth+gid->Left+j]=si->RasterBits[i*gid->Width+j];
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi->bmiHeader.biWidth = gif->SWidth;
+ bmi->bmiHeader.biHeight = gif->SHeight;
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biBitCount = 8;
+ bmi->bmiHeader.biCompression = BI_RGB;
+ bmi->bmiHeader.biSizeImage = gif->SWidth*gif->SHeight;
+ bmi->bmiHeader.biXPelsPerMeter = 0;
+ bmi->bmiHeader.biYPelsPerMeter = 0;
+ bmi->bmiHeader.biClrUsed = 1 << gif->SColorResolution;
+ bmi->bmiHeader.biClrImportant = 0;
+
+ hdcref = GetDC(0);
+ This->desc.u.bmp.hbitmap=CreateDIBitmap(
+ hdcref,
+ bmi,
+ CBM_INIT,
+ bytes,
+ bmi,
+ DIB_PAL_COLORS
+ );
+ DeleteDC(hdcref);
+ This->desc.picType = PICTYPE_BITMAP;
+ OLEPictureImpl_SetBitmap(This);
+ DGifCloseFile(gif);
+ HeapFree(GetProcessHeap(),0,bytes);
+ return S_OK;
+#else
+ FIXME("Trying to load GIF, but no support for libgif/libungif compiled in.\n");
+ return E_FAIL;
+#endif
+ break;
+ }
case 0xd8ff: { /* JPEG */
#ifdef HAVE_LIBJPEG
struct jpeg_decompress_struct jd;
@@ -1009,9 +1141,18 @@
break;
}
default:
- FIXME("Unknown magic %04x\n",magic);
+ {
+ int i;
+ FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread);
hr=E_FAIL;
+ for (i=0;i<xread+8;i++) {
+ if (i<8) MESSAGE("%02x ",((unsigned char*)&header)[i]);
+ else MESSAGE("%02x ",xbuf[i-8]);
+ if (i % 10 == 9) MESSAGE("\n");
+ }
+ MESSAGE("\n");
break;
+ }
}
/* FIXME: this notify is not really documented */
More information about the wine-patches
mailing list