How to add text to an image?

This was the original question: Pdf vertical postion method gives the next page position instead of current page In my project I use iText to generate a PDF document. Suppose that the height of

This was the original question:

Pdf vertical postion method gives the next page position instead of current page

In my project I use iText to generate a PDF document. Suppose that the height of a page measures 500pt (1 user unit = 1 point), and that I write some text to the page, followed by an image. If the content and the image require less than 450pt, the text precedes the image. If the content and the image exceed 450pt, the text is forwarded to the next page. My question is: how can I obtain the remaining available space before writing an image?

Posted on StackOverflow on Nov 6, 2014 by Madhesh

Based on the extra information added in the comments, it is now clear that the OP wants to add images that are watermarked.

There are two approaches to achieve this, depending on the actual requirement.

Approach 1:

The first approach is explained in the WatermarkedImages1 example. In iText 7 we create a PdfFormXObject template as a Rectangle with the proper width and height. From this template we create a Canvas, where we can add an image as well as some text written on top of that image. We can then wrap this PdfFormXObject inside an image and add that image together with its watermark using a single doc.add() statement.

This is the method that performs all the magic:

public Image getWatermarkedImage(PdfDocument pdfDoc, Image img, String watermark) {
    float width = img.getImageScaledWidth();
    float height = img.getImageScaledHeight();
    PdfFormXObject template = new PdfFormXObject(new Rectangle(width, height));
    new Canvas(template, pdfDoc).
            add(img).
            setFontColor(DeviceGray.WHITE).
            showTextAligned(watermark, width / 2, height / 2, TextAlignment.CENTER, (float) Math.PI / 6);
    return new Image(template);
}

This is how we add the images:

Document doc = new Document(pdfDoc);
doc.add(getWatermarkedImage(pdfDoc, new Image(ImageDataFactory.create(IMAGE1)), "Bruno"));
doc.add(getWatermarkedImage(pdfDoc, new Image(ImageDataFactory.create(IMAGE2)), "Dog"));
doc.add(getWatermarkedImage(pdfDoc, new Image(ImageDataFactory.create(IMAGE3)), "Fox"));
Image image = new Image(ImageDataFactory.create(IMAGE4));
image.scaleToFit(400, 700);
doc.add(getWatermarkedImage(pdfDoc, image, "Bruno and Ingeborg"));

As you can see, we have one very large image (a picture of my wife and me). We need to scale this image so that it fits the page. If you want to avoid this, take a look at the second approach.

Approach 2:

The second approach is explained in the WatermarkedImages2 example. In this case, we add each image to a Cell. This Cell will scale the image so that it fits the width of the page. To add the watermark, we use a cell renderer:

private class WatermarkedCellRenderer extends CellRenderer {
    private String content;
    public WatermarkedCellRenderer(Cell modelElement, String content) {
        super(modelElement);
        this.content = content;
    }
    @Override
    public CellRenderer getNextRenderer() {
        return new WatermarkedCellRenderer((Cell) modelElement, content);
    }
    @Override
    public void draw(DrawContext drawContext) {
        super.draw(drawContext);
        Paragraph p = new Paragraph(content).setFontColor(DeviceRgb.WHITE);
        Rectangle rect = getOccupiedAreaBBox();
        new Canvas(drawContext.getCanvas(), drawContext.getDocument(), getOccupiedAreaBBox())
                .showTextAligned(p, (rect.getLeft() + rect.getRight()) / 2, (rect.getBottom() + rect.getTop()) / 2,
                        getOccupiedArea().getPageNumber(), TextAlignment.CENTER, VerticalAlignment.MIDDLE, (float) Math.PI / 6);
    }
}

This cell renderer can be used like this:

Cell cell;

cell = new Cell().add(new Image(ImageDataFactory.create(IMAGE1)).setAutoScaleWidth(true));
cell.setNextRenderer(new WatermarkedCellRenderer(cell, "Bruno"));
table.addCell(cell);

cell = new Cell().add(new Image(ImageDataFactory.create(IMAGE2)).setAutoScaleWidth(true));
cell.setNextRenderer(new WatermarkedCellRenderer(cell, "Dog"));
table.addCell(cell);

cell = new Cell().add(new Image(ImageDataFactory.create(IMAGE3)).setAutoScaleWidth(true));
cell.setNextRenderer(new WatermarkedCellRenderer(cell, "Fox"));
table.addCell(cell);

cell = new Cell().add(new Image(ImageDataFactory.create(IMAGE4)).setAutoScaleWidth(true));
cell.setNextRenderer(new WatermarkedCellRenderer(cell, "Bruno and Ingeborg"));
table.addCell(cell);

You will use this approach if all images have more or less the same size, and if you don't want to worry about fitting the images on the page.

Consideration:

Obviously, both approaches have a different result because of the design choice that is made. Please compare the resulting PDFs to see the difference: watermark_template.pdf versus watermark_table.pdf

Related question:

I'm creating a PDF using iTextSharp and it contains a table that spans multiple pages. After adding the table, my pdf PDF document has 3 pages. Now I want to add a signature image and add some text on that signature image using PdfContentByte. Text added on top of an image I also want to add some text on the last page using PdfContentByte. I've tried the ImageWatermark examples, but they don't work.

Posted on StackOverflow on Feb 14, 2015 by rahlrokks

Please take a look at the WatermarkedImages3 example.

public Image getWatermarkedImage(PdfDocument pdfDoc, Image img, String watermark) {
    float width = img.getImageScaledWidth();
    float height = img.getImageScaledHeight();
    PdfFormXObject template = new PdfFormXObject(new Rectangle(width, height));
    new Canvas(template, pdfDoc).
            add(img).
            setFontColor(DeviceGray.WHITE).
            showTextAligned(watermark, width / 2, height / 2, TextAlignment.CENTER, (float) Math.PI * 30f / 180f);
    return new Image(template);
}

Rahlrokks claims that this doesn't work. It is easy to prove that rahlrokks is not telling us the truth. If we look at watermark3.pdf, we clearly see the text added on top of the image on the last page.

Text added on top of an image
Text added on top of an image

I've also answered the second question about adding text using ColumnText. In iText 7 we use doc.showTextAligned() method:

protected void manipulatePdf(String dest) throws Exception {
    PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
    Document doc = new Document(pdfDoc);
    Table table = new Table(1).setWidthPercent(80);
    for (int i = 0; i 

Not only am I adding text on the image, I am also adding text on the last page using PdfContentByte:

Adding text using PdfContentByte
Adding text using PdfContentByte

I'm sorry rahlrokks, but you should not say it doesn't work in cases where it's so easy to prove that it does work!

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


Share this article

Ready to use iText?

Try our iText 7 Library and add-ons FREE for 30 days. Test your proof of concept, and see if our solution is right for you.

Get my FREE trial
Contact

Still have questions? 

We're happy to answer your questions. Reach out to us and we'll get back to you shortly.

Contact us
Stay updated

Join 11,000+ subscribers and become an iText PDF expert by staying up to date with our new products, updates, tips, technical solutions and happenings.

Subscribe Now