[FIXED] PNG: read/write degrades/corrupts image
[FIXED] PNG: read/write degrades/corrupts image
Reference post: viewtopic.php?f=1&t=22128
Test environment: IM 6.8.0.2 x64 debug, MSVC 11, Win7 x64
Problem: a simple file read & file write changes the shading of the following image (via color reduction), unless '-set colorspace RGB' is specified.
http://cssignet.free.fr/png-test-corpus ... dbe-c0.png
Another file with the same issue (but more noticeable), notice the grays turn to blacks:
http://cssignet.free.fr/png-test-corpus ... dbe-c4.png
I am using the Magick++ interface, but was also able to reproduce this same behavior with convert.exe. I can post a resulting output file if needed, but the output issue is clear upon comparison; the images become progressively darker, and contain fewer colors, with each iteration.
Convert.exe:
convert "01-c3-shouldbe-c0.png" "01-c3-shouldbe-c0.converted.png"
Magick++ (same behavior)
Image input;
input.read( "01-c3-shouldbe-c0.png" );
input.write( "01-c3-shouldbe-c0.imread.png" );
Moreover, looping on a read/write causes the progressive degradation of the image on each loop iteration. See referenced post for code sample.
Reference post: viewtopic.php?f=1&t=22128
Thank you
Test environment: IM 6.8.0.2 x64 debug, MSVC 11, Win7 x64
Problem: a simple file read & file write changes the shading of the following image (via color reduction), unless '-set colorspace RGB' is specified.
http://cssignet.free.fr/png-test-corpus ... dbe-c0.png
Another file with the same issue (but more noticeable), notice the grays turn to blacks:
http://cssignet.free.fr/png-test-corpus ... dbe-c4.png
I am using the Magick++ interface, but was also able to reproduce this same behavior with convert.exe. I can post a resulting output file if needed, but the output issue is clear upon comparison; the images become progressively darker, and contain fewer colors, with each iteration.
Convert.exe:
convert "01-c3-shouldbe-c0.png" "01-c3-shouldbe-c0.converted.png"
Magick++ (same behavior)
Image input;
input.read( "01-c3-shouldbe-c0.png" );
input.write( "01-c3-shouldbe-c0.imread.png" );
Moreover, looping on a read/write causes the progressive degradation of the image on each loop iteration. See referenced post for code sample.
Reference post: viewtopic.php?f=1&t=22128
Thank you
Last edited by tc33 on 2013-01-31T16:18:45-07:00, edited 1 time in total.
Re: PNG: read/write degrades/corrupts image
I guess that ImageMagick reads the image, converts it from sRGB (or a similar colorspace) to linear color, and writes it out as linear color, but (mis)labels it as sRGB. And it does this because the (paletted) image's pixels all happen to be shades of gray.
The immediate problem is that the output image's colorspace label does not match its colorspace. Labeling it as linear color would be better than nothing, but it really ought to be converted back to sRGB.
Another problem is that it treats an image in a special way if all its pixels are gray, regardless of whether it is actually encoded as a grayscale image.
The immediate problem is that the output image's colorspace label does not match its colorspace. Labeling it as linear color would be better than nothing, but it really ought to be converted back to sRGB.
Another problem is that it treats an image in a special way if all its pixels are gray, regardless of whether it is actually encoded as a grayscale image.
-
- Posts: 1944
- Joined: 2010-08-28T11:16:00-07:00
- Authentication code: 8675308
- Location: Montreal, Canada
Re: PNG: read/write degrades/corrupts image
I can confirm the problem. (Actually checked the Forum to see if someone else had reported it.)Another problem is that it treats an image in a special way if all its pixels are gray, regardless of whether it is actually encoded as a grayscale image.
-
- Posts: 1944
- Joined: 2010-08-28T11:16:00-07:00
- Authentication code: 8675308
- Location: Montreal, Canada
Re: PNG: read/write degrades/corrupts image
For example: Donwload
messes up the pixel intensities and actually turns the 3-band original into a 1-band one.
Code: Select all
convert MiniOrg.png out.png
Code: Select all
Version: ImageMagick 6.8.0-2 2012-10-17 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
Features: OpenMP HDRI
-
- Posts: 1944
- Joined: 2010-08-28T11:16:00-07:00
- Authentication code: 8675308
- Location: Montreal, Canada
Re: PNG: read/write degrades/corrupts image
Still broken with svn 9745:
Code: Select all
Version: ImageMagick 6.8.0-3 2012-10-22 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
Features: OpenMP HDRI
-
- Posts: 1944
- Joined: 2010-08-28T11:16:00-07:00
- Authentication code: 8675308
- Location: Montreal, Canada
Re: PNG: read/write degrades/corrupts image
Code: Select all
convert MiniOrg.png -define png:color-type=2 temp.png
Re: PNG: read/write degrades/corrupts image
This was already posted in the "users" forum and I answered it there.
If the image has only gray pixels, there may be a confusion of sRGB versus RGB, and it's possible that a loop is continually converting back and forth and losing precision each time around. I have noticed that that happens when converting between PNG and PNG24 formats, unless -colorspace RGB is used. I have not yet nailed down exactly what is happening but am working on it (I didn't try looping the command but assume the the loss would accumulate; I'll test that now)... Yes, the number of colors decreases continually unless I use "-colorspace rgb".
If the image has only gray pixels, there may be a confusion of sRGB versus RGB, and it's possible that a loop is continually converting back and forth and losing precision each time around. I have noticed that that happens when converting between PNG and PNG24 formats, unless -colorspace RGB is used. I have not yet nailed down exactly what is happening but am working on it (I didn't try looping the command but assume the the loss would accumulate; I'll test that now)... Yes, the number of colors decreases continually unless I use "-colorspace rgb".
Re: PNG: read/write degrades/corrupts image
As a follow up, I stumbled on a workaround while doing some grayscale image processing. Basically, I manually set the colorspace to RGB and then call IsGrayImage in attribute.c, which contains auto-detect logic based on image pixel data.
Also, I noticed that any transparent, non-gray pixels will cause IsGrayImage to return false, since the PNG image decoder (or something else?) returns the pixel value even if the pixel is fully transparent. Not sure if this is by design. Here's an example PNG file; note that if you do a straight command-line conversion to bmp you'll see the non-gray pixels. http://cssignet.free.fr/png-test-corpus ... gbdata.png
To workaround the transparent pixel issue, I use the SetImageAlphaChannel with BackgroundAlphaChannel to eliminate these transparent pixels before calling IsGrayImage.
Here's an excerpt of my Magick++ solution:
Also, I noticed that any transparent, non-gray pixels will cause IsGrayImage to return false, since the PNG image decoder (or something else?) returns the pixel value even if the pixel is fully transparent. Not sure if this is by design. Here's an example PNG file; note that if you do a straight command-line conversion to bmp you'll see the non-gray pixels. http://cssignet.free.fr/png-test-corpus ... gbdata.png
To workaround the transparent pixel issue, I use the SetImageAlphaChannel with BackgroundAlphaChannel to eliminate these transparent pixels before calling IsGrayImage.
Here's an excerpt of my Magick++ solution:
Code: Select all
#include <Magick++.h> // Magick++
#include <magick/channel.h> // SetImageAlphaChannel
#include <magick/attribute.h> // IsGrayImage
bool is_gray_img( const Magick::Image& img )
{
Magick::Image cpy = Magick::Image( img );
// if colorspace is sRGB, must change colorspace to RGB, forcing IsGrayImage to auto-detect based on pixel data
if ( cpy.image()->colorspace == MagickCore::ColorspaceType::sRGBColorspace )
cpy.image()->colorspace = MagickCore::ColorspaceType::RGBColorspace;
// eliminate alpha channel garbage
if ( cpy.constImage()->matte )
SetImageAlphaChannel( cpy.image(), MagickCore::AlphaChannelType::BackgroundAlphaChannel ) ;
return IsGrayImage( cpy.constImage(), &cpy.image()->exception );
} // is_gray_img
// image load routine...
Magick::Image img;
// load image data here
// set grayscale type if appropriate
if ( is_gray_img( img ) )
img.colorspaceType( MagickCore::ColorspaceType::GRAYColorspace );
// now the image is handled properly
Re: PNG: read/write degrades/corrupts image
Glenn, I was looking through the changelog for IM 6.8.2.x. I noted that you have made changes related to PNG en/decoding that may have addressed these issues, but I can't be certain. Were both of these issues addressed? The first issue being the grayscale image, the second being the transparent pixel issue I noted in my previous post.
Thanks for your continued support/improvements!
Thanks for your continued support/improvements!
Re: PNG: read/write degrades/corrupts image
The transparent-pixel issue is outside the scope of the png encoder. The png encoder writes whatever ImageMagick hands it, and in this case it receives an image with garbage colors that are not visible if the viewer accounts for the alpha channel. The bug is in whatever application created the image in the first place.tc33 wrote:Glenn, I was looking through the changelog for IM 6.8.2.x. I noted that you have made changes related to PNG en/decoding that may have addressed these issues, but I can't be certain. Were both of these issues addressed? The first issue being the grayscale image, the second being the transparent pixel issue I noted in my previous post.
Thanks for your continued support/improvements!
Re: PNG: read/write degrades/corrupts image
Thanks for your response regarding the transparent pixel issue. Is the grayscale image issue still open then?
Re: PNG: read/write degrades/corrupts image
Fixed/confirmed in IM 6.8.2.2. Thank you!