Add a tile watermark to a part of the image only - imagemagick

Usually, I add watermark text on documents with something like this:
convert -size 700x360 xc:none -fill "#00000020" -font "Liberation-Sans-Bold" -pointsize 60 \
-gravity NorthWest -draw "text 0,75 \"${3}\"" \
-gravity SouthEast -draw "text 0,75 \"${3}\"" \
miff:- |\
composite -tile - "${1}" "${2}"
It spreads a tile with text over the whole image.
Now I need to add a watermark that excludes a specific area on the document.
My question is:
How to limit "operating area" only to a specific rectangular image region defined as x,y,width,height?
On the other hand: Is it possible and how to exclude a specific rectangular region and spread my tiles only outside of it?

You can do that as follows in Imagemagick by creating a tiled watermark image of the size you want and then compositing over the background image.
Here I create the tile image (mpr:wm) . Then tile it out with a transparent background using -draw "color 0,0 reset". Then I composite that over the background image at the desired upper left corner (+32+32). This is all done in one convert command line without needing to pipe.
In:
in="mandril3.jpg"
out="mandril3_wm.jpg"
text="Testing"
convert -size 64x64 xc:none -fill black \
-font "candice" -pointsize 14 \
-gravity NorthWest -draw "text 0,5 '$text'" \
-gravity SouthEast -draw "text 0,5 '$text'" \
-write mpr:wm +delete \
-size 128x128 xc:none -tile mpr:wm -draw "color 0,0 reset" \
$in +swap -geometry +32+32 \
-compose over -composite \
$out
Out:

Related

How to use ImageMagick to place a watermark in multiple locations on an image

I am currently using imagemagick through the command line to place a watermark in multiple locations on another image, but the way I am doing it seems like it probably isn't the best way to go about doing it.
Here is how I am doing it:
exec("convert 'originalImage.jpg' 'watermark.jpg' -gravity NorthWest -geometry +3+3 -define compose:args=30,100 -compose dissolve -composite 'finalImage.jpg'");
exec("convert 'finalImage.jpg' 'watermark.jpg' -gravity NorthEast -geometry +3+3 -define compose:args=30,100 -compose dissolve -composite 'finalImage.jpg'");
exec("convert 'finalImage.jpg' 'watermark.jpg' -gravity SouthWest -geometry +3+3 -define compose:args=30,100 -compose dissolve -composite 'finalImage.jpg'");
This is (1) taking originalImage.jpg and adding watermark.jpg to the top-left corner (with a 3px margin from the top left, using 30% opacity), then (2) taking that resulting finalImage.jpg and adding the watermark to the top-right corner, and then (3) taking that finalImage.jpg again and adding the watermark to the bottom-left corner.
So it is recreating the file three times to come up with the final image. Is there a shorthand way to do this same thing without having to save the file three separate times?
Thanks!
Here is another solution using multiple "-draw" options:
"-draw" doesn't have a "dissolve" option so you'd need to prepare the
watermark image ahead of time to have 30% alpha.
convert watermark.jpg -alpha set -channel alpha -fx .30 watermark30.png
convert originalImage.jpg \
-gravity NorthWest -draw "image over 3,3 0,0 watermark30.png" \
-gravity NorthEast -draw "image over 3,3 0,0 watermark30.png" \
-gravity SouthWest -draw "image over 3,3 0,0 watermark30.png" \
finalImage.jpg
You could combine this with Mark's good recommendation to use the MPR format instead of watermark30.png. I did a couple of "-draw" versus "-composite" timing tests, and it appears that Mark's method is somewhat faster.
I hope you don't mind my editing your post - delete it if you wish - but here is how a single command might look that does the same all in one go:
convert watermark.jpg -alpha set -channel alpha -fx .30 -write MPR:wm30 +delete original.jpg \
-gravity NorthWest -draw "image over 3,3 0,0 'MPR:wm30'" \
-gravity NorthEast -draw "image over 3,3 0,0 'MPR:wm30'" \
-gravity SouthWest -draw "image over 3,3 0,0 'MPR:wm30'" \
finalImage.jpg
Not at a computer, so untested, but this should be close:
convert originalImage.jpg \( watermark.jpg -write MPR:wm \) \
-define compose:args=30,100 -compose dissolve \
-gravity NorthWest -geometry +3+3 -composite \
MPR:wm -gravity NorthEast -geometry +3+3 -composite \
MPR:wm -gravity SouthWest -geometry +3+3 -composite finalImage.jpg
MPR is a RAM-based "Magick Persistent Register" which I use to avoid needing to keep re-reading the watermark.jpg.
The compose arguments persist until changed, so I don't repeat them. It may not be necessary to repeat the second and third -geometry.

ImageMagick draw rectangle with special corners

Hi I would like to create a mask image with "special corners" I am calling them special because I don't really know how to call them in english here is what I would like to achieve:
what I am using now is
convert xc:black -size 300x300 -fill white -draw "roundrectangle 3,3,296,296,5,5"
but this gives me rounded corners. Thank you in advance for any suggestions.
Here's one way of doing it.
convert -size 300x300 xc:none \
-shave 10 -bordercolor black -border 10 \
-fill black -draw "polyline 0,0 30,0 0,30" \
\( +clone -flip \) -gravity north -composite \
\( +clone -flop \) -gravity south -composite -background white -flatten result.png
That says... "Draw a rectangle your full size and transparent, shave 10 pixels off all round and add a 10 pixel black border (easier than doing the maths and making a 280x280 and adding 10 on each side). Draw a triangle in the top-left. Copy the whole shape and flip it and draw it on top of the original. Copy the whole shape and flop it and draw it again on the original. Now make all the transparent areas white."
Here is another way - maybe a little easier. Draw the original square, then copy it, enlarge it by square-root(2) (i.e. 141%), thicken the borders, rotate 45 degrees and composite it onto itself. Kinda depends how your brain works!
magick -size 300x300 xc:none -shave 10 -bordercolor black -border 10 \
\( +clone -scale 142% -shave 30 -border 30 -rotate 45 \) \
-gravity center -composite -background white -flatten result.png
Here is a link to a page showing how to do what you want along with other effects https://www.imagemagick.org/Usage/thumbnails/#rounded
This is the code from the page:
convert thumbnail.gif -alpha set -compose DstOut \
\( -size 20x15 xc:none -draw "polygon 0,0 0,14 19,0" \
-write mpr:triangle +delete \) \
\( mpr:triangle \) -gravity northwest -composite \
\( mpr:triangle -flip \) -gravity southwest -composite \
\( mpr:triangle -flop \) -gravity northeast -composite \
\( mpr:triangle -rotate 180 \) -gravity southeast -composite \
corner_cutoff.png
You should check out the examples as there is another method you could use for smaller images.

Chain 2 imagemagick commands

I would like to add a logo and some text to an image.
I can achieve this through the following:
// Add logo
composite -geometry +10+20 logo.png input.jpg \
output_with_logo.jpg
// Add text
convert output_with_logo.jpg -font Arial -pointsize 20 \
-draw "fill black text 20,50 'Test'" \
final.jpg
However I'm wondering if I can chain these 2 commands together so I can work from the same source file at once, instead of saving out staged versions of the image.
I've tried:
convert -font Arial -pointsize 20 \
-draw "fill black text 20,50 'Test'" \
-composite -geometry +10+20 input.jpg logo.png \
final.jpg
However this creates 2 "Test" strings on the image
Like this:
convert input.jpg logo.jpg -geometry +10+20 -composite -font Arial -pointsize 20 -draw "fill black text 20,50 'Test'" final.jpg
Rather than use the composite command which won't let you add text, use the convert command and its -composite operator which does the same thing. So, I am saying:
composite A.jpg B.jpg result.jpg = convert A.jpg B.jpg -composite result.jpg
Then, once you have done the compositing, you can add the text afterwards - exactly as you had it.

Appending a label of variable width to one with a fixed size

I am trying to use an Imagemagick command to create a single-letter text label, give it a shadow, place it on the left side of a fixed-size canvas area, and then append this it another label of fixed height but unknown width. So, the desired result is a single letter on the left side of the final transparent PNG, and another label set about 100px to the right of the origin, e.g. this mockup:
I have all of this working in the following command, except that the shadowed text label is not in a fixed size box (should be 100px by 25px). Here's the result:
I think that what I need to do is to turn off the -trim option somehow, but I'm not sure how to do that. +trim is not a valid option, and +repage doesn't do it.
convert \
\( -background transparent \
\( -gravity west -fill lavender -font Constantia.ttf \
-pointsize 12 label:'x' -trim \
\( +clone -background black -shadow 100x3+0+0 -channel A -level 0,50% \
+channel \) \
+swap +repage -gravity center -composite \) \
-size 100x25 -gravity west \) \
\( -size x25 -fill black -background transparent -font MyriadPro-Semibold.otf \
-pointsize 15 label:'Long legend for x' -gravity west \) \
+append -strip legend_test.png
(The trim option is needed to get the height down to 25px--the shadow operation generates too large a vertical extension otherwise. EDIT: And I guess I was wrong above--even w/o the -trim anywhere in the command, the fixed-size image I'm hoping for doesn't work out.)
Hm, looks like there isn't much of a community for ImageMagick left here. I posted to the ImageMagick phpBB board and was able to put together an answer. Briefly:
The -trim option is not an option that affects every image after it is invoked. Instead, it is essentially a command that executes immediately.
The -extent option can be used to increase or decrease an image to a desired size. Apparently the -size command, which I used in my original code, can only be used to set the initial size of an image, not to change the size of an image that already exists.
Here is the final working command:
convert \
\( -background transparent -extent 100x25 -gravity west \
\( -fill lavender -font Constantia.ttf \
-pointsize 12 label:'x' -trim -extent 100x25 -gravity west \
\( +clone -background black -shadow 100x3+0+0 -channel A -level 0,50% \
+channel \) \
+swap +repage -gravity center -composite \) \
-background transparent -extent x25 \) \
\( -size x25 -fill black -background transparent -font MyriadPro- Semibold.otf \
-pointsize 15 label:'Long legend for x' -gravity west \) \
+append -strip legend_test.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