[1/2] oleaut32: add PNG loading [try2]
Evan Stade
estade at gmail.com
Tue Jun 19 15:12:57 CDT 2007
Hi,
Try2: This time the rowsize is correctly aligned (on 4-byte
boundaries) and palette-mode PNGs are allowed as well as RGB-mode
PNGs.
Changelog:
*added support to decode some PNG files
*added check for png.h / dynamic loading of libpng.so
configure.ac | 2
dlls/oleaut32/olepicture.c | 205 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 207 insertions(+), 0 deletions(-)
--
Evan Stade
-------------- next part --------------
diff --git a/configure.ac b/configure.ac
index 070faac..d922153 100644
--- a/configure.ac
+++ b/configure.ac
@@ -209,6 +209,7 @@ AC_CHECK_HEADERS(\
netinet/tcp_fsm.h \
openssl/err.h \
openssl/ssl.h \
+ png.h \
poll.h \
process.h \
pthread.h \
@@ -1102,6 +1103,7 @@ then
WINE_GET_SONAME(ncurses,waddch)
WINE_GET_SONAME(curses,waddch)
WINE_GET_SONAME(jpeg,jpeg_start_decompress)
+ WINE_GET_SONAME(png, png_create_read_struct)
WINE_GET_SONAME(capi20,capi20_isinstalled)
WINE_GET_SONAME(sane,sane_init)
fi
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c
index 5d3a9f0..7b3363f 100644
--- a/dlls/oleaut32/olepicture.c
+++ b/dlls/oleaut32/olepicture.c
@@ -67,6 +67,14 @@ #include "wine/unicode.h"
#include "wine/wingdi16.h"
+#ifdef HAVE_PNG_H
+#undef FAR
+#include <png.h>
+#ifndef SONAME_LIBPNG
+#define SONAME_LIBPNG "libpng.so"
+#endif
+#endif
+
#ifdef HAVE_JPEGLIB_H
/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
#define XMD_H
@@ -1337,6 +1345,197 @@ static HRESULT OLEPictureImpl_LoadDIB(OL
return S_OK;
}
+/*****************************************************
+* start of PNG-specific code
+* currently only supports colortype PNG_COLOR_TYPE_RGB
+*/
+#ifdef HAVE_PNG_H
+typedef struct{
+ ULONG position;
+ ULONG size;
+ BYTE * buff;
+} png_io;
+
+static void png_stream_read_data(png_structp png_ptr, png_bytep data,
+ png_size_t length)
+{
+ png_io * io_ptr = png_ptr->io_ptr;
+
+ if(length + io_ptr->position > io_ptr->size){
+ length = io_ptr->size - io_ptr->position;
+ }
+
+ memcpy(data, io_ptr->buff + io_ptr->position, length);
+
+ io_ptr->position += length;
+}
+
+static void *libpng_handle;
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(png_create_read_struct);
+MAKE_FUNCPTR(png_create_info_struct);
+MAKE_FUNCPTR(png_set_read_fn);
+MAKE_FUNCPTR(png_read_info);
+MAKE_FUNCPTR(png_read_image);
+MAKE_FUNCPTR(png_get_rowbytes);
+MAKE_FUNCPTR(png_set_bgr);
+MAKE_FUNCPTR(png_destroy_read_struct);
+MAKE_FUNCPTR(png_set_palette_to_rgb);
+MAKE_FUNCPTR(png_read_update_info);
+#undef MAKE_FUNCPTR
+
+static void *load_libpng(void)
+{
+ if((libpng_handle = wine_dlopen(SONAME_LIBPNG, RTLD_NOW, NULL, 0)) != NULL) {
+
+#define LOAD_FUNCPTR(f) \
+ if((p##f = wine_dlsym(libpng_handle, #f, NULL, 0)) == NULL) { \
+ libpng_handle = NULL; \
+ return NULL; \
+ }
+ LOAD_FUNCPTR(png_create_read_struct);
+ LOAD_FUNCPTR(png_create_info_struct);
+ LOAD_FUNCPTR(png_set_read_fn);
+ LOAD_FUNCPTR(png_read_info);
+ LOAD_FUNCPTR(png_read_image);
+ LOAD_FUNCPTR(png_get_rowbytes);
+ LOAD_FUNCPTR(png_set_bgr);
+ LOAD_FUNCPTR(png_destroy_read_struct);
+ LOAD_FUNCPTR(png_set_palette_to_rgb);
+ LOAD_FUNCPTR(png_read_update_info);
+
+#undef LOAD_FUNCPTR
+ }
+ return libpng_handle;
+}
+#endif /* HAVE_PNG_H */
+
+static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
+{
+#ifdef HAVE_PNG_H
+ png_io io;
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ INT row, rowsize, height, width;
+ png_bytep* row_pointers = NULL;
+ png_bytep pngdata = NULL;
+ BITMAPINFOHEADER bmi;
+ HDC hdcref = NULL;
+ HRESULT ret;
+ BOOL set_bgr = FALSE;
+
+ if(!libpng_handle) {
+ if(!load_libpng()) {
+ FIXME("Failed reading PNG because unable to find %s\n",
+ SONAME_LIBPNG);
+ return E_FAIL;
+ }
+ }
+
+ io.size = xread;
+ io.position = 0;
+ io.buff = xbuf;
+
+ png_ptr = ppng_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+
+ if(setjmp(png_jmpbuf(png_ptr))){
+ TRACE("Error in libpng\n");
+ ret = E_FAIL;
+ goto pngend;
+ }
+
+ info_ptr = ppng_create_info_struct(png_ptr);
+ ppng_set_read_fn(png_ptr, &io, png_stream_read_data);
+ ppng_read_info(png_ptr, info_ptr);
+
+ if(!(png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+ png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)){
+ FIXME("Unsupported .PNG type: %d\n", png_ptr->color_type);
+ ret = E_FAIL;
+ goto pngend;
+ }
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE){
+ ppng_set_palette_to_rgb(png_ptr);
+ set_bgr = TRUE;
+ }
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+ png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ set_bgr){
+ ppng_set_bgr(png_ptr);
+ }
+
+ ppng_read_update_info(png_ptr, info_ptr);
+
+ rowsize = ppng_get_rowbytes(png_ptr, info_ptr);
+ /* align rowsize to 4-byte boundary */
+ rowsize += 4 - rowsize % 4;
+ height = info_ptr->height;
+ width = info_ptr->width;
+
+ pngdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, height * rowsize);
+ row_pointers = HeapAlloc(GetProcessHeap(), 0, height * (sizeof(VOID *)));
+
+ if(!pngdata || !row_pointers){
+ ret = E_FAIL;
+ goto pngend;
+ }
+
+ for (row = 0; row < height; row++){
+ row_pointers[row] = pngdata + row * rowsize;
+ }
+
+ ppng_read_image(png_ptr, row_pointers);
+
+ bmi.biSize = sizeof(bmi);
+ bmi.biWidth = width;
+ bmi.biHeight = -height;
+ bmi.biPlanes = 1;
+ bmi.biBitCount = info_ptr->channels * 8;
+ bmi.biCompression = BI_RGB;
+ bmi.biSizeImage = height * rowsize;
+ bmi.biXPelsPerMeter = 0;
+ bmi.biYPelsPerMeter = 0;
+ bmi.biClrUsed = 0;
+ bmi.biClrImportant = 0;
+
+ hdcref = GetDC(0);
+ This->desc.u.bmp.hbitmap = CreateDIBitmap(
+ hdcref,
+ &bmi,
+ CBM_INIT,
+ pngdata,
+ (BITMAPINFO*)&bmi,
+ DIB_RGB_COLORS
+ );
+ DeleteDC(hdcref);
+ This->desc.picType = PICTYPE_BITMAP;
+ OLEPictureImpl_SetBitmap(This);
+ ret = S_OK;
+
+pngend:
+ if(png_ptr)
+ ppng_destroy_read_struct(&png_ptr,
+ (info_ptr ? &info_ptr : (png_infopp) NULL),
+ (png_infopp)NULL);
+ if(row_pointers)
+ HeapFree(GetProcessHeap(), 0, row_pointers);
+ if(pngdata)
+ HeapFree(GetProcessHeap(), 0, pngdata);
+
+ return ret;
+#else /* HAVE_PNG_H */
+ ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
+ return E_FAIL;
+#endif
+}
+
+/*****************************************************
+* start of Icon-specific code
+*/
+
static HRESULT OLEPictureImpl_LoadIcon(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
{
HICON hicon;
@@ -1586,6 +1785,9 @@ static HRESULT WINAPI OLEPictureImpl_Loa
case 0x4d42: /* Bitmap */
hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
break;
+ case 0x5089: /* PNG */
+ hr = OLEPictureImpl_LoadPNG(This, xbuf, xread);
+ break;
case 0x0000: { /* ICON , first word is dwReserved */
hr = OLEPictureImpl_LoadIcon(This, xbuf, xread);
break;
@@ -1881,6 +2083,9 @@ static HRESULT WINAPI OLEPictureImpl_Sav
case 0x4947:
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty);
break;
+ case 0x5089:
+ FIXME("(%p,%p,%d), PICTYPE_BITMAP (format PNG) not implemented!\n",This,pStm,fClearDirty);
+ break;
default:
FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty);
break;
--
1.4.1
More information about the wine-patches
mailing list