Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different behaviour between PNG24 and PNG32 when using transparency mask #511

Closed
saurabheights opened this issue Jun 13, 2017 · 8 comments
Closed
Labels

Comments

@saurabheights
Copy link

saurabheights commented Jun 13, 2017

Hi,
I am working on a command for cropping 200x200 area from the center of any picture and then creating a circular image from the cropped image.

To increase speed, I pre-generate the alpha mask as below:-
convert -size 200x200 xc:none -fill black -draw "circle 100,100 1,100" -depth 8 mpc:ThumbnailCreator200x200.mpc

Next, I have used below commands, one for PNG32 and one for PNG24:-

#Added url for quick test of below commands on a sample JPEG image
wget http://roposoimg.s3.amazonaws.com/userImages/5032123647776630600242640054363301521117206.jpeg

# Create Circular alpha mask
convert -size 200x200 xc:none  -fill black -draw "circle 100,100 1,100" -depth 8 mpc:ThumbnailCreator200x200.mpc

#PNG24
convert -synchronize 5032123647776630600242640054363301521117206.jpeg -auto-orient -strip -resize 200x200^ -gravity center -extent 200x200  \( +clone -alpha on ThumbnailCreator200x200.mpc -compose CopyOpacity -composite -background rgb\(0,0,0\) -alpha Background -write PNG24:output_circle_24.png \) null:

#PNG 32
convert -synchronize 5032123647776630600242640054363301521117206.jpeg -auto-orient -strip -resize 200x200^ -gravity center -extent 200x200  \( +clone -alpha on ThumbnailCreator200x200.mpc -compose CopyOpacity -composite -background rgb\(0,0,0\) -alpha Background -write PNG32:output_circle_32.png \) null:

I tried removing the following command options which sets any fully transparent pixel to the background colour, while leaving it fully-transparent.
-background rgb\(0,0,0\) -alpha Background

This resulted in attached images 4 and 5.

1 - Input Image
5032123647776630600242640054363301521117206

2 - PNG24 Image
output_circle_24

3 - PNG32 Image
output_circle_32

4 - PNG24 Image without resetting transparent pixels to the background colour.
output_circle_24

5 - PNG32 Image without resetting transparent pixels to the background colour.
output_circle_32

Thank you for looking into the issue and I appreciate any help you can provide.

Other info:-
IM is built from latest code as of yesterday to test.
Version: ImageMagick 7.0.6-0 Q16 x86_64 2017-06-12 http://www.imagemagick.org
Copyright: © 1999-2017 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI
Delegates (built-in): bzlib fftw fontconfig freetype jng jpeg lcms lzma openexr pangocairo png tiff webp x xml zlib

@fmw42
Copy link

fmw42 commented Jun 13, 2017

Your syntax is overly complex with unnecessary clones. Make your mask image (ThumbnailCreator200x200.png) white on black rather than black on transparent. Then simplify your commands. I am not sure why you get an transparent result with PNG24, since it should remove the alpha channel. So I have posted three versions for PNG24. The second explicitly removes the alpha channel with a black background. The third does the same with a white background. Here is my code. I have used PNG for the mask, but you can change that to mpc if you want.

convert -size 200x200 xc:black -fill white -draw "circle 100,100 1,100" -depth 8 ThumbnailCreator200x200.png

thumbnailcreator200x200

convert 5032123647776630600242640054363301521117206.jpeg -auto-orient -strip -resize 200x200^ -gravity center -extent 200x200 ThumbnailCreator200x200.png -alpha off -compose CopyOpacity -composite -background black -alpha Background PNG24:output_circle_24a.png

output_circle_24a

convert 5032123647776630600242640054363301521117206.jpeg -auto-orient -strip -resize 200x200^ -gravity center -extent 200x200 ThumbnailCreator200x200.png -alpha off -compose CopyOpacity -composite -background black -alpha Background -alpha off PNG24:output_circle_24b.png

output_circle_24b

convert 5032123647776630600242640054363301521117206.jpeg -auto-orient -strip -resize 200x200^ -gravity center -extent 200x200 ThumbnailCreator200x200.png -alpha off -compose CopyOpacity -composite -background white -alpha Background -alpha off PNG24:output_circle_24c.png

output_circle_24c

convert 5032123647776630600242640054363301521117206.jpeg -auto-orient -strip -resize 200x200^ -gravity center -extent 200x200 ThumbnailCreator200x200.png -alpha off -compose CopyOpacity -composite -background black -alpha Background PNG32:output_circle_32.png

output_circle_32

I do not see the need to use explicit PNG24: or PNG32. You can just leave it off and the PNG writer will generally provide the correct result, especially if you have transparency already in your image. If you do not want the transparency, then just do -alpha off at the end.

@ImageMagick ImageMagick deleted a comment from fmw42 Jun 13, 2017
@glennrp
Copy link
Contributor

glennrp commented Jun 13, 2017

Your png32 results have alpha channels with semitransparent pixels (alpha neither 0 nor 1). I guess "convert" is having difficulty transforming that into PNG24 which all transparent pixels need to be fully transparent and all of them have to be the same color. Forcing them all to have the same underlying color helps.

@saurabheights
Copy link
Author

saurabheights commented Jun 14, 2017

My gratitude to both of you for looking into this issue.

@fmw42 - My apologies, the original command was very long, with multiple output images and even after removing the redundant stuff, some still got left out(clone and use of parentheses). Alas, I have to use the alpha channel. The examples that you have provided will only work if these images are displayed on a static background colour. However, at our platform, we use black, white and even a user specific cover image as the background for a profile picture. Thus choosing a static background colour(white or black) is not an option.

@glennrp - You are right on the mark, this is due to anti-aliasing. I did notice that the circumference in PNG32 looks better than PNG24, but failed to correlate it with the current issue. Anti-aliasing would add values other than 0 or 1.

I went ahead and turned anti-aliasing off when creating the alpha mask, however, this also fails with the few pixels within the circle area being turned transparent.

@glennrp: I didn't fully understand the same color part in your comment.

I guess "convert" is having difficulty transforming that into PNG24 which all transparent pixels need to be fully transparent and all of them have to be the same color. Forcing them all to have the same underlying color helps.

Commands(broken further to separate square image generation with alpha masking):-


convert 5032123647776630600242640054363301521117206.jpeg -resize 200x200^ -gravity center -extent 200x200 PNG24:square.png

convert -size 200x200 xc:none +antialias -fill black -draw "circle 100,100 1,100" -depth 8 ThumbnailCreator200x200.png

convert square.png -alpha on ThumbnailCreator200x200.png -compose CopyOpacity -composite -background rgb\(0,0,0\) -alpha Background PNG24:output_circle_24.png

convert square.png -alpha on ThumbnailCreator200x200.png -compose CopyOpacity -composite -background rgb\(0,0,0\) -alpha Background PNG32:output_circle_32.png

The result was same as the image uploaded at the start of the issue:-
output_circle_24

Edit - The 32-bit image was again fine.

@glennrp
Copy link
Contributor

glennrp commented Jun 14, 2017

That's because the original has a few pixels that have the same underlying color (black, in this case) as the transparent pixels. You could make a first pass over the image to change those (something like
"-fill # 00001 -opaque # 000000") to change the black pixels to dark blue.

@saurabheights
Copy link
Author

@glennrp - Thank you so much. This is a good solution, I can just change all black color pixels to rgb(0,0,1) and the change which will be imperceptible to human eyes.

For future users:-

convert square.png  -fill 'rgb(0,0,1)' -opaque black test.png
convert test.png -alpha on ThumbnailCreator200x200.png -compose CopyOpacity -composite -background rgb\(0,0,0\) -alpha Background PNG24:output_circle_24_BlackReplacedToNearBlack.png

This worked fine and created an 11.7% smaller image than the PNG32 counterpart.

P.S. - @dlemstra - Shouldn't the issue be marked bug along with question tag? The commands in the first comment shouldn't replace pure Black pixels where alpha is Foreground. In case, if my understanding is incorrect, please do comment.

-compose CopyOpacity -composite - should only do alpha masking,
-background rgb\(0,0,0\) - Set background color to black for future operations,
-alpha Background - wherever alpha is 0(Background), set color to previous defined background color. Done for better compression.

Thank you in advance.

@glennrp
Copy link
Contributor

glennrp commented Jun 14, 2017

It's not a bug but simply a feature of the PNG format. When using the tRNS chunk with a PNG24 RGB image, all pixels of the color named in the tRNS chunk are transparent.

@saurabheights
Copy link
Author

saurabheights commented Jun 15, 2017

Ohhh..., wasn't aware of how PNG24 stored the alpha mask. Thank you Glenn.

@glennrp
Copy link
Contributor

glennrp commented Jun 15, 2017

The PNG Developers refer to that as "GIF-style transparency". It is used with PNG color-type 2 (RGB) and color-type 0 (grayscale).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants