Use ImageMagick to resize and then crop an image from command line - imagemagick

I have a jpg image which I want to resize as follows:
Keeping the aspect-ratio of the image same, resize it to as close as 640x360 as possible, without keeping any portion of the new image "blank"/"empty". That is, it's okay if after resizing, it becomes 800x360 or 640x420, but not okay if it is 400x360 (because 400 is lesser than 640) or 640x200 (because 200 is lesser than 360).
After this, I need to center-crop the above-resized image to the ratio of 16:9.
What would be the easiest set of shell commands which can be used to achieve this using imagemagick?
I tried both
convert 'orig_image.jpg' -resize 640x360 -gravity Center -crop 640x360+0+0 'changed_image.jpg' and
convert 'orig_image.jpg' -resize 640x360 -gravity Center -crop 640x360+0+0 +repage 'changed_image.jpg'
but none worked. -resize 640x360 is resizing the image, but not fulfilling my above requirement. That is, 2448x3264 is resizing to 270x360 instead of 640x480

Perhaps you can use this:
convert orig.jpg \
-resize 640x360^ \
-gravity Center \
-extent 640x360
changed.jpg
Where -resize 64x360^ preserves the minimum aspect ratio, and -extent 640x360 (without +0+0) respected -gravity Center

Related

Can I refer to the image width and height in an argument?

I want to convert multiple images into square format, filling any empty space with black. Assuming the images have a width of 1000 and a height of less than 1000 (or vice versa), I can do it like this (using PowerShell):
magick.exe convert -background black -gravity center `
-resize 1000x1000 -extent 1000x1000 `
-set filename:original '%t' '.\*.jpg' './%[filename:original]-resized.jpg'
However, I want this to work for arbitrarily sized images. I need to do something like this, which is not an actually supported syntax:
#...
-resize 'max(%w,%h)xmax(%w,%h)' -extent 'max(%w,%h)xmax(%w,%h)' `
# ...
Is there an Imagemagick syntax for what I'm trying to do?
In Imagemagick 7, use magick, not magick convert and move the input parameter to the first parameter position, i.e. magick '.\*.jpg'.
Then, to do what you want change
-resize 'max(%w,%h)xmax(%w,%h)' -extent 'max(%w,%h)xmax(%w,%h)'
to
-resize "%[fx:max(w,h)]x%[fx:max(w,h)]" -extent "%[fx:max(w,h)]x%[fx:max(w,h)]"

How to resize overlay image by ratio and with relative position it from the right?

Let's start with a background and an overlay image:
magick convert -size 500x500! xc:red background.jpg # make a big red background
magick convert -size 100x100! xc:blue overlay.jpg # make a smaller blue overlay
To composite from right side I can use
$geom=magick convert overlay.jpg -print "+%[fx:w+50]+0" null:
magick convert background.jpg overlay.jpg -gravity northeast -geometry $geom -composite output.jpg
However, in my real project, I need to run this with various background images, whose sizes are also various. I would like the overlay to use relative size to the background instead of absolute size.
To overlaying a watermark/logo with relative dimentions, I can use:
magick background.jpg overlay.jpg -resize %[fx:t?u.w*0.9:u.w]x%[fx:t?u.h*0.9:u.h] -gravity northease -composite output.jpg
To resize overlay image by ratio and with relative position it from the right, I try:
magick background.jpg overlay.jpg -resize %[fx:t?u.w*0.1:u.w]x%[fx:t?u.h*0.1:u.h] -gravity northeast -geometry +[fx:t?u.w*0.1:u.w]+[fx:t?u.h*0.1:u.h] -composite output.jpg
But it says:
magick.exe: invalid argument for option '-geometry' '+[fx:t?u.w*0.1:u.w]+[fx:t?u.h*0.1:u.h]' at CLI arg 7 # error/operation.c/CLISimpleOperatorImage/2522.
The documentation for geometry doesn't seem to talk about this. Do you know why?
I'm using v7 on Windows
I miss the %. Correct code:
magick .\base.jpg .\logo.png -resize %[fx:t?u.w*0.1:u.w]x%[fx:t?u.h*0.1:u.h] -gravity northeast -geometry +%[fx:t?u.w*0.03:u.w]+%[fx:t?u.w*0.03:u.w] -composite output.png
See Format and Print Image Properties
The reasoning behind the %[fx:t?u.w*0.9:u.w]
From The FX Special Effects Image Operator:
u: first image in list
v: second image in list
t: index of current image (s) in list
w: width of this image
So in plain language, it means that if the image in question is the second image, whose index is one, of which the ternary conditional operator also read as true, then resize it to 90% width of the first image, else do no resize. Or else -resize option will apply to each images in an image sequence (i.e. all input images before it, but not after it).

Imagemagick convert to name tiles as row/column doesn't work as expected with -extent

I have an image, 5120  ×  4352 that I crop into 2048x2048 tiles. I want to name my cropped tiles like
tile_0_0.png
tile_0_1.png
tile_0_2.png
tile_1_0.png
tile_1_1.png
tile_1_2.png
...
But this command:
convert image.png -crop 2048x2048 -gravity northwest \
-extent 2048x2048 -transparent white \
-set 'filename:tile' '%[fx:page.x/2048]_%[fx:page.y/2048]' \
+repage +adjoin 'tile_%[filename:tile].png'
Gives me this result:
tile_0_0.png
tile_0_1.png
tile_0_16.png
tile_1_0.png
tile_1_1.png
tile_1_16.png
tile_4_0.png
tile_4_1.png
tile_4_16.png
I suspect it has do with the tiles on the last row and column aren't fully 2048x2048, but the extent command makes the end result still 2048, but how can I use this with tiles and file names?
My current workaround is to first resize the original image like this, and then run the above command:
convert image.png -gravity northwest \
-extent 2048x2048 -transparent white bigger.png
But it would be nice to do it in one swoop :)
Using ImageMagick you could set a viewport that is just enough larger than the input image so it divides evenly by 2048. Then a no-op distort will enlarge the viewport to that size. That way the "-crop 2048x2048" will create pieces that are already 2048 square.
Here's a sample command I worked up in Windows, and I'm pretty sure I translated it to work correctly as a *nix command.
convert image.png \
-set option:distort:viewport '%[fx:w-(w%2048)+2048]x%[fx:h-(h%2048)+2048]' \
-virtual-pixel none -distort SRT 0 +repage -crop 2048x2048 \
-set 'filename:tile' '%[fx:page.x/2048]_%[fx:page.y/2048]' \
+repage +adjoin 'tile_%[filename:tile].png'
The "-distort SRT" operation does nothing except expand the viewport to dimensions that divide evenly by 2048, with a result just like doing an "-extent" before the crop. And "-virtual-pixel none" will leave a transparent background in the overflow areas.
Edited to add: The formula for extending the viewport in the above command will incorrectly add another 2048 pixels even if the dimension is already divisible by 2048. It also gives an incorrect result if the dimension is less than 2048. Consider using a formula like this for setting the viewport to handle those conditions...
'%[fx:w+(w%2048?2048-w%2048:0)]x%[fx:h+(h%2048?2048-h%2048:0)]'

ImageMagick crop keeping the height

I'm trying to crop image by height with this command line:
convert 1053257.png -gravity South -crop 2910x3312+0+0 -background black +repage image-cropped-top.png
The generated image is not cropped correctly, as the dimensions after running the command are 2791 x 3312.
The width is cropped as well!
Can anyone help with this?
The general form is:
convert input.jpg -crop WIDTHxHEIGHT+0+0 result.jpg
If you want to crop to a specific width, say 1024, leaving the height unaffected:
convert image.jpg -crop 1024x+0+0 result.jpg
If you want to crop to a specific height, say 768, leaving the width unaffected - note the height is after the x:
convert image.jpg -crop x768+0+0 result.jpg
If you want to crop to a maximum width and height, say 1024 wide by 768 tall without distorting the aspect ratio:
convert image.jpg -crop 1024x768+0+0 result.jpg
If you want to crop to a specific width and height, say 1024 wide by 768 tall and are happy to allow gross distortions:
convert image.jpg -crop 1024x768+0+0\! result.jpg
Think of the exclamation mark as meaning "just do it!". Note that the backslash is only needed on Linux/Unix/macOS to escape the exclamation mark, you omit the backslash on Windows.
Note, if you are saving the cropped image in PNG format, you probably want to reset the page afterwards so the image "forgets" it used to be part of a larger image:
convert input.jpg -crop 1024x768+0+0 +repage result.png
With ImageMagick a problem like that can occur if you've done a "-trim" to the image before the crop. When you "-trim" an image it can still remember the original page dimensions from before the trim, then when you crop it, it uses those page dimensions as the starting reference for the crop. You probably need to "+repage" before the crop to start with fresh paging information. Try something like this...
convert 1053257.png -gravity South +repage -crop 2910x3312+0+0 +repage image-cropped-top.png

imagemagick: center and resize multiple images an keep original filename

Good morning,
I'd like to center and resize multiple images in a folder with different aspect ratios and keep the filename. The following is nearly what I like to have (it works perfect for the particular picture), but there I have to name every specific pic.
convert -size 100x100 xc:black -gravity center originalpic.jpg -thumbnail 300x300 -composite newpic.jpg
I tried to work with * to keep the original file name and to process every file in the folder but without success. Does anybody know how to do that?
Thank you!
Use the mogrify command to work with multiple files.
mogrify -size 100x100 xc:black -gravity center -thumbnail 300x300 -composite *.jpg
Another way would be to iterate over the images in bash and use the same name as output to overwrite:
for f in *.jpg
do convert -size 100x100 xc:black -gravity center $f -thumbnail 300x300 -composite $f
done
I think I got it for me in general:
First size down to the height you want, e.g. to 364px:
mogrify -resize x364 *.jpg
And then, e.g. you want to get a dimension of 546x364px, this:
mogrify -extent 546x364 -gravity center *.jpg
But at image with original size of 512x768 background is getting filled with white color, so I tried
mogrify -extent 546x364 -gravity center -background black *.jpg
and
mogrify -extent 546x364 -gravity center -fill black *.jpg
but background is still white :-(

Resources