Extraction
OCR - search PDFs and Extract Text
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:
Get started with Server SDK in your language/framework
Add the sample code provided below
To use this feature in production, your license key will need the OCR Package. Trial keys already include this package.
//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2024 by Apryse Software Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------
using System;
using pdftron;
using pdftron.Common;
using pdftron.SDF;
using pdftron.PDF;
namespace OCRTestCS
{
/// <summary>
//---------------------------------------------------------------------------------------
// The following sample illustrates how to use OCR module
//---------------------------------------------------------------------------------------
/// </summary>
class Class1
{
private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
static Class1() {}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
// The first step in every application using PDFNet is to initialize the
// library and set the path to common PDF resources. The library is usually
// initialized only once, but calling Initialize() multiple times is also fine.
PDFNet.Initialize(PDFTronLicense.Key);
// Can optionally set path to the OCR module
PDFNet.AddResourceSearchPath("../../../../../Lib/");
// if the IRIS OCR module is available, will use that instead of the default
bool use_iris = OCRModule.IsIRISModuleAvailable();
if( !OCRModule.IsModuleAvailable() )
{
Console.WriteLine("");
Console.WriteLine("Unable to run OCRTest: Apryse SDK OCR module not available.");
Console.WriteLine("---------------------------------------------------------------");
Console.WriteLine("The OCR module is an optional add-on, available for download");
Console.WriteLine("at https://docs.apryse.com/core/guides/info/modules#ocr-module . If you have already downloaded this");
Console.WriteLine("module, ensure that the SDK is able to find the required files");
Console.WriteLine("using the PDFNet.AddResourceSearchPath() function.");
Console.WriteLine("");
return;
}
// Relative path to the folder containing test files.
string input_path = "../../../../TestFiles/OCR/";
string output_path = "../../../../TestFiles/Output/";
//--------------------------------------------------------------------------------
// Example 1) Process image
try
{
// A) Setup empty destination doc
using (PDFDoc doc = new PDFDoc())
{
// B) Set English as the language of choice
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("eng");
// C) Run OCR on the .png with options
OCRModule.ImageToPDF(doc, input_path + "psychomachia_excerpt.png", opts);
// D) check the result
doc.Save(output_path + "psychomachia_excerpt.pdf", SDFDoc.SaveOptions.e_remove_unused);
Console.WriteLine("Example 1: psychomachia_excerpt.png");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
//--------------------------------------------------------------------------------
// Example 2) Process document using multiple languages
try
{
// A) Setup empty destination doc
using (PDFDoc doc = new PDFDoc())
{
// B) Setup options with multiple target languages, English will always be considered as secondary language
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("deu");
opts.AddLang("fra");
opts.AddLang("eng");
// C) Run OCR on the .jpg with options
OCRModule.ImageToPDF(doc, input_path + "multi_lang.jpg", opts);
// D) check the result
doc.Save(output_path + "multi_lang.pdf", SDFDoc.SaveOptions.e_remove_unused);
Console.WriteLine("Example 2: multi_lang.jpg");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
//--------------------------------------------------------------------------------
// Example 3) Process a .pdf specifying a language - German - and ignore zone comprising a sidebar image
try
{
// A) Open the .pdf document
using (PDFDoc doc = new PDFDoc(input_path + "german_kids_song.pdf"))
{
// B) Setup options with a single language and an ignore zone
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("deu");
RectCollection ignoreZones = new RectCollection();
ignoreZones.AddRect(424, 163, 493, 730);
opts.AddIgnoreZonesForPage(ignoreZones, 1);
// C) Run OCR on the .pdf with options
OCRModule.ProcessPDF(doc, opts);
// D) check the result
doc.Save(output_path + "german_kids_song.pdf", SDFDoc.SaveOptions.e_remove_unused);
Console.WriteLine("Example 3: german_kids_song.pdf");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
//--------------------------------------------------------------------------------
// Example 4) Process multipage tiff with text/ignore zones specified for each page
try
{
// A) Setup empty destination doc
using (PDFDoc doc = new PDFDoc())
{
// B) Setup options with a single language plus text/ignore zones
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("eng");
RectCollection zones = new RectCollection();
// ignore signature box in the first 2 pages
zones.AddRect(1492, 56, 2236, 432);
opts.AddIgnoreZonesForPage(zones, 1);
zones.Clear();
zones.AddRect(1492, 56, 2236, 432);
opts.AddIgnoreZonesForPage(zones, 2);
zones.Clear();
// can use a combination of ignore and text boxes to focus on the page area of interest,
// as ignore boxes are applied first, we remove the arrows before selecting part of the diagram
zones.AddRect(992, 1276, 1368, 1372);
opts.AddIgnoreZonesForPage(zones, 3);
zones.Clear();
// select horizontal BUFFER ZONE sign
zones.AddRect(900, 2384, 1236, 2480);
// select right vertical BUFFER ZONE sign
zones.AddRect(1960, 1976, 2016, 2296);
// select Lot No.
zones.AddRect(696, 1028, 1196, 1128);
// select part of the plan inside the BUFFER ZONE
zones.AddRect(428, 1484, 1784, 2344);
zones.AddRect(948, 1288, 1672, 1476);
opts.AddTextZonesForPage(zones, 3);
// C) Run OCR on the .pdf with options
OCRModule.ImageToPDF(doc, input_path + "bc_environment_protection.tif", opts);
// D) check the result
doc.Save(output_path + "bc_environment_protection.pdf", SDFDoc.SaveOptions.e_remove_unused);
Console.WriteLine("Example 4: bc_environment_protection.tif");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
//--------------------------------------------------------------------------------
// Example 5) Alternative workflow for extracting OCR result JSON, postprocessing (e.g., removing words not in the dictionary or filtering special
// out special characters), and finally applying modified OCR JSON to the source PDF document
try
{
// A) Open the .pdf document
using (PDFDoc doc = new PDFDoc(input_path + "zero_value_test_no_text.pdf"))
{
// B) set English language
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("eng");
// C) Run OCR on the .pdf
string json = OCRModule.GetOCRJsonFromPDF(doc, opts);
// D) Post-processing step (whatever it might be), but we just print JSON here
Console.WriteLine("Have OCR result JSON, re-applying to PDF");
// E) Apply potentially modified OCR JSON to the PDF
OCRModule.ApplyOCRJsonToPDF(doc, json);
// F) check the result
doc.Save(output_path + "zero_value_test_no_text.pdf", SDFDoc.SaveOptions.e_remove_unused);
Console.WriteLine("Example 5: extracting and applying OCR JSON from zero_value_test_no_text.pdf");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
//--------------------------------------------------------------------------------
// Example 6) The postprocessing workflow has also an option of extracting OCR results in XML format, similar to the one used by TextExtractor
try
{
// A) Setup empty destination doc
using (PDFDoc doc = new PDFDoc())
{
// B) set English language
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("eng");
// C) Run OCR on the .tif with default English language, extracting OCR results in XML format. Note that
// in the process we convert the source image into PDF. We reuse this PDF document later to add hidden text layer to it.
string xml = OCRModule.GetOCRXmlFromImage(doc, input_path + "physics.tif", opts);
// D) Post-processing step (whatever it might be), but we just print XML here
Console.WriteLine("Have OCR result XML, re-applying to PDF");
// E) Apply potentially modified OCR XML to the PDF
OCRModule.ApplyOCRXmlToPDF(doc, xml);
// F) check the result
doc.Save(output_path + "physics.pdf", SDFDoc.SaveOptions.e_remove_unused);
Console.WriteLine("Example 6: extracting and applying OCR XML from physics.tif");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
//--------------------------------------------------------------------------------
// Example 7) Check whether a page needs OCR before running it, to avoid unnecessary OCR processing on pages that already contain extractable text
try
{
// lorem_ipsum.pdf already exists in the general TestFiles folder, so it is
// referenced there instead of duplicating it into the OCR-specific TestFiles/OCR folder.
string test_files_path = "../../../../TestFiles/";
// lorem_ipsum.pdf is a scanned document with no extractable text, so it should need OCR.
using (PDFDoc scannedDoc = new PDFDoc(test_files_path + "lorem_ipsum.pdf"))
{
Page scannedPage = scannedDoc.GetPage(1);
// Ask OCRModule whether the page needs OCR. Passing accept_invisible_text as false
// means invisible text (e.g. from a prior OCR pass) is ignored and only visible content
// is considered, while true would treat an existing invisible text layer as sufficient
// to consider the page as not needing OCR.
bool scannedNeedsOCR = OCRModule.PageNeedsOCR(scannedPage, false);
Console.WriteLine("Example 7: page 1 of lorem_ipsum.pdf " + (scannedNeedsOCR ? "needs" : "does not need") + " OCR");
// Only run OCR if it is actually needed
if (scannedNeedsOCR)
{
OCROptions opts = new OCROptions();
if(use_iris) opts.SetOCREngine("iris");
opts.AddLang("eng");
OCRModule.ProcessPDF(scannedDoc, opts);
scannedDoc.Save(output_path + "lorem_ipsum_conditional.pdf", SDFDoc.SaveOptions.e_remove_unused);
}
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
PDFNet.Terminate();
}
}
}