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

Requirements

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

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
Use Handwriting ICR to make searchable PDFs and extract text with Server SDK in Obj-C | Apryse documentation