25

I have a watermark that I would like to put into my pdf. The watermark is a .bmp image, and is 2290 x 3026. I am having a lot of trouble trying to resize this picture to fit the page, does anyone have any suggestions?

Document document = new Document(); 
PdfWriter.getInstance(document, new FileOutputStream("result.pdf")); 
document.open(); 
document.add(new Paragraph("hello")); 
document.close(); 
PdfReader reader = new PdfReader("result.pdf"); 
int number_of_pages = reader.getNumberOfPages(); 
PdfStamper pdfStamper = new PdfStamper(reader, new FileOutputStream("result_watermark.pdf")); 
// Get the PdfContentByte type by pdfStamper. 
Image watermark_image = Image.getInstance("abstract(0307).bmp"); 
int i = 0; 
watermark_image.setAbsolutePosition(0, 0);
watermark_image.scaleToFit(826, 1100);
System.out.println(watermark_image.getScaledWidth());
System.out.println(watermark_image.getScaledHeight()); 
PdfContentByte add_watermark; 
while (i < number_of_pages) { 
    i++; 
    add_watermark = pdfStamper.getUnderContent(i); 
    add_watermark.addImage(watermark_image); 
} 
pdfStamper.close();

Here is the output for the getScaled() methods.

826.0 - Width
1091.4742 - Height

I would share the picture of the pdf with you guys but unfortunately I can't.

Should I try using a .jpg instead? I don't really know how well iText handles different image extensions.

Alexis Pigeon
  • 7,423
  • 11
  • 39
  • 44
Failsafe
  • 750
  • 2
  • 7
  • 23
  • you can add screenshot of PDF. See http://meta.stackexchange.com/questions/75491/how-to-upload-an-image-to-a-post or http://meta.stackexchange.com/questions/57125/inserting-an-image-in-a-pre-tag – Ritesh Jun 20 '12 at 13:53
  • That's not the problem. The watermark I am adding is a company watermark, and I can't just be passing it around.. Well I was told not to anyway. – Failsafe Jun 20 '12 at 13:56
  • 1
    have you tried scaling the image manually, instead of programmatically, and use the manually scaled image in your code? since you seem to hardcode the scaled dimension, that would save you some processing every time you watermark PDF documents. – Alexis Pigeon Jun 20 '12 at 14:06
  • @AlexisPigeon - No I haven't, but I'll try it and get back to you.. – Failsafe Jun 20 '12 at 14:08
  • @AlexisPigeon - The manual resize worked, it's a little blurry, but I can deal. Add your comment as an answer and I'll give you a check mark. – Failsafe Jun 25 '12 at 17:36
  • @Failsafe its too late to answer I think but you can use scaleAbsolute(float x, float y) method. See my answere below. – MGDroid Jan 11 '13 at 11:47

7 Answers7

64

I do it like that:

//if you would have a chapter indentation
int indentation = 0;
//whatever
Image image = coolPic;

float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
               - document.rightMargin() - indentation) / image.getWidth()) * 100;

image.scalePercent(scaler);
Franz Ebner
  • 4,951
  • 3
  • 39
  • 57
  • Unfortunately that doesn't work for me. The closest I have ever gotten was to do: watermark_image.scalePercent(110 * 72 / 300); – Failsafe Jun 20 '12 at 14:36
  • can you describe exactly what's your problem!? the scaling doesn't work- ok but what's your output with the scaler you use at the time!? – Franz Ebner Jun 21 '12 at 06:42
  • 4
    This approach worked for me better than the idea proposed by Alexis because the default scaling has a pretty low resolution, so if you resize the original image to fit the pdf document, you get a pixelated low resolution image at maybe 72 dpi equivalent. But with scaling, you can use a much larger image resized to fit but preserving the high resolution. – Ted Jan 27 '14 at 23:11
  • Works perfect for me! Thanks a lot! – Allan Andrade Jun 01 '19 at 23:51
  • This solution worked for me. Though I would say it's rather a workaround and there might be a proper way to set the image to fit the width – Markiian Benovskyi Feb 15 '21 at 12:03
  • 1
    didn't work for images with larger height – Siddharth Shakya Mar 01 '22 at 14:29
24

use

watermark_image.scaleAbsolute(826, 1100);

instead of

watermark_image.scaleToFit(826, 1100);
MGDroid
  • 1,659
  • 2
  • 17
  • 32
  • 1
    What is the difference between these two methods? – Fred Feb 10 '20 at 11:55
  • From the iText in Action 2nd ed: The width and height parameters of scaleToFit() define the maximum dimensions of the image. If the width/height ratio differs from the aspect ratio of the image, either the width, or the height, will be smaller than the corresponding parameter of this method. The width and height parameters will be respected when using scaleAbsolute(). The resulting image risks being stretched in the X or Y direction if you don’t choose the parameters wisely. You can also use ScaleAbsoluteWidth() and scaleAbsoluteHeight(). – alrts Apr 21 '22 at 07:17
17

Just in case if the image height exceeds the document height:

float documentWidth = document.getPageSize().width() - document.leftMargin() - document.rightMargin();
float documentHeight = document.getPageSize().height() - document.topMargin() - document.bottomMargin();
image.scaleToFit(documentWidth, documentHeight);
Roman Popov
  • 171
  • 1
  • 3
  • 1
    This is good. Simply writing `image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight());` can lead bigger images to go out of page border – Oleksandr Firsov Nov 06 '17 at 18:49
  • 4
    .height() and .width() don't seem to be valid method names. I had to change to document.getPageSize().getWidth() and document.getPageSize().getHeight() to make it work. – M.A.Naseer May 14 '18 at 17:43
15

you can use

imageInstance.scaleAbsolute(requiredWidth, requiredHeight);
Alexis Pigeon
  • 7,423
  • 11
  • 39
  • 44
Coach005
  • 151
  • 1
  • 2
7

You could use another approach : resize the image "manually" (i.e. through an image processing software) instead of programmatically through iText.

Since the final dimension seems hardcoded, you could use an already resized image and save yourself some processing time every time you watermark PDF documents.

Alexis Pigeon
  • 7,423
  • 11
  • 39
  • 44
5
Document document = new Document();
PdfWriter.getInstance(document, new 
FileOutputStream("F:\\Directory1\\sample1.pdf"));
document.open();

Image img = 
Image.getInstance("F:\\Server\\Xyz\\WebContent\\ImageRestoring\\Rohit.jpg");
img.scaleToFit(200, 200);
document.add(new Paragraph("Sample 1: This is simple image demo."));
document.add(img);
document.close();
System.out.println("Done");
Mike G
  • 4,232
  • 9
  • 40
  • 66
Paresh Jain
  • 59
  • 1
  • 1
  • sorry for answering late, but i had started working professionally in this 5 months, and i had got lot help from this site, so, i taught, i should pay back something to this site, till my capability. – Paresh Jain Jan 24 '18 at 12:17
  • 1
    @Failsafe You at least owe it to Paresh to _try_ his solution and see if it works better. He did go through the effort of writing it. – Sidney Sep 11 '19 at 17:29
  • @Sidney CS0246 The type or namespace name 'Document' could not be found (are you missing a using directive or an assembly reference?) help!? How do i solve this? – Failsafe Sep 11 '19 at 17:31
4

Sometimes it is useful to only scale down if the image is too large and not scale up if the image fits OK. In other words, the scaling will only happen if the width doesn't fit in the available width or the height doesn't fit in the available height. This can be done as follows:

float scaleRatio = calculateScaleRatio(doc, image);
if (scaleRatio < 1F) {
    image.scalePercent(scaleRatio * 100F);
}

with this calculateScaleRatio method:

/**
 * Calculate scale ratio required to fit supplied image in the supplied PDF document.
 * @param doc    PDF to fit image in.
 * @param image  Image to be converted into a PDF.
 * @return       Scale ratio (0.0 - 1.0), or 1.0 if no scaling is required.
 */
private float calculateScaleRatio(Document doc, Image image) {
    float scaleRatio;
    float imageWidth = image.getWidth();
    float imageHeight = image.getHeight();
    if (imageWidth > 0 && imageHeight > 0) {
        // Firstly get the scale ratio required to fit the image width
        Rectangle pageSize = doc.getPageSize();
        float pageWidth = pageSize.getWidth() - doc.leftMargin() - doc.rightMargin();
        scaleRatio = pageWidth / imageWidth;

        // Get scale ratio required to fit image height - if smaller, use this instead
        float pageHeight = pageSize.getHeight() - doc.topMargin() - doc.bottomMargin();
        float heightScaleRatio = pageHeight / imageHeight;
        if (heightScaleRatio < scaleRatio) {
            scaleRatio = heightScaleRatio;
        }

        // Do not upscale - if the entire image can fit in the page, leave it unscaled.
        if (scaleRatio > 1F) {
            scaleRatio = 1F;
        }
    } else {
        // No scaling if the width or height is zero.
        scaleRatio = 1F;
    }
    return scaleRatio;
}
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
  • 1
    This helped me a lot, thank you! As iText almost never works as you think it works at the first attempt, such modules save time and give you more time to think about the real problem at hand. – alrts Apr 21 '22 at 11:45