How can I combine these commands to achieve circular crop in ImageMagick? - imagemagick

How can I combine these commands to achieve circular crop in ImageMagick?
So this command works:
convert -size 200x200 xc:none -fill samia.jpg -draw "circle 100,100 100,1" circle_thumb.png
The above will take a picture and make a circular crop out of it BUT the crop will be based on the upper left corner of the picture not the center of the picture.
This command also works for cropping:
convert *.jpg -resize 200x200^ -gravity Center -crop 200x200+0+0 +repage out.png
The above will make a square crop of an image based on the center of the image.
So what I want to do is to combine both commands.
My aim:
A command that takes a picture as input and makes a circular crop of it based on the center of the picture, not based on the upper left corner of the picture.
Anyone with IM skills who can show a dude how to resolve this?
Vesa
Ubuntu 15.10
Update:
I tried Mark Setchell's solution below but got the following error message:
axx#axx-VPCEA3S1E:~/Desktop/circular-crop$ magick samia.png \( +clone -threshold 101% -fill white -draw 'circle %[fx:int(w/2)],%[fx:int(h/2)] %[fx:int(w/2)],%[fx:80+int(h/2)]' \) -channel-fx '| gray=>alpha' circle.png
magick: no decode delegate for this image format `PNG' # error/constitute.c/ReadImage/509.
magick: no image to apply a property "%w" # warning/property.c/GetMagickPropertyLetter/2561.
magick: unknown image property "%w" # warning/property.c/InterpretImageProperties/3499.
magick: no image to apply a property "%h" # warning/property.c/GetMagickPropertyLetter/2449.
magick: unknown image property "%h" # warning/property.c/InterpretImageProperties/3499.
magick: no image to apply a property "%m" # warning/property.c/GetMagickPropertyLetter/2480.
magick: unknown image property "%m" # warning/property.c/InterpretImageProperties/3499.
axx#axx-VPCEA3S1E:~/Desktop/circular-crop$

This question gets asked a lot.
Given an image larger than circle.
convert -size 300x300 plasma: input.png
We can draw a shape, convert values to alpha channel, and compose it over the input image.
convert input.png \
-gravity Center \
\( -size 200x200 \
xc:Black \
-fill White \
-draw 'circle 100 100 100 1' \
-alpha Copy \
\) -compose CopyOpacity -composite \
-trim output.png
Now if your planing to crop many resources, I would highly suggest creating a mask once. The reuse the mask as needed.
convert -size 200x200 xc:Black -fill White -draw 'circle 100 100 100 1' -alpha Copy mask.png
for f in $(ls *.jpg)
do
convert $f -gravity Center mask.png -compose CopyOpacity -composite -trim ${f}_output.png
done

Not sure about cropping circles, but if you want to make all but a central circle transparent, you can do this...
Start image
Extract a circle with radius 80, using:
magick start.png \( +clone -threshold 101% -fill white -draw 'circle %[fx:int(w/2)],%[fx:int(h/2)] %[fx:int(w/2)],%[fx:80+int(h/2)]' \) -channel-fx '| gray=>alpha' circle.png

Related

Image Magick - Cropping picture into circle

I have 100+ png files all 500x500, I'm trying to crop a circle in the centre of the image 400x400 and save it into a separate png, keeping the 500x500. example below
Does anyone know how to use image magick to achieve this and run through each file in the folder? - thanks
Source
Desired output
Make a 500x500 image with a 400px opaque circle in it (mask.png) (this is of course going to be same image for all your input):
Then from a source:
convert source.png mask.png -compose copy-opacity -composite result.png
yields:
You can find answers in How can I combine these commands to achieve circular crop in ImageMagick?
magick convert input.jpg -gravity center ( -size 480x480 xc:black -fill white -draw "circle 240 240 240 0" -alpha copy ) -compose copyopacity -composite output.png
magick input.jpg ( +clone -threshold 101% -fill white -draw "circle %[fx:int(w/2)],%[fx:int(h/2)] %[fx:int(w/2)],%[fx:int(h)]" ) -channel-fx "| gray=>alpha" output.png
magick input.jpg ( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 50,50" ) -channel-fx "| gray=>alpha" output.png
magick input.jpg ( +clone -threshold 101% -fill white -draw "roundRectangle %[fx:int((w-h)/2)],0 %[fx:int((h+w)/2)],%[fx:int(h)] 50,50" ) -channel-fx "| gray=>alpha" -trim output.png
You can process every (png) image in a folder using mogrify. Assuming Imagemagick 6. Just change directories to the folder and add the path to your mask.png image, which should not be in that directory.
mogrify -alpha set -draw "image copy_opacity 0,0 0,0 'mask.png'" *.png

How to draw a image on top of a shape

Simplified example:
I do create a cirlce like following:
magick convert -size 256x256 xc:none -fill #FFFFFF -draw "circle 128,128 256,128" +profile "icc" out.png
And I do convert a given image like following:
magick convert in.png -background none -gravity center -resize 181x181 +profile "icc" out.png
Question:
In my examples above I do have following "core" functions:
-size 256x256 xc:none -fill #FFFFFF -draw "circle 128,128 256,128" +profile "icc"
in.png -background none -gravity center -extent 181x181 +profile "icc"
How can I combine those images WITHOUT saving the first one to a temporary file? I want to create a 256x256 output image, draw the circle to this image and then draw the converted input image on top of the circle (centered).
My current solution
Create 2 different images and combine them like following:
magick convert -composite -gravity Center out1.png out2.png out.png
EDIT - FULL EXAMPLE
PS Script looks like following:
$in = ".\in.png"
$out1 = ".\tmp1.png"
$out2 = ".\tmp2.png"
$out = ".\out.png"
// 1) create circle image
magick convert -size 256x256 xc:none -fill #FFFFFF -draw "circle 128,128 256,128" +profile "icc" PNG32:$out1
// 2) convert input image
magick convert $in -background none -gravity center -resize 181x181 +profile "icc" -colorspace Gray -fill "#E91FCB" -colorize 50 PNG32:$out2
// 3) combine circle + converted image
magick convert -composite -gravity Center $out1 $out2 PNG32:$out
// 4) delete temp. images
Remove-Item $out1
Remove-Item $out2
Input Image:
Output Image (not visible, but it has the white circle as background + a transparent background otherwise):
You can use parenthesised processing like this:
magick -size 256x256 xc:none -fill white -draw "circle 128,128 256,128" \( in.png -background none -gravity center -resize 181x181 -colorspace Gray -fill "#E91FCB" -colorize 50 \) -composite result.png
On Windows, omit the \ before parentheses.

ImageMagick - change the background color of the selected bounding box

I already have the normalized vertices of my selected bounding box (e.g xmin: 0.68, ymin: 0.47, xmax: 0.94, ymax: 0.82) and I want to save this box in an other .jpg file. Furthermore, in the original image I want to make this highlighted box all white. Is this possible using Imagemagick?
Starting with this:
and knowing the top-left corner of the monument is at 400,10 and the bottom-right is at 500,200, you can extract the monument to a file with:
magick photo.jpg -crop 100x190+400+10 extract.jpg
and overpaint in white with:
magick photo.jpg -fill white -draw "rectangle 400,10 500,200" overpainted.jpg
Or, for extra fun, overpaint in semi-transparent white with:
magick photo.jpg -fill "rgba(255,255,255,0.5)" -draw "rectangle 400,10 500,200" overpainted.jpg
You can do both operations in one go with:
magick photo.jpg \( +clone -fill white -draw "rectangle 400,10 500,200" -write overpainted.jpg +delete \) -crop 100x190+400+10 extract.jpg
Using ImageMagick version 6, the command below will create two output images. (An example command for ImageMagick version 7 is further down in the reply.)
The first output image will be cropped from the input image using the bounding box starting at w*0.68xh*0.47 and ending at w*0.94xh*0.82.
The second output will be the input with a white section corresponding to the sub-image cropped out to make the first image.
convert input.png \
-set option:distort:viewport "%[fx:(w*0.94)-(w*0.68)]x%[fx:(h*0.82)-(h*0.47)]" \
\( +clone -distort affine "0,0 -%[fx:w*0.68],-%[fx:h*0.47]" \
-write result1.png -fill white -colorize 100 \) \
-set page "%[fx:u.w]x%[fx:u.h]+%[fx:t*(u.w*0.68)]+%[fx:t*(u.h*0.47)]" \
-flatten result2.png
That starts by reading the input image and calculating the viewport, the dimensions of the sub-image to crop, according to the bounding box dimensions you've provided.
Then inside the parentheses it creates a clone and does a "-distort affine" which, in effect, crops the image and locates it properly in that viewport. It writes that result to the first output image "result1.png". Then, still inside the parentheses, it fills that cropped piece with white.
After that it sets the paging geometry so that white piece can eventually be composited back into its original location over the input image.
It finishes by flattening the white piece onto the input image, and writes the second output image "result2.png".
The same thing can be done using ImageMagick version 7 with a slightly less complicated command...
magick input.png \
\( +clone \
-crop "%[fx:(w*0.94)-(w*0.68)]x%[fx:(h*0.82)-(h*0.47)]+%[fx:w*0.68]+%[fx:h*0.47]" \
-write result1.png -fill white -colorize 100 \) \
-flatten result2.png
That does the calculations directly in the "-crop" operation, and the paging geometry is saved in the cropped piece so it can be flattened back to its original position without resetting the geometry.
Those are in *nix syntax. To make it work in Windows change the continued line backslashes "\" to carets "^", and eliminate those backslashes that escape the parentheses "\(...\)".
Here is one other variation in ImageMagick 6. It crops the image and saves it and then deletes it. Then it use -region to write white into that bounding box.
This is Unix syntax. For Windows, remove \ from parenthesis and change end of line \ to ^.
Input:
convert img.jpg \
\( +clone -crop 100x190+400+10 +repage +write result1.jpg +delete \) \
-region 100x190+400+10 -fill white -colorize 100 +region result2.jpg

Replace Colors in Image with Transparency

How do I replace a color in an image which contains transparency with ImageMagick, but afterwards retain the transparency of the original image.
This is very useful for batch-changing of colors in icons.
Updated Answer
Option 1
A simpler option might be like this:
convert start.png -alpha deactivate -fill blue -opaque red -alpha activate result.png
which changes this:
to this:
Option 2
Another option, which uses an in-memory copy of the image, can also avoid the need to create 2 processes and write an intermediate file to disk:
convert start.png -write MPR:orig \
-alpha off -fill blue -opaque red \
MPR:orig -compose CopyOpacity -composite result.png
Option 3
Yet another method, that uses clone instead of MPR:
convert start.png \
\( +clone -alpha off -fill blue -opaque red \) \
+swap -compose CopyOpacity -composite result.png
Original Answer
If I create an image that contains transparency like this:
convert -size 400x400 xc:none -fill red -draw "rectangle 10,10 100,100" -fill blue -draw "rectangle 200,200 300,300" -bordercolor black -border 5 start.png
I'll get this (I am showing it overlaid on a checkerboard just to visualise the transparency):
If I now run this
convert start.png -fill yellow -opaque red result.png
I'll get this (again overlaid on a checkerboard):
Not sure why you need a more complicated, 2-stage process - or have I misunderstood your question?
convert file-in.png -alpha off -fill REPLACEMENT -opaque COLOR file-out.png
then
convert file-out.png file-in.png -compose CopyOpacity -composite PNG32:file-final.png

How to square an image and pad with transparency from the commandline (imagemagick)

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

Resources