mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-06 06:20:56 +00:00
oleaut32: Use WIC to decode PNG images.
This commit is contained in:
parent
ab199297bc
commit
e5d2a6932d
|
@ -8,7 +8,6 @@ IMPORTS = uuid ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll
|
|||
DELAYIMPORTS = comctl32 urlmon windowscodecs
|
||||
EXTRADEFS = -D_OLEAUT32_ -DCOM_NO_WINDOWS_H \
|
||||
-DENTRY_PREFIX=OLEAUTPS_ -DPROXY_CLSID=CLSID_PSDispatch -DPROXY_DELEGATION -DREGISTER_PROXY_DLL
|
||||
EXTRAINCL = @PNGINCL@
|
||||
|
||||
C_SRCS = \
|
||||
connpt.c \
|
||||
|
|
|
@ -46,13 +46,6 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_PNG_H
|
||||
#include <png.h>
|
||||
#endif
|
||||
|
||||
/* Must be before wine includes, the header has things conflicting with
|
||||
* WINE headers.
|
||||
*/
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
|
@ -1191,254 +1184,6 @@ static HRESULT OLEPictureImpl_LoadWICDecoder(OLEPictureImpl *This, REFCLSID deco
|
|||
return hr;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* start of PNG-specific code
|
||||
* currently only supports colortype PNG_COLOR_TYPE_RGB
|
||||
*/
|
||||
#ifdef SONAME_LIBPNG
|
||||
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);
|
||||
MAKE_FUNCPTR(png_get_tRNS);
|
||||
MAKE_FUNCPTR(png_get_PLTE);
|
||||
MAKE_FUNCPTR(png_set_expand);
|
||||
#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);
|
||||
LOAD_FUNCPTR(png_get_tRNS);
|
||||
LOAD_FUNCPTR(png_get_PLTE);
|
||||
LOAD_FUNCPTR(png_set_expand);
|
||||
|
||||
#undef LOAD_FUNCPTR
|
||||
}
|
||||
return libpng_handle;
|
||||
}
|
||||
#endif /* SONAME_LIBPNG */
|
||||
|
||||
static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xread)
|
||||
{
|
||||
#ifdef SONAME_LIBPNG
|
||||
png_io io;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
INT row, rowsize, height, width, num_trans, i, j;
|
||||
png_bytep* row_pointers = NULL;
|
||||
png_bytep pngdata = NULL;
|
||||
BITMAPINFOHEADER bmi;
|
||||
HDC hdcref = NULL, hdcXor, hdcMask;
|
||||
HRESULT ret;
|
||||
BOOL transparency;
|
||||
png_bytep trans;
|
||||
png_color_16p trans_values;
|
||||
COLORREF white = RGB(255, 255, 255), black = RGB(0, 0, 0);
|
||||
HBITMAP hbmoldXor, hbmoldMask, temp;
|
||||
|
||||
if(!libpng_handle) {
|
||||
if(!load_libpng()) {
|
||||
ERR("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 end;
|
||||
}
|
||||
|
||||
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 ||
|
||||
png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)){
|
||||
FIXME("Unsupported .PNG type: %d\n", png_ptr->color_type);
|
||||
ret = E_FAIL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
transparency = (ppng_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values)
|
||||
== PNG_INFO_tRNS);
|
||||
|
||||
/* sets format from anything to RGBA */
|
||||
ppng_set_expand(png_ptr);
|
||||
/* sets format to BGRA */
|
||||
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 = (rowsize + 3) & ~3;
|
||||
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 end;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
/* only fully-transparent alpha is handled */
|
||||
if((info_ptr->channels != 4) || !transparency){
|
||||
ReleaseDC(0, hdcref);
|
||||
goto succ;
|
||||
}
|
||||
|
||||
This->hbmXor = CreateDIBitmap(
|
||||
hdcref,
|
||||
&bmi,
|
||||
CBM_INIT,
|
||||
pngdata,
|
||||
(BITMAPINFO*)&bmi,
|
||||
DIB_RGB_COLORS
|
||||
);
|
||||
|
||||
/* set transparent pixels to black, all others to white */
|
||||
for(i = 0; i < height; i++){
|
||||
for(j = 3; j < rowsize; j += 4){
|
||||
if(row_pointers[i][j] == 0)
|
||||
*((DWORD*)(&row_pointers[i][j - 3])) = black;
|
||||
else
|
||||
*((DWORD*)(&row_pointers[i][j - 3])) = white;
|
||||
}
|
||||
}
|
||||
|
||||
temp = CreateDIBitmap(
|
||||
hdcref,
|
||||
&bmi,
|
||||
CBM_INIT,
|
||||
pngdata,
|
||||
(BITMAPINFO*)&bmi,
|
||||
DIB_RGB_COLORS
|
||||
);
|
||||
|
||||
ReleaseDC(0, hdcref);
|
||||
|
||||
This->hbmMask = CreateBitmap(width,-height,1,1,NULL);
|
||||
hdcXor = CreateCompatibleDC(NULL);
|
||||
hdcMask = CreateCompatibleDC(NULL);
|
||||
|
||||
hbmoldXor = SelectObject(hdcXor,temp);
|
||||
hbmoldMask = SelectObject(hdcMask,This->hbmMask);
|
||||
SetBkColor(hdcXor,black);
|
||||
BitBlt(hdcMask,0,0,width,height,hdcXor,0,0,SRCCOPY);
|
||||
|
||||
SelectObject(hdcXor,This->hbmXor);
|
||||
DeleteObject(temp);
|
||||
|
||||
SetTextColor(hdcXor,white);
|
||||
SetBkColor(hdcXor,black);
|
||||
BitBlt(hdcXor,0,0,width,height,hdcMask,0,0,SRCAND);
|
||||
|
||||
SelectObject(hdcXor,hbmoldXor);
|
||||
SelectObject(hdcMask,hbmoldMask);
|
||||
|
||||
DeleteDC(hdcXor);
|
||||
DeleteDC(hdcMask);
|
||||
|
||||
succ:
|
||||
This->desc.picType = PICTYPE_BITMAP;
|
||||
OLEPictureImpl_SetBitmap(This);
|
||||
ret = S_OK;
|
||||
|
||||
end:
|
||||
if(png_ptr)
|
||||
ppng_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : NULL, NULL);
|
||||
HeapFree(GetProcessHeap(), 0, row_pointers);
|
||||
HeapFree(GetProcessHeap(), 0, pngdata);
|
||||
return ret;
|
||||
#else /* SONAME_LIBPNG */
|
||||
ERR("Trying to load PNG picture, but PNG supported not compiled in.\n");
|
||||
return E_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* start of Icon-specific code
|
||||
*/
|
||||
|
@ -1721,7 +1466,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
|
|||
hr = OLEPictureImpl_LoadDIB(This, xbuf, xread);
|
||||
break;
|
||||
case BITMAP_FORMAT_PNG: /* PNG */
|
||||
hr = OLEPictureImpl_LoadPNG(This, xbuf, xread);
|
||||
hr = OLEPictureImpl_LoadWICDecoder(This, &CLSID_WICPngDecoder, xbuf, xread);
|
||||
break;
|
||||
case BITMAP_FORMAT_APM: /* APM */
|
||||
hr = OLEPictureImpl_LoadAPM(This, xbuf, xread);
|
||||
|
|
Loading…
Reference in a new issue