Monthly Archives: July 2013

Creating Thumbnails of PDF Pages

A common question we receive from our customers is how do I create thumbnails of a PDF document? The best class to use for this is PDFDraw, which rasterizes* PDF pages one at a time, and provides methods for saving these images in a variety of formats. The C# code snippet below shows how to extract all of the pages from a document and save them as JPEGs with a quality of 80.

// A collection of rendering 'hints'.
ObjSet hint_set=new ObjSet();
try
{
	using (PDFDoc doc = new PDFDoc("myDocument.pdf"))
	{
		// Initialize the security handler, in case the PDF is encrypted.
		doc.InitSecurityHandler();

		// Set the output resolution is to 72 DPI.
		draw.SetDPI(72);

		// Use optional encoder parameter to specify JPEG quality.
		Obj encoder_param = hint_set.CreateDict();
		encoder_param.PutNumber("Quality", 80);

		// Traverse all pages in the document.
		for (PageIterator itr=doc.GetPageIterator(); itr.HasNext(); itr.Next())
		{
			string outname = string.Format("{0}myDocument{1:d}.jpg", output_path, itr.GetPageNumber());
			Console.WriteLine("Result saved in {0}", outname);
			draw.Export(itr.Current(), outname, "JPEG", encoder_param);
		}
	}
}
catch (PDFNetException e)
{
		Console.WriteLine(e.Message);
}

One thing of note in this sample is the use of a PageIterator. Using a PageIterator is more efficient than repeatedly calling GetPage(i), because GetPage(int pageNumber) is an O(n) operation.

For more example code on how to use PDFDraw, see the PDFDraw sample on our sample code page.

* When we speak of “rasterizing” a PDF, we mean convert it to bitmapped image data. PDF documents contain vector elements such as lines, text, gradients, etc. that are defined formulaically, and hence can be accurately viewed at any resolution. When you convert a PDF page to an image, you are converting it to raster data at a specific resolution.

PDFTron to Present at PDF Association’s Technical Conference 2013

PDFTron will be sending representatives to the PDF Association’s Technical Conference North America 2013 in Seattle from August 14-15. The conference will be a gathering of PDF industry professionals with educational sessions in two tracks over two days. We will be giving a talk on PDF rendering and viewing on mobile devices and the web. We will also attend PDF/A day on August 16th.

See you there!

Getting Started with the iOS Static Framework

NOTE: This is the getting started document for static framework of PDFNet for iOS. We strongly recommend using the dynamic framework.

Introduction

This tutorial shows how to integrate the static version of the PDFNet framework. It also shows how to add support for annotating, and opening encrypted documents. This document assumes this use of PDFNet V7.3 or greater. You should use the latest versions of the PDFNet Framework and the tools source code, available by request on our website. The tutorial is made four parts:

  • Part 1: Showing a PDF.
  • Part 2: Adding support for text selection, annotation creation and editing, link following and form filling.
  • Part 3: Adding support for encrypted PDF documents.
  • Part 4: Next Steps

Part 1: Showing a PDFCreate a new project.

  1. Create a new projectOpen Xcode and create a new iOS Project, choosing “Single View Application” from the list of available templates. After clicking “next”, name the project PTTest. Save the new project at the location of your choosing.
  2. Prepare the ProjectPDFNet relies on C++, and projects that do not include any .cpp or .mm files must specifically instruct the linker to include the C++ standard library:
    • In Xcode, selection the project file in the left hand panel, then under the Build Phases tab, “Link binaries With Libraries section”, add libc++.tbd.
  3. Add the required PDFNet files, and a PDF Document.Add PDFNet.framework to the proejct:
    • Click on the project file, then making sure that it is the app under TARGETS that is selected, click the General tab, and under Linked Frameworks and Libraries, click the ‘+’ icon, and then click the “Add Other…” button, to add PDFNet.framework.

    Ensure that the framework can be located:

    • Under the Build Settings tab, in the Search Paths section, locate the Framework Search Paths entry. (You may need to ensure “All” entries are visible, not just the “Basic” ones.) Add the path to the location of PDFNet.framework. (If the path includes spaces, enclose the path in quotes.)

    Add the following supporting files to the project:

    • NSObjectInitWithCptr.{h,m} – Adds a needed category to NSObject.
    • ResourceFiles/pdfnet.res – Resources used by PDFNet
    • ResourceFiles/pdftron_layout_resources.plugin – Resources used by PDFNet
    • ResourceFiles/pdftron_smart_substitution.plugin – Resources used by PDFNet

    Make sure that pdfnet.res, pdftron_layout_resources.plugin and pdftron_smart_substitution.plugin will be copied into the app bundle:

    • Click on the project file, then making sure that it is the app under TARGETS that is selected, click the build phases tab, and under the Copy Bundle Resources section, use the ‘+’ button to add the three files.

    Lastly, add a PDF file:

    • In the TestFiles folder, locate “mech.pdf”, and add it by dragging to XCode. You may use any PDF you wish, just replace “mech” with the name of your PDF in the code snippets that follow.
    • Add the PDF file to the Copy Bundle Resources section (as was done for pdfnet.res, etc.).
  4. Add code to show a PDF.Change ViewController.m to include the following.
    #import <PDFNet/PDFNet.h>
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
      [super viewDidLoad];
    
      // Do any additional setup after loading the view, typically from a nib
    
      // Initilize PDFNet (in demo mode - pages will be watermarked)****
      [PTPDFNet Initialize:@""];
    
      // Get the path to document in the app bundle.
      NSString* fullPath = [[NSBundle mainBundle] pathForResource:@"mech" ofType:@"pdf"];
    
      // Initialize a new PDFDoc with the path to the file
      PTPDFDoc* docToOpen = [[PTPDFDoc alloc] initWithFilepath:fullPath];
    
      // Create a new PDFViewCtrl that is the size of the entire screen
      PTPDFViewCtrl* pdfViewCtrl = [[PTPDFViewCtrl alloc] initWithFrame:[self.view bounds]];
    
      // Makes the background light gray
      [self.view setBackgroundColor:[UIColor lightGrayColor]];
    
      // Set the document to display
      [pdfViewCtrl SetDoc:docToOpen];
    
      // Add the PDFViewCtrl to the root view
      [self.view addSubview:pdfViewCtrl];
    
    }
    
    - (void)didReceiveMemoryWarning
    {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
    }
    
    @end
  5. Run the app.

You can now run the app. If you run in the simulator, you will see the following. Note that the PDF can be scrolled and zoomed.

Part 2: Adding support for Annotations, Text Selection and Form Filling.

PDFNet comes with built-in support for text selection, interactive annotation creation and editing, form filling and link following. These features have been implemented in an open-source project that uses PDFNet’s API. Because the source is provided, implementers have complete flexibility and control to customize how users interact with the PDF so that it can fit their requirements exactly.

To add support for annotations, text selection, etc. you must include the Tools library. As the pre-compiled version of the tools library expects the dynamic PDFNet framework, you must compile a version that does not rely on it.

  1. Open the Tools project, found in Lib/Tools/src/PDFViewCtrlTools/, and change the Scheme to Static - Release.
  2. Compile the project for the simulator or device (whichever you are using).
  3. Add the project’s output, libTools.a, plus tools-strings.bundle which is found at Lib/Tools/src/PDFViewCtrlTools/, to your project.
  4. Add Tool.h, PanTool.h and ToolManager.h files found in Lib/Tools/src/PDFViewCtrlTools/Tools/ to your project.
  5. In the target’s Build Phases, under “Link Binary With Libraries”, add libTools.a, AVKit.framework and AVFoundation.framework.
  6. In the target’s Build Phases, under “Copy Bundle Resources”, add tools-strings.bundle.
  7. Under the Build Settings tab, locate the Library Search Paths entry in the Search Paths section. (You may need to ensure “All” entries are visible, not just the “Basic” ones.) Add the path to the location of libTools.a. (If the path includes spaces, enclose the path in quotes.)
  8. Add #import “Tool.h” and #import “PanTool.h” and #import “ToolManager.h” at the top of ViewController.m
  9. Add the following lines as the last lines of the viewDidLoad selector in ViewController.m
// creates a new tool manager using the designated initializer
ToolManager* toolManager = [[ToolManager alloc] initWithPDFViewCtrl:pdfViewCtrl];
 
// registers the tool manager to receive events
[pdfViewCtrl setToolDelegate:toolManager];
 
// sets the initial tool
[toolManager changeTool:[PanTool class]];

You are now ready to run the project again. Now, when you run the project, you can select text, follow links and create and edit annotation. To create a new annotation, long press on an area of the document to trigger a popup with annotation types to create.

Part 3: Opening encrypted documents.

PDFNet supports opening encrypted PDF documents. To open an encrypted document, all you need to do is initialize a PDFDoc’s security handler with the correct password. Add the following code snippet after creating the PDFDoc in order to display an encrypted PDF.

if( [docToOpen InitStdSecurityHandlerWithPassword:@"password-string" password_sz:0] == NO )
{
  NSLog("Password is incorrect");
  return;
}

Of course a “real” app would require that the password be obtained from the user, which is implemented in the sample viewer that is included with the PDFNet for iOS download.

Part 4: Next Steps

This concludes our introductory PDFNet for iOS Tutorial. For more help, please see the online documentation, sample code, and other tutorials.

Document Collaboration With PDFNet

Introduction

PDFNet makes sharing annotations easy by offering an simple way to import and export annotations. The annotations are saved in a standardized XML format, XFDFThis makes the annotations easy to share across PDFTron’s product line, as well as third-party applications such as Acrobat. The XML annotation files are typically much smaller than a PDF file, making it an ideal format to use when transmitting over a network. The XML format is also well suited for conflict resolution algorithms. This tutorial will demonstrate how to use PDFNet’s APIs to export and import annotations saved in the XFDF format.

Exporting Annotations

The following code snippet shows how to extract annotation data from a PDF, and save it as an XFDF XML file. It is written in Objective-C, but the same API applies for all supported languages.

In Objective-C:

// Create a new PDF Doc
PDFDoc *pdfDoc = [[PDFDoc alloc] initWithFilepath: @"file_with_annotations.pdf"];
[pdfDoc InitSecurityHandler];

// Extract the annotations
FDFDoc *doc_annots = [pdfDoc FDFExtract: e_annots_only];

// This is an optional field that specifies the PDF docuemnt that the FDF file
// was exported from or is intended to be imported into
[doc_annots SetPDFFileName: @"file_with_annotations.pdf"];

// Export the annotations in XFDF format
[doc_annots SaveAsXFDF: @"annotations.xfdf"];

In C#:

// Create a new PDF Doc
PDFDoc in_doc = new PDFDoc("file_with_annotations.pdf");
in_doc.InitSecurityHandler();

// Extract the annotations
FDFDoc doc_annots = in_doc.FDFExtract(PDFDoc.ExtractFlag.e_annots_only);

// This is an optional field that specifies the PDF docuemnt that the FDF file
// was exported from or is intended to be imported into
doc_annots.SetPdfFileName("file_with_annotations.pdf");

// Export the annotations in XFDF format
doc_annots.SaveAsXFDF(output_path + "annotations.xfdf");

Importing Annotations

The following code snippet shows how to import annotations data from an XFDF XML file, and merge them into a PDF file.

In Objective-C:

// load XFDF annotations
FDFDoc *fdfDoc = [FDFDoc CreateFromXFDF: @"annotations.xfdf"];

// load PDF with which to merge the annotations
PDFDoc *pdfDoc = [[PDFDoc alloc] initWithFilepath: @"file_without_annotations.pdf"];
[pdfDoc InitSecurityHandler];

// merge in the annotations
[pdfDoc FDFMerge: fdfDoc];

// save the PDF with the annotations
[pdfDoc SaveToFile: @"file_with_annotations.pdf" flags: e_remove_unused];

[pdfDoc Close];

In C#:

// load XFDF annotations
FDFDoc fdfDoc = new FDFDoc(FDFDoc.CreateFromXFDF("annotations.xfdf"));

// load PDF with which to merge the annotations
PDFDoc pdfDoc = new PDFDoc("file_without_annotations.pdf");
in_doc.InitSecurityHandler();

// merge in the annotations
pdfDoc.FDFMerge(fdfDoc);

// save the PDF with the annotations
pdfDoc.Save("pdfDoc_with_annotations.pdf");

pdfDoc.Close();

XFDF & WebViewer

A nice thing about XFDF is that once annotations are exported to XML they can be easily loaded across all platforms supported by PDFNet (Android, iOS, WinRT, Linux, Mac, etc). Besides PDFNet SDK, the same annotations can be loaded & saved in the WebViewer via CoreControls.AnnotationManager.ImportAnnotations.

The net effect is that a single XML data representation is consistently used across all mobile & desktop platforms as well as the Web.

For more information about XFDF in conjunction with the WebViewer, as well as sample code showing how to implement XFDF processing on the server side, please see section “Processing Annotations and Forms” in WebViewer Developer Guide.