many fixes for PNG reading after recent alpha changes; grey scale images reading was in particular broken
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@20581 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -86,6 +86,20 @@ static void
|
|||||||
FindMaskColour(unsigned char **lines, png_uint_32 width, png_uint_32 height,
|
FindMaskColour(unsigned char **lines, png_uint_32 width, png_uint_32 height,
|
||||||
unsigned char& rMask, unsigned char& gMask, unsigned char& bMask);
|
unsigned char& rMask, unsigned char& gMask, unsigned char& bMask);
|
||||||
|
|
||||||
|
// is the pixel with this value of alpha a fully opaque one?
|
||||||
|
static inline
|
||||||
|
bool IsOpaque(unsigned char a)
|
||||||
|
{
|
||||||
|
return a == 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is the pixel with this value of alpha a fully transparent one?
|
||||||
|
static inline
|
||||||
|
bool IsTransparent(unsigned char a)
|
||||||
|
{
|
||||||
|
return !a;
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxPNGHandler implementation
|
// wxPNGHandler implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -191,9 +205,9 @@ PNGLINKAGEMODE wx_png_warning(png_structp png_ptr, png_const_charp message)
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// determine the kind of transparency we need for this image: if the only alpha
|
// determine the kind of transparency we need for this image: if the only alpha
|
||||||
// values it has are 0 and 0xff then we can simply create a mask for it, we
|
// values it has are 0 (transparent) and 0xff (opaque) then we can simply
|
||||||
// should be ok with a simple mask but otherwise we need a full blown alpha
|
// create a mask for it, we should be ok with a simple mask but otherwise we
|
||||||
// channel in wxImage
|
// need a full blown alpha channel in wxImage
|
||||||
//
|
//
|
||||||
// parameters:
|
// parameters:
|
||||||
// ptr the start of the data to examine
|
// ptr the start of the data to examine
|
||||||
@@ -206,24 +220,30 @@ CheckTransparency(const unsigned char *ptr,
|
|||||||
png_uint_32 x, png_uint_32 y, png_uint_32 w, png_uint_32 h,
|
png_uint_32 x, png_uint_32 y, png_uint_32 w, png_uint_32 h,
|
||||||
size_t numColBytes)
|
size_t numColBytes)
|
||||||
{
|
{
|
||||||
|
// we start from (x + 1, y)
|
||||||
|
x++;
|
||||||
|
|
||||||
// suppose that a mask will suffice and check all the remaining alpha
|
// suppose that a mask will suffice and check all the remaining alpha
|
||||||
// values to see if it does
|
// values to see if it does
|
||||||
unsigned char a2;
|
|
||||||
unsigned const char *ptr2 = ptr;
|
unsigned const char *ptr2 = ptr;
|
||||||
for ( png_uint_32 y2 = y; y2 < h; y2++ )
|
for ( png_uint_32 y2 = y; y2 < h; y2++ )
|
||||||
{
|
{
|
||||||
for ( png_uint_32 x2 = x + 1; x2 < w; x2++ )
|
for ( png_uint_32 x2 = x; x2 < w; x2++ )
|
||||||
{
|
{
|
||||||
// skip the grey byte
|
// skip the grey or colour byte(s)
|
||||||
ptr2 += numColBytes;
|
ptr2 += numColBytes;
|
||||||
a2 = *ptr2++;
|
|
||||||
|
|
||||||
if ( a2 && a2 != 0xff )
|
unsigned char a2 = *ptr2++;
|
||||||
|
|
||||||
|
if ( !IsTransparent(a2) && !IsOpaque(a2) )
|
||||||
{
|
{
|
||||||
// not fully opaque nor fully transparent, hence need alpha
|
// not fully opaque nor fully transparent, hence need alpha
|
||||||
return Transparency_Alpha;
|
return Transparency_Alpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// during the next loop iteration check all the pixels in the row
|
||||||
|
x = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mask will be enough
|
// mask will be enough
|
||||||
@@ -238,14 +258,12 @@ unsigned char *InitAlpha(wxImage *image, png_uint_32 x, png_uint_32 y)
|
|||||||
unsigned char *alpha = image->GetAlpha();
|
unsigned char *alpha = image->GetAlpha();
|
||||||
|
|
||||||
// set alpha for the pixels we had so far
|
// set alpha for the pixels we had so far
|
||||||
for ( png_uint_32 y2 = 0; y2 <= y; y2++ )
|
png_uint_32 end = y * image->GetWidth() + x;
|
||||||
{
|
for ( png_uint_32 i = 0; i < end; i++ )
|
||||||
for ( png_uint_32 x2 = 0; x2 < x; x2++ )
|
|
||||||
{
|
{
|
||||||
// all the previous pixels were opaque
|
// all the previous pixels were opaque
|
||||||
*alpha++ = 0xff;
|
*alpha++ = 0xff;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
@@ -339,7 +357,7 @@ void CopyDataFromPNG(wxImage *image,
|
|||||||
|
|
||||||
// the first time we encounter a transparent pixel we must
|
// the first time we encounter a transparent pixel we must
|
||||||
// decide about what to do about them
|
// decide about what to do about them
|
||||||
if ( a != 0xff && transparency == Transparency_None )
|
if ( !IsOpaque(a) && transparency == Transparency_None )
|
||||||
{
|
{
|
||||||
// we'll need at least the mask for this image and
|
// we'll need at least the mask for this image and
|
||||||
// maybe even full alpha channel info: the former is
|
// maybe even full alpha channel info: the former is
|
||||||
@@ -371,7 +389,24 @@ void CopyDataFromPNG(wxImage *image,
|
|||||||
|
|
||||||
switch ( transparency )
|
switch ( transparency )
|
||||||
{
|
{
|
||||||
|
case Transparency_Mask:
|
||||||
|
if ( IsTransparent(a) )
|
||||||
|
{
|
||||||
|
*ptrDst++ = rMask;
|
||||||
|
*ptrDst++ = bMask;
|
||||||
|
*ptrDst++ = gMask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// else: !transparent
|
||||||
|
|
||||||
|
// must be opaque then as otherwise we shouldn't be
|
||||||
|
// using the mask at all
|
||||||
|
wxASSERT_MSG( IsOpaque(a), _T("logic error") );
|
||||||
|
|
||||||
|
// fall through
|
||||||
|
|
||||||
case Transparency_Alpha:
|
case Transparency_Alpha:
|
||||||
|
if ( alpha )
|
||||||
*alpha++ = a;
|
*alpha++ = a;
|
||||||
// fall through
|
// fall through
|
||||||
|
|
||||||
@@ -380,11 +415,6 @@ void CopyDataFromPNG(wxImage *image,
|
|||||||
*ptrDst++ = g;
|
*ptrDst++ = g;
|
||||||
*ptrDst++ = g;
|
*ptrDst++ = g;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Transparency_Mask:
|
|
||||||
*ptrDst++ = rMask;
|
|
||||||
*ptrDst++ = bMask;
|
|
||||||
*ptrDst++ = gMask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -403,7 +433,7 @@ void CopyDataFromPNG(wxImage *image,
|
|||||||
|
|
||||||
// the logic here is the same as for the grey case except
|
// the logic here is the same as for the grey case except
|
||||||
// where noted
|
// where noted
|
||||||
if ( a != 0xff && transparency == Transparency_None )
|
if ( !IsOpaque(a) && transparency == Transparency_None )
|
||||||
{
|
{
|
||||||
transparency = CheckTransparency
|
transparency = CheckTransparency
|
||||||
(
|
(
|
||||||
@@ -427,17 +457,9 @@ void CopyDataFromPNG(wxImage *image,
|
|||||||
|
|
||||||
switch ( transparency )
|
switch ( transparency )
|
||||||
{
|
{
|
||||||
case Transparency_Alpha:
|
|
||||||
*alpha++ = a;
|
|
||||||
// fall through
|
|
||||||
|
|
||||||
case Transparency_None:
|
|
||||||
*ptrDst++ = r;
|
|
||||||
*ptrDst++ = g;
|
|
||||||
*ptrDst++ = b;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Transparency_Mask:
|
case Transparency_Mask:
|
||||||
|
if ( IsTransparent(a) )
|
||||||
|
{
|
||||||
// if we couldn't find a unique colour for the mask, we
|
// if we couldn't find a unique colour for the mask, we
|
||||||
// can have real pixels with the same value as the mask
|
// can have real pixels with the same value as the mask
|
||||||
// and it's better to slightly change their colour than
|
// and it's better to slightly change their colour than
|
||||||
@@ -450,6 +472,26 @@ void CopyDataFromPNG(wxImage *image,
|
|||||||
*ptrDst++ = rMask;
|
*ptrDst++ = rMask;
|
||||||
*ptrDst++ = bMask;
|
*ptrDst++ = bMask;
|
||||||
*ptrDst++ = gMask;
|
*ptrDst++ = gMask;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// else: !transparent
|
||||||
|
|
||||||
|
// must be opaque then as otherwise we shouldn't be
|
||||||
|
// using the mask at all
|
||||||
|
wxASSERT_MSG( IsOpaque(a), _T("logic error") );
|
||||||
|
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
case Transparency_Alpha:
|
||||||
|
if ( alpha )
|
||||||
|
*alpha++ = a;
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
case Transparency_None:
|
||||||
|
*ptrDst++ = r;
|
||||||
|
*ptrDst++ = g;
|
||||||
|
*ptrDst++ = b;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user