import java.io.*; import com.lowagie.text.pdf.*; import com.lowagie.text.*; import java.util.*; public class DConvert { public static void main(String[] args) { if (args.length == 2) (new DConvert()).go(args[0],args[1]); else System.out.printf("usage: java DConvert input-file output-file\n"); } public void go(String infile,String outfile) { HashMap bookmarks; // Raw bookmarks Map> parsed; // Parsed bookmarks try { // Open existing PDF and read in the destinations into a HashMap PdfReader reader = new PdfReader(infile); reader.consolidateNamedDestinations(); bookmarks = SimpleNamedDestination.getNamedDestination(reader,false); parsed = convertToDestinations(bookmarks); int n = reader.getNumberOfPages(); // Set up new document Rectangle psize = reader.getPageSize(1); float width = psize.height(); float height = psize.width(); Document document = new Document(new Rectangle(height,width)); PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outfile)); document.open(); PdfContentByte cb = writer.getDirectContent(); // Iterate through pages int i = 0; while (i < n) { document.newPage(); i++; PdfImportedPage page1 = writer.getImportedPage(reader, i); cb.addTemplate(page1,1,1); System.out.print("\rProcessing Page "+i); // Check if this page has a bookmark if (parsed.containsKey(i)) { java.util.List marklist = parsed.get(i); // Insert the destination, changing spaces to underscores in the process for (Destination d : marklist) { cb.localDestination(d.getName().replace(' ','_'),d.getPdfDestination()); } } } document.close(); System.out.println("\r"+i+" pages processed.\n"); } catch (Exception de) { de.printStackTrace(); } } /* Converts Hashmap of Raw Destinations to a Hashmap of > See below for the Destination class */ private Map> convertToDestinations(HashMap map) { HashMap> outmap = new HashMap>(); Iterator it = map.keySet().iterator(); while(it.hasNext()) { String key = (String)it.next(); Destination d = new Destination(key,(String)map.get(key)); if (outmap.containsKey(d.getPage())) { java.util.List l = (java.util.List)outmap.get(d.getPage()); l.add(d); } else { java.util.List l = new ArrayList(); l.add((Destination)d); outmap.put(d.getPage(),l); } } return outmap; } } /* Raw Destinations look like in the HashMap Para1 <---> 39 XYZ 0 539 1.5 where Para1 = name of destination 39 = Page number XYZ = type 0 = x-coordinate 539 = y-coordinate 1.5 = zoom factor This needs to be parsed into a different form where all Destinations on a page can be accessed in one shot. The Destination class is a convenience class that holds the following information for each Destination * Page number * Type * Name * PdfDestination object */ class Destination { int page; String type,name; PdfDestination dest; // Arguments: "Para_1.1", "52 XYZ -83 726 1.25" public Destination(String destname,String parameters) { float x,y,z; type = "XYZ"; name = new String(destname); StringTokenizer st = new StringTokenizer(parameters); page = Integer.parseInt(st.nextToken()); st.nextToken(); // Ignore type--is XYZ for all records x = Float.parseFloat(st.nextToken()); if (x < 0.0) x = (float)0.0; //Location to the left of margin is set to margin y = Float.parseFloat(st.nextToken()); z = Float.parseFloat(st.nextToken()); dest = new PdfDestination(PdfDestination.XYZ, x,y,z); } public int getPage() { return page; } public PdfDestination getPdfDestination() { return dest; } public String getName() { return name; } public String toString() { return "Page: "+page+", Name:"+name+", type: "+type+", dest:"+dest; } }