Platinum Partner
java,frameworks

Converting PDF to HTML Using PDFBox

Over the past few days, while working on another project, I needed to covert PDF documents into HTML. I did the usual searches for tools, but as I'm sure you'll have noticed, the tools available don't get great results. But then, seeing as I'm a software developer, I decided to see if I could program it myself. My requirements were quite simple: get the text out of the document, with the aim of HTML output, and extract the images at the same time.

My first port of call was iText, as it was a library that I was already familiar with. iText is great for creating documents, and I was able to get some text out, but the image extraction wasn't really working out for me. The following is a code snippet that I was using to get the images from the PDFs in iText, based on a post on the iText mailing list. But when I used it, none of the images I generated were right - mostly just the box outlines/borders of the images in the PDF. I presume I was doing something wrong.

PdfReader reader = new PdfReader(new FileInputStream(new File("C:\\test.pdf")));

for(int i =0; i < reader.getXrefSize(); i++)
{
PdfObject pdfobj = reader.getPdfObject(i);
if(pdfobj != null)
{
if (!pdfobj.isStream()) {
//throw new Exception("Not a stream");
}
else
{
PdfStream stream = (PdfStream) pdfobj;
PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
if (pdfsubtype == null) {
// throw new Exception("Not an image stream");

}
else
{
if (!pdfsubtype.toString().equals(PdfName.IMAGE.toString())) {
//throw new Exception("Not an image stream");
}
else
{
// now you have a PDF stream object with an image
byte[] img = PdfReader.getStreamBytesRaw((PRStream) stream);
// but you don't know anything about the image format.
// you'll have to get info from the stream dictionary
System.out.println("----img ------");
System.out.println("height:" + stream.get(PdfName.HEIGHT));
System.out.println("width:" + stream.get(PdfName.WIDTH));
int height = new Integer(stream.get(PdfName.HEIGHT).toString()).intValue();
int width = new Integer(stream.get(PdfName.WIDTH).toString()).intValue();
System.out.println("bitspercomponent:" +
stream.get(PdfName.BITSPERCOMPONENT));

java.awt.Image image = Toolkit.getDefaultToolkit().createImage(img);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
ImageIO.write(bi, "PNG",new File("C:\\images\\"+ i + ".png"));
}

}
}
// ...
// // or you could try making a java.awt.Image from the array:
// j

}
}


}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}

As I was low on time, I moved onto PDFBox which looked like it had already considered my use cases. I got the latest source code from SVN and tried the org.apache.pdfbox.ExtractText class straight away. This allows you to specify a -html flag instead of using the default text output. I ran into an exception straight away. After some debugging I found that what I had downloaded was missing the resources/glyphlist.txt file. I found a copy on the Adobe site and was able to run the utility then. 

One other thing to note while using these utilities is that you'll need to have ICU4J, iText and the Apache Commons Logging libraries on your build path. 

The good news was that the utility got all the text out and put it into a HTML format. But the generated HTML wasn't that pretty. Each line that it read got terminated with a <br/>, admittedly, an easy thing to change around.

Moving onto image extraction, I tried out org.apache.pdfbox.ExtractImages. This class worked perfectly, saving all the images in the PDF as jpeg. I did make one alteration to PDXObjectImage.write2file so that I put the images in a particular folder.

The PDFBox utilities really impressed me, as I wasn't sure if it was possible to get this information out of the PDF so easily. All the pieces are there for one single utility that would generate better HTML for you along with the images. As far as I know, no solution exists to do all of this in Java (if I'm wrong, please let me know in the comments section). Have any of the readers tried to achieve this process using iText, PDFBox or any other Java library? 

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}