oleaut32: Handle transparency data when loading PNG images.

This commit is contained in:
Evan Stade 2007-08-08 19:42:33 -07:00 committed by Alexandre Julliard
parent ad8ea1b0a6
commit a08b998f20
1 changed files with 82 additions and 16 deletions

View File

@ -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),