Overview
Directory organization
Getting the requisite external libraries
The
leptonlib Visual
Studio 2008 Solution
Building the
leptonlib library
Building the
prog directory programs
Building other programs that link with
leptonlib
Installing Cygwin
coreutils
Installing IrfanView to view images
Installing gnuplot to view plots
c# and
leptonlib
Appendix: Building
zlib,
libjpeg, and
libpng
leptonlib is a library of image processing routines written in C. This page discusses building the library and linking with it to create working executables using Microsoft's Visual Studio 2008 and the command line. leptonlib can process a number of image file types. This guide only covers using the default three image types: jpg, png, and tiff. Adding support for other file types should be relatively straightforward by simply following what was done for the default types.
Unlike Linux where libraries and their dependencies are usually in consistent places, there is no standard for organizing directories in Windows. In order to build and link with leptonlib this procedure has to assume one such organization. All required files should reside within a single directory. This guide calls that directory BuildFolder but you can call it whatever you want, only the relative placement and names of the subdirectories matter. In addition, this discussion uses the latest actual directories from the required libraries at the time this guide was written. You can of course use different versions and name these directories as you please.
To give an idea of what will be required to build and link with leptonlib using Visual Studio 2008, here's what the complete top-level contents of \BuildFolder will need to look like. All the subdirectories are required if you decide to build the default image file libraries yourself. If you instead opt to use pre-built libraries the italicized directories can be omitted:
BuildFolder\ include\ jpeg-7\ leptonlib-1.64\ lib\ libpng-1.2.40\ libtiff-3.9.2\ zlib\
leptonica\ jconfig.h jerror.h jmorecfg.h jpeglib.h png.h pngconf.h tiff.h tiffconf.h tiffio.h tiffvers.h tif_config.h zconf.h zlib.h
allheaders.h alltypes.h array.h arrayaccess.h bbuffer.h bmf.h bmp.h ccbord.h environ.h freetype.h gplot.h heap.h imageio.h jbclass.h leptprotos.h list.h morph.h pix.h ptra.h queue.h readbarcode.h stack.h watershed.h
leptonlib-static-mtdll-debug.lib leptonlib-static-mtdll.lib libjpeg-static-mtdll-debug.lib libjpeg-static-mtdll.lib libpng-static-mtdll-debug.lib libpng-static-mtdll.lib libtiff-static-mtdll-debug.lib libtiff-static-mtdll.lib zlib-static-mtdll-debug.lib zlib-static-mtdll.lib
In order to build leptonlib you first need to populate \BuildFolder\include with all the header files that it needs. Therefore the first thing you need to do is download the requisite external libraries and build them.
This can be quite a challenge since unlike Linux, you can't just do a make at the command line and have everything magically build. In order to create working programs that use leptonlib you have to also link with four default libraries: zlib, libjpeg, libpng, and libtiff. This section discusses using pre-built binaries for the first three libraries, and how to build libtiff. For advanced users, building the other required libraries is also discussed later.
A very important consideration to keep in mind is that all parts of a program have to be built with references to the exact same runtime library. Or as Visual C++ Compiler Options /MD, /MT, /LD (Use Run-Time Library) succinctly states:
All modules passed to a given invocation of the linker must have been compiled with the same run-time library compiler option (/MD, /MT, /LD).
In our case this means consistently using the or the compiler option. See How to link with the correct C Run-Time (CRT) library for more details. If you attempt to mix and match libraries and object files built with references to different runtime libraries you'll get lots of warning messages similar to the following:
LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with
use of other libs; use /NODEFAULTLIB:library
LIBCMTD.lib(crt0dat.obj) :
error LNK2005: _exit already defined in MSVCRTD.lib(MSVCR90D.dll)
In particular you can't even mix and match libraries built with references to the Multi-threaded Debug DLL (/MDd) runtime library with those built with references to the Multi-threaded DLL (/MD) runtime library. This is the reason why the ClanLib pre-built libraries mentioned in the next section have such long filenames. They are needed to make sure that only libraries referencing the same runtime library are used together.
To diagnose these kinds of issues you can use dumpbin /directives somelibrary.lib from the command line to see which runtime library somelibrary.lib was built to use.
The /MD and /MDd switches were chosen because the /clr option which enables linking with .NET languages can only be used with those runtime libraries. See C Run-Time Libraries for more details.
The easiest way to start using leptonlib is to first download the ClanLib External Libraries package. The current file is at http://www.clanlib.org/download/binaries-win32-vc90/all-2.0-external-libs-msvc90.zip. It contains Windows binary libraries and header files for zlib, libjpeg, and libpng (and a bunch of other libraries that you can ignore).
Unpack this file to the same directory that leptonlib will be in. For example, after unpacking you should have something similar to this:
BuildFolder\ include\ lib\
You might think you could use the GnuWin32 Project's Tiff for Windows files, but that only supports GCC not the Visual C compiler. Therefore in order to have tiff support, you're going to have to build libtiff yourself and unfortunately it doesn't come with a Visual Studio solution. After a long quiet period, libtiff is undergoing a flurry of changes so it seems best to get the latest version (currently 3.9.2).
BuildFolder\ include\ lib\ tiff-3.9.2\
nmake /f makefile.vc cleannmake /f makefile.vc DEBUG=1 nmake /f makefile.vc DEBUG=1 install
nmake /f makefile.vc nmake /f makefile.vc install
nmake /f makefile.vc DEBUG=1
nmake /f makefile.vc
The Visual Studio 2008 Solution Explorer shows these three main sections for the leptonlib solution:
leptonlib-1.64\ Main project for building leptonlib Header files\ Source files\ prog_files\ Solution Folder (NOT projects) for prog directory contents ByFilename\ ByCategory\ Basic Box, Boxa and Boxaa Functions\ Basic Image Operations\ Basic Pix Array Functions\ Basic Pix Functions\ Colormap Utilities and Related Operations\ Connected Components in Binary Images\ Formatted IO\ Fundamental Data Structures for Computation\ Image Display\ Image Morphology\ Image Operations With Filling\ Image Quantization, Depth Conversion\ Image Scaling\ Line Graphics and Special Output\ Low-level Pixel Access\ Misc\ Other Geometric Image Transformations\ Postscript\ Printing\ Specialized Document Image Processing\ Specialized Image Filters\ ByType Example\ Exploration\ Helper\ Regression Test\ Test\ Utility\ proj_projects Projects for building prog programs ioformats_reg\ Source Files
config\ Not used for Windows builds prog\ Regression tests, examples, utilities src\ Source files for leptonlib vs2008\ Visual Studio 2008 specific files Debug\ leptonlib Debug build output prog_projects\ Projects for prog programs ioformats_reg\ Sample project for prog\ioformats_reg.exe Debug\ Debug build output for sample project Release\ Release build output for sample project ioformats_reg.vcproj The ioformats_reg project file Release\ leptonlib Release build output leptonlib.sln The leptonlib solution file leptonlib.vcproj The leptonlib project file
The leptonlib source files assume that tabs are 8 spaces, indents are 4 spaces wide, and that indentation uses spaces and tabs. To set this in Visual Studio 2008 choose and set as follows:
8
4
Building the library itself is straightforward since a Visual Studio solution file is provided.
BuildFolder\ include\ leptonlib-1.64\ lib\ tiff-3.9.2\
Debug builds use the following C compiler options:
/Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_LIB"
/D "L_LITTLE_ENDIAN" /D "USE_PSTDINT" /D "snprintf=_snprintf" /D
"COMPILER_MSVC=1" /D "XMD_H" /FD /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb"
/W3 /nologo /c /Z7 /errorReport:prompt
Release builds use the following compiler options:
/O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D
"_LIB" /D "L_LITTLE_ENDIAN" /D "USE_PSTDINT" /D "snprintf=_snprintf" /D
"COMPILER_MSVC=1" /D "XMD_H" /D "NO_CONSOLE_IO" /FD /EHsc /MD /Fo"Release\\"
/Fd"Release\vc90.pdb" /W3 /nologo /c /errorReport:prompt
Both configurations turn off some warnings with the following options:
/wd4244 /wd4305 /wd4018 /wd4267 /wd4996
Now that you have all the pre-requisite libraries, you can finally start using leptonlib. There are two basic ways to build the programs in the leptonlib-1.64\prog directory. The quickest way is to use the cl command from a Windows Command Prompt. However, if you plan to spend a lot of time investigating how a particular prog program works, it's better to create a new Visual Studio Project for it.
We'll assume that you are going to build ioformats_reg.c. This is an excellent program to run if you want to be sure you correctly built all the necessary image libraries.
Create a \tmp directory on the same drive from which you will be running your leptonlib based programs. Some parts of leptonlib assume they can write to /tmp and will mysteriously fail if this directory doesn't exist. In particular, the leptonlib-1.64\prog\ioformats_reg test will have multiple false failures if the \tmp directory doesn't exist.
First, set up the proper environment variables for running the Visual Studio 2008 compiler from the command line by executing C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat.
To avoid cluttering the prog directory with object and executable files, make subdirectories for Debug and Release builds:
cd
to \BuildFolder\leptonlib-1.64\prog.
md Debug
md Release
cd
to \BuildFolder\leptonlib-1.64\prog\Debug.
Then copy and paste the following cl command to build a Debug version of ioformats_reg.exe:
cl /Od /MDd /EHsc /W3 /RTC1 /Z7 /I ..\..\src /D WIN32 /D _DEBUG
/D _CONSOLE /D "snprintf=_snprintf" /D "COMPILER_MSVC=1" /D _CRT_SECURE_NO_WARNINGS
..\ioformats_reg.c /link /LIBPATH:"..\..\..\lib" libpng-static-mtdll-debug.lib zlib-static-mtdll-debug.lib
libjpeg-static-mtdll-debug.lib
libtiff-static-mtdll-debug.lib leptonlib-static-mtdll-debug.lib
To try it out do the following:
cd ..
Debug\ioformats_reg
If you are doing this a lot it's probably easier to set up some environmental variables in a batch file for the compiler and linker (see Setting the Path and Environment Variables for Command-Line Builds for more information).
SET INCLUDE=C:\BuildFolder\include;C:\BuildFolder\include\leptonica;%INCLUDE% SET LIB=C:\BuildFolder\lib;%LIB%
For Debug builds do the following:
SET CL=/Od /MDd /EHsc /W3 /RTC1 /Z7 /D WIN32 /D _DEBUG /D _CONSOLE
/D "snprintf=_snprintf" /D "COMPILER_MSVC=1" /D _CRT_SECURE_NO_WARNINGS
SET LINK=leptonlib-static-mtdll-debug.lib libpng-static-mtdll-debug.lib zlib-static-mtdll-debug.lib
libjpeg-static-mtdll-debug.lib libtiff-static-mtdll-debug.lib
For Release builds do the following:
SET CL=/O2 /MD /EHsc /W3 /D WIN32 /D NDEBUG /D _CONSOLE
/D "snprintf=_snprintf" /D "COMPILER_MSVC=1" /D _CRT_SECURE_NO_WARNINGS
SET LINK=leptonlib-static-mtdll.lib libpng-static-mtdll.lib
zlib-static-mtdll.lib libjpeg-static-mtdll.lib libtiff-static-mtdll.lib
Then all you have to do to build ioformats_reg.exe is:
cd Debug
cl ..\ioformats_reg
You can use the Visual Studio 2008 debugger even for executables built from the command line. See How to: Debug an Executable Not Part of a Visual Studio Solution for more information. Once you've imported ioformats_reg.exe into the leptonlib solution by creating an EXE project for it, you can right-click ioformats_reg.exe and the choose or from the context menu. You can even set breakpoints in ioformats_reg.c before you do this.
For anything other than just quickly trying out a leptonlib-1.64\prog program, you should create a Visual Studio 2008 project for it.
I tried to make the process simpler by creating a Project Template but Visual Studio 2008 doesn't seem to support them for Visual C++. You'll just have to use the brute force method.
First you have to correctly set up the ioformats_reg project which we'll use as the basis for new prog program projects (you only have to do this once):
Now to make projects for leptonlib-1.64\prog programs:
Tip: When debugging console apps like the ones in the prog directory, put a breakpoint on the very last line in main() or on any exit() statements. That way you can view the program output in the Command Prompt window before it automatically disappears when the program exits.
It's much simpler to make projects that only link with leptonlib since you can just use the standard Visual Studio wizards. Most of the compiler and linker setting will be dictated by your application's needs; you only have to add where to find the header files and libraries needed with leptonlib.
First open up your project's (right-click the project then choose from the context menu). Change to . You then have to set two items:
C:\BuildFolder\include;C:\BuildFolder\leptonica
C:\BuildFolder\lib
Of course, if you've used some other location/name instead of C:\BuildFolder for where you've put include and lib then use that instead.
Alternatively, if you don't mind having all programs use these header files and libraries, you could also globally change where Visual Studio 2008 looks for include files and libraries by setting .
Intellisense is a great Visual Studio feature that automatically completes function names, shows function arguments, quickly lets you go to a function's definition, etc. There seems to be a problem, however, with navigating to leptonlib function definitions. When you right click a function name that is part of the leptonlib library and choose (or press the F12 key), instead of jumping to the definition it shows you the declaration in leptprotos.h.
Adding the location of leptonlib-1.64\src to doesn't help, even though that list is described as "Path to use when searching for source files to use for Intellisense."
(The commercial program Visual Assist X for Visual Studio has the command (Alt+G) that does do the correct thing as long as you follow these instructions.)
In order to have Visual Studio's command work correctly with leptonlib, you have to add its project to your current solution:
Leptonica sometimes assumes the presence of standard Unix/Linux command line utilities (like rm, diff, sleep). The easiest way to handle this under Windows is to install the Cygwin Linux-like Environment for Windows. You'll probably only need the base | coreutils package and the simplest thing is just to use the initial setup defaults which installs only the "minimal base packages".
The pixDisplay() function is used throughout leptonlib to display images for debugging purposes. Under Windows this uses the free IrfanView image viewer application. We have to assume the presence of IrfanView because many Leptonica routines don't use file extensions when naming files. Since Windows depends on the file extension to determine a file's type (unlike Linux), it is unable to automatically determine what application to use when opening extensionless files. In addition, unlike other Windows image viewers (for example, ACDSee's Photo Manager), IrfanView will correctly display an image file even if it doesn't have an extension.
Besides installing IrfanView, you also have to add the location of i_view32.exe (normally C:\Program Files\IrfanView) to your system's PATH environment variable.
Each time pixDisplay() is called, it will display an image using IrfanView and wait for it to be closed. You can hit the <Escape> key to quickly close IrfanView.
Alternatively, you can manually edit pixDisplayWithTitle() in src\writefile.c to change the executable used to display images under Windows.
Leptonica uses gnuplot to display plots. Download the standard gnuplot Windows version (not the Windows X11 version unless you know what you are doing). Besides installing gnuplot you have to set the following environment variables:
Add c:\gnuplot\bin to your system's PATH.
Create a new environment variable called GDFONTPATH and set it to C:/WINDOWS/FONTS
Create a new environment variable called GNUPLOT_FONTPATH and also set it to C:/WINDOWS/FONTS
After showing a plot, the calling program will pause until both the plot window and gnuplot window are closed.
vs2008\LeptonicaVS2008Samples.zip contains a sample Visual Studio Solution which shows how simple it is to call leptonlib functions from c# (or any other .NET language). Unpack it to BuildFolder. You should have:
BuildFolder\
include\
leptonlib-1.64\
LeptonicaVS2008Samples\
deskew1bpp\
LeptonicaCLR\
TestLeptonica\
LeptonicaVS2008Samples.sln
lib\
tiff-3.9.2\
deskew1bpp is a standard C++ Win32 Console program, using precompiled headers, C++ strings, Unicode support, and ATL macros to convert Unicode to null-terminated C strings. In other words, it's a typical Visual C++ style program. deskew1bpp demonstrates the problems with directly rotating 1bpp images. It demonstrates how first converting a b&w image to gray, block convolving, rotating using area mapping, and then thresholding back to b&w yields better results.
LeptonicaCLR contains the same basic functionality as deskew1bpp written in C++/CLI. In fact two of the routines, renderCC() and binImageDiff(), are copied verbatim from deskew1bpp.cpp showing how easy it is to port C/C++ to C++/CLI. The resultant DLL is a bridge between the native leptonlib library and the .NET Common Language Runtime (CLR). It calls native code while at the same time exposing functions to c#. The main difference from a normal DLL is that LeptonicaCLR.cpp is compiled with the /clr switch.
TestLeptonica is a c# program that has a Reference to the LeptonicaCLR DLL to demonstrate calling leptonlib functions from C#. It does a bit of argument checking and then calls LeptonicaCLR.Utils.DeskewBinaryImage() to actually deskew a b&w image. If you want to be able to step into leptonlib functions while debugging c#, just right-click the project and choose . Then make sure is checked.
You'll notice that the leptonlib project is also included in this Solution. As explained above, that's to allow Visual Studio's Intellisense to correctly navigate to leptonlib function definitions.
The ClanLib pre-built binaries can be somewhat out of date so you might want to also build the other default libraries leptonlib depends on. If you do this you have to make zlib and libjpeg before you make libtiff.
The process involves downloading and extracting the library sources, building them, and then copying the required header files to BuildFolder\include, and the libraries to BuildFolder\lib.
Here's a summary of the default required libraries and their dependencies:
libjpeg current version: http://www.ijg.org/files/jpegsr7.zip libjpeg has no other dependencies. A Visual Studio solution file is provided. The ClanLib libjpeg release currently builds the older (but more commonly used 6b version of libjpeg). It's all set up to use with Visual Studio but if you want that version it's easier just to use their pre-built binaries. zlib current version: http://www.zlib.net/zlib123.zip zlib has no other dependencies. An older Visual Studio solution file is provided (but use the one included with libpng instead) libpng current version: http://prdownloads.sourceforge.net/libpng/libpng-1.2.40.tar.gz libpng depends on zlib. A Visual Studio solution file is provided. libpng also builds zlib. libtiff current version: ftp://ftp.remotesensing.org/pub/libtiff/tiff-3.9.2.zip libtiff depends on libjpeg and zlib. Only a nmake file is provided.
BuildFolder\ include\ jpeg-7\ leptonlib-1.64\ lib\ libpng-1.2.40\ libtiff-3.9.2\ zlib\
At this point you might want to empty your include and lib directories to get rid of any files that were supplied with the ClanLib pre-built binaries archive.
libpng-static-mtdll.lib or
libpng-static-mtdll-debug.lib
zlib-static-mtdll.lib or
zlib-static-mtdll-debug.lib
As per the instructions in the "Microsoft Windows, Microsoft Visual C++ 2008 Developer Studio (v9)" section of jpeg-7\install.txt, a number of files have to be copied. To make that easier, put the following copy commands into BuildFolder\jpeg-7\makevc9.bat and run it from the command line:
copy jconfig.vc jconfig.h copy makejsln.vc9 jpeg.sln copy makeasln.vc9 apps.sln copy makejvcp.vc9 jpeg.vcproj copy makecvcp.vc9 cjpeg.vcproj copy makedvcp.vc9 djpeg.vcproj copy maketvcp.vc9 jpegtran.vcproj copy makervcp.vc9 rdjpgcom.vcproj copy makewvcp.vc9 wrjpgcom.vcproj
Here's what the libjpeg build C/C++ command line should look like:
/Od /D "WIN32" /D "_DEBUG" /D "_LIB"
/D "_CRT_SECURE_NO_WARNINGS"
/FD /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb"
/W3 /nologo /c /Z7 /errorReport:prompt
The libjpeg build Librarian command line should be:
/OUT:"Debug\jpegd.lib" /NOLOGOSee the instructions above.
Since header files may have changed, build leptonlib by following these instructions.
