Evan Stade : oleaut32: Handle transparency data when loading PNG
images.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Aug 9 08:23:15 CDT 2007
Module: wine
Branch: master
Commit: a08b998f204374fedfbb73aaa7daf7a18fa2a5ee
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a08b998f204374fedfbb73aaa7daf7a18fa2a5ee
Author: Evan Stade <estade at gmail.com>
Date: Wed Aug 8 19:42:33 2007 -0700
oleaut32: Handle transparency data when loading PNG images.
---
dlls/oleaut32/olepicture.c | 98 ++++++++++++++++++++++++++++++++++++-------
1 files changed, 82 insertions(+), 16 deletions(-)
diff --git a/dlls/oleaut32/olepicture.c b/dlls/oleaut32/olepicture.c
index b12a85b..d8f01db 100644
--- a/dlls/oleaut32/olepicture.c
+++ b/dlls/oleaut32/olepicture.c
@@ -1376,6 +1376,9 @@ 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)
@@ -1397,6 +1400,9 @@ static void *load_libpng(void)
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
}
@@ -1410,13 +1416,17 @@ static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xr
png_io io;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
- INT row, rowsize, height, width;
+ INT row, rowsize, height, width, num_trans, i, j;
png_bytep* row_pointers = NULL;
png_bytep pngdata = NULL;
BITMAPINFOHEADER bmi;
- HDC hdcref = NULL;
+ HDC hdcref = NULL, hdcXor, hdcMask;
HRESULT ret;
- BOOL set_bgr = FALSE;
+ 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()) {
@@ -1435,7 +1445,7 @@ static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xr
if(setjmp(png_jmpbuf(png_ptr))){
TRACE("Error in libpng\n");
ret = E_FAIL;
- goto pngend;
+ goto end;
}
info_ptr = ppng_create_info_struct(png_ptr);
@@ -1447,19 +1457,16 @@ static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xr
png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)){
FIXME("Unsupported .PNG type: %d\n", png_ptr->color_type);
ret = E_FAIL;
- goto pngend;
+ goto end;
}
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE){
- ppng_set_palette_to_rgb(png_ptr);
- set_bgr = TRUE;
- }
+ transparency = (ppng_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values)
+ == PNG_INFO_tRNS);
- 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);
- }
+ /* 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);
@@ -1474,7 +1481,7 @@ static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xr
if(!pngdata || !row_pointers){
ret = E_FAIL;
- goto pngend;
+ goto end;
}
for (row = 0; row < height; row++){
@@ -1504,12 +1511,71 @@ static HRESULT OLEPictureImpl_LoadPNG(OLEPictureImpl *This, BYTE *xbuf, ULONG xr
(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;
-pngend:
+end:
if(png_ptr)
ppng_destroy_read_struct(&png_ptr,
(info_ptr ? &info_ptr : (png_infopp) NULL),
More information about the wine-cvs
mailing list