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:
Vadim Zeitlin
2003-05-11 10:49:27 +00:00
parent edb57eaebe
commit c9fcf5817f

View File

@@ -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;
} }
} }
} }