Imagemagick crop transparent image to mask - imagemagick

So here is my original image (note the transparent border) src.png:
Here's the mask I want to use to crop. White means keep, black means crop mask.png: (Note that it isn't necessarily going to be a square. It could be a heart or a star or anything)
I also have transparent.png, which is a fully transparent image. All three images have the same dimensions.
So, running this command generates the following image:
convert transparent.png src.png mask.png -composite out.png
Which is masking perfectly, but now I want it cropped to the size of the white mask area. Using -trim is sort of close, but it gets rid of the transparent areas that are inside the mask.
How can I resize the masked image to the size of the white area in the mask?

I am not sure I understand what you want for the result. Why do you need the fully transparent image? Do either of these do what you want?
Full sized transparent image with masked area showing:
convert src.png mask.png -alpha off -compose copy_opacity -composite result1.png
Trimmed to just the part you want:
convert src.png mask.png -alpha off -compose copy_opacity -composite -trim +repage result2.png

Not sure I understand what you are trying to do, not least why you need a full size transparent canvas. Your command does not give the same results on my ImageMagick version 7.
This command may be what you are looking for:
convert src.png mask.png -compose darken -composite -trim out.png
It gives this - I have artificially added a red border so you can see the full extent on StackOverflow's white background:
Or maybe you want the trim box from your mask and to use that to crop your source:
convert mask.png -format %# info:
113x113+570+33
convert src.png -crop 113x113+570+33 result.png

If you want to crop a square from picture, you no needs using mask, just crop it:
magick Uq328.png -crop -crop 111x111+570+331 +repage cropped.png
according to https://legacy.imagemagick.org/Usage/crop/

Related

imagemagick trim but keep canvas size and *position*

Friends,
I need to -trim some images but keep the original canvas size. Works like this:
convert in.png -fuzz 10% -trim -background white -set page "%[fx:w]x%[fx:h]" +repage out.png
But how can I position the trimmed image part at it's original position? -gravitiy center is not an option as the to-be-trimmed part usually not at the canvas center.
Any ideas?
You should be able to -trim an image, then use -flatten to lay it back onto its original canvas. Try this command...
convert logo: -background none -trim -flatten trimmed.png
#GeeMack's answer is certainly simpler and more succinct, but if you need more flexibility for dinking around, another way is to get the image height and width and the trimbox in one invocation and use them in the next - maybe with adaptation.
So, starting with this image:
# Get image width and height and the trim-box
read geom trim < <(magick start.png -format "%G %#" info:)
# Make a new white canvas same size as original and trim new image onto it
magick -size $geom xc:white \( start.png -crop $trim \) -flatten result.png
I put an artificial yellow border around it so you can see the extent of it on SO's white background.

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

ImageMagick get image side only - not a edge detection problem

This is not a finding edge problem but I am trying to find the background color of the image, in order to find it, I am trying to get the edge of the image and guess the best color.
In order to do so, I want to remove the center of the image and just get image like a frame with transparent center.
Is it possible through ImageMagick?
For example
If want
Try this tested on Windows with IM V7:
magick "input.png" ( -size 200x200 xc:black ) -gravity center -compose DstOut -composite "output.png"
Takes the original photo, creates a rectangular mask, places it over the middle of the image and "cuts" out the rectangle
If the input is not a png ( for instance a jpg ) you will have to do some work setting the alpha channel
EDIT: This seems to work for both jpg and png images
magick "input.png" -alpha on ( -size 200x200 xc:black ) -gravity center -compose DstOut -composite "output.png"
I'll offer a simple variation on Bonzo's solution. This command allows you to specify in pixels the amount of edge you want to keep...
magick input.jpg -alpha on -bordercolor none -background none ^
( +clone -shave 24 -border 24 ) -compose dstout -composite output.png
It reads the input image, sets the alpha "on", and sets the border and background colors to "none".
Then inside the parentheses it makes a clone of the input image, shaves off the amount you want to retain around the edges, then adds that amount back as a transparent border all around. That will be the mask.
Then after the parentheses use a compose method of "dstout" to composite that mask onto the input image, which results in a transparent "hole" in the image with your specified amount of the original edge retained.
If you want to keep different amounts from the vertical and horizontal edges, specify those amounts in the shave and border operations...
... -shave 24x32 -border 24x32 ...
If you're using IMv7 you can even use FX expressions to specify the widths...
... -set option:v1 %[fx:(w+h)/2*0.1] -shave %[v1] -border %[v1] ...
The command is in Windows syntax using IMv7. Change "magick" to "convert" to use it with IMv6. To make it work in *nix you need to change the continued-line caret "^" to a backslash "\" and escape the parentheses with backslashes "\(...\)".

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.

Use ImageMagick to place an image inside a larger canvas

Getting started with ImageMagic and trying to find a way to do this... If an image is less than 50 pixels tall or 50 pixels wide, I'd like to place it (un-scaled) in the horizontal/vertical center of a new 50x50 pixel canvas on top of a white background - and save that as the new image. Anyone know if this is possible with ImageMagick? Thanks!
I used -extent to do this:
convert input.jpg -gravity center -background white -extent 50x50 output.jpg
I wanted to do the same, except shrink the image to 70% inside. I used this:
convert input.png -resize 70%x70% -gravity center -background transparent -extent 72x72 output.png
Not exactly what was requested but hopefully it will help someone ;).
I have once used this code to place an image in the center of a new canvas with white background. hope this will help you
convert -background white -gravity center your_image.jpg -extent 50x50 new_image.jpg
See cutting and bordering for a huge number of examples. Here's one simple way you might do it:
convert input.png -bordercolor Black -border 5x5 output.png
Of course, you'll need to calculate the size of the border to add (if any) based on the dimensions of the input image. Are you using an ImageMagick API, or just the command line tools?
I tried this:
convert test.jpg -resize 100x100 -background black -gravity center -extent 100x100 output.png
You can use single composition to do this. So it would look something like this:
convert -size 50x50 xc:white null: ( my_image.png -coalesce ) -gravity Center -layers Composite -layers Optimize output.png
To modify the source image you need to use mogrify:
mogrify -gravity center -background white -extent 50x50 source.jpg
If an image is less than 50 pixels tall or 50 pixels wide
In my case, the images were much larger than the destination canvas, and weren't square. So I resize them proportionally to fit inside. Example:
convert in.png -resize 46x46 -background none -gravity center -extent 50x50 out.png
The 46x46 limit ensures a 2 pixel margin minimum. Note that the above does not distort the image, e.g. a rectangle does not become a square.
I used background none for a transparent background, but you can choose a solid color instead.

Resources