Imagemagick parameters in Bash variables are not interpreted properly? - bash

I need to dinamically compose an image using Imagemagick with a canvas as a base and some other images on top of that.
Currently, the most simple scenario just works (please notice you will need two images named src1.png and src2.png for this to work):
convert src1.png -gravity northwest -draw 'image Over 10,10 0,0 "src2.png"' result.png
However, I need to dinamically forge these parameters to be able to draw one, two or more images on top of src1.png.
To do that, I tried storing the parameters in a variable, and then doing a substitution. I tried two versions of this, both with arrays and with simple strings:
DRAWOPTS=(-draw 'image Over 10,10 0,0 \"src2.png\"')
convert src1.png -gravity northwest ${DRAWOPTS[#]} result.png
DRAWOPTS="-draw 'image Over 10,10 0,0 \"src2.png\"'"
convert src1.png -gravity northwest $DRAWOPTS result.png
But I always get these errors:
convert.im6: non-conforming drawing primitive definition `image' # error/draw.c/DrawImage/3160.
convert.im6: unable to open image `Over': No such file or directory # error/blob.c/OpenBlob/2641.
convert.im6: no decode delegate for this image format `Over' # error/constitute.c/ReadImage/544.
convert.im6: unable to open image `10,10': No such file or directory # error/blob.c/OpenBlob/2641.
convert.im6: no decode delegate for this image format `10,10' # error/constitute.c/ReadImage/544.
convert.im6: unable to open image `0,0': No such file or directory # error/blob.c/OpenBlob/2641.
convert.im6: no decode delegate for this image format `0,0' # error/constitute.c/ReadImage/544.
convert.im6: unable to open image `"src2.png"'': No such file or directory # error/blob.c/OpenBlob/2641.
convert.im6: no decode delegate for this image format `"src2.png"'' # error/constitute.c/ReadImage/544.
convert.im6: non-conforming drawing primitive definition `image' # error/draw.c/DrawImage/3160.
And I can't get this to work. Need some help with this quoting hell, please.

You need to quote the expansion of the array.
DRAWOPTS=( -draw 'image Over 10,10 0,0 "src2.png"' )
convert src1.png -gravity northwest "${DRAWOPTS[#]}" result.png

Related

How to resize images using ImageMagick? (mac os)

There is a pack of images and I want to reduce the height and width on 10 px of each image. The problem is that every image has a different size (i mean height and width). I found out how to resize images in terminal using ImageMagick, but it could resize images only to a fixed size (for example: convert example.png -resize 200x100 example.png). I need resizing to ((current width)-10px)x((current height)-10px) for every image. I am new to programming, be patient, please :)
If using Imagemagick 7, you can write a loop over all your images. In Unix syntax (assuming your images names have no spaces in them):
cd to your current directory
list=$(ls)
for img in $list; do
magick $img -resize "%[fx:w-10]x%[fx:h-10]" $img
done
If you do not want to overwrite your images, then create a new directory and put the path to that directory before the output.
If you want to do more than one image at a time, you can do:
cd to your current directory
magick * -resize "%[fx:s.w-10]x%[fx:s.h-10]" result.suffix
This will make the resulting images all with the same name, but with numbers appended, such as result-0.suffix, result-1.suffix, etc.
If you are using Imagemagick 6, then you will have to precompute the sizes in a separate command.
cd to your current directory
list=$(ls)
for img in $list; do
dimensions=$(convert image -format "%[fx:w-10]x%[fx:h-10]" info:)
convert $img -resize $dimensions $img
done
Note that resizing will not necessarily give you the result you want, since Imagemagick will try to keep the aspect ratio. So if you want to force the exact sizes, then you need to add ! to your resize argument. However, that will cause some distortion, though probably not too much for only resizing by 10 pixels.
An easier way would be to just shave off 5 pixels all around. Then you could do a whole folder using mogrify:
cd to current directory after creating a new directory for the output if desired:
mogrify -path path/to/new_directory -shave 5x6 *
In Imagemagick 7, that would be magick mogrify ...

How to crop 486 pixels from the bottom of each JPG image in the folder with ImageMagick?

How to crop 486 pixels from the bottom of each JPG image in the folder with ImageMagick?
The following command
magick -crop -0-486 *.jpg
says
magick.EXE: no images found for operation `-crop' at CLI arg 1 # error/operation.c/CLIOption/524
magick.EXE: no image to apply a property "%w" # warning/property.c/GetMagickPropertyLetter/2561.
magick.EXE: unknown image property "%w" # warning/property.c/InterpretImageProperties/3499.
magick.EXE: no image to apply a property "%h" # warning/property.c/GetMagickPropertyLetter/2449.
magick.EXE: unknown image property "%h" # warning/property.c/InterpretImageProperties/3499.
magick.EXE: no image to apply a property "%m" # warning/property.c/GetMagickPropertyLetter/2480.
magick.EXE: unknown image property "%m" # warning/property.c/InterpretImageProperties/3499.
Please, give specific example, internet in controversal (various names like mogrify, convert, various commands etc). Also don't point to ImageMagick "Talmud". Need just a simple example.
OS is Windows, Magick is installed with Chocolatey.
Please make a backup of your images before using the following commands.
The command for a single image is convert or if you have ImageMagick 7+, it is magick.
The command for multiple images is mogrify, or if you have ImageMagick 7+, it is magick mogrify.
The command you want is as follows and it will chop 486 pixels off the bottom of each image in the current directory:
magick mogrify -gravity south -chop x486 *.jpg
The main ImageMagick command command used to be called convert but there is a Microsoft tool with the same name that has caused confusion for years, so all the ImageMagick commands were prefixed with magick, followed by the old name. So,
animate ...
becomes:
magick animate ...
And
mogrify ...
becomes:
magick mogrify ...
In the case of convert, which is the most common usage, you can now use
magick convert ...
or simply
magick ...
where convert is implied.

Converting tiff to mode 1 bit images

Is it possible to convert a tiff image to mode 1-bit image using command line tools. I saw it can be done with gimp but I need to run a script so I prefer a solution using packages like imagemagick etc
If the image contents is already black and white, and you just need to convert, use:
convert input.tif -depth 1 output.tif
If you also require to threshold the image, use something like:
convert input.tif -separate -black-threshold 128 -depth 1 output.tif

Batch convert/resize different image formats to JPEG of certain resolution with ImageMagick

How do I use mogrify to batch-convert a ton of files (.TIF, .EPS, .JPG but most annoyingly of all-) .PSD files and only keep their first layer?
I found a solution on how to convert all images, but I kept getting filenames in my output-directory which were different from my originals (they had -0, -1, -2 etc. attached to the original filename).
I have 2 folders, ./original/ (which contains my PSDs, EPS, TIF, GIF, JPGs and other images) + the folder ./converted/ (which is the target folder for my conversion)
The command I use to convert my images are:
mogrify -verbose -path ./converted/ \
-alpha off -strip -mattecolor white -background white \
-resize 512x512 -format jpg -quality 75% -interlace Plane ./original/*.*
But no matter what I try, I keep getting this garbage which mangles my filenames. There is one mode however which just merges every interpretation of the files into one, but that's also quite useless as I am getting black backgrounds on my transparent files.
After 2 hours of searching I finally found the answer, and since I love stackoverflow, I'm sharing it here:
In order to select the best image of PSD's or first frame of .GIF's, all you need to add is an index of 0 (litterally, without the double quotes: "[0]") to the input file.
So the command to convert all images (you need to install ImageMagick with mogrify first), with a white background for anything transparant, within a bounding box of 512x512 pixels, outputted at jpg with 50% compression quality, the layers Disposed and the first index used, you need to execute the following command:
mogrify -verbose -path ./converted/ \
-alpha off -strip -mattecolor white -background white -layers Dispose \
-resize 512x512 -format jpg -quality 75% -interlace Plane ./original/*.*[0]
Hopefully this will serve as an easy to use template for anyone who needs to batch convert a lot of images.
I found several image converters but none were as easy to use as mogrify, and of course, it being a linux executable, it gives near infinite possibilities about what you can do with it... everything should be scriptable.

How to force ImageMagick to produce single output image?

I'm trying to convert tiff file to jpg in bash script, although I get 3 jpeg files (good, average and poor quality, I assume, same image) instead of one.
Here's an example of command:
convert -resize 200x200 -quality 90 "$CURRENT_DIR/$i" "$OP/$WITHOUT_EXT.thumb.jpg"
I've also tried without resize and quality params, but result is still the same.
Is it possible to get a single output file? Thank you!
try to add [] or [0] at end of source file:
convert -resize 200x200 -quality 90 "$CURRENT_DIR/${i}[0]" "$OP/$WITHOUT_EXT.thumb.jpg"

Resources