I have a script that converts a PDF to JPG in the correct aspect ratio.
magick.exe c:\test\2.pdf -page A4 -set option:wd "%[fx:(4/3)>(w/h)?(4/3*h):w]" -set option:ht "%[fx:(4/3)>(w/h)?h:(w/(4/3))]" -gravity center -background white -extent "%[wd]x%[ht]" c:\test\2.jpg
I have 2 questions:
Is it possible to create a batch file that will perform conversions for the input file PDF downloaded from the Internet. Something like open in 'convert.bat' where the result will be JPG in the specified location.
Is it possible to set a variable name of the output file
I was able to create a batch file. I adds below. Maybe it will be useful to someone.
#echo off
setlocal
set INIMAGE="%~1"
magick ^
%INIMAGE% ^
-set filename:f "%%[t]" ^
-page A4^
-set option:wd "%%[fx:(4/3)>(w/h)?(4/3*h):w]" ^
-set option:ht "%%[fx:(4/3)>(w/h)?h:(w/(4/3))]" ^
-gravity center ^
-background white ^
-extent "%%[wd]x%%[ht]" ^
"c:\test\%%[filename:f].jpg"
Related
Background:
I have been trying to implement image enhancement using wand library to add drop shadow to a SingleImage.
I was able to create drop-shadow using ImageMagick CLI, but want to replicate the same using wand package. As CLI solution reduced the throughput of the system while using python subprocess to execute ImageMagick commands, I am hopeful to improvise using wand package.
Goal
Add drop shadow around an object using wand package. Successfully implemented using CLI commands.
Command: magick $in \ \( +clone -background black -shadow "35x11+0+11" \) -background none -compose DstOver -flatten -compose Over $out x 7 with different shadow parameters.
Input Image
Expected Output
ImageMagick Version: 7
Attempts
Below code produced this image wand package output
python version : 3.9
wand package version: 0.6.11
img = Image(filename="input.png", colorspace='rgb')
#pardon the indent
with img.clone() as shadow:
shadow.background_color = Color('black')
shadow.shadow(alpha=90, sigma=10, x=0, y=2)
shadow.save(filename="shadow.png")
with Image(filename="input.png", background=Color('none')) as front:
with Image(filename="shadow.png") as back:
with front.clone() as new_image:
new_image.composite(back, 4, 4, operator='flatten')
# merge layers has no effect
# back.merge_layers('merge')
new_image.save(filename="image_with_shadow.png")
One of the solution on internet was use to merge_layer, but I am unable to create the match CLI output. Can I add multiple shadows with different parameters on shadow image ?
Standard shadow in Imagemagick command line is:
magick rose: \( +clone -background navy -shadow 80x3+5+5 \) +swap -background none -layers merge +repage shadow.png
So in your command it would be:
magick $in ( +clone -background black -shadow "35x11+0+11" ) +swap -background none -compose Over -layers merge +repage $out
Note the +swap, -compose over (only), -layers merge, and +repage
So swap your foreground and background images, use merge rather than flatten in the composite (though composite may not be correct as -layers merge is not the same as -composite).
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)]"
i have a folder of images with names foo<bar>.png where <bar> ranges from 0 to 100.
When i create a gif of these images with
convert -dispose previous -delay 10 -resize 25% -loop 0 *.png myimage.gif
it creates a gif with images in order like 0,1,2,3...
Is there a command to select images in random order?
If your PNG images are all the same dimensions, and if the number of images can be evenly divided into a grid, like 72 images would make a grid of 8 x 9 images, and if your images are small enough to read them all into a single ImageMagick command, here is a command that will randomize the order of a group of 72 input images...
convert *.png -virtual-pixel tile +append -crop 9x1# -append +repage ^
-crop 1x9# -distort affine "0,0 %[fx:floor(rand()*8)*(w/8)],0" -append +repage ^
-crop 8x1# -distort affine "0,0 0,%[fx:floor(rand()*9)*(h/9)]" +append +repage ^
-crop 8x9# +repage -set delay 10 -loop 0 image.gif
It basically makes a grid, randomly rolls all the rows, then randomly rolls all the columns. The shuffle scatters the images pretty well, but if you want a deeper shuffle, copy and paste those two "-crop ... -distort" lines, and add them below the first two...
convert *.png -virtual-pixel tile +append -crop 9x1# -append +repage ^
-crop 1x9# -distort affine "0,0 %[fx:floor(rand()*8)*(w/8)],0" -append +repage ^
-crop 8x1# -distort affine "0,0 0,%[fx:floor(rand()*9)*(h/9)]" +append +repage ^
-crop 1x9# -distort affine "0,0 %[fx:floor(rand()*8)*(w/8)],0" -append +repage ^
-crop 8x1# -distort affine "0,0 0,%[fx:floor(rand()*9)*(h/9)]" +append +repage ^
-crop 8x9# +repage -set delay 10 -loop 0 image.gif
Carefully replace the "8"s and "9"s with the width and height of the grid that holds the number of images you're using. I use it in a script that shuffles a deck of playing card images, 13 rows and 4 columns.
This uses ImageMagick v6 in Windows CMD syntax. In a BAT script double all the percent signs "%%". It would probably work on a *nix OS by changing all the continued-line carets "^" to backslashes "\". For ImageMagick v7 use "magick" instead of "convert".
I can tell you 2/3 of the answer on Windows, and hopefully some other kind soul can add the rest for you. Nobody said answers have to be complete.
Create a text file containing the names of the PNGs you want to animate. I believe that is:
DIR /B *.png > filelist.txt
Shuffle the lines in that file. I don't know how to do that in Windows. In Linux and macOS it is shuf. Here's a little Python equivalent:
python -c "import random, sys; lines = open(sys.argv[1]).readlines(); random.shuffle(lines); print ''.join(lines)," filelist.txt > shuffled.txt
Pass that file to ImageMagick like this:
convert -loop 0 -delay 80 #filelist.txt animation.gif
If you get that working, you can avoid the need for a temporary file by using this syntax:
DIR /B *.png | SHUFFLELINES | convert -loop 0 -delay 80 #- animation.gif
The section entitled Square Padding or Cropping describes a method to generate a square image--for a file whose dimensions are unknown--and pad the background with a color.
How do I perform the same operation, but create a transparent background.
Let's make a red off-square image first, that is 300x200:
convert -size 300x200 xc:red image.png
Now let's put make a square image of it, but using a yellow background so you can see it:
convert -background yellow -gravity center image.png -resize 400x400 -extent 400x400 result.png
Now we can do the same thing again, but make the background transparent:
convert -background none -gravity center image.png -resize 400x400 -extent 400x400 result.png
and, just check to make sure it has worked:
identify result.png
result.png PNG 400x400 400x400+0+0 8-bit sRGB 418B 0.000u 0:00.000
These modified methods from Anthony's examples both work for me:
convert thumbnail.gif \
\( +clone -rotate 90 +clone -mosaic +level-colors grey -transparent grey \) \
+swap -gravity center -composite square_padded.gif
convert thumbnail.gif -virtual-pixel none -set option:distort:viewport \
"%[fx:max(w,h)]x%[fx:max(w,h)]-%[fx:max((h-w)/2,0)]-%[fx:max((w-h)/2,0)]" \
-filter point -distort SRT 0 +repage square_external.gif
A pure imagemagick command would be preferable, but here's a script that uses the 'file' unix/linux command to extract the dimensions of the file which can then be used on a resize to a square of the max dimension.
#!/usr/bin/env ruby
require 'shellwords'
def dims(image_escaped)
size_data = `file #{image_escaped}`
size_data[/, (\d+ x \d+),/, 1].split(' x ').map(&:to_i)
end
def square(image, pad_color='transparent')
image_esc = Shellwords.escape(image)
maxdim = dims(image_esc).max
geometry = "#{maxdim}x#{maxdim}"
# could use convert if don't want to clobber the image
system "mogrify -resize #{geometry} -background #{pad_color} -gravity center -extent #{geometry} -format png #{image_esc}"
end
ARGV.each do |image|
square(image)
end
When using mogrify -crop 500x500 *.jpg
I get output as *-1.jpg, *-2.jpg, *-3.jpg, *-4.jpg
Is it possible to change so that it gets a different separator. eg. underscore?
output: *_1.jpg, *_2.jpg, *_3.jpg, *_4.jpg,
You can do this with convert:
convert *.jpg -crop 500x500 -set filename:f "%t_%p" '%[filename:f].jpg'
See this page for more info.