Uploaded image for project: 'PDFBox'
  1. PDFBox
  2. PDFBOX-3594

Use PDOutlineItem#findDestinationPage() cannot get PDPage, return was null

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.8.12, 2.0.3
    • 1.8.13, 2.0.4, 3.0.0 PDFBox
    • PDModel
    • None
    • Java 8

    Description

      Overview

      I try to extract Bookmarks of a PDF, but I could not get a destination page.

      PDF

      http://www.line6.jp/products/pod-hd-x/img-pod-hd-x-resource/pod-hd-500x-advanced-guide.pdf

      Code

      main.PDFBookmarkExtractor.java
      package main;
      
      import java.io.File;
      import java.io.IOException;
      
      import org.apache.pdfbox.pdmodel.PDDocument;
      import org.apache.pdfbox.pdmodel.PDPage;
      import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
      import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
      import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineNode;
      
      public class PDFBookmarkExtractor {
      
      	public static void main(String args[]) throws Exception {
      		PDFBookmarkExtractor extractor = new PDFBookmarkExtractor();
      		extractor.extract();
      	}
      
      	public void extract() {
      		File pdf = new File("pod-hd-500x-advanced-guide.pdf");
      		try (PDDocument document = PDDocument.load(pdf)) {
      			PDDocumentOutline outline =  document.getDocumentCatalog().getDocumentOutline();
      			this.getBookmarks(document, outline);
      		} catch(IOException e) {
      			e.printStackTrace();
      		}
      	}
      
      	private void getBookmarks(PDDocument document, PDOutlineNode outlineNode) throws IOException {
      		PDOutlineItem current = outlineNode.getFirstChild();
      		while(current != null) {
      			this.getBookmark(document, current, 0);
      			current = current.getNextSibling();
      		}
      	}
      	private int getBookmark(PDDocument document, PDOutlineItem current, int indentCount) throws IOException {
      		PDPage page = current.findDestinationPage(document);
      
      		StringBuilder sb = new StringBuilder();
      		for(int i=0; i<indentCount; i++) {
      			sb.append("\t");
      		}
      		sb.append(current.getTitle());
      		sb.append("[").append(page).append("]");
      		System.out.println(sb);
      
      		if(current.hasChildren()) {
      			for(PDOutlineItem child : current.children()) {
      				this.getBookmark(document, child, indentCount + 1);
      			}
      		}
      		return indentCount;
      	}
      }
      

      Result

      POD® HD500 アドバンスド・ガイド[org.apache.pdfbox.pdmodel.PDPage@5910e440]
      1 - 概要[null]
      	ホーム・ビュー[null]
      		チューナー・モード[null]
      		タップ・テンポ[null]
      		接続[null]
      		POD HD500エディット・ソフトウエア[null]
      	2 - システム・セットアップ[org.apache.pdfbox.pdmodel.PDPage@26a1ab54]
      		システム・セットアップへアクセスする[org.apache.pdfbox.pdmodel.PDPage@26a1ab54]
      		ページ 1、Setup:Utilities[org.apache.pdfbox.pdmodel.PDPage@3d646c37]
      		ページ 2、Setup:Utilities[org.apache.pdfbox.pdmodel.PDPage@41cf53f9]
      
      [...snip...]
      
      

      Problem

      I think PDNameTreeNode#getValue has problems.

      org.apache.pdfbox.pdmodel.common.PDNameTreeNode.java
          /**
           * The name to retrieve.
           *
           * @param name The name in the tree.
           * @return The value of the name in the tree.
           * @throws IOException If an there is a problem creating the destinations.
           */
          public T getValue( String name ) throws IOException
          {
              T retval = null;
              Map<String, T> names = getNames();
              if( names != null )
              {
                  retval = names.get( name );
              }
              else
              {
                  List<PDNameTreeNode<T>> kids = getKids();
                  if (kids != null)
                  {
                      for( int i=0; i<kids.size() && retval == null; i++ )
                      {
                          PDNameTreeNode<T> childNode = kids.get( i );
                          // [Problem] Cannot get retval.
                          // Because "kids" were not sorted by name
                          if( childNode.getLowerLimit().compareTo( name ) <= 0 &&
                              childNode.getUpperLimit().compareTo( name ) >= 0 )
                          {
                              retval = childNode.getValue( name );
                          }
                      }
                  }
                  else
                  {
                      LOG.warn("NameTreeNode does not have \"names\" nor \"kids\" objects.");
                  }
              }
              return retval;
          }
      

      Attachments

        Activity

          People

            tilman Tilman Hausherr
            kohdai kohdai
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: