From 1b5352688f3646b0721e5973ce727238c0ae3d3e Mon Sep 17 00:00:00 2001 From: thierry Date: Fri, 15 Jan 2016 17:35:10 +0100 Subject: [PATCH 1/3] better png transparency handling --- modules/imgcodecs/src/grfmt_png.cpp | 27 ++++++++++++++++----------- modules/imgcodecs/src/loadsave.cpp | 5 ----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index 2f4a62bae..e75f0bf45 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -187,15 +187,12 @@ bool PngDecoder::readHeader() if( bit_depth <= 8 || bit_depth == 16 ) { + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); switch(color_type) { case PNG_COLOR_TYPE_RGB: - m_type = CV_8UC3; - break; case PNG_COLOR_TYPE_PALETTE: - png_get_tRNS( png_ptr, info_ptr, &trans, &num_trans, &trans_values); - //Check if there is a transparency value in the palette - if ( num_trans > 0 ) + if( num_trans > 0 ) m_type = CV_8UC4; else m_type = CV_8UC3; @@ -203,8 +200,14 @@ bool PngDecoder::readHeader() case PNG_COLOR_TYPE_RGB_ALPHA: m_type = CV_8UC4; break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + m_type = CV_8UC2; + break; default: - m_type = CV_8UC1; + if( num_trans > 0 ) + m_type = CV_8UC2; + else + m_type = CV_8UC1; } if( bit_depth == 16 ) m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type)); @@ -227,7 +230,7 @@ bool PngDecoder::readData( Mat& img ) volatile bool result = false; AutoBuffer _buffer(m_height); uchar** buffer = _buffer; - int color = img.channels() > 1; + int color = img.channels() > 2; uchar* data = img.ptr(); int step = (int)img.step; @@ -246,7 +249,7 @@ bool PngDecoder::readData( Mat& img ) else if( !isBigEndian() ) png_set_swap( png_ptr ); - if(img.channels() < 4) + if(img.channels() != 4 && img.channels() != 2) { /* observation: png_read_image() writes 400 bytes beyond * end of data when reading a 400x118 color png @@ -257,12 +260,13 @@ bool PngDecoder::readData( Mat& img ) * stripping alpha.. 18.11.2004 Axel Walthelm */ png_set_strip_alpha( png_ptr ); - } + } else + png_set_tRNS_to_alpha( png_ptr ); if( m_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); - if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 ) + if( (m_color_type & PNG_COLOR_MASK_COLOR) != 0 && m_bit_depth < 8 ) #if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \ (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18) png_set_expand_gray_1_2_4_to_8( png_ptr ); @@ -270,7 +274,7 @@ bool PngDecoder::readData( Mat& img ) png_set_gray_1_2_4_to_8( png_ptr ); #endif - if( CV_MAT_CN(m_type) > 1 && color ) + if( CV_MAT_CN(m_type) > 2 && color ) png_set_bgr( png_ptr ); // convert RGB to BGR else if( color ) png_set_gray_to_rgb( png_ptr ); // Gray->RGB @@ -410,6 +414,7 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16, channels == 1 ? PNG_COLOR_TYPE_GRAY : + channels == 2 ? PNG_COLOR_TYPE_GRAY_ALPHA : channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index 70a31c37a..e0080bd3b 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -452,8 +452,6 @@ static bool imwrite_( const String& filename, const Mat& image, Mat temp; const Mat* pimage = ℑ - CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 ); - ImageEncoder encoder = findEncoder( filename ); if( !encoder ) CV_Error( CV_StsError, "could not find a writer for the specified extension" ); @@ -590,9 +588,6 @@ bool imencode( const String& ext, InputArray _image, { Mat image = _image.getMat(); - int channels = image.channels(); - CV_Assert( channels == 1 || channels == 3 || channels == 4 ); - ImageEncoder encoder = findEncoder( ext ); if( !encoder ) CV_Error( CV_StsError, "could not find encoder for the specified extension" ); From bdb9cf4d476a3d11956dc058ee114f0dd0718406 Mon Sep 17 00:00:00 2001 From: thierry Date: Mon, 18 Jan 2016 17:56:26 +0100 Subject: [PATCH 2/3] fix inversed grayscale conditional --- modules/imgcodecs/src/grfmt_png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index e75f0bf45..5b33c6648 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -266,7 +266,7 @@ bool PngDecoder::readData( Mat& img ) if( m_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); - if( (m_color_type & PNG_COLOR_MASK_COLOR) != 0 && m_bit_depth < 8 ) + if( (m_color_type & PNG_COLOR_MASK_COLOR) == 0 && m_bit_depth < 8 ) #if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \ (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18) png_set_expand_gray_1_2_4_to_8( png_ptr ); From ea911d34c60d3868debc9dc3a5dc1179d93d5baf Mon Sep 17 00:00:00 2001 From: thierry Date: Thu, 14 Jul 2016 14:46:05 +0200 Subject: [PATCH 3/3] remove 2-channel png encoder/decoder support --- modules/imgcodecs/src/grfmt_png.cpp | 18 ++++++------------ modules/imgcodecs/src/loadsave.cpp | 5 +++++ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_png.cpp b/modules/imgcodecs/src/grfmt_png.cpp index a7dae8348..c8ff2447f 100644 --- a/modules/imgcodecs/src/grfmt_png.cpp +++ b/modules/imgcodecs/src/grfmt_png.cpp @@ -187,27 +187,22 @@ bool PngDecoder::readHeader() if( bit_depth <= 8 || bit_depth == 16 ) { - png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); if( num_trans > 0 ) m_type = CV_8UC4; else m_type = CV_8UC3; break; + case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA: m_type = CV_8UC4; break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - m_type = CV_8UC2; - break; default: - if( num_trans > 0 ) - m_type = CV_8UC2; - else - m_type = CV_8UC1; + m_type = CV_8UC1; } if( bit_depth == 16 ) m_type = CV_MAKETYPE(CV_16U, CV_MAT_CN(m_type)); @@ -230,7 +225,7 @@ bool PngDecoder::readData( Mat& img ) volatile bool result = false; AutoBuffer _buffer(m_height); uchar** buffer = _buffer; - int color = img.channels() > 2; + int color = img.channels() > 1; if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height ) { @@ -247,7 +242,7 @@ bool PngDecoder::readData( Mat& img ) else if( !isBigEndian() ) png_set_swap( png_ptr ); - if(img.channels() != 4 && img.channels() != 2) + if(img.channels() < 4) { /* observation: png_read_image() writes 400 bytes beyond * end of data when reading a 400x118 color png @@ -272,7 +267,7 @@ bool PngDecoder::readData( Mat& img ) png_set_gray_1_2_4_to_8( png_ptr ); #endif - if( CV_MAT_CN(m_type) > 2 && color ) + if( (m_color_type & PNG_COLOR_MASK_COLOR) && color ) png_set_bgr( png_ptr ); // convert RGB to BGR else if( color ) png_set_gray_to_rgb( png_ptr ); // Gray->RGB @@ -413,7 +408,6 @@ bool PngEncoder::write( const Mat& img, const std::vector& params ) png_set_IHDR( png_ptr, info_ptr, width, height, depth == CV_8U ? isBilevel?1:8 : 16, channels == 1 ? PNG_COLOR_TYPE_GRAY : - channels == 2 ? PNG_COLOR_TYPE_GRAY_ALPHA : channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); diff --git a/modules/imgcodecs/src/loadsave.cpp b/modules/imgcodecs/src/loadsave.cpp index e0080bd3b..70a31c37a 100644 --- a/modules/imgcodecs/src/loadsave.cpp +++ b/modules/imgcodecs/src/loadsave.cpp @@ -452,6 +452,8 @@ static bool imwrite_( const String& filename, const Mat& image, Mat temp; const Mat* pimage = ℑ + CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 ); + ImageEncoder encoder = findEncoder( filename ); if( !encoder ) CV_Error( CV_StsError, "could not find a writer for the specified extension" ); @@ -588,6 +590,9 @@ bool imencode( const String& ext, InputArray _image, { Mat image = _image.getMat(); + int channels = image.channels(); + CV_Assert( channels == 1 || channels == 3 || channels == 4 ); + ImageEncoder encoder = findEncoder( ext ); if( !encoder ) CV_Error( CV_StsError, "could not find encoder for the specified extension" );