I use iText 7 http://itextpdf.com/ libraries: itext7-io-7.0.2.jar, itext7-kernel-7.0.2.jar, itext7-layout-7.0.2.jar, slf4j-api-1.7.25.jar, slf4j-simple-1.7.25.jar in the project that sets the background image of the document page and saves several similar pages in the same document (pdf-file). The image file
final String IMAGE = "/resources/image.jpg";
must be stored as a resource in the jar-file. The ImageData object is created using the method create(java.awt.Image image, java.awt.Color color) of com.itextpdf.io.image.ImageDataFactory:
ImageData imgData = ImageDataFactory.create(new Main().loadImage(IMAGE), true);
The code of the java.awt.image.BufferedImage loadImage(String imageFilename) method is:
private BufferedImage loadImage(String imageFilename) {
BufferedImage img = null;
try {
img = javax.imageio.ImageIO.read(getClass().getResourceAsStream(imageFilename));
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return img;
}
The ImageData object is used in the loop:
Document document = ... (get Document object)
PdfDocument pdf = document.getPdfDocument();
PageSize pageSize = pdf.getDefaultPageSize();
PdfPage page = pdf.addNewPage();
for (int i = 0; i < documents.size(); i++) {
PdfCanvas canvas = new PdfCanvas(page);
canvas.addImage(imgData, pageSize, false);
... (add document body)
if (i < documents.size() - 1) {
page = pdf.addNewPage();
document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
}
document.close();
The problem is that after I run the program from jar-file, I get a pdf-document that is much larger than when I run the program from IDE using direct image reference (81 Mbytes vs 9 MBytes for 17 page document):
ImageData imgData = ImageDataFactory.create("src/resources/image.jpg");
If you create an ImageData object from the bytes of the image using the method create(byte[] bytes, boolean recoverImage) of com.itextpdf.io.image.ImageDataFactory:
ImageData imgData = ImageDataFactory.create(new Main().loadImageByte(IMAGE), true);
and use byte[] loadImageByte(String imageFilename) method:
private byte[] loadImageByte(String imageFilename) {
byte[] dataBytes = null;
try {
InputStream is = getClass().getResourceAsStream(imageFilename);
dataBytes = new byte[is.available()];
is.read(dataBytes);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return dataBytes;
}
the size of the resulting pdf-document is small both when you run the program from IDE, or when you start from the jar-file. However, in the latter case, the document does not open, Adobe Acrobat 9 gives an error "Insufficient data for an image" (and bytes of both documents are different).
What is the reason for the difference between file sizes and is there a way to get a small size pdf-document by program starting from a jar-file?
loadImageByte
: you useis.available()
to determine the size of the resource file. This is wrong, though,is.available()
might well return a smaller value depending on theInputStream
class actually used, and theInputStream
class actually used might differ between runs from IDE with resources being in the file system and runs from jar with resources compressed in a JAR archive. - mklcreate(java.awt.Image image, java.awt.Color color)
ofcom.itextpdf.io.image.ImageDataFactory
would useXObject
, but obviously it is not. - Gennady KolomoetsImageDataFactory.create(new MainSOQ().loadImageByte(IMAGE), true);
throws an exception Premature EOF while reading JPEG. - Gennady Kolomoets