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

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.

Related

How to handle multiple elements with imagemagick cli?

We need to put 'information bar's to thousands of image files. For like a week or so i'm trying to learn imagemagick but i just couldn't figure this many elements out so i wanted to ask for a help here.
I get the idea of '-/+append'ing elements and swapping between them but when it comes to 3x3 matrix cells and text/image mixings, i just can't do it. As an example, i can get the 3 rows appended and a column next to it but i can't get to the next step of 'appending 2 more rows together then put them as a column block again' because when i try, all those append gets right or bottom as a whole image.. Well, you will get the idea when you see my brief image below..
magick.exe -size 150x100 -gravity center caption:"txt2" caption:"txt3" caption:"txt4" \
-append -size 94x294 xc:white -border 3 -swap 0,1 \
+append outoutout.jpg
FYI, height/width of rows/columns are there just for example not important.. And here comes MSPaint skills:
You have to create each section separately using parenthesis processing. Then if you want append them appropriately. Alternately, you can create a background image and compose ... -composite each image into its correct location.
Here is an example in ImageMagick using the second method.
Unix Syntax:
magick -size 400x400 xc:white \
\( barn.jpg -crop 400x200+0+0 +repage \) \
-geometry +0+0 -compose over -composite \
\( -size 100x200 xc:white -shave 5x5 -bordercolor black -border 5 \) \
-gravity northwest -geometry +0+200 -compose over -composite \
\( -size 100x200 -background white -gravity center -fill black \
-font Candice label:"Text1\n\nText2\n\nText3" \) \
-gravity northwest -geometry +100+200 -compose over -composite \
\( -size 100x200 -background skyblue -gravity center -fill red \
-font Arial label:"First_line\n\n\nSecond_line" \) \
-gravity northwest -geometry +300+200 -compose over -composite \
result.png
See for example:
parenthesis processing
appending
convert ... -composite

ImageMagick apply watermark multiple times

Currently, with ImageMagick I apply watermark.png on top of picture.jpg in the center using:
convert -size 700x1300 -composite picture.jpg watermark.png -gravity center -geometry 700x1300 output.jpg
This nicely overlays my watermark in the middle of the image. However, I want to achieve this effect in the top-left, center, and bottom-right. I've tried combining multiple -composites with no result. I would like to avoid calling 3 different commands to avoid the extra overhead it introduces, but I'm starting to believe it isn't possible without doing so.
What can I do to achieve the three watermark positions in one command, NorthWest, Center and SouthEast?
Hold the watermark image in a memory register with "-write mpr:watermark", then recall it into your command for the second and third composite. Here's a simple example of how that works...
convert watermark.png -write mpr:watermark input.png +swap \
-gravity center -composite mpr:watermark -gravity northwest -composite \
mpr:watermark -gravity southeast -composite output.png
Set the geometry before each composite if necessary to give the mark some padding from the corners.
In Imagemagick, there is a -gravity setting that allows you to put the watermark in various locations specified by the compass directions. See http://www.imagemagick.org/script/command-line-options.php#gravity. However, your syntax is not proper and may fail for use with IM 7. The proper syntax is to read the input image first. So your command should be
convert background watermark -gravity center -compose over -composite output
Change center to one of the other gravity settings such as northwest or southeast
Also your -size does nothing in your command. If you want to use -size WxH xc:somecolor, then you would use that in place of the background.
If you want to resize, then do not use -geometry. That is typically used for offsetting the gravity placement. Use -resize WxH if you want to resize the result.
See
http://www.imagemagick.org/Usage/compose/#compose
http://www.imagemagick.org/Usage/layers/#convert
I would modify GeeMack's answer just slightly so it reads a bit more symmetric:
convert watermark.png -write mpr:watermark +delete \
input.png \
mpr:watermark -gravity center -compose over -composite \
mpr:watermark -gravity northwest -compose over -composite \
mpr:watermark -gravity southeast -compose over -composite \
output.png
EDITED: to followup with OP question. If you need to resize the watermark, then do
convert watermark.png -resize 700x1300 -write mpr:watermark +delete \
input.png \
mpr:watermark -gravity center -compose over -composite \
mpr:watermark -gravity northwest -compose over -composite \
mpr:watermark -gravity southeast -compose over -composite \
output.png

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.

add image to transparent section

I have an image with a couple of transparent boxes. I need to insert some specific images in to the transparent boxes. I tried several convert commands but couldn't end up with a solution.
I am using Windows 10 and imagemagick is working on my CLI with no issues. Hope someone can point me into the right direction.
Let's say this 500x400 image is your starting image and it has transparent holes in it at 10,10 and 250,250.
Now, let's say you have two Mr Beans, bean1.jpg and bean2.jpg like this:
Let's lay it out on a red background so you can see what is going on. We'll resize bean1.jpg and place him in the area of the top-left transparent hole, then we'll set up bean2.jpg for the bottom-right transparent hole:
convert -size 500x400 xc:red \
\( bean1.jpg -resize 101x101! -geometry +10+10 \) -composite \
\( bean2.jpg -resize 131x131! -geometry +250+250 \) -composite \
result.png
Now let's do that again, but this time, overlay the original image so the Beans peek through it:
convert -size 500x400 xc:red \
\( bean1.jpg -resize 101x101! -geometry +10+10 \) -composite \
\( bean2.jpg -resize 131x131! -geometry +250+250 \) -composite \
image.png -composite result.png
On Windows, you have to change the backslashes into carets, so \( becomes ^( and \) becomes ^).

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

Resources