I'm trying to cut out a shape from an image based on a mask I have. I tried a number of ways but I'm really struggling to get the result I need.
I'm using ImageMagick 7.1.0-51 Q16-HDRI on Windows.
The "base" image:
https://imgur.com/a/j1kioWu
The mask i'm using:
https://imgur.com/a/OcArICa
Expected result(photoshoped):
https://imgur.com/a/GjRoxyS
Edit: Reuploaded direct on imgur to maintain transparent background
In Imagemagick, you want to invert (negate) the polarity of black and white, then do a -compose difference -composite, then invert again.
Hair:
Face:
magick hair.png face.png -alpha off -colorspace gray -negate -compose difference -composite -negate result.png
Result:
If you want pure white in the face area, threshold the two images after the conversion to grayscale
magick hair.png face.png -alpha off -colorspace gray -auto-threshold otsu -negate -compose difference -composite -negate result2.png
Result 2:
ADDITION
If your input images have transparent backgrounds, then you have to extract the alpha channels, combine them to do the difference and then put that alpha channel back on the input.
Unix Syntax:
magick hair.webp \
\( +clone face_mask.webp -alpha extract -compose difference -composite \) \
-alpha off -compose copy_opacity -composite result.png
For Windows,remove the \ in front of the parentheses and change the end of line \ to ^.
Related
I'm trying to add a PNG file as background to an PNG image with transparent regions using ImageMagick like so:
convert input.png -texture bg.png output.png
I'm not so far to find out how to fill my background to 100% width / height, because the above example does not work. I end up with the same file that is transparent and I don't know why.
How can I apply a background that uses full width/height across the whole file? (Preferable using the cover method, meaning to keep aspect ratio of the background and cutting overlaps)
If you want to tile out the background then on Unix, try
convert input.png \( +clone -tile bg.png -draw "color 0,0 reset" \) +swap -compose over -composite output.png
On Windows:
convert input.png ( +clone -tile bg.png -draw "color 0,0 reset" ) +swap -compose over -composite output.png
If you just want to resize the background, then on Unix try
dims=$( convert input.png -format "%wx%h" info: )
convert input.png \( bg.png -resize $dims +repage \) +swap -compose over -composite output.png
I do not know Windows that well to tell you how to do the variable
On ImageMagick 7, in Unix, you can do it easier as:
magick input.png -set option:dims "%wx%h" \( bg.png -resize "%[dims]" \) +swap -compose over -composite output.png
Or in Windows:
magick input.png -set option:dims "%wx%h" ( bg.png -resize "%[dims]" ) +swap -compose over -composite output.png
I am having these two pictures, labeled 1.png and 2.png, respectively:
When I run this code from ImageMagick in my Linux terminal:
composite -blend 75 -gravity West 2.png 1.png prueba.png
I get this result:
However, I would like the logo (2.png) to be half or one-third size reduced and placed in the bottom left corner. How can I do it from the terminal?
You can do that in ImageMagick by using the convert syntax. It is more flexible than the composite syntax.
convert 1.png \( 2.png -resize 50% \) -gravity southwest -define compose:args=75 -compose blend -composite 1_2.png
If you want to move it further left, you can simply chop off some of the left side before compositing using ImageMagick.
convert 1.png \( 2.png -resize 50% -gravity west -chop 20x0 \) -gravity southwest -define compose:args=75 -compose blend -composite 1_2_b.png
Alternately, you can simply trim the excess empty space around the 2.png before blending.
convert 1.png \( 2.png -resize 50% -trim +repage \) -gravity southwest -define compose:args=75 -compose blend -composite 1_2_c.png
How can I draw a grid, 1px black borders no fill, over an image?
Each section of the grid should be 480x360px.
E.g., given this 1440x1080px solid white input:
It should have a 3x3 grid drawn onto it (because 9 480x360px rectangles fit into it) to make an output kind of like this:
That's not as accurate as I'd like the command to be (I was just drawing rectangles by eye), but I hope it illustrates what I'm after.
Here is a command that will read an input image, create a 480x360 transparent cell with a black border, create a grid of those cells the size of the input image, and composite that grid over the input...
infile="MyPic.png"
convert "$infile" -size 480x360 -set option:distort:viewport "%[w]x%[h]" \
\( xc:none -shave 1x1 -compose copy -bordercolor black -border 1x1 \) \
-virtual-pixel tile -distort SRT 0 -compose over -composite output.png
That will make the lines of the grid 2 pixels thick. If the lines must be 1 pixel thick, the same sort of thing can be done with a command like this...
convert "$infile" -size 480x360 -set option:distort:viewport "%[w]x%[h]" \
\( xc:none -chop 1x1 -background black -splice 1x1 \) \
-virtual-pixel tile -distort SRT 0 -compose over -composite \
-bordercolor black -shave 1x1 -compose copy -border 1x1 output.png
EDITED TO ADD: If the objective is to divide the grid into a particular number of cells rather than cells of specified dimensions, a command like this should work...
convert "$infile" \( +clone -channel A -evaluate set 0 +channel \
-crop 3x4# -chop 1x1 -background black -splice 1x1 \) -background none \
-flatten -shave 1x1 -bordercolor black -border 1x1 output.png
That creates a clone of the input image and makes it transparent, uses "-crop 3x4#" to crop it into a grid of 3x4 cells, puts a black border on the top and left edges of the cells, then reassembles them into a grid by flattening them onto the input image. It finishes by adding a border to the right and bottom edges while preserving the input image's original dimensions.
Obviously using this method the cells may not all have the exact same dimensions if the the input image can't be divided evenly by the number of cells.
EDITED AGAIN: If you don't actually need the grid to be an overlay, you can directly crop the image into tiles, put black lines around the tiles, and reassemble them to create the required output image. That can be done with a simple command like this to make 480x360 sized cells...
convert "$infile" -background black -bordercolor black \
-crop 480x360 -chop 1x1 -splice 1x1 -flatten -shave 1x1 -border 1x1 output.png
Or it can be done with "-crop 3x3#" like this to make a grid of 3 rows and 3 columns letting ImageMagick calculate the sizes as nearly as possible...
convert "$infile" -background black -bordercolor black \
-crop 3x3# -chop 1x1 -splice 1x1 -flatten -shave 1x1 -border 1x1 output.png
Again, if the image size isn't evenly divisible by the number of cells, there will be one pixel difference in the sizes of some of the cells.
I had a little attempt at this and got kind of stymied at every turn. Here is the best I got so far.
convert xc:white[1440x1080\!] -colorspace gray -fx "(i==0||i==479||i==959||i==1439||j==0||j==359||j==719||j==1079)?0:1" grid.png
So, for practical use, you would take your snow scene and clone it. Then go to greyscale (to reduce the processing time by a factor of 3) and set all the lines black and the other pixels white. Then overlay onto the snow scene choosing the darkest pixel at each location:
convert scene.jpg \( +clone -colorspace gray \
-fx "(i==0||i==479||i==959||i==1439||j==0||j==359||j==719||j==1079)?0:1" \) -compose darken -composite result.png
If you wanted it marginally smarter and adaptive to different sized images, you could calculate the third-points as a function of image size:
magick scene.jpg \( +clone -colorspace gray \
-fx "(i==0||i==int(w/3)||i==2*int(w/3)||i==w-1||j==0||j==int(h/3)||j==2*int(h/3)||j==h-1)?0:1" \) \
-compose darken -composite result.png
The best I came up with so far:
convert blank.png -fill black -draw 'line 480,0 480,1080 line 960,0 960,1080 line 0,360 1440,360 line 0,720 1440,720' level1.png
But this is all manual.
Is there a way to automate this?
Here's another variant that is fast and easy to understand - not 100% identical to your requirements but maybe good enough.
Create a starter box with a black border, duplicate twice and append across the page, duplicate twice and append down the page, make minor correction to size:
convert xc:red[478x358\!] -bordercolor black -border 1 \
-duplicate 2,0 +smush -1 \
-duplicate 2,0 -smush -1 -transparent red -scale 1440x1080\! result.png
Or you could make your initial box, duplicate it 8 times and let montage lay the resulting 9 boxes out:
convert xc:red[478x358\!] -bordercolor black -border 1 \
-transparent red -duplicate 8,0 miff:- | montage -background none -geometry +0+0 miff:- result.png
People, I am using imagemagick to crop a circle out of an image. But I am getting nothing when I run this command :
convert input.jpg +clone -threshold -1 -negate -fill white -draw "circle 539,539 539,0" -alpha off -compose copy_opacity -composite output_circ.jpg
I am getting an output like this:
Please let me know if I am missing something.
Fundamentally, you are only missing one aspect - JPEG files cannot store transparency, so you need to use a PNG or GIF, for example.
convert input.jpg -alpha on \( +clone -threshold -1 -negate -fill white -draw "circle 539,539 539,0" \) -compose copy_opacity -composite output_circ.png
I want to use Imagemagick to add a transparent gradient from the left and right to be composed with an image.
I can generate the image with:
convert -size 100x100 gradient: -function Polynomial -4,4,0 -distort SRT 90 gradient.png
And it looks like:
I can also compose that image on top of the image I want with:
composite original.jpg -compose Multiply gradient.png final_image.jpg
All of this works fine. My question is, how do I change the color of that gradient?
Thanks!
Simply add comma-separated colors after gradient: option:
convert -size 100x100 gradient:white,blue -function Polynomial -4,4,0 -distort SRT 90 gradient.png
Note, that -function converts channels too, so colors in gradient wont be original.
Found a way around this by doing
convert input.jpg -alpha set -virtual-pixel transparent -background red -channel A -blur 0x34 -level 75%,100% +channel -flatten final.jpg
which works in my case, giving me: