Set image inside png transparency - imagemagick

As the title suggests I have a PNG image that has some transparency. I'd like to fill that transparency with a second image (which is currently a JPEG, but it's not a problem to convert it to a PNG).
Every post I have found searching on the Internet was about the "inverse" problem (from an image with a background to an image with transparency), so obviously it did not work out for my situation; for example, I tried
convert -flatten myimg.png myimg.png
(taken from here) and
convert myimg1.png -transparent white myimg.png
(taken from here).

In ImageMagick 6, if the two images are the same size, then you can just flatten the transparent image over the background image.
Background (lena.jpg):
Transparent (logo_crop_trans.png):
convert lena.jpg logo_crop_trans.png -flatten lena_logo.jpg
If using ImageMagick 7, then change convert to magick.
If you want to anti-alias the transparent image so that it is not so jagged, then use some blur to smooth the outline (Unix syntax):
convert lena.jpg \( logo_crop_trans.png -channel a -blur 0x1 -level 50x100% +channel \) -compose over -composite lena_logo2.jpg
If on Windows remove the \ before the parentheses.

Related

How to merge 2 images (border, actual image) with different sizes into 1 in linux

I have around 2500 images. Some of them contains border while others arent. What I want to accomplish is to add border to the ones that doesn't have any.
Images with border are 64x64 and images without border are 56x56
I prepared a border image file with size of 64x64 in PNG format and I want to merge all files without border within this image to get them borders and output them as PNG format aswell.
I have tried several ways using ImageMagic but no luck so far.
If you make a 64x64 lime-magenta gradient as background.png and a solid blue 56x56 image as foreground.png like this:
magick -size 64x64 gradient:lime-magenta background.png
magick -size 56x56 xc:blue foreground.png
Your command to paste the foreground into the centre of the background is as simple as:
magick -gravity center background.png foreground.png -composite result.png
I figured out it's pretty doable with convert tool from the ImageMagick package.
First I extracted all images with size of 56x56 to different location, then I did the following;
I added 4 pixels on each side since my border is 64x64
for image in ICO_*.png; do
convert -page +0+0 border.png \
-page +4+4 $image \
-background none -layers merge +repage $image-withBorder.png
done

How to add a border to a transparent PNG using ImageMagick, while preserving transparency?

I am trying to add a 10px red border to a transparent PNG using ImageMagick, while preserving any existing transparency that might exist within the image. Here is my source image:
If you download and view that image with an image viewer, you'll see that it has a transparent background.
According to everything I've read, the following Imagemagick command should add a 10px red border to the image:
convert input.png -bordercolor red -border 10 output.png
It actually does add the red border to the image, since the output dimensions are 20px larger in both directions. Unfortunately it also changes the background color of the image to red as well. Here is the output file:
I do not want the transparent area to be changed to red. I only want to add a red border around the transparent image.
I've tried using both ImageMagick version 6.9.10-23 (Ubuntu) and 7.1.0 (via CloudConvert API), with the same result. I've spent hours(!) trying to solve this.
What am I doing wrong?
I found the answer in this thread: https://legacy.imagemagick.org/discourse-server/viewtopic.php?t=31843 . Here are the two money quotes:
So, "-bordercolor red -border 2" should create an opaque red image 2
pixels larger than the input, and composite the input over this. As
your input is "-size 100x100 xc:none", the result should be 102x102
opaque red pixels. You might think this is "pretty obviously
incorrect", but it is the documented behaviour.
and
Nevertheless, you can get it to work to have the transparent inside,
if you add -compose copy before -bordercolor red -border 2 in both the
current IM 6 and IM 7. This just may have to be the way to do it from
here on, if there is a good reason for the changed behavior.
Here is the command that produces the result I am after:
convert -background transparent -bordercolor red -compose Copy -border 10 input.png output.png
Here's an answer that fully preserves the transparency
convert input.png +write mpr:INP -alpha extract -morphology dilate disk:10 \\( +clone -fill Black -colorize 100 \\) +swap -compose CopyOpacity -composite mpr:INP -compose Over -composite output.png
From https://legacy.imagemagick.org/Usage/crop/#extent
Here is a simple way to do that in Imagemagick. Change the compose setting from over to copy.
Input:
convert logo_transp.png -compose copy -bordercolor red -border 10 logo_transp_border.png

Convert PNG with transparency to JPG

Edit: The original title of this question was "Drawbacks of using -flatten option". However, after this question was answered, I decided to change its title, to make it easier found on Google. Also, new title is actually better describes what is told below.
As I discovered today, to convert PNG with transparency into JPG, we need to use -flatten option.
Try it yourself: download Google logo and convert it from PNG to JPG with the following line
convert google.png google.jpg
the picture will be messed:
With -flatten option, it works fine:
convert google.png -flatten google.jpg
I'm wondering are there any drawbacks of using -flatten permanently, for all conversions between PNG, JPG/JPEG and GIF.
The problem with converting PNG to JPG is when the PNG has transparency. JPG does not allow transparency and any transparent areas will show what color is underneath the transparency, which is often black. So you should use -flatten to properly do that conversion. But you should specify -background somecolor before -flatten, if you do not want the default background color. GIF only allows binary transparency -- fully transparent or fully opaque. PNG allows 8-bit transparency (partial transparent). I know of no significant issues using -background xx -flatten when converting PNG or GIF to JPG. However, the background color you use will change the appearance in transparent areas from that of the underneath color. Here is what is happening:
Input:
Turn alpha off:
convert google.png -alpha off google_aoff.jpg
The stripes are from the underneath color below the alpha channel.
Alpha Channel (nicely antialiased):
convert google.png -alpha extract google_alpha.jpg
Simple Flatten (default background is white):
convert google.png -flatten google_flatten.jpg
Flatten with black background:
convert google.png -background black -flatten google_flatten_black.jpg
Often one will reprocess the original transparent PNG image so that it has some constant color underneath the alpha channel so that later one can remove the alpha channel and not have odd colors showing. It will look the very same as the original PNG.
convert google.png -background white -alpha background google_bg_white.png
However, if you simply remove the alpha channel the JPG will show aliasing since only the fully transparent pixels' background colors were changed to white. You have a nice clean background, but the image is still aliased (as it was in the original when the alpha channel was remove).
convert google_bg_white.png google_bg_white.jpg
So one still needs to flatten the result, so that the antialiasing of the alpha channel will smoothly blend the colors near the boundaries.
convert google_bg_white.png -flatten google_bg_white_flatten.jpg
An alternate method to -flatten is to use -alpha remove, which is discussed http://www.imagemagick.org/Usage/masking/#alpha_remove. So starting with the original PNG, we do
convert google.png -background white -alpha remove google_alpharemoveoff.jpg
The result is the same as -background white -flatten. We do not need the -alpha off mentioned in the reference, since JPG does not support any alpha channel. The reference says this is more efficient and is the preferred method.
#John C wrote:
1st approach:
convert google.png -flatten google_flatten.jpg
2nd approach:
convert google.png -background white -alpha background google_bg_white.png
convert google_bg_white.png -flatten google_bg_white_flatten.jpg
3rd approach:
convert google.png -background white -alpha remove google_alpharemoveoff.jpg
More properly, these should be
1st approach
convert google.png -background white -flatten google_flatten.jpg
2nd approach
convert google.png -background white -alpha background -flatten google_bg_white_flatten.jpg
3rd approach
convert google.png -background white -alpha remove -alpha off google_alpharemoveoff.jpg
In case 1: -background white is the default. But if you want some other background color you need to specify it.
In case 2: there is no need to save to an intermediate file
In case 3: you will need -alpha off if you save to PNG. JPG does not support transparency, so turning alpha off is not needed.

imagemagick mean image sequence and ignore alpha channel

I want to get the mean of a sequence of images by using Imagemagick. Therefore I use the following command:
convert *.png -evaluate-sequence mean MEAN.png
Each of my images does contain an alpha channel. What I want is: Combine all the images by ignoring the alpha channel.
When I combine the images, the alpha channel is considered in the "mean" method and my final image has transparency. That isn't what I want.
Result:
I tried to add the parameter -alpha off, but then Imagemagick converts the alpha channel to black.
convert *.png -alpha off -evaluate-sequence mean MEAN.png
Result:
Photoshop does it right. I load all images in a stack and create a smart object. When I use the "mean" method in Photoshop, the alpha channel is not considdered in the final result.
Result that I want with Imagemagick:
Does someone have an idea how to do that with Imagemagick?
What you need to do is to use the alpha channels as weighting images for each image. The total fraction of white values at each pixel from all the alpha channels would be the weight to use for the average. So something like this should do what you want or at least be close.
First, cd to your directory of images. Then run the following.
convert *.png -evaluate-sequence mean \
\( -clone 0 -alpha off \) \
\( -clone 0 -alpha extract \) \
-delete 0 +swap -compose divide -composite result.png
This will work if there is some image texture at each pixel coming from al least one image. That is at a given pixel all images are not totally black (transparent).
compare -metric rmse result.png mean_photoshop.png null:
125.167 (0.00190993)
So this shows that there is about 0.2% difference between my result and what you got from photoshop
Maybe this way of working will help you get there - or at least explain the problem:
convert xc:"rgba(255,0,0,1)" xc:"rgba(0,0,0,1)" xc:"rgba(0,0,0,0)" -depth 8 -evaluate-sequence mean txt:
Output
# ImageMagick pixel enumeration: 1,1,65535,srgba
0,0: (21845,0,0,43690) #550000AA srgba(85,0,0,0.666667)
Using IM 6.8.9.4 Q16 or IM 7.0.5.5 Q16 Mac OSX Sierra, this seems to work fine for me:
Make transparent image
convert logo: -transparent white logot.png
Get mean
convert logot.png logot.png logot.png -alpha off -evaluate-sequence mean result.png
magick logot.png logot.png logot.png -alpha off -evaluate-sequence mean result.png
This also seems to work:
convert logot.png logot.png logot.png -channel rgb -evaluate-sequence mean -alpha off result.png
So perhaps you need to upgrade your ImageMagick (and/or libpng?)
Can you post a zip file of some of your input images, so we can test with your images?
One problem that I see is that the PNG images that you provided have black under the transparent areas and not image texture. So when you disable alpha as in my commands above, you see black and the black gets averaged into the final result. Did you use these same PNG images in Photoshop or did you have Photoshop PSD images or some other images that you used and then exported to PNG, which may have put black under the transparent areas. Have you tried using the same PNG images in Photoshop to do the average?
In fact, you have 8-bit color (palette) images, which have one color (black) assigned to be the transparent color.

Compositing premultiplied images using ImageMagick

I have two images. One is background with no alpha. The other is a white cloud. The alpha of the cloud image is premultiplied with black. When I composite them the white cloud has black in it, so it looks grey instead of white like it should. I'm doing:
convert -gravity Center bg.tga whitecloud.tga -composite comp.tga
Is there a way to composite premultiplied images in ImageMagick, or does the image have to be non-premultiplied? Can I make a premultiplied image non-premultiplied using ImageMagick?
Update:
Ok, here are the images as TGA for download:
http://acatysmoof.com/posting/problems/imagemagick/premultiplication/bg.tga
http://acatysmoof.com/posting/problems/imagemagick/premultiplication/whitecloud.tga
http://acatysmoof.com/posting/problems/imagemagick/premultiplication/aftereffects.tga
http://acatysmoof.com/posting/problems/imagemagick/premultiplication/imagemagick.tga
and in the same order as jpgs to view in your browser:
I tried all the modes provided, but none of them create the same result as After Effects.
It would be easier if you showed your images, but try adding -compose lighten before -composite in your command, like this:
convert a.tga b.tga -compose lighten -composite out.tga
Basically that will make ImageMagick choose the lighter pixel of the two images at every point.
If that doesn't work, try other blending modes
for b in $(identify -list compose); do
convert -label "$b" bg.tga whitecloud.tga -compose $b -composite miff:-
done | montage - -tile 5x out.png
I am kind of thinking Atop, Dissolve, SrcAtop and SrcOver might be your friends but have a look full-size and see what floats your boat. That would be
convert a.tga b.tga -compose Atop -composite out.tga
Here is an Imagemagick command that does what you want:
convert -gravity Center whitecloud.tga -fx "u/max(u.a, 1/255)" bg.tga +swap -composite -fx "u*u.a" comp.tga
What's happening here?
-fx command #1: Convert whitecloud.tga from premultiplied alpha to "normal". The max() operator is a special case to avoid dividing by zero.
+swap command: Make bg.tga the first image and the revised whitecloud.tga the second.
-composite these two regular, non-premultiplied images.
-fx command #2: take the result, and return to a premultiplied alpha format.
This gives exactly the same result as After Effects.
Note that, as I wrote it, it only works for an opaque bg.tga. You'd need to do some extra work to handle a transparent background image.
If you want to duplicate the After Effects result, then I believe what you want to do in ImageMagick is the following -- composite the background image with a white image using the cloud as a mask:
convert bg.tga \( -clone 0 -fill white -colorize 100 \) whitecloud.tga -compose over -composite cloud_blue.tga
I have posted a JPG result, but my .tga result is the same.

Resources