semi-flatten PNG images
semi-flatten PNG images
Hi all,
how would one semi-flatten a PNG image against some background image using ImageMagick?
I.e. blend a partially translucent source image over a background image, but only let the background image shine through on those pixels where the source image has an opacity greater than 0. (Fully transparent pixels in the source image should also be fully transparent in the output image!)
Abstract example:
I would appreciate any help...
Thanks!
how would one semi-flatten a PNG image against some background image using ImageMagick?
I.e. blend a partially translucent source image over a background image, but only let the background image shine through on those pixels where the source image has an opacity greater than 0. (Fully transparent pixels in the source image should also be fully transparent in the output image!)
Abstract example:
I would appreciate any help...
Thanks!
Re: semi-flatten PNG images
Ok, after more experimentation, I did manage to get it to work after all... (At least for the sample images I checked with.)
If anybody knows if there's a better way to do this, or if it can be written in a more compact form (maybe a single console command instead of three?), then please tell.
-----------------------------------------------------------
Example source: (has translucency due to anti-aliasing!) ... Example background for semi-flattening:
This is how I went about it:
EDIT: The first of the three ImageMagick commands above caused the final outcome to have severe artifacts for some of my input images; I found the following replacement for it which seems to eliminate the problem:
If anybody knows if there's a better way to do this, or if it can be written in a more compact form (maybe a single console command instead of three?), then please tell.
-----------------------------------------------------------
Example source: (has translucency due to anti-aliasing!) ... Example background for semi-flattening:
This is how I went about it:
- create a transparency mask from the source image
(Such that the mask is fully opaque wherever the source image is opaque or translucent, and fully transparent wherever the source image is fully transparent.)
--->Code: Select all
convert source.png -channel matte -threshold 99.5% mask.png
- clip the background image with this mask
+ --->Code: Select all
composite -compose Dst_In mask.png background.png background_masked.png
- blend the source image over the clipped background image
+ --->Code: Select all
composite source.png background_masked.png output.png
EDIT: The first of the three ImageMagick commands above caused the final outcome to have severe artifacts for some of my input images; I found the following replacement for it which seems to eliminate the problem:
Code: Select all
convert source.png -alpha extract -threshold 0% mask.png
Last edited by sas on 2011-01-11T14:54:00-07:00, edited 2 times in total.
- anthony
- Posts: 8883
- Joined: 2004-05-31T19:27:03-07:00
- Authentication code: 8675308
- Location: Brisbane, Australia
Re: semi-flatten PNG images
You are not specifically clear about what you want.
Do you want to just 'overlay' a semi-transparent image on a background?
That results in just background where overlay is transparent
Just teh overlay colors where the overlay image is fully-opaque
and a mix of color where it is semi-transparent.
Or do you just want to replace the colors of the source image with the colors from the
background preserving the transparency? (That is a 'In' compositon.
Basically given the two top images in this diagram....
What do you want the result to be in each of the 4 triangular areas
top, left, right, bottom (always transparent!)
A 5th area is for the results in areas where the first image does not overlap the destination, and can be controlled by a separate '-define' switch.
These are ALL the logical choices for any form of composition, semi-transparency is automatically decided from those choices in a
So what do you want?
If what you want is NOT listed in the above, it is illogical and non-standard. As such you will need to describe it much more fully.
The above table is from IM examples, Duff-Porter Alpha Composition Operators
http://www.imagemagick.org/Usage/compose/#duff-porter
Do you want to just 'overlay' a semi-transparent image on a background?
That results in just background where overlay is transparent
Just teh overlay colors where the overlay image is fully-opaque
and a mix of color where it is semi-transparent.
Or do you just want to replace the colors of the source image with the colors from the
background preserving the transparency? (That is a 'In' compositon.
Basically given the two top images in this diagram....
What do you want the result to be in each of the 4 triangular areas
top, left, right, bottom (always transparent!)
A 5th area is for the results in areas where the first image does not overlap the destination, and can be controlled by a separate '-define' switch.
These are ALL the logical choices for any form of composition, semi-transparency is automatically decided from those choices in a
So what do you want?
If what you want is NOT listed in the above, it is illogical and non-standard. As such you will need to describe it much more fully.
The above table is from IM examples, Duff-Porter Alpha Composition Operators
http://www.imagemagick.org/Usage/compose/#duff-porter
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
https://imagemagick.org/Usage/
- anthony
- Posts: 8883
- Joined: 2004-05-31T19:27:03-07:00
- Authentication code: 8675308
- Location: Brisbane, Australia
Re: semi-flatten PNG images
your final example results seems to indicate you are wanting to define the background of a GIF image that only has boolean transparency, in termes of a web page background.
That is you want to replace semi-transparency with an appropriate opaque color blend, while keeping fully-transparent transparent and fully-opaque opaque.
If so, say so, rather than what you think you want!
Okay. First, can you align your GIF image with yoru web page background exactly??
That is if you just overlay the GIF image on the background, can you syncronize the image on the web page so the background does not become disjoint?
If you can not do that, then what you are doing is useless!!!! You will always get a disjoint result, so it is better to try and reduce that disjoint result.
You are better off using a 'average' or 'solid' color that roughly matches the whole background for the task.
See GIFs on a background pattern
http://www.imagemagick.org/Usage/formats/#bg_pattern
In BOTH cases you can just overlay the semi-transparent image on your background pattern or average color, then find what pixels did not change, to generate a mask of the image.
One method is shown in Change Mask Composition.
http://www.imagemagick.org/Usage/compose/#changemask
Whcih will directly produce what you want.
NOTE I can't test this as the images you provide has a checkerboard background pattern rather than transparency!!!
That is you want to replace semi-transparency with an appropriate opaque color blend, while keeping fully-transparent transparent and fully-opaque opaque.
If so, say so, rather than what you think you want!
Okay. First, can you align your GIF image with yoru web page background exactly??
That is if you just overlay the GIF image on the background, can you syncronize the image on the web page so the background does not become disjoint?
If you can not do that, then what you are doing is useless!!!! You will always get a disjoint result, so it is better to try and reduce that disjoint result.
You are better off using a 'average' or 'solid' color that roughly matches the whole background for the task.
See GIFs on a background pattern
http://www.imagemagick.org/Usage/formats/#bg_pattern
In BOTH cases you can just overlay the semi-transparent image on your background pattern or average color, then find what pixels did not change, to generate a mask of the image.
One method is shown in Change Mask Composition.
http://www.imagemagick.org/Usage/compose/#changemask
Whcih will directly produce what you want.
Code: Select all
convert imbackground.png \( +clone imsource.png -composite \) \
-fuzz 25% -compose ChangeMask -composite output.gif
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
https://imagemagick.org/Usage/
Re: semi-flatten PNG images
Yes, pretty much.anthony wrote:your final example results seems to indicate you are wanting to define the background of a GIF image that only has boolean transparency, in termes of a web page background.
That is you want to replace semi-transparency with an appropriate opaque color blend, while keeping fully-transparent transparent and fully-opaque opaque.
(Similar to what the Semi-Flatten filter in Gimp does).
The reason I didn't is that I wasn't looking for a generic manual solution for "somehow make anti-aliased GIF look good for a given background color/pattern, no matter the details", but rather a very specific solution that ties in with an existing scripted work-flow, in which an anti-aliased foreground image of arbitrary shape has already been generated as PNG, as have one or more background images of the same dimensions which provide the (approximate) color values of certain parts of the web page background which the GIF image will be shown on.anthony wrote:If so, say so, rather than what you think you want!
I do admit however that the abstract example images I gave weren't really sensible use cases of this problem/solution (I didn't use real-life images as the ones I had at hand were really small), and my original description of the problem might not have been as clear as I intended. Sorry about that.
No, not necessarily.anthony wrote:You are better off using a 'average' or 'solid' color that roughly matches the whole background for the task.
Imagine a GIF image that represents the edge or corner of an outlined/shadowed box on a web page. The background color/pattern inside the box might be different from the background color/pattern outside the box, so in the GIF image the pixels belonging to the "inside" of the box need to be semi-flattened against a different color than the pixels belonging to the "outside" of the box.
Anyways in the work-flow mentioned above, the information about which pixel should be semi-flattened against which color already exists, in the form of the given background image(s).
When removing the -fuzz option, this produces something very similar to the result of the first two steps of my 3-step solution above:anthony wrote:In BOTH cases you can just overlay the semi-transparent image on your background pattern or average color, then find what pixels did not change, to generate a mask of the image.
One method is shown in Change Mask Composition.
http://www.imagemagick.org/Usage/compose/#changemask
Whcih will directly produce what you want.
Code: Select all
convert imbackground.png \( +clone imsource.png -composite \) \ -fuzz 25% -compose ChangeMask -composite output.gif
+ =
The third step (overlaying the source image on this masked background) would still have to be done as a separate command though, right?
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: semi-flatten PNG images
You should be able to combine all steps as long as you use convert rather than composite to merge the images and use clones and parenthesis processing.
see
http://www.imagemagick.org/script/compose.php
http://www.imagemagick.org/Usage/basics/#parenthesis
http://www.imagemagick.org/Usage/layers/#convert
see
http://www.imagemagick.org/script/compose.php
http://www.imagemagick.org/Usage/basics/#parenthesis
http://www.imagemagick.org/Usage/layers/#convert
- anthony
- Posts: 8883
- Joined: 2004-05-31T19:27:03-07:00
- Authentication code: 8675308
- Location: Brisbane, Australia
Re: semi-flatten PNG images
Apologies. Add a +swap before the ChangeMask composition...
here is the example again but with the image given that have no checkerboard pattern,
The colors retained are from the background, so the swap is needed to place the 'overlaid' image first (as background).
Parenthesis is used so as to remove the need to read the background image twice.
This is equivalent without parenthesis.
The fuzz is recommended to threshold the most minor changes, especially when you have a large semi-transparent gradient produced by blur, such gradients can show changes a great distances from the main image boundary. Adjust as needed -fuzz 0 is equivalent to 'no fuzz'.
here is the example again but with the image given that have no checkerboard pattern,
Code: Select all
convert backgroundtv.png \( +clone sourceup.png -composite \) \
+swap -fuzz 5% -compose ChangeMask -composite output.gif
Parenthesis is used so as to remove the need to read the background image twice.
This is equivalent without parenthesis.
Code: Select all
convert backgroundtv.png sourceup.png -composite \
backgroundtv.png -fuzz 5% -compose ChangeMask -composite output.gif
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
https://imagemagick.org/Usage/
Re: semi-flatten PNG images
Thanks, anthony!
Your solution works great:
+ -->
Also thanks for including the "without parenthesis" version, as that really helped me understand how the command works.
PS: Will this command work with every (moderately recent) ImageMagick version, or do I need to make sure to upgrade to a certain minimum version on all machines on which the command is supposed to be run?
Your solution works great:
+ -->
Also thanks for including the "without parenthesis" version, as that really helped me understand how the command works.
PS: Will this command work with every (moderately recent) ImageMagick version, or do I need to make sure to upgrade to a certain minimum version on all machines on which the command is supposed to be run?
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: semi-flatten PNG images
From Anthony's page on compose methods (http://www.imagemagick.org/Usage/compose/), it says:
"The 'ChangeMask' composition method was added to IM v6.3.4 ..."
So that is likely the minimum version needed
"The 'ChangeMask' composition method was added to IM v6.3.4 ..."
So that is likely the minimum version needed
- anthony
- Posts: 8883
- Joined: 2004-05-31T19:27:03-07:00
- Authentication code: 8675308
- Location: Brisbane, Australia
Re: semi-flatten PNG images
Correct.fmw42 wrote:"... added to IM v6.3.4 ..."
So that is likely the minimum version needed
No need for any -matte or -alpha set settings as 'ChangeMask' will add alpha automatically to the result, and the first 'Over' composite will handle images with or without alpha correctly.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
https://imagemagick.org/Usage/
Re: semi-flatten PNG images
Hi,
the "Over + ChangeMask" solution still seems to have issues after all. (Well, they might not be issues for other people, but for my use-case, they're problematic.)
For example, given below is a real-life example of my use-case (well, real-life plus -sample 1000% plus black border).
The "Over + ChangeMask" method suggested by anthony produces:
+ -->
Note how all semi-transparent pixels for have been flattened (even ones for which the background image did not provide a background color for semi-flattening), and how the black border was removed since it appeared in both the source and background image (even though this has nothing to do with semi-flattening).
Compare this with the most recent incarnation of my "alpha extract + Dst_In + Over" method (I managed to put it into a single command now):
+ -->
This is really how I would prefer the outcome to look.
The only downside is that it needs to read the source image twice. (Or is there something else wrong with doing it this way?)
Any thoughts?
the "Over + ChangeMask" solution still seems to have issues after all. (Well, they might not be issues for other people, but for my use-case, they're problematic.)
For example, given below is a real-life example of my use-case (well, real-life plus -sample 1000% plus black border).
The "Over + ChangeMask" method suggested by anthony produces:
Code: Select all
convert cbackground.png \( +clone csource.png -composite \) \
+swap -fuzz 2% -compose ChangeMask -composite csemiflat.png
Note how all semi-transparent pixels for have been flattened (even ones for which the background image did not provide a background color for semi-flattening), and how the black border was removed since it appeared in both the source and background image (even though this has nothing to do with semi-flattening).
Compare this with the most recent incarnation of my "alpha extract + Dst_In + Over" method (I managed to put it into a single command now):
Code: Select all
convert \( cbackground.png \( csource.png -alpha extract -threshold 5% -alpha copy \) \
-compose Dst_In -composite \) csource.png \
-compose Over -composite csemiflat2.png
This is really how I would prefer the outcome to look.
The only downside is that it needs to read the source image twice. (Or is there something else wrong with doing it this way?)
Any thoughts?
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: semi-flatten PNG images
convert \( cbackground.png \( csource.png -alpha extract -threshold 5% -alpha copy \) \
-compose Dst_In -composite \) csource.png \
-compose Over -composite csemiflat2.png
try changing the above to
convert cbackground.png csource.png \
\( -clone 1 -alpha extract -threshold 5% -alpha copy \) \
\( -clone 0 -clone 2 -compose Dst_In -composite \) \
-delete 0,2 +swap -compose Over -composite csemiflat2.png