How can I watermark an image in Java?

I had a similar need recently and found this post rather useful: http://www.codeyouneed.com/java-watermark-image/

The watermark method there uses ImgScalr for resizing the watermark when needed and supports placing text in the bottom / top of the image + the watermark image.

For choosing the correct placement it uses a simple ENUM

public enum PlacementPosition {
    TOPLEFT, TOPCENTER, TOPRIGHT, MIDDLELEFT, MIDDLECENTER, MIDDLERIGHT, BOTTOMLEFT, BOTTOMCENTER, BOTTOMRIGHT
}

And the whole watermarking logic is in this method:

/**
 * Generate a watermarked image.
 * 
 * @param originalImage
 * @param watermarkImage
 * @param position
 * @param watermarkSizeMaxPercentage
 * @return image with watermark
 * @throws IOException
 */
public static BufferedImage watermark(BufferedImage originalImage,
        BufferedImage watermarkImage, PlacementPosition position,
        double watermarkSizeMaxPercentage) throws IOException {

    int imageWidth = originalImage.getWidth();
    int imageHeight = originalImage.getHeight();

    int watermarkWidth = getWatermarkWidth(originalImage, watermarkImage,
            watermarkSizeMaxPercentage);
    int watermarkHeight = getWatermarkHeight(originalImage, watermarkImage,
            watermarkSizeMaxPercentage);

    // We create a new image because we want to keep the originalImage
    // object intact and not modify it.
    BufferedImage bufferedImage = new BufferedImage(imageWidth,
            imageHeight, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
    g2d.drawImage(originalImage, 0, 0, null);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

    int x = 0;
    int y = 0;
    if (position != null) {
        switch (position) {
        case TOPLEFT:
            x = 0;
            y = 0;
            break;
        case TOPCENTER:
            x = (imageWidth / 2) - (watermarkWidth / 2);
            y = 0;
            break;
        case TOPRIGHT:
            x = imageWidth - watermarkWidth;
            y = 0;
            break;

        case MIDDLELEFT:
            x = 0;
            y = (imageHeight / 2) - (watermarkHeight / 2);
            break;
        case MIDDLECENTER:
            x = (imageWidth / 2) - (watermarkWidth / 2);
            y = (imageHeight / 2) - (watermarkHeight / 2);
            break;
        case MIDDLERIGHT:
            x = imageWidth - watermarkWidth;
            y = (imageHeight / 2) - (watermarkHeight / 2);
            break;

        case BOTTOMLEFT:
            x = 0;
            y = imageHeight - watermarkHeight;
            break;
        case BOTTOMCENTER:
            x = (imageWidth / 2) - (watermarkWidth / 2);
            y = imageHeight - watermarkHeight;
            break;
        case BOTTOMRIGHT:
            x = imageWidth - watermarkWidth;
            y = imageHeight - watermarkHeight;
            break;

        default:
            break;
        }
    }

    g2d.drawImage(Scalr.resize(watermarkImage, Method.ULTRA_QUALITY,
            watermarkWidth, watermarkHeight), x, y, null);

    return bufferedImage;

}

And the corresponding methods for calculating the watermark size is:

/**
 * 
 * @param originalImage
 * @param watermarkImage
 * @param maxPercentage
 * @return
 */
private static Pair<Double, Double> calculateWatermarkDimensions(
        BufferedImage originalImage, BufferedImage watermarkImage,
        double maxPercentage) {

    double imageWidth = originalImage.getWidth();
    double imageHeight = originalImage.getHeight();

    double maxWatermarkWidth = imageWidth / 100.0 * maxPercentage;
    double maxWatermarkHeight = imageHeight / 100.0 * maxPercentage;

    double watermarkWidth = watermarkImage.getWidth();
    double watermarkHeight = watermarkImage.getHeight();

    if (watermarkWidth > maxWatermarkWidth) {
        double aspectRatio = watermarkWidth / watermarkHeight;
        watermarkWidth = maxWatermarkWidth;
        watermarkHeight = watermarkWidth / aspectRatio;
    }

    if (watermarkHeight > maxWatermarkHeight) {
        double aspectRatio = watermarkWidth / watermarkHeight;
        watermarkHeight = maxWatermarkHeight;
        watermarkWidth = watermarkHeight / aspectRatio;
    }

    return Pair.of(watermarkWidth, watermarkHeight);
}

/**
 * 
 * @param originalImage
 * @param watermarkImage
 * @param maxPercentage
 * @return
 */
public static int getWatermarkWidth(BufferedImage originalImage,
        BufferedImage watermarkImage, double maxPercentage) {

    return calculateWatermarkDimensions(originalImage, watermarkImage,
            maxPercentage).getLeft().intValue();

}

/**
 * 
 * @param originalImage
 * @param watermarkImage
 * @param maxPercentage
 * @return
 */
public static int getWatermarkHeight(BufferedImage originalImage,
        BufferedImage watermarkImage, double maxPercentage) {

    return calculateWatermarkDimensions(originalImage, watermarkImage,
            maxPercentage).getRight().intValue();

}

Again, all credits to http://www.codeyouneed.com/java-watermark-image/ for a nice sample.


In Thumbnailator, one can add a text caption to an existing image by using the Caption image filter:

// Image to add a text caption to.
BufferedImage originalImage = ...;

// Set up the caption properties
String caption = "Hello World";
Font font = new Font("Monospaced", Font.PLAIN, 14);
Color c = Color.black;
Position position = Positions.CENTER;
int insetPixels = 0;

// Apply caption to the image
Caption filter = new Caption(caption, font, c, position, insetPixels);
BufferedImage captionedImage = filter.apply(originalImage);

In the above code, the text Hello World will be drawn on centered on the originalImage with a Monospaced font, with a black foreground color, at 14 pt.

Alternatively, if a watermark image is to be applied to an existing image, one can use the Watermark image filter:

BufferedImage originalImage = ...;
BufferedImage watermarkImage = ...;

Watermark filter = new Watermark(Positions.CENTER, watermarkImage, 0.5f);
BufferedImage watermarkedImage = filter.apply(originalImage);

The above code will superimpose the watermarkImage on top of the originalImage, centered with an opacity of 50%.

Thumbnailator will run on plain old Java SE -- one does not have to install any third party libraries. (However, using the Sun Java runtime is required.)

Full disclosure: I am the developer for Thumbnailator.


You can have a look to the "Drawing the Watermark" section of http://web.archive.org/web/20080324030029/http://blog.codebeach.com/2008/02/watermarking-images-in-java-servlet.html

Or you may use the GIF4J library http://www.gif4j.com/java-gif4j-pro-gif-image-watermark.htm#gifimagewatermarkapply