Technical FAQs

Question

If you have a copy of ImagXpress, there are cases where calling certain functions will trigger the following message:

"This function is available in another edition of ImagXpress v13.00
control"

What could cause this error?

Answer

This error can occur if ImagXpress Standard Edition is licensed on a system, but you’re trying to call operations that are only available in ImagXpress Professional Edition. So, you will need to ensure you’re using the proper license.

This documentation page specifies the functions that are supported for each edition.

This can also occur if you own both Barcode Xpress and ImagXpress Professional. Barcode Xpress includes ImagXpress Standard Edition, so if you install the ImagXpress Professional license first, and then install Barcode Xpress, the included Standard license will overwrite the Professional license. The resolution in this case is to re-install the ImagXpress license to overwrite Standard with Professional.

Question

I am combining multiple PDF documents together, and I need to create a new bookmark collection, placed at the beginning of the new document. Each bookmark should go to a specific page or section of the new document.
Example structure:

  • Section 1
    • Document 1
  • Section 2
    • Document 2

How might I do this using ImageGear .NET?

Answer

You are adding section dividers to the result document. So, for example, if you are to merge two documents, you might have, say, two sections, each with a single document, like so…

  • Section 1
    • Document 1
  • Section 2
    • Document 2

…The first page will be the first header page, and then the pages of Document 1, then another header page, then the pages of Document 2. So, the first header page is at index 0, the first page of Document 1 is at index 1, the second header is at 1 + firstDocumentPageCount, etc.

The following code demonstrates adding some blank pages to igResultDocument, inserting pages from other ImGearPDFDocuments, and modifying the bookmark tree such that it matches the outline above, with "Section X" pointing to the corresponding divider page and "Document X" pointing to the appropriate starting page number…

// Create new document, add pages
ImGearPDFDocument igResultDocument = new ImGearPDFDocument();
igResultDocument.CreateNewPage((int)ImGearPDFPageNumber.BEFORE_FIRST_PAGE, new ImGearPDFFixedRect(0, 0, 300, 300));
igResultDocument.InsertPages((int)ImGearPDFPageNumber.LAST_PAGE, igFirstDocument, 0, (int)ImGearPDFPageRange.ALL_PAGES, ImGearPDFInsertFlags.DEFAULT);
igResultDocument.CreateNewPage(igFirstDocument.Pages.Count, new ImGearPDFFixedRect(0, 0, 300, 300));
igResultDocument.InsertPages((int)ImGearPDFPageNumber.LAST_PAGE, igSecondDocument, 0, (int)ImGearPDFPageRange.ALL_PAGES, ImGearPDFInsertFlags.DEFAULT);

// Add first Section
ImGearPDFBookmark resultBookmarkTree = igResultDocument.GetBookmark();
resultBookmarkTree.AddNewChild("Section 1");
var child = resultBookmarkTree.GetLastChild();
int targetPageNumber = 0;
setNewDestination(igResultDocument, targetPageNumber, child);

// Add first Document
child.AddNewChild("Document 1");
child = child.GetLastChild();
targetPageNumber = 1;
setNewDestination(igResultDocument, targetPageNumber, child);

// Add second Section
resultBookmarkTree.AddNewChild("Section 2");
child = resultBookmarkTree.GetLastChild();
targetPageNumber = 1 + igFirstDocument.Pages.Count;
setNewDestination(igResultDocument, targetPageNumber, child);

// Add second Document
child.AddNewChild("Document 2");
child = child.GetLastChild();
targetPageNumber = 2 + igFirstDocument.Pages.Count;
setNewDestination(igResultDocument, targetPageNumber, child);

// Save
using (FileStream stream = File.OpenWrite(@"C:\path\here\test.pdf"))
{
    igResultDocument.Save(stream, ImGearSavingFormats.PDF, 0, 0, igResultDocument.Pages.Count, ImGearSavingModes.OVERWRITE);
}

...

private ImGearPDFDestination setNewDestination(ImGearPDFDocument igPdfDocument, int targetPageNumber, ImGearPDFBookmark targetNode)
{
    ImGearPDFAction action = targetNode.GetAction();
    if (action == null)
    {
        action = new ImGearPDFAction(
            igPdfDocument,
            new ImGearPDFDestination(
                igPdfDocument,
                igPdfDocument.Pages[targetPageNumber] as ImGearPDFPage,
                new ImGearPDFAtom("XYZ"),
                new ImGearPDFFixedRect(), 0, targetPageNumber));
        targetNode.SetAction(action);
    }
    return action.GetDestination();
}

(The setNewDestination method is a custom method that abstracts the details of adding the new destination.)

Essentially, the GetBookmark() method will allow you to get an instance representing the root of the bookmark tree, with its children being subtrees themselves. Thus, we can add a new child to an empty tree, then get the last child with GetLastChild(). Then, we can set the action for that node to be a new "GoTo" action that will navigate to the specified destination. Upon save to the file system, this should produce a PDF with the below bookmark structure…

Bookmarks example

Note that you may need to use the native Save method (NOT SaveDocument) described in the product documentation here in order to save a PDF file with the bookmark tree included. Also, you can read more about Actions in the PDF Specification.

Question

I am trying to deploy my ImageGear Pro ActiveX project and am receiving an error stating

The module igPDF18a.ocx failed to load

when registering the igPDF18a.ocx component. Why is this occurring, and how can I register the component correctly?

Answer

To Register your igPDF18a.ocx component you will need to run the following command:

regsvr32 igPDF18a.ocx

If you receive an error stating that the component failed to load, then that likely means that regsvr32 is not finding the necessary dependencies for the PDF component.

The first thing you will want to check is that you have the Microsoft Visual C++ 10.0 CRT (x86) installed on the machine. You can download this from Microsoft’s site here:

https://www.microsoft.com/en-us/download/details.aspx?id=5555

The next thing you will want to check for is the DL100*.dll files. These files should be included in the deployment package generated by the deployment packaging wizard if you included the PDF component when generating the dependencies. These files must be in the same folder as the igPDF18a.ocx component in order to register it.

With those dependencies, you should be able to register the PDF component with regsvr32 without issue.


There’s no easy way around it. We live in a digital world where paper is less and less efficient to manage. Email started the first round of digital transformation, but now our inboxes get flooded with messages making it almost impossible to get the job done on time. Not to mention, the potential security risks if documents are lost or stolen in cyberspace.

So what’s the solution? A simple process automation platform that enables your team to evolve your business process. Now you can stop using outdated methods of the 90s, like passing paper forms from desk-to-desk or using your inbox as your task list, and start operating efficiently. Discover how Docubee can simply automate your forms and processes so you can get back to work.

Fast Form Creator

Forms are a critical piece of most business processes no matter what industry you’re operating in. The fast form creator helps you create reusable digital forms in minutes by automatically finding and placing fields on documents so you don’t waste time manually updating static forms. Why print, scan, and fax paper forms when you can easily create digital assets? With Docubee, you can eliminate manual processes and streamline your document-based workflows.

Dynamic Web Forms

Creation isn’t the only challenge when it comes to forms. Companies need a faster, more accurate way for their customers and employees to complete forms in a mobile world. So why use static PDFs and paper forms that make collecting data tedious and time consuming? Even email, spreadsheets, and chat fall short when it comes to collecting and syncing data to your other systems.
With Docubee’s dynamic web forms, organizations can collect data faster and more accurately with mobile-responsive web forms. Designed to support today’s on-the-go teams, Docubee gives you the freedom to complete tasks from the field, the office, or wherever you need to get the job done.

Process Builder

Having a standard process in place helps every project move from start to finish more efficiently. Many organizations have processes that are undocumented and difficult to duplicate. Wouldn’t it be easier to lay the foundation to allow your business to grow before it gets out of control? With Docubee’s process builder, you can easily map, replicate, and update your business processes with an intuitive, no-code workflow tool.

Give your organization the ability to scale and have more visibility into existing processes. With no custom-coding required, you can create new processes quickly and update them on the fly as your business evolves. Don’t put your company at risk of non-compliance. Standardized processes are the key to taking the guesswork out of completing mission-critical tasks and alleviating your company’s growing pains.

Digital Signatures

Your John Hancock is not what it used to be. Ink and paper are tried and true, but in today’s digital age, there’s a more secure and efficient way to approve official documents. With Docubee’s digital signatures, you can ensure documents get signed and returned quickly from any device. With wet signatures, there’s no audit trail. Not to mention the hassle of printing, scanning, and emailing. With a growing mobile and remote workforce, you can avoid documents getting stalled in the signing process. Don’t wait for the signer to get back to their desk to physically see the hard copy waiting to be signed. Docubee provides legally-binding digital signatures for secure, trackable transactions.

Auto-Merge

Requiring the same data, say your name and address, to be entered over and over again into several forms is just a waste of time. Why make it more difficult than it has to be? Docubee can help you auto-merge your data directly into your form and document templates. Enter it once and your data flows seamlessly across all your forms and your other systems. Eliminate human error and get the right information into the right hands faster. Discover a more efficient way to populate your data with Docubee.

Everyone needs efficient, structured business processes that digitize cumbersome email and paper-based workflows. Add value to your business, boost process efficiency, and empower your team to get work done faster with Docubee. Ready to get started? Schedule a demo today.

The top InsurTech news for 2020? In a post-pandemic world, insurance technology offers “the prescription for safety.” In a world now dominated by worry around what’s currently happening, what will probably happen, and what could suddenly happen under the right (or wrong) circumstances, the agile and adaptable potential of InsurTech offerings paves the way for proactive service delivery that both boosts consumer piece of mind and reduces insurer risk.

For insurance companies to capitalize on evolving market conditions and outpace the competition, data-driven decision making is key. Even more critical is the need to convert critical information from standardized ACORD formats into actionable, accessible data. Here’s how Accusoft’s FormSuite for Structured Forms can help.

The InsurTech Innovation

As noted by research firm PWC, “What used to be a sign of success may not be anymore.” Now, clients want next-day decisions about insurance applications and claims along with detailed descriptions of cost assessments and timelines for action. What does this mean in practice? 

That it’s no longer enough to rely on legacy solutions and applications to get the job done. Instead, companies need applications augmented by next-generation forms processing technology capable of integrating with internal assets while simultaneously delivering the data-driven decision-making inherently tied to quick, accurate, and complete insurance information capture.

Now more than ever, the fundamental value proposition for insurance companies is the ability to disrupt existing functional frameworks with new policies and practices that streamline document processing, improve decision timelines, and secure client data. 

The ACORD Form Challenge

If building better applications was the only challenge facing InsurTech product managers and development teams, companies would have their hands full. There’s also a common form type that can be challenging for automation.

Since 1972, ACORD has been the source of standardized forms for the insurance industry. While these forms are standard, there is nothing standard about their format. Every year, ACORD changes the format of its forms, leaving insurance organizations  with a challenge for automation. 

Despite generalized standardization which sees consistency in the type of data recorded by specific forms — including client information, claim details, and policy requirements — how this data is structured and displayed within the form itself can vary from provider to provider and even agent to agent. Forms used for identical purposes are often close in format, but not quite the same when it comes to placement of critical data. This compels insurance agencies to manually process common forms, in turn increasing both the risk of human error and the time required for completion.

For insurance application developers looking to create applications that can process ACORD forms more efficiently and deliver on customer expectations around speed and accuracy, FormSuite for Structured Forms provides the capability to create a standard form library for easy form recognition and data capture.

The FormSuite Solution: Document Delivery Done Right

FormSuite for Structured Forms can help insurance companies get the best of both worlds. With an Agile framework, this SDK is capable of streamlining the standardization of ACORD-compliant forms with a little help from developers.

Key benefits of this solution include:

  • Complete Forms Recognition Manual data entry and capture both reduces forms processing speed and can introduce the potential for significant errors. Form recognition toolkits allow developers to create form libraries for their users to scan and recognize forms for data capture. In practice, this means developers only need to update the library when a new ACORD form is released to ensure reliable and robust recognition. 
  • Accurate Data Capture With forms continually arriving from multiple sources, document standardization is often lacking. But no matter how forms are scanned into the system — upside down, sideways, or at differing resolutions — FormSuite uses its image cleanup functionality to deliver accurate forms processing.
  • Form Field DetectionFormSuite uses the application’s form library to identify form fields on standard forms and capture the data within each form field.
  • Optical Character RecognitionFrom optical character recognition (OCR) to intelligent character recognition (ICR) and optical mark recognition (OMR), FormSuite offers it all. Advanced OCR ensures your application can easily capture everything from legible hand printed names to check boxes and dollar amounts.
  • Confidence and Accuracy ReportingData confidence matters for insurance documents. If uncertainty about data translates to errors in evaluation or decision-making, the results could be disastrous for ongoing ROI. That’s why FormSuite for Structured Forms generates customized confidence and accuracy values for all data captured. Firms then send all document OCR capture for confidence evaluation; if results meet or exceed confidence thresholds, document processing can continue automatically. If confidence levels are too low, meanwhile, your app can trigger employee review to ensure data entered matches captured results.

Embracing the InsurTech Advantage

Just as other industries have faced significant disruption this year, insurance companies now find themselves at an operational crossroads. While augmenting familiar forms and functions with application overlays offers the potential to improve on existing processes, firms must also build out apps and services capable of delivering accessible, actionable, and accurate ACORD forms data to staff. When they commit to doing this, insurance companies can deliver on the proactive promise of digital-first insurance with policies and processes capable of keeping pace with evolving client expectations.

Ready to improve insurance processes? Discover FormSuite for Structured Forms and deliver on document potential.

developer sitting at computer

Offering product integrations can be one of the easiest ways to expand the feature set of a product without adding loads of time and cost on development resources. Docubee currently has external integrations with Salesforce, Sharepoint, and Brother scanners that we offer to our customers. Internally, we have an integration with Slack that allows our development team to be notified of different events that happen within Docubee. As a team of engineers, we are always looking for new ways that we could possibly use Docubee with other products, and luckily, we usually find some time to prototype out these integrations.

Being an Apple enthusiast myself, one of the first things I wanted to try to integrate Docubee with was Apple HomeKit so I could use Siri to launch workflows. I configured my Apple TV to work with the Home app and was all ready to go. Unfortunately, I quickly found out that HomeKit does not natively support customizations like this. Lucky for me, someone had already come up with a solution to this problem using Homebridge and a node module called homebridge-cmdswitch2.

According to their Github, Homebridge is “a lightweight NodeJS server you can run on your home network that emulates the iOS HomeKit API” and homebridge-cmdswitch2 “allows you to run Command Line Interface (CLI) commands via HomeKit”. After that, the setup was pretty simple to get everything working. I had to create a workflow in Docubee that I wanted to start, configure my Home app to work with Homebridge, and write this config file below. Before I knew it, Siri was launching workflows for me.

{
  "bridge": {
      "name": "Homebridge",
      "username": "CC:22:3D:E3:CE:30",
      "pin": "031-45-154"
  },
  
  "description": "Homebridge Docubee Config",

  "accessories": [],

  "platforms": [{
    "platform": "cmdSwitch2",
    "name": "CMD Switch",
    "switches": [{
      "name" : "Docubee Workflow",
      "on_cmd": "curl -d '{\"wfModelId\":\"ec6e7fc4-1c38-4ebf-8a32-a02ba6721ffe\", \"wfData\": {}}' -H \"Content-Type: application/json\" -X POST {LAUNCH_WORKFLOW_ENDPOINT}",
      "state_cmd": "exit 1",
      "off_cmd": "echo off"
    }]
 }]
}

One of the next integrations I wanted to try to play with was Slack. I mentioned that we already use it internally, but I wanted to see if there was a way that we could make a Slack integration that was useful for an end-user. After creating my own Slack app to play with, I wanted to be able to launch a workflow from Slack as well as send a message back to Slack notifying me that a workflow was launched. To do both of these things, I had to create a handler somewhere to take the callback IDs that Slack would send to our API and do something with them. The finished handler looked like this:

'use strict';
const qs = require('qs');
const request = require('request')

function handleInteractiveMessage(req, res) {
  const task = req.task;
  res.status(200);
  res.end();
  task.log.info({ source: 'slack-connector.handInteractiveMessage' }, qs.parse(req.body));
  const payload = JSON.parse(qs.parse(req.body).payload);
  const responseUrl = payload.response_url;
  const callbackId = payload.callback_id;
  task.log.info({ source: 'slack-connector.handleInteractiveMessage', responseUrl }, 'response url');
  task.log.info({ source: 'slack-connector.handleInteractiveMessage', callbackId }, 'callback id');
  if (payload.callback_id === 'docubee_workflow_start') {
    kickOffWorkflow(task);
  } else if (payload.callback_id === 'handle_workflow_actions' && payload.actions[0].value !== 'redirect') {
    confirmCancelWorkflow(task, responseUrl, payload.actions[0].value);
  } else if (payload.callback_id === 'confirm_cancel_workflow' && payload.actions[0].value !== 'No') {
    cancelWorkflow(task, payload.actions[0].value, responseUrl)
  }
}

function confirmCancelWorkflow(task, responseUrl, wfInstanceId) {
  return new Promise((resolve, reject) => {
    task.log.info({ source: 'slack-connector.confirmCancelWorkflow', wfInstanceId }, 'wf instance id');
    request({
      url: responseUrl,
      method: 'POST',
      json: true,
      body: {
        text: 'Are you sure you want to cancel this workflow?',
        attachments: [
          {
            fallback: 'See what\'s going on!',
            author_name: 'Owner: ntorretti',
            title: 'Confirm Cancel',
            text: 'Please confirm you want to cancel this workflow',
            callback_id: 'confirm_cancel_workflow',
            actions: [
              {
                name: 'action',
                type: 'button',
                text: 'Yes',
                style: '',
                value: wfInstanceId
              },
              {
                name: 'action',
                type: 'button',
                style: '',
                text: 'No',
                value: 'No'
              }
            ]
          }
        ]
      }
    }, (err, response) => {
      if (err) {
        task.log.error({ source: 'slack-connector.confirmCancelWorkflow', err }, 'whoops');
        reject(err);
      } else {
        task.log.info({ source: 'slack-connector.confirmCancelWorkflow', response }, 'response');
        resolve({ status: 'Request successfully sent to callback API endpoint.' });
      }
    });
  });
}

function sendCancelConfirmation(task, responseUrl) {
  return new Promise((resolve, reject) => {
    request({
      url: responseUrl,
      method: 'POST',
      json: true,
      body: {
        text: 'We have successfully cancelled your workflow.',
      }
    }, (err, response) => {
      if (err) {
        task.log.error({ source: 'slack-connector.sendCancelConfirmation', err }, 'whoops');
        reject(err);
      } else {
        task.log.info({ source: 'slack-connector.sendCancelConfirmation', response }, 'response');
        resolve({ status: 'Request successfully sent to callback API endpoint.' });
      }
    });
  });
}

function cancelWorkflow(task, wfInstanceId, responseUrl) {
  return new Promise((resolve, reject) => {
    request({
      headers: { 'content-type': 'application/json' },
      url: {CANCEL_WORKFLOW_ENDPOINT},
      method: 'POST'
    }, (err, response) => {
      if (err) {
        task.log.error({ source: 'slack-connector.cancelWorkflow', err }, 'whoops');
        reject(err);
      } else {
        task.log.info({ source: 'slack-connector.cancelWorkflow', response }, 'yay');
        sendCancelConfirmation(task, responseUrl);
        resolve(response);
      }
    });
  });
}

function kickOffWorkflow(task) {
  return new Promise((resolve, reject) => {
    request({
      headers: { 'content-type': 'application/json' },
      url: {LAUNCH_WORKFLOW_ENDPOINT},
      method: 'POST',
      body: JSON.stringify({
        wfModelId: 'd32aa8ba-f153-46b5-8c62-81d14327c924',
        wfInstanceName: 'Untitled',
        wfData: {
          Originator: 'Natalie Torretti',
          Originator_Email: 'ntorretti@accusoft.com',
          email: 'ntorretti@accusoft.com'
        }
      }),
    }, (err, response) => {
      if (err) {
        task.log.error({ source: 'slack-connector.handleInteractiveMessage', err }, 'whoops');
        reject(err);
      } else {
        task.log.info({ source: 'slack-connector.handleInteractiveMessage', response }, 'yay');
        resolve(response);
      }
    });
  });
}

module.exports.initialize = (params, imports, ready) => {
  const framework = imports['prv-common-service-base'];
  const task = framework.taskLogging.createTask();
  const server = imports.server;

  task.begin('Initializing Slack connector component');

  server.post('/interactiveMessage', handleInteractiveMessage);

  task.log.info({ source: 'slack-connector.initialize' }, 'Slack connector component initialized');
  task.end();
  ready();
};

Slack has some great documentation and really is built to handle these kind of integrations. It was not that much work to get everything configured after I had the connector in place. I still needed one more piece of code on the Docubee end to be able to actually send the message to Slack. That send message function ended up looking like this:

const sendSlackMessage = imports => (task, redirectUrl, workflowInstanceId, message) => {
  return new Promise((resolve, reject) => {
    task.log.info({ source: 'utils.sendSlackMessage' }, 'sending slack message');
    request({
      url: 'https://hooks.slack.com/services/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',
      method: 'POST',
      json: true,
      body: {
        text: JSON.stringify(message),
        attachments: [
          {
            fallback: 'See what\'s going on!',
            author_name: 'Owner: ntorretti',
            title: 'Workflow Actions',
            text: 'Here are some actions you can take!',
            callback_id: 'handle_workflow_actions',
            actions: [
              {
                name: 'action',
                type: 'button',
                text: 'View dashboard',
                style: '',
                value: 'redirect',
                url: {LINK_URL}
              },
              {
                name: 'action',
                type: 'button',
                text: 'Go to workflow',
                style: '',
                value: 'redirect',
                url: redirectUrl
              },
              {
                name: 'action',
                type: 'button',
                style: '',
                text: 'Cancel Workflow',
                value: workflowInstanceId
              }
            ]
          }
        ]
      }
    }, (err, response) => {
      if (err) {
        task.log.error({ source: 'utils.sendSlackMessage', err }, 'whoops');
        reject(err);
      } else {
        task.log.info({ source: 'utils.sendSlackMessage', response }, 'response');
        resolve({ status: 'Request successfully sent to callback API endpoint.' });
      }
    });
  });
}

We called this the send SlackMessage function after the “Start Demo Workflow” was started. This sends a message back to Slack that gives the user a couple different actions that they could take on that message. If a user clicked one of the buttons in the message, a request with a specific callback ID was sent to the slack handler and the appropriate action was taken. The first image below shows how I integrated starting a workflow in Slack and the second image shows the message we sent back to Slack after a workflow was started giving the user different actions they can take.

These are just a few ways that Accusoft’s Docubee can be integrated into your daily routines. Whether it’s starting a workflow with Siri or enabling automated Slack processes, Docubee is built to help you and your organization to find the best way to automate processes.

Natalie Torretti

Natalie Torretti, Software Engineer III

Natalie joined Accusoft as a software engineer in 2016. She started on the eDocr team but has spent the last two and a half years on Docubee development team. Natalie has been a large contributor to the React front-end UI of Docubee and made several enhancements to the back-end microservices as well. She obtained her B.S. in Biobehavioral Health with a Psychology minor from Penn State as well as her A.S.T. in Information Technology from South Hills School of Business and Technology. When Natalie is not writing code she enjoys working out, spending time at the pool, and playing with her dogs.

Question

What browsers are supported by Accusoft PDF Viewer?

Answer
  • Windows: All chromium based browsers such as Microsoft Edge and Google Chrome.
  • Mac: Safari
  • iOS: Native Safari Browser
  • Android: Native Chrome Browser

InsurTech SDK

The insurance market is booming. As noted by research firm Deloitte, the property and casualty (P&C) sector saw a massive income uptick in 2018 and steady growth last year that’s predicted to carry forward through 2020. To help manage the influx of new clients and handle more claims, many firms are spending on insurance technology (insurtech) — digital services and solutions that make it possible to reduce error rates and enhance operational efficiency. InsurTech SDKs are important components of this transformation.

Both in-house insurtech solutions and third-party platforms often excel in specific areas but come up short in others, putting insurance firms at risk of writing off potential gains. While solution switching and ground-floor rebuilds offer one route to success, there’s another option that’s more custom to your business needs: software development kits (SDKs). Here’s a look at three top SDKs that offer customized functionality potential.


FormSuite for Structured Forms: Solving for Data Capture

Time is money. The faster insurance companies accurately complete and file documents, the greater their revenue potential. And as noted by KPMG, the need for speed is more pressing than ever. Many insurance sectors have seen substantial increases in both claims and new applications as the COVID-19 crisis evolves. 

As a result, accurate and agile forms processing is critical to keep up with demand. If current insurance software can’t quickly capture forms data, recognize standard form fields, and let users easily create standard form libraries, policy processing falls behind.

FormSuite for Structured Forms makes it easy for developers to build in form identification and data capture that includes comprehensive form field detection with OCR, ICR, and OMR functionality and the ability to automatically identify scanned forms and match them to existing templates.

ImageGear for .NET and C/C++: Simplifying Conversion

Conversion is critical for insurance firms. Depending on the type and complexity of insurance claims, companies are often dealing with everything from Word documents for initial client assessments and .GIF or .JPG images of existing damage to contractor-specific PDFs or spreadsheets that detail necessary materials, time, and labor costs. The result? A mash-up of multiple file types that forces adjusters to spend valuable time searching for specific data instead of helping clients get their claims process up and running. This makes it difficult to recognize value from emerging digital initiatives. 

Accusoft’s ImageGear for .NET and ImageGear for C/C++ empower developers to integrate enterprise-class file viewing, annotation, conversion, and image processing functions into existing applications, allowing staff to both quickly collaborate on key tasks and find essential data across a single, easy-to-search document.

 


ImageGear: Streamlining PDF Capabilities

While insurance technology offers substantive opportunities for end-users to capture, convert, and retain data, this technology can also come with the challenge of increased complexity. According to recent research from PWC, for example, firms looking to capitalize on insurtech potential must be prepared to rapidly develop new product offerings and embrace the expectations

As a result, companies need applications that streamline current functions and allow them to focus on creating cutting-edge solutions. For example, PDF is a file format that is still used by enterprises worldwide to maintain document format consistency and maximize security. When it comes to converting multiple files into a PDF, software can be expensive and introduce data security issues. 

This can all be solved with an SDK like ImageGear, which makes it possible to integrate the total PDF package into any document management application, both reducing overall complexity and freeing up time for staff to work on new insurance initiatives.

Insurtech forms the framework of functional futures in policy applications, claims processing, and compliance reporting, but existing software systems may not provide the complete capability set companies need to make the most of digital deployments. These top SDKs offer insurance IT teams the ability to integrate key services, improve speed, and boost security at scale. Learn more about Accusoft’s SDKs at www.accusoft.com/products

Question

I am trying to perform OCR on a PDF created from a scanned document. I need to rasterize the PDF page before importing the page into the recognition engine. When rasterizing the PDF page I want to set the bit depth of the generated page to be equal to the bit depth of the embedded image so I may use better compression methods for 1-bit and 8-bit images.

ImGearPDFPage.DIB.BitDepth will always return 24 for the bit depth of a PDF. Is there a way to detect the bit depth based on the PDF’s embedded content?

Answer

To do this:

  1. Use the ImGearPDFPage.GetContent() function to get the elements stored in the PDF page.
  2. Then loop through these elements and check if they are of the type ImGearPDEImage.
  3. Convert the image to an ImGearPage and find it’s bit depth.
  4. Use the highest bit depth detected from the images as the bit depth when rasterizing the page.

The code below demonstrates how to do detect the bit depth of a PDF page for all pages in a PDF document, perform OCR, and save the output while using compression.

private static void Recognize(ImGearRecognition engine, string sourceFile, ImGearPDFDocument doc)
    {
        using (ImGearPDFDocument outDoc = new ImGearPDFDocument())
        {
            // Import pages
            foreach (ImGearPDFPage pdfPage in doc.Pages)
            {
                int highestBitDepth = 0;
                ImGearPDEContent pdeContent = pdfPage.GetContent();
                int contentLength = pdeContent.ElementCount;
                for (int i = 0; i < contentLength; i++)
                {
                    ImGearPDEElement el = pdeContent.GetElement(i);
                    if (el is ImGearPDEImage)
                    {
                        //create an imGearPage from the embedded image and find its bit depth
                        int bitDepth = (el as ImGearPDEImage).ToImGearPage().DIB.BitDepth; 
                        if (bitDepth > highestBitDepth)
                        {
                            highestBitDepth = bitDepth;
                        }
                    }
                }
                if(highestBitDepth == 0)
                {
                    //if no images found in document or the images are embedded deeper in containers we set to a default bitDepth of 24 to be safe
                    highestBitDepth = 24;
                }
                ImGearRasterPage rasterPage = pdfPage.Rasterize(highestBitDepth, 200, 200);
                using (ImGearRecPage recogPage = engine.ImportPage(rasterPage))
                {
                    recogPage.Image.Preprocess();
                    recogPage.Recognize();
                    ImGearRecPDFOutputOptions options = new ImGearRecPDFOutputOptions() { VisibleImage = true, VisibleText = false, OptimizeForPdfa = true, ImageCompression = ImGearCompressions.AUTO, UseUnicodeText = false };
                    recogPage.CreatePDFPage(outDoc, options);
                }
            }
            outDoc.SaveCompressed(sourceFile + ".result.pdf");
        }
    }

For the compression type, I would recommend setting it to AUTO. AUTO will set the compression type depending on the image’s bit depth. The compression types that AUTO uses for each bit depth are: 

  • 1 Bit Per Pixel – ImGearCompressions.CCITT_G4
  • 8 Bits Per Pixel – ImGearCompressions.DEFLATE
  • 24 Bits Per Pixel – ImGearCompressions.JPEG

Disclaimer: This may not work for all PDF documents due to some PDF’s structure. If you’re unfamiliar with how PDF content is structured, we have an explanation in our documentation. The above implementation of this only checks one layer into the PDF, so if there were containers that had images embedded in them, then it will not detect them.

However, this should work for documents created by scanners, as the scanned image should be embedded in the first PDF layer. If you have more complex documents, you could write a recursive function that goes through the layers of the PDF to find the images.

The above code will set the bit depth to 24 if it wasn’t able to detect any images in the first layer, just to be on the safe side.