A fast, modern and generic image processing library
In the mid-2000s we were wondering about the ridiculous amounts of CPU cycles ImageMagick spent on certain image processing tasks. After the first code review it became clear that imagemagick was coded for anything but speed.
We prototyped the needed code in C++, just for speed, and achieved processing times about 1/20th of what ImageMagick consumed.
In the library we also will experiment and explore several new algorithms, e.g. for de-screening, data-dependant triangulation scaling, lossless JPEG transforms and others as we see need. You are very much welcome to contribute thrilling state-of-the-art algorithms.
The included codecs take C++ STL std::istreams and std::ostreams allowing library users to implement their own data sources and destinations, such as in memory locations or network transfers.
It is intended to become a modern, generic (template) based C++ library, as time permits. - Hopefully a viable alternative to ImageMagick.
Since the 0.8 release series comes with support for multiple images per file, e.g. in the TIFF codec and econvert command line front-end.
Since the 0.7 release series ExactImage comes with even more image codecs, and support to completely synthesize, that is create images from scratch and work with vector paths thru the external API.
Since the 0.6 release series ExactImage comes with a completely rewritten PDF codec, which is not only capable of dumping image data into a PDF container, but offers complete support for arbitrary vector data, vector font writing support as well as multi-page documents. Based on the new PDF codec a new command line front-end named "hocr2pdf" is included which allows creating searchable PDFs out of hOCR annotated HTML as obtained from some OCR engines.
Since the 0.5 release series ExactImage comes with the first open-source, GPL, barcode recognition support ever, an additional, high-performance image pixel iteration, code generation facility was added, providing an additional speed boost over the former, pre-0.5 Image iteration implementation. All algorithms converted to the new iterator can profit from up to 10x acceleration. Support for writing non-RGB BMP files, as well as EPS, PS and PDF files and rendering some SVG files was added. Additionally, language bindings for PHP, Python and Lua can be generated by the build system (pre-0.5 only a Perl bindings was generated).
Since the 0.4 release series ExactImage supports drawing vector graphic thru the Anti Grain Geometry rendering engine as well as image segmentation and fuzzy image pattern matching.
Since the 0.3 release series ExactImage supports per-codec acceleration of rotation, flipping, scaling and color-space conversion (for JPEG, ala jpegtran) as well as on-demand decoding.
Since the 0.2 release series ExactImage comes with a stable, simple and easy to use external API including SWIG support, thus allowing the use out of any SWIG supported scripting language, such as Perl, PHP, Python, Ruby or LUA.
Support, commercial licensing & custom development
Please contact us for support, commercial licenses of our barcode recognition framework, or to develop custom solution - for example additional code types - for your needs.
Image conversion and processing
Is a command line frontend for the image processing library and mimicks Imagemagick's convert. However since some aspects of the convert arguments are too limited (e.g. even now we have two ditherizers to select from) or annoying (colorspace conversion is quite unintuitive to control with Imagemagick and the data is often blown up to an more generic colorspace) the econvert syntax never will be 1:1 compatible with convert. Also because those options only start with one dash (-) ... or are named density rather than resolution and so on.
First image data must be read using -i or --input, processing routines are selected by their name with two leading dashes (e.g. --rotate) and at any point the data might be written into a file with -o or --output, for example:
econvert -i lenea.tiff --box-scale 0.5 -o medium.png --box-scale 0.5 -o little.png
Since version 0.3 the library tries to delay image decoding as much as possible and provides lossless and accelerated algorithms to work on compressed data (such as JPEGs) directly:
econvert -i AV220-Scan.JPG --resolution 300x300 -o 1.jpg --rotate 90 -o 2.jpg --rotate 180 -o 3.jpg --rotate -90 -o 4.jpg --flip -o 5.jpg --flop -o 6.jpg --scale 0.25 -o thumb.jpg
In this example 1.jpg will be created from the original JPEG DCT coefficients, those coefficients will be rearranged and 2.jpg, 3.jpg, 4.jpg, 5.jpg and 6.jpg will be written without any additional loss in precision (no new JPEG artefacts) and with outstanding speed. Only at the end, for image thumb.jpg, the DCT will actually be decoded - but due to the accelerated JPEG scaling only partially! The whole chain of operations applied to an 8 bit RGB JPEG only takes 0.99s on 2GHz Intel Core2.
For a detailed list of available procesing options please refer to the tool's help (-h, --help).
CMYK support YUV support ICC color calibration EXIF support XMP support
Tips & Tricks
Thumbnails of black and white (bi-level) images
When 1 bit, black and white, images are scaled down the output often might look pretty awful. The box scaling algorithm usually does a pretty good job thumbnailing b/w images, however as the ExactImage algorithms always operate in the color-space the image data is stored in the colorspace must be changed (e.g. to 8 bit gray) before applying the box scaler. At the end the result might be converted back to just a few shades of gray such as 2 or 4 bit: econvert -i avision-bw-scan.pbm --colorspace gray8 --box-scale 0.125 --colorspace gray2 -o thumb.png
Slightly faster JPEG down-scaling
As outlined in the lossless JPEG page, ExactImage is slightly slower than EPEG, though with noticeable higher output quality. If you do not care about quality, only about bare thruput (maybe in an web application?) you can force nearest neighbor scaling by just specifing a scale factor the JPEG decoder can accellerate (1/2, 1/4, or 1/8) and apply the remaining scalling manually. To archive a faster scaling with the effective factor 0.33: econvert -i big.jpg --scale .5 --nearest-scale 0.66 -o thumb.jpg
Working with digital camera RAW data
Digital still camera raw images differ from model to model and are sometimes even obfuscated to prevent loading by third parties. However, ExactImage supports a wide range of RAW formats thanks to the embedded dcraw code (we had to embed a copy of dcraw as the orignal project is only available as a command line program and not in form of a library - ExactImage needs to have some more control about how the image data is passed around, e.g. in memory and not by pipes).
Usually decoding of RAW data should be transparent and automatic, however some formats also are valid TIFF files and the embedded thumbnail might be picked by ExactImage's TIFF support in favour of the actual RAW content. This this cases the dcraw backend decoder can explicitly be request with the decoder prefix of the input parameter: econvert -i dcraw:img_0123.cr2 ...
As of version 0.6.5 ExactImage also allows to quickly extract the embedded thumbnail preview, if any, by specifing "thumb"(nail) as decompress argument before the image is loaded: econvert --decompress thumb -i dcraw:img_0123.cr2 ...
This usually just takes parts of a second and is useful to generate previews, galleries, etc.
Loading real raw data
While working on algorithms, dumping frame-buffer content or doing low-level driver development it often is handy to also load arbitrary RAW pixel data. Via the "raw:" codec specification this is possible in econvert. As econvert does use the current color-depth (colorspace) and size for the raw data they have to be specified before loading the image like this: econvert --size 1696x32 --colorspace rgb8 -i raw:data-file ...
Loads the specified images, one by one, and displays them on a X-server (or other display device if the minimal abstracted needed is added).
In the top-left corner a tiny, shaded on-screend-display shows the current cursor position as well as the color value of the pixel.
For images including an alpha channel a checkboard is displayed in the background.
The default key and mouse bindings are:
space, backspace: go thru the list of specified images arrow keys, page up/down, left mouse button and mouse-wheel: image panning +, -, Ctrl-mouse-wheel: zooming tab, shift-tab: cycling thru the image channels as color dropout and intensity maps 1: reset zoom to 1:1 a: toggle anti-aliasing <, >: counter-clockwise and clockwise orthogonal rotation q: quit application
Lua shell for on-the-fly algorithm design direct OpenGL output more efficient image loading, e.g. not load the whole image into an Evas canvas but partially on-demand (to support GB sized images)
Is a command line frontend for the image processing library and mimicks Imagemagick's identify.
Edentify is used to identify images, that is print the codec, pixel dimensions, resolution and physical sizes (if any resolution is specified in the image data) as well as the color space.
edentify lenea.tiff lenea.tiff: TIFF 512x512 24 bits, 3 channels
It is also supported to specify a identify a-like custom format string (-f, --format) - for a detailed list of available procesing options please refer to the tool's help (-h, --help).
Verbose output (historgram et al.)
Creating a Searchable PDF from hOCR input
Is a command line front-end for the image processing library to create perfectly layouted, searchable PDF files from hOCR, annotated HTML, input obtained from an OCR system.
hOCR, annotated HTML, input must be provided to STDIN, and the image data is read using the filename from the -i or --input argument. For example:
hocr2pdf -i scan.tiff -o test.pdf < cuneiform-out.hocr
By default the text layer is hidden by the real image data. Including image data can be disabled via the -n, --no-image, so that just the recognized text from the OCR is visible - e.g. for debugging or to save storage space:
hocr2pdf -i scan.tiff -n -o test.pdf < cuneiform-out.hocr
Tips & Tricks
Too many gabs between letters in individual words
This might be a problem with imprecise OCR data or justified text with huge gabs. ExactImage includes a special mode activated with the command line argument -s, --sloppy-text, to group glyphs between whitespace to words which can help PDF viewers to produce better results while cut and pasting text:
hocr2pdf -i scan.tiff -s -o test.pdf < cuneiform-out.hocr
Supported image formats
ExactImage currently already supports most wide-spread image formats. We plan to add at least one new format with each major version release:
BMP: internal C++ library in absence of an external one Digital Camera RAW: via incooperated dcraw code, might use libopenraw in the future GIF: via libungif JPEG: via libjpeg, including lossless transformations JPEG2000: via jasper, might use openjpeg in the future OpenEXR: via the official libOpenEXR PNG: via libpng PBM: internal C++ code as netpbm does not support arbitrary source and destination RAW: internal C++ code to be able to decode in-memory RAW data TIFF: via libtiff and it's C++ binding XPM: internal C++ code SVG: internal C++ code via Agg, read-only PDF: internal C++ code, write-only, allows embedding JPEG and JPEG2000, as well as vector geometry & fonts and write multiple pages PS: internal C++ code, write-only, allows embedding JPEG EPS: internal C++ code, write-only, allows embedding JPEG PCX: internal C++ code Targa, TGA: internal C++ code
Next to implement
PS: rendering / rasterizer PDF: rendering / rasterizer PCL: rendering / rasterizer TIFF: jpeg embedding BMP: jpeg / PNG embedding Apple Icon Image Windows Icon Image file format JBIG Fax files sgi Sun DJVU HVIF - Haiku Vector Icon Format ...
If you miss a format important for you do not hesitate to contact us.
Stable, SWIG exported API
Since version 0.2 ExactImage includes script binding generated through SWIG. This API is supposed to be stable and if changes are done backward compatibility is guaranteed to be preserved.
We decided to be that strong with the external API stability even in this early stage of development, because ever changing APIs just annoy any serious programmer away and ExactImage is deployed in production solutions by partner companies.
Incrementally over version 0.3, and 0.4 the external API was extended with functionality as required by partner companies and build for the Perl language by default.
Since version 0.5 ExactImage comes with built-in support to generate not only the Perl, but additionally PHP, Python and Lua laguange bindings - if the specific language support is detected and requested during configuration.
In the future we will provide API documentation at this place as well as in-depth introduction and examples.
The JPEG format is based on the Discrete Cosine Transform (DCT) performed on equally sized blocks of the pixel image data. With this in mind one can conclude that it is possible to perform some transformations on the image data directly on these DCT coefficients by just moving and transforming the coefficients.
As just working on the DCT coefficients is less expensive (in terms of CPU cycles) as the decoding and re-encoding process is skipped, it saving a lot time and additionally prevents new compression artefacts.
Lossless JPEG transformations where first implemented in the Open Source jpegtran program - a companion application of the JPEG library, but as using a different tool or library for every image format is a bit unhandy. Support for these transformations based on the jpegtran code was added to ExactImage version 0.3.0.
ExactImage 0.3.0 supports lossless: orthogonal rotations (90, 180, 270 degree) flipping the image data on the X and Y axis ExactImage 0.3.1 further introduced: fast color image to gray conversion fast down-scaling by partial decoding DCT coefficients ExactImage 0.4.1 further introduced: cropping
Common with all this operations is that they are way faster than performing the pixel-level algorithm on the decoded image data and (aside down-scaling) do not introduce new artefacts.
Fast down-scaling is also implemented by Enlightenment's EPEG library explicitly and we should mention that EPEG is slightly faster, but with cost to image quality - mostly because it does just nearest neighbor scaling of the residual scaling applied on top of the partial DCT decoding:
(A trick how to get a few percent faster down-scaling is outlined in the econvert Tips & Tricks section.)
Due the lack of open source, cross platform and high quality barcode recognition offerings, ExactCODE developed an own, portable barcode recognition framework targeting highest recognition accuracy and fast processing. To our knowledge ExactImage comes with the first (production quality) open source barcode recognition support ever.
The following are real-world example images, selected from production systems to demonstrate some challenges:
This example shows overlapping dot matrix printed barcodes as used by a German postal service. Not only are gaps in the code resulting from the rather huge dots compensated, even partial overlapping does usually not pose a problem.
For processing by ExactImage's barcode recognition the barcodes also neither have to be pure black and white. This example shows a segment-wise skew'ed barcode printed by an unaligned dot-matrix printer, in blue on yellow. Again from a real-world delivery note.
Using the command line frontend
Even in low contrast images - here due to a rather saturated, dark background - the ExactImage library can still separate the barcode from the background. This also clearly shows that barcode recognition is not just a matter of simply searching for pure, back and white areas.
Another example of the outstanding recognition accuracy is this heavily, non-linear distorted code on a shrinked down plastic tube that the ExactImage barcode recognition library is still able to recognize.
bardecode files/* files/1.tif: XDM152EU-U [type: code39 at: (1094,392)] files/2.tif: 471186080198 [type: ean13 at: (1148,32)] files/3.tif: 06396500104997 [type: code128 at: (578,83)]
We have several snapshots in the release area. However since the package is currently envolvoing quite quickly it is recommended to checkout the source out of the SVN repository.
How to compile
Just run ./configure ; make in the checked out source. It does use an modern, non recursive Makefile system. The binaries are by default placed in sub-directory named "objdir":
Note: On BSD systems you might need to execute "gmake" instead of just "make" if the system's "make" program is the historic BSD version.
With the executables in the directory named after the corresponding sub-module.
A make install run will install them as usual.
To improve the software please send feature ideas, report compile problems, bugs and so on back to us.
You can post to our mailing lists without subscribing, just send an email to firstname.lastname@example.org.
Contact the author
If you hesitate to post to an international audience on the ExactImage mailing list or mind notifing e.g. security problems in private you can also reach the author via email@example.com.