Technical FAQs for "SDK"

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

In some cases, when the Server Licensing Utility (SLU) is run, it may return an error similar to the following:

"Server License Utility – Auto register failed

Failed to auto-register. Extra code
#0100-20(RCN=Accusoft.ULF.LicenseService.GenerateLicenseKey,
RC=-56, REC=428). Contact Accusoft support. Error #1"

If, on the other hand, you manually register, you might see a message such as this:

An error has occurred: object (Accusoft.ULF.LicenseService.GenerateLicenseKey), value1 (-56), value2 (429)

What could be the cause?

Answer

A possible cause for this error is if you have a license with an expiration date and you have not specified the Access Key in the field on the SLU main window. Since these particular keys expire, our licensing needs to know which specific Access Key to use to differentiate it from any other licenses you may have with different expiration dates or OEM licenses. So, supplying the Access Key will point the license utility to the specific license in the license pool, and should resolve this error.

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.

Question

During the installation of ImageGear for .NET (v23.4 and above), the installer reaches out to Microsoft’s site to download the VC++ redistributable and .NET packages. Which one(s) does it download?

Answer

The ImageGear for .NET installer places the following redistributables onto a system:

In addition to this, the following .NET framework versions are installed:

  • Microsoft .NET Framework 2.x
  • Microsoft .NET Framework 3.0
  • Microsoft .NET Framework 3.5
  • Microsoft .NET Framework 4.0

So, if a system already has all of these installed on it, this should prevent the installer from trying to reach out to download them.

Question

In FormSuite for Invoices, what are the accepted characters for the Currency and CurrencyPlus field data types?

Answer

Note: FSI assumes that currency values are United States values. It normalizes fields that are marked as Currency (not CurrencyPlus), any punctuation (except negative and decimal).

The Currency and CurrencyPlus formats are used in the FSI recognition to help determine currency values on the page.

The Currency value is of the form

dd¢

[$|€|£|¥]ddd[\{separator}ddd][\{decimal}dd][-|=][ €]

The CurrencyPlus value is of the form

dd¢

[$|€|£|¥|E|EUR]ddd[\{separator}ddd][\{decimal}dd][-|=][ €| E|EUR|DKK|DKR|NOK|NKR|SEK|SK|GBP|KR|USD]

Where separator “,” and decimal “.” Or separator “.” and decimal “,”

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.

Question

The logging for ImageGear C & C++ Deployment Packaging Wizard (DPW) is showing different output for some components since v19.3, why is this?

In ImageGear C & C++ v19.2 and prior, the DPW had additional logging information for the ARTX component in its deployment.log:

Deploying an application that uses the ARTXGUI library of ImageGear
ARTX Component requires the following merge modules to be installed:

Microsoft_VC90_CRT_x86_x64.msm

Microsoft_VC90_MFC_x86_x64.msm

But since v19.3, the logs are no longer telling me to install these modules. Is this a mistake, or are they no longer necessary?

Answer

This was an intentional change on our end, and the Deployment Packaging Wizard (DPW) is working as intended. We made some updates to the DPW in the latest release; one update is that the CRM requirements for CORE (which is required in every project) now also covers the ARTX component. If the DPW is not saying you need additional components to use the ARTX component, then you’ll be fine.

Question

Is the main FormSuite for Invoices (FSI) process multithreaded? If so, would more cores or more CPU’s increase the performance?

Answer

Internally, we do multi-threading where we can at the beginning of the process. Improving your hardware will help if you are doing multiple pages at once, otherwise it will not. FormSuite for Invoices is thread-safe as long as each thread owns the FSI object being used. 

Please see: https://help.accusoft.com/FSInvoices/v2.1/dotnet/webframe.html#topic5.html

Question

When using OCR in ImageGear .NET, is there any way to distinguish between a capital/uppercase letter O and the number 0?

Answer

Not without context or a font that makes the difference clear (such as one with a slashed 0). ImageGear will properly recognize Oliver and 1530 as containing O and 0, respectively, but cannot reliably distinguish it when letters and numbers are mixed. That is, ImageGear may not reliably distinguish between 1ABO0F3 and 1AB0OF3.

Question

I encounter an Unhandled Exception error, as shown below, in ImageGear when trying to load a page into the recognition engine.

Error Message: An unhandled exception of type
‘ImageGear.Core.ImGearException’ occurred in ImageGear22.Core.dll

Additional information: IMG_DPI_WARN (0x4C711): Non-supported
resolution. Value1:0x4C711

What is causing this and how can I fix it?

Answer

This is probably because the original image used to create the page didn’t have a Resolution Unit set.

Resolution unit not set in original image

To fix this, check if the page has a Resolution Unit set. If it does not, set it to inches. You should also set the DPI of the image as those values were probably not carried over from the original image since the Resolution Unit wasn’t set. The following code demonstrates how to do this.

// Open file and load page.
using (var inStream = new FileStream(@"C:\Path\To\InputImage.jpg", FileMode.Open, FileAccess.Read, FileShare.Read))
{
    // Load first page.
    ImGearPage igPage = ImGearFileFormats.LoadPage(inStream, firstPage);

    if (igPage.DIB.ImageResolution.Units == ImGearResolutionUnits.NO_ABS)
    {
        igPage.DIB.ImageResolution.Units = ImGearResolutionUnits.INCHES;
        igPage.DIB.ImageResolution.XNumerator = 300;
        igPage.DIB.ImageResolution.XDenominator = 1;
        igPage.DIB.ImageResolution.YNumerator = 300;
        igPage.DIB.ImageResolution.YDenominator = 1;
    }

    using (var outStream = new FileStream(@"C:\Path\To\OutputImage.jpg", FileMode.OpenOrCreate, FileAccess.ReadWrite))
    {
        // Import the page into the recognition engine.
        using (ImGearRecPage recognitionPage = recognitionEngine.ImportPage((ImGearRasterPage)igPage))
        {
            // Preprocess the page.
            recognitionPage.Image.Preprocess();

            // Perform recognition.
            recognitionPage.Recognize();

            // Write the page to the output file.
            recognitionEngine.OutputManager.DirectTextFormat = ImGearRecDirectTextFormat.SimpleText;
            recognitionEngine.OutputManager.WriteDirectText(recognitionPage, outStream);
        }
    }
}
Question

For ImageGear .NET, what are the feature differences between an OCR Standard license, an OCR Plus license, and an OCR Asian license?

https://www.accusoft.com/products/imagegear-collection/imagegear-dot-net/#pricing

Answer

ImageGear’s OCR library has three different functionality options that you can choose for your website or application. The primary difference between the three options is the output formats created by the OCR engine. The options for your development are as follows:

  1. OCR Standard:
    The standard edition creates output formats for Western languages such as English. The standard edition outputs text only files and generates a PDF. The file formats it includes are searchable text PDFs and text documents.

  2. OCR Plus:
    The standard plus edition creates formatted outputs for Western languages like English. The formatted output is created with recognition technology that identifies font detail, locates image zones, and recognizes table structure in order to create a representation of the original document. The file formats it includes are Word, Excel, HTML, searchable PDF, and text documents.

  3. OCR Asian:
    The Asian edition creates a formatted output for Asian languages like Chinese, Japanese, and Korean. This formatted output is created with the same recognition technology as the Standard Plus that identifies font detail, locates image zones, and recognizes table structure. It also creates a representation of the original file. Formats include Word, Excel, HTML, searchable PDF, and text documents.

Question

Using ScanFix Xpress (as illustrated in the ImageCleanUp sample) I can deskew an image, but the leftover blank space is filled with a user-specified pad color, which might clash horribly with the edges of the original image. Is it possible to automatically detect a matching pad color before executing a deskew operation?

Answer

A simple approach would be to crop off the four edges of the image, specified perhaps by a percentage of width/height floor-bound by a minimum pixel count, then use the RGBColorCount method from ImagXpress on each edge to generate a histogram for each color channel, find the most frequent or average intensity (or some combination of the most frequent and the average), and then find the average intensity among all four edges. Then this resultant color could be used as the pad color for the image when it is deskewed.

For example, you can crop out portions of an image using the Crop method of the Processor class…

// Crop out the top edge of the image referred to by proc.Image
Rectangle cropRectangle = new Rectangle(0, 0, inputImg.Width, verticalSliceSize);
_processor.Crop(cropRectangle);
return proc.Image;

We can do this for all four edges of the image. Then, for each edge, we can determine the frequencies at which each intensity occurs in the image’s pixel grid using the RGBColorCount Method…

int[] redHistogram, greenHistogram, blueHistogram;
_processor.Image = edge;
_processor.RGBColorCount(out redHistogram, out greenHistogram, out blueHistogram);

…now, redHistogram, greenHistogram, and blueHistogram will contain the frequencies of red, green, and blue intensities (0 to 255), respectively. We can use this data to extrapolate either the most frequent or the average intensity (or some combination of the two) in each channel. We can then construct RGB triplets representing the detected border color for that edge, and then average the values for each edge to get the appropriate overall pad color. 

For example (using an average intensity)…

public int[] DetectEdgeAverageColor(ImageX edge)
{
    int[] averageRGB = new int[] { 0, 0, 0 };
    int[] redHistogram, greenHistogram, blueHistogram;
    _processor.Image = edge;
    _processor.RGBColorCount(out redHistogram, out greenHistogram, out blueHistogram);

    int numPixels = edge.Width * edge.Height;
    averageRGB[0] = findAverageIntensity(redHistogram, numPixels);
    averageRGB[1] = findAverageIntensity(greenHistogram, numPixels);
    averageRGB[2] = findAverageIntensity(blueHistogram, numPixels);
    

    return averageRGB;
}

private int findAverageIntensity(int[] frequencies, int numPixels)
{
    double averageIntesntity = 0;
    for (int intensityValue = 0; intensityValue < 256; intensityValue++)
    {
        int frequencyOfThisIntesity = frequencies[intensityValue];
        averageIntesntity += (intensityValue * frequencyOfThisIntesity);
    }
    averageIntesntity /= numPixels;
    return (int)Math.Round(averageIntesntity);
}

This should produce an RGB triplet representing a color similar to the edges of the image to be deskewed.