Watermark with JMagick
I know you can do watermarking in thousands of ways, but this is if you want to embed it in your Java application. I know that you can also do this with Java2D, but it’s so much easier with ImageMagick. Moreover you have JMagick distributions for most of the major OSes.
First of all, if you haven’t heard about JMagick, this is the Java/JNI implementation for ImageMagick.
Unfortunately the JMagick documentation is very few and it includes only a few examples.
This next example will guide step by step in adding a watermark to an image. The idea is simple: first you create a watermark image from a text and then combine this image with your initial image.
So, let’s create the watermark image. If you want to watermark more than one image, this will be a one time only step.
// create the watermark image info structure ImageInfo markImageInfo = new ImageInfo(); // set a size for the image high enough to accommodate the text markImageInfo.setSize("1024x1024"); // create the image markImage = new MagickImage(); markImage.allocateImage(markImageInfo); // make the image transparent markImage.setMatte(true); // set the background image to black // actually the color doesn't matter, only the alpha value - 65535 markImage.setBackgroundColor(new PixelPacket(0, 0, 0, 65535)); // make the initial black background color transparent markImage.transparentImage(new PixelPacket(0, 0, 0, 0), 65535);
Now what we have is an image with a black transparent background. Next we have to paint the text on it. For this we will create the drawing and put it into the image.
// create the drawing info structure ImageInfo drawInfo = new ImageInfo(); // create the drawing structure DrawInfo draw = new DrawInfo(drawInfo); draw.setOpacity(0); draw.setGeometry("+0+0"); draw.setGravity(GravityType.CenterGravity); // set the watermark color to gray draw.setFill(new PixelPacket(0xaf00, 0xaf00, 0xaf00, 0)); // set the font size draw.setPointsize(48); // set the font name or the path to the font file draw.setFont("Arial"); // set the watermark text draw.setText("Adrian's blog"); // make the text smoother draw.setTextAntialias(true);
Now we have the text and we have to put it into the watermark image:
// draw the text on the image markImage.annotateImage(draw); // remove the transparent borders of the image so that only the text will remain markImage = markImage.trimImage();
The initial setup is finished. Now we have to load every image that we want to watermark it, combine it with the watermark image and save it.
// load the image from the specified filename ImageInfo imageInfo = new ImageInfo(filename); MagickImage image = new MagickImage(imageInfo); // watermark the image image.compositeImage(CompositeOperator.HardLightCompositeOp, markImage, 10, 10); // save the image image.setFileName(watermarkedFilename); image.writeImage(imageInfo);
The watermark is put in the upper left corner, 10 pixels away from both borders. This is actually what the third and fourth parameters of the compositeImage
method represent.
Instead of CompositeOperator.HardLightCompositeOp
you may also use CompositeOperator.SoftLightCompositeOp
or CompositeOperator.OverlayCompositeOp
.
If you probably watermark the image you may also want to resize it
image = image.scaleImage(newWidth, newHeight);
or remove the EXIF and IPTC info from it
image.profileImage("*", null);
So, in just a few easy steps you were able to watermark an image (or more) with your text. The nice part is that using JMagick you can do a lot of other stuff with the same ease.
This solution can be easily embedded into GUI or web applications.
Later edit: I also tried the DissolveOp
and the results are very good.
I hate jmagic..it makes my jvm runtime to shutdown…i also heared some other people reporting this JNI problem. I think it is better to use Process builder and directly use ImageMagic via its command line.