We're sorry Aspose doesn't work properply without JavaScript enabled.

Free Support Forum - aspose.com

Creating searchable pdfs (ocr)

Hello,

it is possible to ocr text in an existing pdf and create a new pdf with the recognized text so it becomes searchable?

@BSchwab,

You can identify whether the source PDF has only text or also including images. PdfExtractor class helps identify this, please refer to this code help topic: Find whether PDF file contains images or text only

Furthermore, in order to convert non-searchable PDF file (scanned image PDF) to searchable PDF document, please try using following code snippet with Tesseract.

C#

Document doc = new Document("D:/Downloads/input.pdf");
doc.Convert(CallBackGetHocr);
doc.Save("E:/Data/pdf_searchable.pdf");
//********************* CallBackGetHocr method ***********************//
static string CallBackGetHocr(System.Drawing.Image img)
{
    string dir = @"E:\Data\";
    img.Save(dir + "ocrtest.jpg");
    ProcessStartInfo info = new ProcessStartInfo(@"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe");
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.Arguments = @"E:\data\ocrtest.jpg E:\data\out hocr";
    Process p = new Process();
    p.StartInfo = info;
    p.Start();
    p.WaitForExit();
    StreamReader streamReader = new StreamReader(@"E:\data\out.html");
    string text = streamReader.ReadToEnd();
    streamReader.Close();
    return text;
}

Hi, thanks for code snippet. It seems to work … but only for some PDF files.
With PDF files created with Microsoft Word (just with a single picture) nothing happens … why?
See attached file “test.pdf”: test.pdf (26.4 KB)

@BSchwab,

There may an issue with software package Tesseract. You can use Aspose.OCR API to detect the text from images. Please modify the code as follows:
C#

static string CallBackGetHocr(System.Drawing.Image img)
{
    string dataDir = @"C:\Pdf\test701\";
    img.Save(dataDir + "ocrtest.jpg");
    // Initialize an instance of OcrEngine
    Aspose.OCR.OcrEngine ocrEngine = new Aspose.OCR.OcrEngine();

    // Set the Image property by loading the image from file path location or an instance of MemoryStream 
    ocrEngine.Image = Aspose.OCR.ImageStream.FromFile(dataDir + "ocrtest.jpg");

    // Process the image
    ocrEngine.Process();            
    string text = ocrEngine.Text.ToString();
    return text;
}

Hello,
i think there is a problem with the “Convert” method. Using the “test.pdf” the “CallBackGetHocr” Method isnt reached/triggered. So a code modification for the CallBackGetHocr Method does not help.
test.pdf (26.4 KB)

Is the “CallBackGetHocr” the only way to add hocr to a pdf file?

@BSchwab,

Please try the following code example:
C#

string dataDir = @"C:\Pdf\test705\";
Document doc = new Document(dataDir + "test.pdf");

// Create ImagePlacementAbsorber object to perform image placement search
ImagePlacementAbsorber abs = new ImagePlacementAbsorber();
// Accept the absorber for all the pages
doc.Pages[1].Accept(abs);
// Loop through all ImagePlacements, get image and ImagePlacement Properties
ImagePlacement imagePlacement = abs.ImagePlacements[1];
// Get the image using ImagePlacement object
XImage xImage = imagePlacement.Image;
FileStream outputImage = new FileStream(dataDir + "ocrtest.jpg", FileMode.Create);
// Save output image
xImage.Save(outputImage, ImageFormat.Jpeg);
outputImage.Close();

// Initialize an instance of OcrEngine
Aspose.OCR.OcrEngine ocrEngine = new Aspose.OCR.OcrEngine();
// Set the Image property by loading the image from file path location or an instance of MemoryStream 
ocrEngine.Image = Aspose.OCR.ImageStream.FromFile(dataDir + "ocrtest.jpg");

// Process the image
ocrEngine.Process();
string text = ocrEngine.Text.ToString();

// Create RedactionAnnotation instance for specific page region
RedactionAnnotation annot = new RedactionAnnotation(doc.Pages[1], imagePlacement.Rectangle);
annot.FillColor = Aspose.Pdf.Color.White;
annot.BorderColor = Aspose.Pdf.Color.Yellow;
annot.Color = Aspose.Pdf.Color.White;
// Text to be printed on redact annotation
//annot.OverlayText = text;
           
// Add annotation to annotations collection of first page
doc.Pages[1].Annotations.Add(annot);
// Flattens annotation and redacts page contents (i.e. removes text and image
// Under redacted annotation)
annot.Redact();
FloatingBox box = new FloatingBox();

TextFragment fragment = new TextFragment(text);
///fragment.Margin = new MarginInfo(0, 20, 0, 0);
fragment.TextState.HorizontalAlignment = HorizontalAlignment.Justify;

box.Paragraphs.Add(fragment);
//box.Left = imagePlacement.Rectangle.LLX;
doc.Pages[1].Paragraphs.Add(box);
doc.Save(dataDir + "Output.pdf");

This is the output PDF: Output.pdf (21.1 KB)

@BSchwab,

We managed to replicate the XML format error in our environment. We have logged an investigation under the ticket ID PDFNET-44340 in our bug tracking system. We have linked your post to this ticket and will keep you informed regarding any available updates.

Hi,
thanks for the code but the output.pdf looks completly different (see here: compare.jpg (136.6 KB) )
It seems that the original picture is invisible and the recognized text is visible but on the wrong position.

thanks for the ticket id, i’am looking forward to an update.

@BSchwab,

You can formulate the position of floating box on PDF page with rectangle coordinates, page coordinates and page margins. Please modify the code as follows:
C#

FloatingBox box = new FloatingBox();
TextFragment fragment = new TextFragment(text);
fragment.TextState.HorizontalAlignment = HorizontalAlignment.Left;
box.Paragraphs.Add(fragment);
box.Top = doc.Pages[1].Rect.URY - imagePlacement.Rectangle.URY - doc.Pages[1].PageInfo.Margin.Top;
doc.Pages[1].PageInfo.Margin.Left = imagePlacement.Rectangle.LLX;
doc.Pages[1].Paragraphs.Add(box);
doc.Save(dataDir + "Output.pdf");

Thanks for the approach but … i´m sorry, that makes no sense for me.
You cant use it that way in a professional environment. Creating a searchable pdf must not change the layout in any way. ‘Real’ pdf-Files are also much more complex than the “test.pdf”.
I will wait for an update for the ticket.

@BSchwab,

The floating box accepts absolute positioning rather than flow layout (Top left to Bottom right) on the page. As a workaround, Top, Left, Bottom and Right properties can be used to adjust the position of a floating box.

We will let you know once the linked ticket ID PDFNET-44340 is resolved.

Hi, it seems that the problem still persists?

@BSchwab

Thank you for getting back to us.

We are afraid this ticket is still pending for investigations owing to previously logged and critical issues in the queue. It will be scheduled on its due turn. Moreover, we have recorded your concerns and will let you know as soon as some significant updates will be available. We appreciate your patience and comprehension in this regard.

The issues you have found earlier (filed as ) have been fixed in this update. This message was posted using BugNotificationTool from Downloads module by MuzammilKhan

how to do it in java

@rabin.samanta

Please visit Converting non searchable PDF to searchable PDF document for your kind reference.

@Farhan.Raza
thanks

Do you have a C# sample code?

@salemantulsa

In order to convert non-searchable PDF file (scanned image PDF) to searchable PDF document in C#, please try using following code snippet with Tesseract .

C#

Document doc = new Document("D:/Downloads/input.pdf");
doc.Convert(CallBackGetHocr);
doc.Save("E:/Data/pdf_searchable.pdf");
//********************* CallBackGetHocr method ***********************//
static string CallBackGetHocr(System.Drawing.Image img)
{
    string dir = @"E:\Data\";
    img.Save(dir + "ocrtest.jpg");
    ProcessStartInfo info = new ProcessStartInfo(@"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe");
    info.WindowStyle = ProcessWindowStyle.Hidden;
    info.Arguments = @"E:\data\ocrtest.jpg E:\data\out hocr";
    Process p = new Process();
    p.StartInfo = info;
    p.Start();
    p.WaitForExit();
    StreamReader streamReader = new StreamReader(@"E:\data\out.html");
    string text = streamReader.ReadToEnd();
    streamReader.Close();
    return text;
}

How do I do this in VB.net?