How to convert PNGs w/ trans bg to GIF w/ white matte edge

PerlMagick is an object-oriented Perl interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning PerlMagick.
Post Reply
asonnenshine

How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

Hi,
I previously had a script that did this perfectly, but after our upgrade (6.2.2 -> 6.4.4), it does no longer work.

Here's the idea:
1) In Photoshop, I have manually cutout the backgrounds of product images and then saved as transparent PNGs and uploaded to server.
2) Next, I simply want to resize the transparent PNG, and then save as transparent GIF format. The GIFs must have a smooth white matte color so they blend into the white background on the website. I can create this effect very easily in Photoshop.

Method that previously worked for me:
1) Read PNG image
2) Resize PNG image
3) Clone PNG image for use as a mask
4) Separate mask (channel=Opacity)
5) Negate mask
6) GaussianBlur mask
7) Flatten PNG image with white bg
8) Composite PNG with mask

With this process I was previously able to get smooth anti-aliases white edges on my transparent GIF output.

Can someone PLEASE provide some insight? I understand there have been some bugs fixed in recent versions. I have read thru the entire forum and re-read and re-read again the "documentation" for ImageMagick, but no success.

I would really appreciate some help.
Thanks in advance,
-aaron
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by magick »

Post a URL to your script and test images. We need to reproduce the problem before we can offer any help.
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

Here is the PNG I start with:
Image

Here is the correct final GIF output with smooth white matte edges:
Image

Here is the OLD code that previously worked correctly, but no longer works:

Code: Select all


sub createProductImage {
	
	my $imgpath = $img_base_dir . "/" . @_[0];
	my $type = @_[1];
	my $target_width = @_[2];
	my $target_height = @_[3];
	my $format = @_[4];
	my $img_target_dir = $img_base_dir . "/path/to/images/catalog/" . $type . "/";
	
	
	#extract just the image name from the full path
	$imgpath =~ m/[a-zA-Z\/]*pngs\/(.*)$/;
	my $imgname = $1;
	
	#create a new image object
	my $product_image = Image::Magick->new;
	my $image_mask = Image::Magick->new;
	my $flattened_image = Image::Magick->new;
		
	#read in the source image data
	$product_image->Read("$imgpath");
	
	#get image width
	my $image_width;
	$image_width = $product_image->Get("width");	

	#get image height
	my $image_height;
	$image_height = $product_image->Get("height");	

	#get aspect ratio (width to height)
	my $aspect_ratio = $image_width / $image_height;
	print "<b>aspect ratio:</b> $aspect_ratio<br>\n";
	
	#determine sizing based on aspect ratio
	if ($aspect_ratio>1.286 ) {
		#resize the image - fixed width
		$product_image->Resize(geometry=>$target_width."x");
	} else {
		#resize the image - fixed height
		$product_image->Resize(geometry=>"x".$target_height);
	}

	#clone the image (so we can use as a mask)
	$image_mask = $product_image->Clone();

	#create a mask
	$image_mask->Separate(channel=>"Opacity");

	#negate the mask
	$image_mask->Negate();
	
	#blur the mask
	$image_mask->GaussianBlur("0.0x0.1");
		
	#flatten the original image onto white bg
	$flattened_image = $product_image->Flatten();
	
	#composite the mask on top of the flattened image
	$product_image->Composite(image=>$flattened_image, mask=>$image_mask);

	#change the format
	$imgname =~ s/png/$format/;
	
	#write the new image to disk
	$product_image->Write("$img_target_dir$imgname");
	
	#clean up
	undef $product_image;
	undef $image_mask;
	undef $flattened_image;

}

Please let me know if there is anything else I can provide!
Thanks again,
-aaron
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by magick »

We can reproduce the problem you posted and should have a fix within a day or two. In the mean-time add
  • $product_image->Rotate(360);
Just before your write statement and you should get the expected results.
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

I tried the suggested additional code:

$product_image->Rotate(360);

It definitely did something!! Previously, the output was mostly black with scattered colored pixels...with the new code snippet, I am now getting an actual product image. The only problem now is that I am seeing some little extra pixels of black around the edges that I wasn't seeing when the script previously worked.

I also wanted to note that I was able to get an actual product image output when I replaced:

Code: Select all

$product_image->Composite(image=>$flattened_image, mask=>$image_mask);
with

Code: Select all

$flattened_image->Composite(compose=>"CopyOpacity", image=>$image_mask);
The problem with the latter was that I was not getting a smooth white matte, but rather "jaggies".

Thanks again for your help,
-aaron
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by magick »

Turns out CompositeImage() is not resetting the image mask. Add
  • $product_image->Set(mask=>undef);
just before the Write().

This problem will be fixed in the next point release of ImageMagick. Thanks.
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

Thanks for helping with this issue.

I've certainly learned a lot about IM in the process.

I've even figured out new processes for other imaging needs, thanks again!
-aaron
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

Upon closer inspection, I am noticing there are slightly more grey pixels appearing in the white matte edge than it did before it stopped working (previously I was getting a cleaner white matte, with less grey pixels).

I would guess that I need to specify the background color as "white", but not sure where in the code I would do that? And to which object? Can you suggest a way to fix that?

Thanks again,
-aaron
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by magick »

Try this command:
  • convert cs50.png -resize 58x112 cs50.gif
Is that what you're looking for>
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

No, unfortunately a simple resize does not create the smooth white matte edge:
[img]
http://www.plantronics.com/images/catal ... e_only.gif
[/img]

Here is the correct smooth white matte edge that I was getting with my script before the upgrade:
[img]
http://www.plantronics.com/images/catal ... ery610.gif
[/img]

Here is the output I am getting after the upgrade with your suggested fix:
[img]
http://www.plantronics.com/images/catal ... 10_new.gif
[/img]

If you look very closely at the original output (old version) vs. the new output (after upgrade), you'll notice that the edge is not as smooth and clean the original. I am seeing some extra grey pixels in there. Essentially what I am trying to do is match the output of Photoshop when you "save for web" as transparent GIF using white matte.

BTW I am using the same source PNG for all the examples on this post:
[img]
http://www.plantronics.com/images/catal ... ery610.png
[/img]

Thanks,
-aaron
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by fmw42 »

what happens when you save your output to png rather than gif. the issue may be in the way IM chooses gif colors and perhaps that has changed over time. also it could be issues with transparency as gif only allows binary transparency.
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

When I save as PNG it looks perfect. But unfortunately I must format these images as GIFs for the website.

Yes, I think there are a lot of changes since IM 6.2.3 and it's difficult to tell what exactly is causing the problem.

That's why i posted here...looking for the experts to chime in with things they know have changed.

I have probably spent over 20 hours working on this problem.

I have even considered reverting to older version of IM.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by anthony »

I was asked to look in on this problem. Now while I understand perl, and understand what you are doing, you are doing things whish to me seems sort of overkill.

First you resize your mail while preserving aspect ratio.

IM does this automatically , so you should be able to resize the image to fit into a $target_width."x".$target_height box directly. no need to do all that aspect ratio stuff.

Second you seem to try to do some mask work so that the final image has white anti-aliasing edges, by overlaying the image on a slightly larger mask.

Why not just -flatten your resized image onto 'white' then make any pixel which is no longer pure white transparent. That should handle the task as well.

The command line equivalent would be

Code: Select all

  convert original.png -thumbnail ${width}x${height} \
               -background white -flatten \
               -transparent white -transparent-color white \
               target.gif
the last operation in the above -transparent-color ensures that the GIF file format uses a 'white' color for its transparent pixels.

All the above should have perl equivalents, though I am not certain what all of them are without more research.

displaying on different background shows I get correct 'white' anti-aliasing pixels around the edges.

Code: Select all

display target.gif
display -texture xc:white target.gif 
display -texture xc:black target.gif 
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
asonnenshine

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by asonnenshine »

Thanks for the tips. Yes, I would agree that some of this seems overkill, but I found that this was the only way I could get the precise results I was looking for. Also, this was my first IM script I ever wrote, so that makes sense that I didn't use the most efficient code :)

I actually found a way to produce the exact output I was looking for; the part I added last night was to "Threshold" the mask before applying the blur...this seemed to really clean-up those stray pixels in the smooth white matte edge.

Here's my final code for others to read, hope this helps someone:

Code: Select all

	#clone the image (so we can use as a mask)
	$image_mask = $product_image->Clone();

	#create a mask
	$image_mask->Set(alpha=>"Extract");
	
	#modify the mask: tweak the greyscale image and then blur for smoothness
	$image_mask->Threshold(threshold=>"20%");
	$image_mask->GaussianBlur("0x0.1");
		
	#flatten the original image onto white bg
	$flattened_image = $product_image->Flatten();
	
	#composite the mask on top of the flattened image
	$product_image->Composite(image=>$flattened_image, mask=>$image_mask);

	#change the format
	$imgname =~ s/png/$format/;
	
	#fix for bug suggested by experts
	$product_image->Set(mask=>undef);
	
	#write the new image to disk
	$product_image->Write("$img_target_dir$imgname");

Thanks again for everyone's help!
-a
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: How to convert PNGs w/ trans bg to GIF w/ white matte edge

Post by anthony »

Note that as you were using a transparency mask, on an image with transparency, then the pixels that were already fully-transparent came out and black (color for fully transparent pixels is undefined, and algorithm tends to make them black)

Remember when you use CopyOpacity, the whole alpha channel of the image is replaced! So these undefined colors could appear. I do this on purpose in the last example of IM Examples, Channels, Masks, and Transparency, Editing a Image Mask

If you really want to use your original method, flatten the main image onto a white background, BEFORE applying the mask and turning off 'alpha channel' using +matte. That will remove the black pixels in the result by actually giving the undefined pixels a proper color.

The short cut method does similar, but converts pure white to transparency afterward, rather than muck around with a separate mask processing.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply