Handwriting ICR to search PDFs and Extract Text - Obj-C Sample Code

Requirements
View Demo

Sample code shows how to use the Apryse Server OCR module on scanned documents in multiple languages; provided in Python, C++, C# (.Net), Java, Node.js (JavaScript), PHP, Ruby and VB. The OCR module can make searchable PDFs and extract scanned text for further indexing.

Looking for OCR + WebViewer? Check out our OCR - Showcase Sample Code

Learn more about our Server SDK and OCR capabilities.

Implementation steps

To run this sample, you will need:

  1. Get started with Server SDK in your language/framework.
  2. Download ICR Module.
  3. Add the sample code provided below.

To use this feature in production, your license key will need the ICR Package. Trial keys already include this package.

1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2026 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6#import <OBJC/PDFNetOBJC.h>
7#import <Foundation/Foundation.h>
8
9//---------------------------------------------------------------------------------------
10// The Handwriting ICR Module is an optional PDFNet add-on that can be used to extract
11// handwriting from image-based pages and apply them as hidden text.
12//
13// The Apryse SDK Handwriting ICR Module can be downloaded from https://dev.apryse.com/
14//---------------------------------------------------------------------------------------
15
16int main (int argc, const char * argv[])
17{
18 @autoreleasepool {
19
20 // The first step in every application using PDFNet is to initialize the
21 // library. The library is usually initialized only once, but calling
22 // Initialize() multiple times is also fine.
23 [PTPDFNet Initialize: 0];
24 // The location of the Handwriting ICR Module
25 [PTPDFNet AddResourceSearchPath:@"../../../Lib/"];
26
27 // Test if the add-on is installed
28 if (![PTHandwritingICRModule IsModuleAvailable]) {
29 NSLog(@"");
30 NSLog(@"Unable to run HandwritingICRTest: Apryse Handwriting ICR Module");
31 NSLog(@"not available.");
32 NSLog(@"---------------------------------------------------------------");
33 NSLog(@"The Handwriting ICR Module is an optional add-on, available for download");
34 NSLog(@"at https://docs.apryse.com/documentation/core/info/modules/. If you have already");
35 NSLog(@"downloaded this module, ensure that the SDK is able to find the required files");
36 NSLog(@"using the [PDFNet AddResourceSearchPath:] function.");
37 NSLog(@"");
38
39 return 1;
40 }
41
42 NSString *inputPath = @"../../TestFiles/HandwritingICR/";
43 NSString *outputPath = @"../../TestFiles/Output/";
44
45 int ret = 0;
46
47 //--------------------------------------------------------------------------------
48 // Example 1) Process a PDF without specifying options
49 @try {
50 NSLog(@"Example 1: processing icr.pdf");
51
52 // Open the .pdf document
53 PTPDFDoc *doc = [[PTPDFDoc alloc] initWithFilepath: [inputPath stringByAppendingString:@"icr.pdf"]];
54
55 // Run ICR on the .pdf with the default options
56 [PTHandwritingICRModule ProcessPDF: doc options: nil];
57
58 // Save the result with hidden text applied
59 [doc SaveToFile: [outputPath stringByAppendingString: @"icr-simple.pdf"] flags: e_ptlinearized];
60 [doc Close];
61 }
62 @catch (NSException *e) {
63 NSLog(@"Exception: %@ - %@\n", e.name, e.reason);
64 ret = 1;
65 }
66
67 //--------------------------------------------------------------------------------
68 // Example 2) Process a subset of PDF pages
69 @try {
70 NSLog(@"Example 2: processing pages from icr.pdf");
71
72 // Open the .pdf document
73 PTPDFDoc *doc = [[PTPDFDoc alloc] initWithFilepath: [inputPath stringByAppendingString:@"icr.pdf"]];
74
75 // Process handwriting with custom options
76 PTHandwritingICROptions* options = [[PTHandwritingICROptions alloc] init];
77
78 // Optionally, process a subset of pages
79 [options SetPages: @"2-3"];
80
81 // Run ICR on the .pdf
82 [PTHandwritingICRModule ProcessPDF: doc options: options];
83
84 // Save the result with hidden text applied
85 [doc SaveToFile: [outputPath stringByAppendingString: @"icr-pages.pdf"] flags: e_ptlinearized];
86 [doc Close];
87 }
88 @catch (NSException *e) {
89 NSLog(@"Exception: %@ - %@\n", e.name, e.reason);
90 ret = 1;
91 }
92
93 //--------------------------------------------------------------------------------
94 // Example 3) Ignore zones specified for each page
95 @try {
96 NSLog(@"Example 3: processing & ignoring zones");
97
98 // Open the .pdf document
99 PTPDFDoc *doc = [[PTPDFDoc alloc] initWithFilepath: [inputPath stringByAppendingString:@"icr.pdf"]];
100
101 // Process handwriting with custom options
102 PTHandwritingICROptions* options = [[PTHandwritingICROptions alloc] init];
103
104 // Process page 2 by ignoring the signature area on the bottom
105 [options SetPages: @"2"];
106 PTPDFRectCollection* ignore_zones_page2 = [[PTPDFRectCollection alloc] init];
107 // These coordinates are in PDF user space, with the origin at the bottom left corner of the page.
108 // Coordinates rotate with the page, if it has rotation applied.
109 [ignore_zones_page2 AddRect: [[PTPDFRect alloc] initWithX1: 78 y1: 850.1 - 770 x2: 340 y2: 850.1 - 676]];
110 [options AddIgnoreZonesForPage: ignore_zones_page2 page_num: 2];
111
112 // Run ICR on the .pdf
113 [PTHandwritingICRModule ProcessPDF: doc options: options];
114
115 // Save the result with hidden text applied
116 [doc SaveToFile: [outputPath stringByAppendingString: @"icr-ignore.pdf"] flags: e_ptlinearized];
117 [doc Close];
118 }
119 @catch (NSException *e) {
120 NSLog(@"Exception: %@ - %@\n", e.name, e.reason);
121 ret = 1;
122 }
123
124 //--------------------------------------------------------------------------------
125 // Example 4) The postprocessing workflow has also an option of extracting ICR results
126 // in JSON format, similar to the one used by the OCR Module
127 @try {
128 NSLog(@"Example 4: extract & apply");
129
130 // Open the .pdf document
131 PTPDFDoc *doc = [[PTPDFDoc alloc] initWithFilepath: [inputPath stringByAppendingString:@"icr.pdf"]];
132
133 // Extract ICR results in JSON format
134 NSString *json = [PTHandwritingICRModule GetICRJsonFromPDF: doc options: nil];
135 [json writeToFile: [outputPath stringByAppendingString: @"icr-get.json"] atomically:YES encoding:NSUTF8StringEncoding error:nil];
136
137 // Insert your post-processing step (whatever it might be)
138 // ...
139
140 // Apply potentially modified ICR JSON to the PDF
141 [PTHandwritingICRModule ApplyICRJsonToPDF: doc json: json];
142
143 // Save the result with hidden text applied
144 [doc SaveToFile: [outputPath stringByAppendingString: @"icr-get-apply.pdf"] flags: e_ptlinearized];
145 [doc Close];
146 }
147 @catch (NSException *e) {
148 NSLog(@"Exception: %@ - %@\n", e.name, e.reason);
149 ret = 1;
150 }
151
152 NSLog(@"Done.");
153 [PTPDFNet Terminate: 0];
154 return ret;
155 }
156}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales