I am using ImageMagick and grunt-exec to generate a favicon for a website I am working on using the command found in the ImageMagick documentation.
convert image.png -bordercolor white -border 0 \
\( -clone 0 -resize 16x16 \) \
\( -clone 0 -resize 32x32 \) \
\( -clone 0 -resize 48x48 \) \
\( -clone 0 -resize 64x64 \) \
-delete 0 -alpha off -colors 256 favicon.ico
However I am getting some issues with line breaks which I think is partially because I do not fully understand what I should do with the line breaks.
In my Gruntfile.js I am currently using no line breaks and it works as expected. Notice that I had to remove all the line breaks and double escape the parentheses because apparently grunt-exec parses the string before it executes it.
exec: {
favicon: 'convert _favicon.svg -bordercolor white -border 0 \\( -clone 0 -resize 16x16 \\) \\( -clone 0 -resize 32x32 \\) \\( -clone 0 -resize 48x48 \\) \\( -clone 0 -resize 64x64 \\) -delete 0 -alpha off -colors 256 favicon.ico'
}
Like I said, I have it working right now but I would like to be able to use line breaks for readability and also because I would like to fully understand what is going on here. So far I have tried adding an extra \ and leaving everything the same, replacing the new lines with \n or \\n and putting everything on the same line but no luck.
The solution I was looking for turned out to be to use \n\ for new lines, like this:
convert image.png -bordercolor white -border 0 \n\
\( -clone 0 -resize 16x16 \) \n\
\( -clone 0 -resize 32x32 \) \n\
\( -clone 0 -resize 48x48 \) \n\
\( -clone 0 -resize 64x64 \) \n\
-delete 0 -alpha off -colors 256 favicon.ico
Try using this:
exec: {
favicon: 'convert _favicon.svg -bordercolor white -border 0 "( -clone 0 -resize 16x16 )" "( -clone 0 -resize 32x32 )" "( -clone 0 -resize 48x48 )" "( -clone 0 -resize 64x64 )" -delete 0 -alpha off -colors 256 favicon.ico'
}
Related
My bash script uses convert of the image magic to stack horizontally two types of the images producing 2xN multi-image chart:
convert \( "${output}/type1*.png" -append \) \( "${output}/type2*.png" -append \) +append -background white -alpha deactivate ${output}/summary.png
how would it be possible to add border of the selected dimensions between stacked images in the manner as I may do via montage -mattecolor $color_id ?
montage \( "${output}/type1*.png" \) \( "${output}/type2*.png" \) -geometry 800x600+1+1 -tile x2 -frame 4 -background white -mattecolor lightgoldenrod2 -mode Frame -bordercolor white ${output}/summary.png
vertical borders between each separate sections of the type1/ type2 and a horizontal border between the both parts joined in the summary:
convert \( "${output}/type1*.png" -bordercolor lightgoldenrod2 -border 0x2 -append \) \( "${output}/type2*.png" -bordercolor lightgoldenrod2 -border 0x2 -append \) -bordercolor lightgoldenrod2 -border 2x0 +append -background white -alpha deactivate ${output}/summary.png
I'm running this from the command line:
magick.exe input.png -shave '1x0' output_%d.png
magick.exe input.png -shave '2x0' output_%d.png
magick.exe input.png -shave '3x0' output_%d.png
magick.exe input.png -shave '4x0' output_%d.png
magick.exe input.png -shave '5x0' output_%d.png
magick.exe input.png -shave '0x1' output_%d.png
magick.exe input.png -shave '0x2' output_%d.png
magick.exe input.png -shave '0x3' output_%d.png
magick.exe input.png -shave '0x4' output_%d.png
magick.exe input.png -shave '0x5' output_%d.png
The first command creates output_0.png but the following commands overwrite the same file. Is there a single command that could generate output_0.png to output_9.png instead?
The ImageMagick documentation says:
Filename References
Optionally, use an embedded formatting character to write a sequential
image list. Suppose our output filename is image-%d.jpg and our image
list includes 3 images. You can expect these images files to be
written:
image-0.jpg
image-1.jpg
image-2.jpg
That's the closest evidence I found it's possible to do what I'm looking for in ImageMagick. It's not clear to me if I need to leverage shell scripting to do this or if ImageMagick provides a command line feature.
With ImageMagick you can run multiple operations on separate instances of the input image in a single command by cloning the input and isolating the operations inside parentheses like this...
magick input.png \
\( -clone 0 -shave '1x0' \) \
\( -clone 0 -shave '2x0' \) \
\( -clone 0 -shave '3x0' \) \
\( -clone 0 -shave '4x0' \) \
\( -clone 0 -shave '5x0' \) \
\( -clone 0 -shave '0x1' \) \
\( -clone 0 -shave '0x2' \) \
\( -clone 0 -shave '0x3' \) \
\( -clone 0 -shave '0x4' \) \
\( -clone 0 -shave '0x5' \) \
-delete 0 output_%02d.png
That will create 10 output images, each with a sequential filename with the number padded to two places, like "output_00.png ... output_10.png".
To convert this to Windows CMD syntax you can remove all the backslashes that escape the parentheses, and replace the continued-line backslashes "\" with carets "^".
EDITED TO ADD: There are many ways to accomplish this task with ImageMagick. Here is another example command that would produce the same results, but it uses FX expressions so it will only work in IMv7. (The above command should work with IMv6 by changing "magick" to "convert".)
magick input.png -duplicate 9 -shave "%[fx:t<5?t+1:0]x%[fx:t>4?t-4:0]" output_%02d.png
This reads the input and duplicates it 9 times, then uses FX expressions as arguments to the -shave operation so it can step through all 10 images, shaving each according to the formula in the FX expression.
As #GeeMack points out, there are many ways of doing this with ImageMagick and I was inspired to try a couple of other methods by his marvellous FX expression - just for fun!
Here's what I was originally proposing:
magick input.png -write MPR:orig \
-shave 1x -write out_1.png \
-shave 1x -write out_2.png \
-shave 1x -write out_3.png \
-shave 1x -write out_4.png \
-shave 1x -write out_5.png \
-delete 0--1 \
MPR:orig \
-shave x1 -write out_6.png \
-shave x1 -write out_7.png \
-shave x1 -write out_8.png \
-shave x1 -write out_9.png \
-shave x1 out_10.png
It loads the input image and saves a copy in an MPR or "Magick Persistent Register" called orig. It then shaves a pixel off left and right sides and writes out_1.png, then shaves a further pixel off left and right sides and saves in out_2.png and continues till left and right are shaved by 5 pixels. It then reloads the original from the MPR and shaves off the top and bottom five times.
With a 1080p image, i.e. 1920x1080, this takes 3.4s and uses 96MB of RAM. By comparison, GeeMack's takes 3.5s on my machine and uses 291MB of RAM.
I then parallelised the creation of the left-right shaving with the top-bottom shaving as follows:
magick input.png \
-shave 1x -write out_1.png \
-shave 1x -write out_2.png \
-shave 1x -write out_3.png \
-shave 1x -write out_4.png \
-shave 1x out_5.png &
magick input.png \
-shave x1 -write out_6.png \
-shave x1 -write out_7.png \
-shave x1 -write out_8.png \
-shave x1 -write out_9.png \
-shave x1 out_10.png &
wait
That takes just 1.97s and peaks at 68MB of RAM.
I think GeeMack's solution is probably simplest and most concise, for most cases, but there may be some mileage in some of the ideas here for some situations, i.e. probably larger images.
In case anyone is interested how to measure the peak RAM usage, I used this:
/usr/bin/time -l ./go
1.97 real 6.01 user 2.48 sys
68354048 maximum resident set size
0 average shared memory size
0 average unshared data size
0 average unshared stack size
10343 page reclaims
0 page faults
0 swaps
...
...
I am writing a shell script to output multiple image sizes and formats from a source PNG. The script works great and outputs the correct sizes and formats but I get an error at the end of the script that I am trying to fix. The shell script code is below:
convert $pic -verbose -strip \
\( +clone -quality 75 -write test-output-$today-xl.jpg -write test-output-$today-xl.webp +delete \) \
\( +clone -resize 900 -quality 75 -write test-output-$today-lg.jpg -write test-output-$today-lg.webp +delete \) \
\( +clone -resize 747 -quality 75 -write test-output-$today-md.jpg -write test-output-$today-md.webp +delete \) \
\( +clone -resize 598 -quality 75 -write test-output-$today-sm.jpg -write test-output-$today-sm.webp +delete \) \
+clone -resize 548 -quality 75 -write test-output-$today-xs.jpg -write test-output-$today-xs.webp +delete
Which produces this output:
test-input.png=>test-output-2020-12-16-xl.jpg PNG 1788x1028 1788x1028+0+0 8-bit sRGB 88171B 0.060u 0:00.065
test-input.png=>test-output-2020-12-16-xl.webp PNG 1788x1028 1788x1028+0+0 8-bit sRGB 52228B 0.180u 0:00.179
test-input.png=>test-output-2020-12-16-lg.jpg PNG 1788x1028=>900x517 900x517+0+0 8-bit sRGB 27070B 0.380u 0:00.070
test-input.png=>test-output-2020-12-16-lg.webp PNG 1788x1028=>900x517 900x517+0+0 8-bit sRGB 16648B 0.490u 0:00.070
test-input.png=>test-output-2020-12-16-md.jpg PNG 1788x1028=>747x429 747x429+0+0 8-bit sRGB 19482B 0.310u 0:00.046
test-input.png=>test-output-2020-12-16-md.webp PNG 1788x1028=>747x429 747x429+0+0 8-bit sRGB 11790B 0.350u 0:00.048
test-input.png=>test-output-2020-12-16-sm.jpg PNG 1788x1028=>598x344 598x344+0+0 8-bit sRGB 13190B 0.330u 0:00.044
test-input.png=>test-output-2020-12-16-sm.webp PNG 1788x1028=>598x344 598x344+0+0 8-bit sRGB 8134B 0.230u 0:00.033
test-input.png=>test-output-2020-12-16-xs-0.jpg[0] PNG 1788x1028=>548x315 548x315+0+0 8-bit sRGB 11719B 0.520u 0:00.073
test-input.png=>test-output-2020-12-16-xs-1.jpg[1] PNG 1788x1028=>548x315 548x315+0+0 8-bit sRGB 11719B 0.340u 0:00.047
INFO: Added frame. offset:0,0 dispose:0 blend:1
test-input.png=>test-output-2020-12-16-xs.webp[0] PNG 1788x1028=>548x315 548x315+0+0 8-bit sRGB 13732B 0.520u 0:00.075
convert: `+delete' # error/convert.c/ConvertImageCommand/3303.
any ideas as to why I get an error with the +delete command and also get two versions of the last jpg outputted?
Apologies if this is a simple solution, i find the imagemagick documentation a little hard to parse for specific questions. Thanks in advance!
I would approach it as follows in Imagemagic. All clones must be enclosed in parentheses. Add null: to make no other output.
convert $pic -verbose -strip \
\( +clone -quality 75 -write test-output-$today-xl.jpg -write test-output-$today-xl.webp +delete \) \
\( +clone -resize 900 -quality 75 -write test-output-$today-lg.jpg -write test-output-$today-lg.webp +delete \) \
\( +clone -resize 747 -quality 75 -write test-output-$today-md.jpg -write test-output-$today-md.webp +delete \) \
\( +clone -resize 598 -quality 75 -write test-output-$today-sm.jpg -write test-output-$today-sm.webp +delete \) \
\( +clone -resize 548 -quality 75 -write test-output-$today-xs.jpg -write test-output-$today-xs.webp +delete \) \
null:
The syntax is :
convert <INPUT> <OUTPUT>
so you must output something at the end, you can't just delete the last image.
You could end with null: to discard the last image, but it's better not to create it in the first place. So your best bet is:
remove the last +clone and just use the input image you loaded on the first line, and
remove the final +delete
Also,-quality 75 is a setting, which means it remains set till you change it, so you can just put it once on the first line, rather than repeating it everywhere.
Also, you should double-quote bash variables:
convert "$pic" ...
then they'll still work when, one rainy day, your filenames have spaces in them.
I've trying to use imagemagick to create a simple reflection, however the documentation has fixed sizes. I've tried to read in the height and width and use those variables but this doesn't produce a reflection.
Here's the documentation
http://www.imagemagick.org/Usage/advanced/
Here's the sample code
convert pokemon.gif \( +clone -flip \) -append \
-size 100x100 xc:black +swap \
-gravity North -geometry +0+5 -composite reflect_perfect.png
Here's my bash script, with my widths and heights...
#!/bin/bash
infile="framed.png"
ww=`convert $infile -format "%w" info:`
hh=`convert $infile -format "%h" info:`
convert $infile -alpha on \
\( +clone -flip -channel A -evaluate multiply .35 +channel \) -append \
-size ${ww}x${hh} xc:black +swap \
-gravity North -geometry +0+5 -composite reflect_alpha.png
My resulting image is exactly the same as the source image.
Here's the exact image I'm using
https://www.dropbox.com/s/l8gtieuqi1yoipm/iPhoneXR-4-categories_framed.png?dl=0
The size for the black background must be larger than twice the height of the input and at least as wide as the input. So I would do the following in Imagemagick
Input:
infile="zelda1.jpg"
ww=`convert $infile -format "%[fx:1.5*w]" info:`
hh=`convert $infile -format "%[fx:2.1*h]" info:`
convert $infile -alpha on \
\( +clone -flip -channel A -evaluate multiply .35 +channel \) -append \
-size ${ww}x${hh} xc:black +swap \
-gravity North -geometry +0+5 -composite reflect_alpha.png
But you can try my bash unix Imagemagick shell script, 3Dreflection at http://www.fmwconcepts.com/imagemagick/index.html, if you want more flexibility.
ADDITION:
To answer your question, it does not matter if PNG or JPG. The issue is that you have transparency. If you put a transparent background, then
infile="WPB-wtpC.png"
ww=`convert $infile -format "%[fx:1.5*w]" info:`
hh=`convert $infile -format "%[fx:2.1*h]" info:`
convert $infile \
\( +clone -flip -alpha on -channel A -evaluate multiply .35 +channel +write tmp1.png \) -append +write tmp2.png \
-size ${ww}x${hh} xc:none +swap \
-gravity North -geometry +0+5 -compose over -composite reflect_alpha.png
If you use a black background, then
infile="WPB-wtpC.png"
ww=`convert $infile -format "%[fx:1.5*w]" info:`
hh=`convert $infile -format "%[fx:2.1*h]" info:`
convert $infile \
\( +clone -flip -alpha on -channel A -evaluate multiply .35 +channel +write tmp1.png \) -append +write tmp2.png \
-size ${ww}x${hh} xc:black +swap \
-gravity North -geometry +0+5 -compose over -composite reflect_alpha.png
NOTE: I had a typo in the first zelda image code. I accidentally typed w rather than h in the hh equation, which I have now fixed. That may have messed you up.
I've been using Fiji's FFT bandpass filter with great success, but I'd like to do this in the command line with ImageMagick. I see that ImageMagick has FFT filters and they documentation includes low-pass and high-pass filters, but can I perform a bandpass filter?
The bandpass filter settings from Fiji that seem to work well for me:
(With apologies that my filter and FFT knowledge is... really bad, so maybe this is easily accomplished if I knew what to chain together, etc...)
A band pass filter similar to the low pass one you show in your link would be a white ring on a black background for square images. The inner and outer radii of the ring determine the frequencies that would be passed. In ImageMagick you can do that as follows:
Input:
Create ring image:
convert lena-1.png -fill black -colorize 100 \
-fill white -draw "translate 64,64 circle 0,0 0,50" \
-fill black -draw "translate 64,64 circle 0,0 0,20" \
-alpha off -blur 0x1 \
ring.png
Do FFT processing with stretch to full dynamic range:
convert lena-1.png -fft \
\( -clone 0 ring.png -compose multiply -composite \) \
-swap 0 +delete -ift -auto-level \
lena_bp.png
Alternate processing with gain of 10x:
convert lena-1.png -fft \
\( -clone 0 ring.png -compose multiply -composite \) \
-swap 0 +delete -ift -evaluate multiply 10 \
lena_bp.png
As I do not know what they have coded in ImageJ or Fiji and you showed no output, I can only guess that what might be equivalent would be to have inner and outer radii at 3 and 40 pixels from the center. Also I have added again a gain of 10x in dynamic range to make it more visible:
convert lena-1.png -fill black -colorize 100 \
-fill white -draw "translate 64,64 circle 0,0 0,40" \
-fill black -draw "translate 64,64 circle 0,0 0,3" \
-alpha off -blur 0x1 \
ring.png
convert lena-1.png -fft \
\( -clone 0 ring.png -compose multiply -composite \) \
-swap 0 +delete -ift -evaluate multiply 10 \
lena_bp.png
Note that I blurred the ring slightly to reduce "ringing" artifacts. (See https://en.wikipedia.org/wiki/Ringing_artifacts). Many low pass, high pass and band pass filters have stronger/longer tapering similar to increasing the blur. There are specially designed tapers, such as Butterworth. (see https://en.wikipedia.org/wiki/Butterworth_filter)
I have an expanded version of the FFT documentation from ImageMagick at http://www.fmwconcepts.com/imagemagick/fourier_transforms/fourier.html (Note some of the Jinc filtering is a bit outdated. Since I wrote that, Imagemagick implemented the Jinc function within -fx)
Here is a small set of commands to do it all in Unix syntax. Remove the +write ring.png if you do not want it to be created. This code is limited to square images.
ImageMagick 6:
inner=3
outer=40
infile="lena-1.png"
cent=`convert "$infile" -format "%[fx:floor((w-1)/2)]" info:`
inname=`convert "$infile" -format "%t" info:`
suffix=`convert "$infile" -format "%e" info:`
convert "$infile" \
\( +clone -fill black -colorize 100 \
-fill white -draw "translate $cent,$cent circle 0,0 0,$outer" \
-fill black -draw "translate $cent,$cent circle 0,0 0,$inner" \
-alpha off -blur 0x1 +write ring.png \
-write mpr:bpass +delete \) \
-fft \( -clone 0 mpr:bpass -compose multiply -composite \) \
-swap 0 +delete -ift -evaluate multiply 10 \
${inname}_bandpass_${inner}_${outer}.$suffix
ImageMagick 7 (only one command line):
inner=3
outer=40
infile="lena-1.png" \
magick "$infile" \
-set option:cent "%[fx:floor((w-1)/2)]" \
-set filename:fn "%t_bandpass_${inner}_${outer}.%e" \
\( +clone -fill black -colorize 100 \
-fill white -draw "translate "%[cent],%[cent]" circle 0,0 0,$outer" \
-fill black -draw "translate "%[cent],%[cent]" circle 0,0 0,$inner" \
-alpha off -blur 0x1 +write ring.png \
-write mpr:bpass +delete \) \
-fft \( -clone 0 mpr:bpass -compose multiply -composite \) \
-swap 0 +delete -ift -evaluate multiply 10 \
"%[filename:fn]"
If you mean band enhanced (band boost) and not band pass, then you add the result back with the original (-compose plus -composite). In ImageMagick 6, that would be:
inner=3
outer=40
infile="lena-1.png"
cent=`convert "$infile" -format "%[fx:floor((w-1)/2)]" info:`
inname=`convert "$infile" -format "%t" info:`
suffix=`convert "$infile" -format "%e" info:`
convert "$infile" \
\( +clone -fill black -colorize 100 \
-fill white -draw "translate $cent,$cent circle 0,0 0,$outer" \
-fill black -draw "translate $cent,$cent circle 0,0 0,$inner" \
-alpha off -blur 0x1 +write ring.png \
-write mpr:bpass +delete \) \
-fft \( -clone 0 mpr:bpass -compose multiply -composite \) \
-swap 0 +delete -ift "$infile" -compose plus -composite \
${inname}_bandenhance_${inner}_${outer}.$suffix
These are different results from what I get with those settings in ImageJ. Unfortunately, I do not know what they are doing. The ImageJ results look more like low pass filtering to me than what I know as band enhanced/band pass. See https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=12&cad=rja&uact=8&ved=2ahUKEwjJvoWD6L7eAhXJslQKHf1jArgQFjALegQICBAC&url=https%3A%2F%2Fcanvas.instructure.com%2Ffiles%2F6907524%2Fdownload%3Fdownload_frd%3D1&usg=AOvVaw2ws15jPD6C2-yAkfHmHYMH and https://www.scribd.com/doc/51981950/Frequency-Domain-Bandpass-Filtering-for-Image-Processing
In ImageJ, perhaps they are using a Butterworth filter or larger Gaussian blur. Or perhaps they are only processing the intensity channel from say HSI or HSV or LAB.