I'm trying to blur the lower part of an image and repeat this for several hundred other images within a target folder. I'm using this command:
magick 1.jpg -write-mask mask.png -blur 0x60 +write-mask 2.jpg
This does the the blurring but it takes between 10 - 20 seconds for one 5888 × 2944 image.
Is there someway to speed up this above command or is there a better command which will quickly batch blur a group of images?
Thanks!
In Imagemagick, you can blur a region by blurring the whole image, then blend that with the original using mask. You can speed up a large blur by resizing (scaling) the image down, use a smaller blur and then resizing back up.
Input:
Mask:
Slow:
time magick barns_grand_tetons.jpg \
\( +clone -blur 0x60 \) \
barns_grand_tetons_mask.png \
-compose over -composite slow_blur.jpg
4.521s
Fast:
time magick barns_grand_tetons.jpg \
-set option:dims "%wx%h" \
\( +clone -scale 10% -blur 0x6 -scale "%[dims]" \) \
barns_grand_tetons_mask.png \
-compose over -composite fast_blur.jpg
0.368s
See
https://imagemagick.org/Usage/compose/#compose
https://imagemagick.org/Usage/resize/
https://imagemagick.org/Usage/masking/#write_mask
ADDITION
If you want to feather the edges, you need to blur the mask as well.
Slow:
time magick barns_grand_tetons.jpg \
\( +clone -blur 0x60 \) \
\( barns_grand_tetons_mask.png -blur 0x10 -level 0x50% \) \
-compose over -composite slow_blur.jpg
5.183s
Fast:
time magick barns_grand_tetons.jpg \
-set option:dims "%wx%h" \
\( +clone -scale 10% -blur 0x6 -scale "%[dims]" \) \
\( barns_grand_tetons_mask.png -scale 20% -blur 0x2 -level 0x50% -scale "%[dims]" \) \
-compose over -composite fast_blur.jpg
0.404s
If you want to feather outside the mask rather than inside the mask (as above), then change -level 0x50% to -level 50x100%.
Related
I'm trying to create a shell file I can set and forget...
Images with resolutions higher than 1920px resizes. Higher than 1920 seems to me too high for an e-commerce store anno 2018 ...
On an 8K+ image, an iPhone in Chrome bv simply crashes...
I have already replaced the scripts in as many places as possible so that front-end appropriate resolutions are shown and therefore no original files are simply resized. Ex 4000 x 6720 original, are now 500 x 1000's and are shown at 250 x 500 (so it is still sharp on retina).
These will then be in this lower resolution in the Magento Cache and then in Varnish Cache.
The idea is now to create a shell script that will clean up these "too large" files, resized themselves:
find /home/customer/customer.com \
-type f \
-regex "^. * \. \ (png \ | jpg \ | jpeg \) $" \
-exec identify -format "% d,% w /% f,% h \ n "{} \; \
| awk -F ',' '$ 2> 1080 && $ 3> 1920' \
| grep "png \ | jpg \ | jpeg"
Gives me:
/home/sample/sample.com/media/catalog_fm/1453138191_LIU.JO_Dames_kleed_P16049T1633_nero_2_x15148601020101.jpg, 1440, 2160
/home/sample/sample.com/media/catalog_fm/1446052276_LIU.JO JEANS_Dames_vest_W65221E0139_22222_2_x14864501010101.jpg, 1440, 2160
/home/sample/sample.com/media/catalog_fm/1446655568_LIU-JO ACCESOIRES_Dames_shoes & boots_S65019P0055_22222_4_x14874601010101.jpg, 1440, 2160
...
The intention is to resize this now as follows:
convert FILENAME -verbose -resize x1920 FILENAME
I want to do all of these separate steps in a single shell file. Now I copy the generated file > .txt and extract it, run the script with the copy pasted data manually.
I don't think your approach is the best, you can tell convert to only resize images if they are larger, IIRC:
convert -resize ${MAXWIDTH}x${MAXHEIGHT}\> ${FILENAME}
So you can just find all the pictures and unleash find on them:
find . -type f \( -name "*.png" -or -name "*.jpg" -or -name "*.jpeg"\) -exec convert -resize ${MAXWIDTH}x${MAXHEIGHT}\> {} \;
Can anyone point me in the direction of how to create a similar effect to that below using imagemagick? I doubt it matters, but I'm working with png images.
Something like this maybe:
convert -size 800x600 caption:"SOME TEXT" -compose darken \
\( -clone 0 -fill "rgb(227,90,130)" -opaque black -roll +10+0 \) -composite \
\( -clone 0 -fill "rgb(71,160,200)" -opaque black -roll -10+0 \) -composite result.png
Another way to do this in ImageMagick uses composite -stereo.
Input:
composite -stereo -20+0 test.png test.png result1.png
But this is less flexible in the color choice than Mark Setchell's method.
This question already has answers here:
Ignore case when trying to match file names using find command in Linux
(5 answers)
Closed 5 years ago.
I wrote a bash script a while back that resizes and compresses all images in directory with Image Magick.
# Usage: smartResize "2400x2400>"
function smartResize() {
find ./ -name "*.jpg" -exec magick mogrify -resize $1 -sampling-factor 4:2:0 -strip -interlace JPEG -quality 85 -colorspace RGB {} \;
find ./ -name "*.JPG" -exec magick mogrify -resize $1 -sampling-factor 4:2:0 -strip -interlace JPEG -quality 85 -colorspace RGB {} \;
find ./ -name "*.jpeg" -exec magick mogrify -resize $1 -sampling-factor 4:2:0 -strip -interlace JPEG -quality 85 -colorspace RGB {} \;
find ./ -name "*.JPEG" -exec magick mogrify -resize $1 -sampling-factor 4:2:0 -strip -interlace JPEG -quality 85 -colorspace RGB {} \;
}
I had to add extra lines to find some alternative cases for .jpg extensions. Which I don't particularly like but got the job done.
Does anybody have a better idea of how to handle case sensitivity and the optional e in jpeg extensions?
n.b. I'm running this in Cmder: Git Bash on Windows.
GNU versions of find have an -iname flag which enables case insensitive matching of file name globs,
find ./ -iname '*.jpg'
or if you are on a system without GNU utilities, use the bracket expressions to the glob
find ./ -name '*.[Jj][Pp][Gg]'
If you are interested in multiple name filters, just use the -o expression for including multiple name globs
find ./ \( -iname "*.jpg" -o -iname "*.jpeg" \)
Using SVG, you can define a clipping path and then apply it when drawing a path. Can the same effect be achieved using ImageMagick command-line options?
The only way I have been able to do it is to create the clipping path as a separate file and use -clip-mask to apply it. Here's a contrived example that works:
convert -size 150x150 xc:none -draw "path 'M50,50 h50 v50 -h-50 z'" clip.png
convert -size 150x150 xc: -fill 'blue' -clip-mask clip.png \
-draw "path 'h150,0 l-75,75 z" image.png
What I want to do is define the clip path in the same command as the drawing, ideally somethig like this:
convert -size 150x150 xc: -fill 'blue' \
-clip-path "path 'M50,50 h50 v50 -h-50 z'" \
-draw "path 'h150,0 l-75,75 z" image.png
Which doesn't work. To try and avoid using an intermediate file, I tried using a stacked image but that doesn't seem to work as a parameter (the below did not work either):
convert -size 150x150 xc: -fill 'blue' \
-clip-mask \( -size 150x150 xc:none -draw "path 'M50,50 h50 v50 -h-50 z'" \) \
-draw "path 'h150,0 l-75,75 z" image.png
This can be done succinctly with SVG - can the ImageMagick command-line do it?
You can create intermediate files using the mpr pseudo format like this:
convert \( -size 150x150 xc:none -draw "path 'M50,50 h50 v50 -h-50 z'" \
-write mpr:clip \) +delete \
-size 150x150 xc: -fill 'blue' -clip-mask mpr:clip \
-draw "path 'h150,0 l-75,75 z" image.png
This uses -write to cause the clip image to be written immediately (otherwise it is stacked until the end of the command sequence). It's then removed from the stack with +delete (otherwise it'll also be written at the end of the command sequence). The -clip-mask then reads the pseudo-file.
The pseudo file mpr is Magick Persistent Registry and is documented here.
Brief:
convert ( -size 585x128 gradient: ) NewImage.png
How do I change the above ImageMagick command so it takes the width and height from an existing image? I need it to remain a one line command.
Details:
I'm trying to programatically create an image reflection using ImageMagick. The effect I am looking for is similar to what you would see when looking at an object on the edge of a pool of water. There is a pretty good thread on what I am trying to do here but the solution isn't exactly what I am looking for. Since I will be calling ImageMagick from a C#.Net application I want to use one call without any temp files and return the image through stdout. So far I have this...
convert OriginalImage.png ( OriginalImage.png -flip -blur 3x5 \
-crop 100%%x30%%+0+0 -negate -evaluate multiply 0.3 \
-negate ( -size 585x128 gradient: ) +matte -compose copy_opacity -composite )
-append NewImage.png
This works ok but doesn't give me the exact fade I am looking for. Instead of a nice solid fade from top to bottom it is giving me a fade from top left to bottom right. I added the (-negate -evaluate multiply 0.3 -negate) section in to lighten it up a bit more since I wasn't getting the fade I wanted. I also don't want to have to hard code in the size of the image when creating the gradient ( -size 585x128 gradient: ) I'm also going to want to keep the original image's transparency if possible.
To go to stdout I plan on replacing "NewImage.png" with "-"
If you are calling it from C#, perhaps you could get retrieve the image dimensions in C#.
Then call the ImageMagick command with
command = String.Format("convert bar %1x%2",img.Width,img.Height)
You should take the existing image as an input, and create the gradient yourself using -fx instead of using the gradient pseudo-format.
May be this can help:
Reflection under an image
#!/bin/sh
gamma=$1
source=$2
destination=$3
size=`identify -format "%wx%h" $source`
convert $source \
\( -size $size xc:none \
\( \( -flip $source -crop $size+0+0 \) \
-size $size gradient: -gamma $gamma \
-compose copy_opacity -composite \) \
-compose blend -composite \) \
-append $destination