Page 1 of 1

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

Posted: 2009-01-20T16:17:12-07:00
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

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

Posted: 2009-01-20T18:44:08-07:00
by magick
Post a URL to your script and test images. We need to reproduce the problem before we can offer any help.

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

Posted: 2009-01-21T10:59:31-07:00
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

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

Posted: 2009-01-21T11:29:55-07:00
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.

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

Posted: 2009-01-21T15:48:53-07:00
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

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

Posted: 2009-01-22T07:38:57-07:00
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.

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

Posted: 2009-01-22T11:46:01-07:00
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

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

Posted: 2009-01-22T13:59:23-07:00
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

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

Posted: 2009-01-22T14:52:35-07:00
by magick
Try this command:
  • convert cs50.png -resize 58x112 cs50.gif
Is that what you're looking for>

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

Posted: 2009-01-22T16:03:37-07:00
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

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

Posted: 2009-01-22T18:13:06-07:00
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.

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

Posted: 2009-01-22T18:37:17-07:00
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.

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

Posted: 2009-01-22T21:44:46-07:00
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 

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

Posted: 2009-01-23T11:51:40-07:00
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

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

Posted: 2009-01-23T19:06:33-07:00
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.