javajavax.imageiotwelvemonkeys

Watermarking on TIFF image


I am Trying to put watermark on images using java. Currently I put watermark on images with extension with png, jpeg but the code is not working on tiff image. Previously it was giving null pointer error but after including twelvemonkey core and tiff plugin jars null pointer error was gone and code is executing line by line. But the output tiff image dosn't have the watermark.

            BufferedImage sourceImage = ImageIO.read(...);
            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
            g2d.setComposite(alphaChannel);
            g2d.setColor(Color.BLACK);
            g2d.setFont(new java.awt.Font("Times New Roman", Font.BOLD, 64));
            FontMetrics fontMetrics = g2d.getFontMetrics();
            Rectangle2D rect = fontMetrics.getStringBounds(watermarkText, g2d);

            int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
            int centerY = sourceImage.getHeight() / 2;

            FontMetrics fm = g2d.getFontMetrics();

            g2d.drawString(watermarkText, centerX, centerY);

            ImageIO.write(sourceImage,extension, outFile);

Can anyone gives a way to put watermark on tiff image?


Solution

  • As already stated in the comments to the question, the problem is likely not that your code is "wrong" or that there's anything specific to the TIFF format that prevents watermarking.

    However, TIFF is a very flexible format, and may contain anything from RGB, CMYK, "deep color" or float samples, to simple indexed or bilevel image data. I would suspect that the problem is related to the latter (and if so, you would have the same problem with some palette PNGs), as in these cases there may not be colors that can represent your transparent black. But it's impossible to say for sure, without further clarification.

    It's easy to fix such problems by creating a full RGB in-memory image, drawing your original onto that and then adding the watermark. But this would drastically change the output file and size, and I don't know if this is acceptable for your use case.


    Anyway, here's a full working example, based on your code above and with verifiable input/output files:

    import java.awt.AlphaComposite;
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics2D;
    import java.awt.geom.Rectangle2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    public class WatermarkTest {
    
        private static String watermarkText = "WaterMark!";
    
        public static void main(String[] args) throws IOException {
            File input = new File(args[0]);
            String extension = getExtension(input);
    
            File output = args.length >= 2 
                    ? new File(args[1]) 
                    : new File(input.getParent(), input.getName().replace("." + extension, "_watermarked." + extension));
    
            BufferedImage sourceImage = ImageIO.read(input);
            Graphics2D g2d = sourceImage.createGraphics();
    
            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f);
            g2d.setComposite(alphaChannel);
            g2d.setColor(Color.BLACK);
            g2d.setFont(new java.awt.Font("Times New Roman", Font.BOLD, 64));
            FontMetrics fontMetrics = g2d.getFontMetrics();
            Rectangle2D rect = fontMetrics.getStringBounds(watermarkText, g2d);
    
            int centerX = (sourceImage.getWidth() - (int) rect.getWidth()) / 2;
            int centerY = sourceImage.getHeight() / 2;
    
            g2d.drawString(watermarkText, centerX, centerY);
    
            g2d.dispose();
    
            ImageIO.write(sourceImage, extension, output);
        }
    
        private static String getExtension(final String fileName) {
            int index = fileName.lastIndexOf('.');
    
            if (index >= 0) {
                return fileName.substring(index + 1);
            }
    
            // No period found
            return null;
        }
    }
    

    Input image: logo.tif

    logo.tif

    Result image: logo_watermarked.tif

    logo_watermarked.tif

    Unfortunately, upload to Stackoverflow converted the images to PNG. Original input and output files in TIFF format can be downloaded from Dropbopx.