Gradient over transparent png image with sparse-color has background color - imagemagick

I have this face source image. I'm tyring to add a gradient to the bottom of the picture so it fades out alpha transparent.
Problem is that the transparent source image is not transparent anymore after sparse-color transformation - the transparent area is now black.
This is my cmd so far:
magick convert face.png -alpha set -background none -channel A -sparse-color barycentric "0,%[fx:h*0.90] white 0,%[h] none" +channel face-gradient.png

Here is how you have to do that in Imagemagick. Your image already has an alpha channel. So you have to create a new grayscale gradient image as a mask and combine that with the existing alpha channel. (The -sparse-color is going to write over your existing alpha channel.)
magick face.png \
\( -clone 0 -alpha extract \) \
\( -clone 0 -sparse-color barycentric "0,%[fx:h*0.90] white 0,%[h] black" \) \
\( -clone 1,2 -compose multiply -composite \) \
-delete 1,2 \
-alpha off -compose copy_opacity -composite face-gradient.png

Related

ImageMagick convert grey shading only fuzz

I want to convert to white any light shades of grey. I am using '-fuzz 10% -fill white -opaque #efeaee'. The problem is that the fuzz converts other colours other than grey, not just shades of grey (ie light yellow and light green get converted). I have tried to reduce the fuzz and repeat for various versions of grey but it really doesn't work and I'm sure there's a better way?
You can do that in ImageMagick, by converting to HSV colorspace. Then threshold the S and V channels. You want low saturation and high value combined as a mask. Then blend the input and a white image using the mask.
sthresh=10
vthresh=10
convert zelda1.jpg \
\( -clone 0 -fill white -colorize 100 \) \
\( -clone 0 -colorspace HSV -channel 1 -separate +channel -threshold $sthresh% -negate \) \
\( -clone 0 -colorspace HSV -channel 2 -separate +channel -negate -threshold $vthresh% -negate \) \
\( -clone 2,3 -compose multiply -composite -blur 0x1 \) \
-delete 2,3 \
-compose over -composite \
result.png
sthresh is the fuzz value for how close in color it is to white
vthresh is the fuzz value for how close it is in brightness to white
Values of zero mean exactly pure white.

ImageMagick: How to create torn page effect for specifc edges?

The ImageMagick documentation provides guidance on how to create torn page effects (https://www.imagemagick.org/Usage/thumbnails/#torn). However, in their implementation, all edges are torn. Suppose I wish to tear off only the bottom or top part of the image. How can I achieve such a thing using ImageMagick?
Simply grow the top & sides by using -extent operator.
convert zelda.png -background pink -extent 148x138-10-10 extent.png
(Adding pink background for visibility on stack)
Apply the effect from the Usage documentation.
convert extent.png \( +clone -alpha extract -virtual-pixel black \
-spread 10 -blur 0x3 -threshold 50% -spread 1 -blur 0x.7 \) \
-alpha off -compose Copy_Opacity -composite torn.png
Then crop back to original image size.
convert torn.png -crop 128x129+10+10 output.png
Update
If you do not want to use geometry, you can use a combination of -border, -shave & -chop.
convert zelda.png -bordercolor pink -border 10x10 -gravity South -chop 0x10 extent.png
convert extent.png \( +clone -alpha extract -virtual-pixel black \
-spread 10 -blur 0x3 -threshold 50% -spread 1 -blur 0x.7 \) \
-alpha off -compose Copy_Opacity -composite torn.png
convert torn.png -shave 10x -chop 0x10 output.png
.. And of course, this all can be done with one command.
convert zelda.png -bordercolor pink -border 10x10 -gravity South -chop 0x10 \
\( +clone -alpha extract -virtual-pixel black -spread 10 -blur 0x3 -threshold 50% \
-spread 1 -blur 0x.7 \) -gravity Forget -alpha off -compose Copy_Opacity -composite \
-shave 10x -chop 0x10 output.png
There are several ways to create a torn edge effect using ImageMagick. Here is another example command using IM version 6 and *nix syntax. This should apply a torn effect to just the top edge of any input image while keeping the original dimensions of the image.
convert input.png -alpha set -background black -fill white \
\( +clone -colorize 100 -gravity south -chop 0x6 -splice 0x6 \
-spread 6 -paint 2 +transparent white -blur 0x0.5 \) \
-background none -compose dstin -composite torn.png
That creates a white mask inside the parentheses. Then a small amount of the "torn" edge is chopped off and a black strip is spliced on to replace it. The random-ish torn edge is created using "-spread" and "-paint" between the white and black areas of the mask. After that, outside the parentheses, that mask is used to apply the transparent torn area to the input image.
To apply the effect to the bottom edge, just change the "-gravity north" to "-gravity south".
To make the torn edge on the left or right, change the gravity setting to "west" or "east", and change the values of the "-chop" and "-splice" operations from "0x6" to "6x0".
This should work the same way using ImageMagick version 7 by changing the "convert" command to "magick".
To use it in Windows, remove the backslashes that escape the parentheses from "\(...\)" to "(...)", and change the continued line backslashes "\" to carets "^".

Trying to add a stroke around a PNG, can it be improved?

I'm trying to find a good way to add a 3px white stroke to a ton of png files, effectively to make them look like "stickers." I've got some sample code that does a decent job, but I can't seem to get the cropping right. Also, the stroke looks a bit pixelated and I wanted to know if it's possible to get cleaner edges!
I did a bunch of internet scouring, found some sample code, tweaked it around, and came to something that almost resembles what I'm looking for. The images are always going to be PNGs, so I looked into things like inkscape/gimp from the command line but realized I should be able to do this just using convert from the terminal.
convert in.png \
\( -clone 0 -alpha extract -threshold 0 \) \
\( -clone 1 -blur 10x65000 -threshold 0 \) \
\( -clone 2 -fill red -opaque white \) \
\( -clone 3 -clone 0 -clone 1 -alpha off -compose over -composite \) \
-delete 0,1,3 +swap -alpha off -compose copy_opacity -composite \
out.png
in:
out:
ideally:
Your main problem is it is that you do not have enough space bettween your object and the sides of the image. You just need to add your image with transparency and then remove any excess later.
In ImageMagick 6, this should do what you want.
1) read the input
2) add a larger border than you need to add
3) extract the alpha channel from the input and dilate it by the amount of border (in this case 10)
4) copy the previous image and color the white as red and the black as transparent
5) composite the original over the red/transparent image
6) delete the original and the red/transparent image
7) swap the composite with the dilated alpha channel and put the dilated alpha channel into the alpha channel of the previous image
8) trim the excess transparency from the border padding
9) save to output
convert img.png \
-bordercolor none -border 20 \
\( -clone 0 -alpha extract -morphology dilate diamond:10 \) \
\( -clone 1 -fuzz 30% -fill red -opaque white -fill none -opaque black \) \
\( -clone 2,0 -compose over -composite \) \
-delete 0,2 \
+swap -alpha off -compose copy_opacity -composite \
-trim +repage \
result.png
For ImageMagick 7, replace convert with magick.
If on a Unix-like system, you might be interested in my bash ImageMagick script, contour, at http://www.fmwconcepts.com/imagemagick/index.php
A better result can be achieved by replacing diamond:10 with disk:10

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

Create an image with text over filling space

I want to create a flare image using imagemagick and then add text on top of it. I was thinking that it was going to be quite easy, but I am having issues adding the text on top of the generated image.
This is so far what I have (keep in mind that the text as well as the dimension are dynamic):
FLARE:
\(
-fill transparent -size 300x1 xc: +noise Random -channel G -separate +channel \
-scale 300x300\! \
\( -size 300x300 gradient: -evaluate cos .5 \) \
-compose hardlight -composite \
-virtual-pixel HorizontalTileEdge -distort Polar -1
\)
TEXT
-fill red \
-gravity center \
-font Arial \
annotate:"Logo 12345678"
EDIT:
The text is showing, but I can't figure out how to overimpress the text on top of the image in a way that it will fill the image for the full width (from left to right, with some padding if possible)
Figured out:
convert \
\( -background transparent -size 300x1 xc: +noise Random -channel G -separate +channel -scale 300x300\! \( -size 300x300 gradient: -evaluate cos .5 \) -compose hardlight -composite -virtual-pixel HorizontalTileEdge -distort Polar -1 \) \
\( -background transparent -size 300x300 -fill blue -gravity center -font Arial caption:"Logo \\n13474899" \) \
-gravity center -composite /tmp/flare_2_final.png
Now I need to figure out how to change the background color of the flare from black to gray and I am done.

Resources