When generating a PDF form BMP the result is allways curios.
Input "hellowworld.bmp"
Output (only the relevant part)
why is there a loss of quality
why is it repeated three times
why is there a black square ( green Frame)
Heres how i test it:
#Test
public final void testWriteSingleBMPtoPDF() throws IOException {
Assert.assertTrue("File existst", TestFileHelper.getBMP(BMPS.HELLOWORLD).exists());
Assert.assertTrue("File readable", TestFileHelper.getBMP(BMPS.HELLOWORLD).canRead());
ArrayList<File> doc = new ArrayList<EncodedPage>();
doc.add(createPage(BMPS.HELLOWORLD));
File result = null;
try {
result = ConvertPDF.bmpToPDF(doc);
} catch (COSVisitorException e) {
e.printStackTrace();
}
Assert.assertTrue("File existst", result.exists());
Assert.assertTrue("File readable", result.canRead());
System.out.println("Please Check >"+result+"<");
}
Heres the part of my java implementation
public static File bmpToPDF(ArrayList<File> inputDoc)
PDDocument document = new PDDocument();
String saveTo = "C:\\temp\\" + System.currentTimeMillis() + ".pdf";
for (File bmpPage : inputDoc) {
PDPage page = null;
PDXObjectImage ximage = null;
page = new PDPage();
document.addPage(page);
BufferedImage awtImage = ImageIO.read(bmpPage);
ximage = new PDPixelMap(document, awtImage);
PDPageContentStream content = new PDPageContentStream(document, page);
content.drawImage(ximage, 0, 0);
content.close();
}
document.save(saveTo);
document.close();
return new File(saveTo) ;
Version of Apache PDFBox is 1.7.1
Related
I'm trying to merge documents side by side with PDFBox, using the following code:
function void generateSideBySidePDF() {
File pdf1File = new File(FILE1_PATH);
File pdf2File = new File(FILE2_PATH);
File outPdfFile = new File(OUTFILE_PATH);
PDDocument pdf1 = null;
PDDocument pdf2 = null;
PDDocument outPdf = null;
try {
pdf1 = PDDocument.load(pdf1File);
pdf2 = PDDocument.load(pdf2File);
outPdf = new PDDocument();
// Create output PDF frame
PDRectangle pdf1Frame = pdf1.getPage(0).getCropBox();
PDRectangle pdf2Frame = pdf2.getPage(0).getCropBox();
PDRectangle outPdfFrame = new PDRectangle(pdf1Frame.getWidth()+pdf2Frame.getWidth(), Math.max(pdf1Frame.getHeight(), pdf2Frame.getHeight()));
// Create output page with calculated frame and add it to the document
COSDictionary dict = new COSDictionary();
dict.setItem(COSName.TYPE, COSName.PAGE);
dict.setItem(COSName.MEDIA_BOX, outPdfFrame);
dict.setItem(COSName.CROP_BOX, outPdfFrame);
dict.setItem(COSName.ART_BOX, outPdfFrame);
PDPage outPdfPage = new PDPage(dict);
outPdf.addPage(outPdfPage);
// Source PDF pages has to be imported as form XObjects to be able to insert them at a specific point in the output page
LayerUtility layerUtility = new LayerUtility(outPdf);
PDFormXObject formPdf1 = layerUtility.importPageAsForm(pdf1, 0);
PDFormXObject formPdf2 = layerUtility.importPageAsForm(pdf2, 0);
// Add form objects to output page
AffineTransform afLeft = new AffineTransform();
layerUtility.appendFormAsLayer(outPdfPage, formPdf1, afLeft, "left");
AffineTransform afRight = AffineTransform.getTranslateInstance(pdf1Frame.getWidth(), 0.0);
layerUtility.appendFormAsLayer(outPdfPage, formPdf2, afRight, "right");
outPdf.save(outPdfFile);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (pdf1 != null) pdf1.close();
if (pdf2 != null) pdf2.close();
if (outPdf != null) outPdf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
However the form fields contained in the original documents are not displayed in the final PDF. I also tried to set the acroform on the final document, doing:
outDoc.getDocumentCatalog().setAcroForm(acroForm);
but it doesn't work.
I Tried adding title , but am getting error for pdPageContentStream.drawString();
Error: " drawString(java.lang.String)' is deprecated "
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
// PDRectangle.LETTER and others are also possible
PDRectangle rect = page.getMediaBox();
document.addPage(page);
try {
// Create a Content Stream
PDPageContentStream pdPageContentStream = new PDPageContentStream(document, page);
pdPageContentStream.beginText();
pdPageContentStream.drawString();
pdPageContentStream.endText();
// Creating an PDImageXObject object
PDImageXObject pdImageXObj = PDImageXObject.createFromFile("resources/images/new.png", document);
// Draw that image to the content stream
pdPageContentStream.drawImage(pdImageXObj, 30, 650);
pdPageContentStream.drawString();
// Once all the content is written, close the stream
pdPageContentStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
I am experiencing an EOF Exception as follows when attempting to read tiff files using iText 5.5.10
ExceptionConverter: java.io.EOFException
at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:249)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:241)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:209)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:314)
at com.itextpdf.text.pdf.codec.TiffImage.getTiffImage(TiffImage.java:302)
at com.itextpdf.text.Image.getInstance(Image.java:428)
at com.itextpdf.text.Image.getInstance(Image.java:374)
at TiffToPdf.main(TiffToPdf.java:137)
The code I am using is:
byte[] data = null;
Image img = null;
try {
data = Files.readAllBytes(Paths.get("tiff.tif"));
img = Image.getInstance(data, true);
}
catch (Exception e) {
e.printStackTrace();
}
I have tried skipping the Image step and using the TiffImage class explicitly but I experience the same error.
byte[] data = null;
Image img = null;
try {
data = Files.readAllBytes(Paths.get("tiff.tif"));
RandomAccessSourceFactory factory = new RandomAccessSourceFactory();
RandomAccessSource fileBytes = factory.createSource(data);
RandomAccessFileOrArray s = new RandomAccessFileOrArray(fileBytes);
img = TiffImage.getTiffImage(s, true, 1, true);
}
catch (Exception e) {
e.printStackTrace();
}
I noticed that there are 2 classes within iText called TIFFFaxDecompressor and TIFFFaxDecoder but I haven't been able to find any resources online on how to use them.
with your given tiff image, the following code does worked for me i.e., converted to pdf successfully.
byte[] data = null;
com.itextpdf.text.Image img = null;
try {
//System.out.println(Paths.get("src/main/resources/tiff.tif"));
data = Files.readAllBytes(Paths.get("src/main/resources/file.tif"));
RandomAccessSourceFactory factory = new RandomAccessSourceFactory();
RandomAccessSource fileBytes = factory.createSource(data);
RandomAccessFileOrArray s = new RandomAccessFileOrArray(fileBytes);
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("src/main/resources/destination.pdf"));
document.open();
int pages = TiffImage.getNumberOfPages(s);
Image image;
for (int i = 1; i <= pages; i++) {
image = TiffImage.getTiffImage(s, i);
Rectangle pageSize = new Rectangle(image.getWidth(),
image.getHeight());
document.setPageSize(pageSize);
document.newPage();
document.add(image);
}
document.close();
} catch (Exception e) {
e.printStackTrace();
}
I'm using PDFBox RC2 in a Windows 7 environment, Java 1.8_66. I'm using it to create a PDF from a collection of 200dpi page-sized image files, both JPEG and PNG.
It turns out that when adding JPEG files to a PDF, the PDImageXObject.createFromFile() routine fails to close an internal file handle, thus locking the image file for the lifetime of the application. When adding PNG files to a PDF, there is no problem.
Here's some sample code that reproduces the issue. Using process explorer (from sysinternals), view the open file handles for the java.exe process and run this code. My test uses about 20 full sized JPEG files. Note that after the method exits, several locked files still remain behind.
public Boolean CreateFromImages_Broken(String pdfFilename, String[] imageFilenames) {
PDDocument doc = new PDDocument();
for (String imageFilename : imageFilenames) {
try {
PDPage page = new PDPage();
doc.addPage(page);
PDImageXObject pdImage = PDImageXObject.createFromFile(imageFilename, doc);
// at this point, if the imageFilename is a jpeg, pdImage holds onto a handle for
// the given imageFilename and that file remains locked until the application is closed
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
float scale = (float)72.0 / 200;
page.setMediaBox(new PDRectangle((int)(pdImage.getWidth() * scale), (int)(pdImage.getHeight() * scale)));
contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth()*scale, pdImage.getHeight()*scale);
}
} catch (IOException ioe) {
return false;
}
}
try {
doc.save(pdfFilename);
doc.close();
} catch (IOException ex) {
return false;
}
return true;
}
As a workaround, I reviewed the source code for PNG and JPEG handling, and I've had success by implementing this, which seems to work for both file types:
public Boolean CreateFromImages_FIXED(String pdfFilename, String[] imageFilenames) {
PDDocument doc = new PDDocument();
for (String imageFilename : imageFilenames) {
FileInputStream fis = null;
try {
PDPage page = new PDPage();
doc.addPage(page);
PDImageXObject pdImage = null;
// work around JPEG issue by opening up our own stream, with which
// we can close ourselves instead of PDFBOX leaking it. For PNG
// images, the createFromFile seems to be OK
if (imageFilename.toLowerCase().endsWith(".jpg")) {
fis = new FileInputStream(new File(imageFilename));
pdImage = JPEGFactory.createFromStream(doc, fis);
} else {
pdImage = PDImageXObject.createFromFile(imageFilename, doc);
}
try (PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {
float scale = (float)72.0 / 200;
page.setMediaBox(new PDRectangle((int)(pdImage.getWidth() * scale), (int)(pdImage.getHeight() * scale)));
contentStream.drawImage(pdImage, 0, 0, pdImage.getWidth()*scale, pdImage.getHeight()*scale);
if (fis != null) {
fis.close();
fis = null;
}
}
} catch (IOException ioe) {
return false;
}
}
try {
doc.save(pdfFilename);
doc.close();
} catch (IOException ex) {
return false;
}
return true;
}
When I try to draw png images using pdfBox, the pages remain blank. Is there any way to insert png images using pdfBox?
public void createPDFFromImage( String inputFile, String image, String outputFile )
throws IOException, COSVisitorException
{
// the document
PDDocument doc = null;
try
{
doc = PDDocument.load( inputFile );
//we will add the image to the first page.
PDPage page = (PDPage)doc.getDocumentCatalog().getAllPages().get( 0 );
PDXObjectImage ximage = null;
if( image.toLowerCase().endsWith( ".jpg" ) )
{
ximage = new PDJpeg(doc, new FileInputStream( image ) );
}
else if (image.toLowerCase().endsWith(".tif") || image.toLowerCase().endsWith(".tiff"))
{
ximage = new PDCcitt(doc, new RandomAccessFile(new File(image),"r"));
}
else
{
BufferedImage awtImage = ImageIO.read( new File( image ) );
ximage = new PDPixelMap(doc, awtImage);
// throw new IOException( "Image type not supported:" + image );
}
PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true);
contentStream.drawImage( ximage, 20, 20 );
contentStream.close();
doc.save( outputFile );
}
finally
{
if( doc != null )
{
doc.close();
}
}
}
There is a pretty nice utility class PDImageXObject to load Images from a java.io.File.
As far as I know, it works well with jpg and png files.
PDImageXObject pdImage = PDImageXObject.createFromFileByContent(imageFile, doc);
contentStream.drawImage(pdImage, 20f, 20f);