How to make an image a qualified mask candidate in itext?

Category: 
Tags: image maskimagestransparencyiText 7

I want to mask an image using another image, for example A.jpg should be masked with image B.jpg. But when I tried to make the image B a mask, I got the following DocumentException:

This image cannot be an image mask

Is there any other way to mask an image using another image in iText? I know how to clip an image but the mask I need can be quite complex, not only rectangles or circles that can be drawn with ContentByte.

Posted on StackOverflow on Mar 17, 2015 by why1905

The reason why your code doesn't work is simple: image masks must be monochrome or grayscale; your JPG is a colored image.

Please take a look at the MakeJpgMask example. In this example, I took two normal JPG files and I used one as mask for the other, resulting in a rather spooky PDF: jpg_mask.pdf

Screen shot
Screen shot

To achieve this, I needed to change one colored JPEG into a black and white image:

public static final String IMAGE = "src/test/resources/img/javaone2013.jpg";
public static final String MASK = "src/test/resources/img/berlin2013.jpg";

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    PageSize pageSize = new PageSize(PageSize.A4).rotate();
    Document doc = new Document(pdfDoc, pageSize);

    ImageData image = ImageDataFactory.create(IMAGE);
    ImageData mask = makeBlackAndWhitePng(MASK);
    mask.makeMask();
    image.setImageMask(mask);

    Image img = new Image(image);
    img.scaleAbsolute(pageSize.getWidth(), pageSize.getHeight());
    img.setFixedPosition(0, 0);
    doc.add(img);

    doc.close();
}

public static ImageData makeBlackAndWhitePng(String image) throws IOException {
    BufferedImage bi = ImageIO.read(new File(image));
    BufferedImage newBi = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_USHORT_GRAY);
    newBi.getGraphics().drawImage(bi, 0, 0, null);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(newBi, "png", baos);
    return ImageDataFactory.create(baos.toByteArray());
}

As you can see, we have converted berlin2013.jpg into a black and white image and we have used this as a mask for the colored javaone2013.jpg image.

Click this link if you want to see how to answer this question in iText 5.