Image Magick - Cropping picture into circle - imagemagick

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

Related

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 - move/offset images within a tiled montage?

Consider this example (Ubuntu 18.04, ImageMagick 6.9.7-4 Q16 x86_64 20170114):
convert -size 300x100 xc:red red.png
convert -size 100x100 xc:blue blue.png
montage red.png blue.png -frame 5 -geometry '+0+0' -tile 1x redblue.png
This gives the following image:
What I'd like to do, is move the blue square on arbitrary x position "within its tile"; say align left edge of blue square to where 25% of the red rectangle width would be, or at 50% - or even align right edge of blue square with right edge of red rectangle.
I have seen that -tile-offset exists (https://imagemagick.org/script/command-line-options.php#tile-offset), and I've tried it with this example, but it doesn't look like it does anything.
How can I move an image, part of a ImageMagick montage, within its tile?
EDIT: it looks like -tile-offset can only be specified for explicit tile images (not as in -tile 1x, but as in -tile red.png), and:
Tile smaller image over a background with offsets? - ImageMagick
-tile-offset must come before the tiling. It represents a single global offset, not the spacing for the tiling.
Here's an example:
convert -size 300x100 radial-gradient:\#400-\#FAA red.png
convert -size 500x500 xc: -tile-offset +100+40 +size -tile red.png -border 5 -geometry +5+5 -draw "color 0,0 reset" out.png
then out.png is this (click for full image):
... so to clarify - I'd like to know is its possible to move an image within a tile as obtained in montage tile 1x
As suggested in the comment:
convert -background none red.png \( -size 25x xc:none blue.png +append \) -append result.png
Or with 2 different offsets:
convert -background none red.png \
\( -size 25x xc:none blue.png +append \) \
\( -size 50x xc:none blue.png +append \) \
-append result.png
Not sure what your end-goal is, but you can also do this:
convert -gravity east -background none red.png blue.png red.png blue.png -append result.png
Or this:
convert -gravity center -background none red.png blue.png red.png blue.png -append result.png
In ImageMagick 6, another way is to extend the transparent background, then composite the blue image in the center of the bottom half of the extended image.
convert -size 300x100 xc:red -background none -extent 300x200 -size 100x100 xc:blue -geometry +100+100 -composite result.png

How can I combine these commands to achieve circular crop in 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

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