diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/README.html leptonlib-1.066/README.html
--- leptonlib-1.66/README.html	2010-08-03 01:57:02.000000000 +0300
+++ leptonlib-1.066/README.html	2010-09-24 07:32:32.000000000 +0300
@@ -65,11 +65,23 @@
  *====================================================================*/
 
 
-README  (3 Aug 2010)
+README  (15 Sept 2010)
 --------------------
 
-gunzip leptonlib-1.66.tar.gz
-tar -xvf leptonlib-1.66.tar
+gunzip leptonlib-1.66.tar.gz
+tar -xvf leptonlib-1.66.tar
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+NOTE:
+ -- Special version for bundling with the new open-source webp library --
+ -- Variation on 1.66 with wrappers for webp library --
+ -- Requires webpimg.h available in order to compile
+ -- Assumes libjpeg, libpng, libtiff and libwebp are available
+ -- Contains just the library; not the application programs in prog
+ -- NOT an official leptonica version --
+ -- Not to be used except bundled in this early release of webp --
+ -- Will NOT be archived --
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 
 1.  This tar includes:
@@ -122,12 +134,23 @@
     for building the library and applications under windows with VC++ 2008:
     </pre>
     <p style='margin-left:5em;'>
-       <A href="http://www.leptonica.org/source/VS2008notes.html">
-               http:///www.leptonica.org/source/VS2008notes.html</A><br>
+       <A href="http://www.leptonica.org/vs2008doc/index.html">
+               http:///www.leptonica.org/vs2008doc/index.html</A><br>
        <A href="http://www.leptonica.org/download.html#VS2008">
                http:///www.leptonica.org/download.html#VS2008</A>
     <pre>
 
+    He has also supplied a zip file that contains the entire 'lib'
+    and 'include' directories needed to build Windows-based programs
+    using static or dynamic versions of the leptonica library
+    (including static library versions of zlib, libpng, libjpeg,
+    libtiff, and giflib).
+    </pre>
+    <p style='margin-left:5em;'>
+       <A href="http://www.leptonica.org/source/leptonica-1.66-win32-lib-include-dirs.zip">
+               leptonica-1.66-win32-lib-include-dirs.zip</A>
+    <pre>
+
 3.  When you compile liblept using the supplied makefile (not autoconf),
     object code is by default put into a tree whose root is also the parent
     of the src and prog directories.  This can be changed using the
@@ -286,16 +309,12 @@
            (1) remove -fPIC from $CC
 
     (d) Windows via MS VC++
-        (1) Tom Powers has written a set of notes for developing the library
-            and executables under MS Visual Studio 2008.  The documentation
-            is included with project files in vs2008.  See the developer
-            notes there.  You can download the vs2008 package separately
-            from the download page or from code.google.com/p/leptonica.
-        (2) Because VC++ does not conform to the 1999 C++ standard,
-            which specifies stdint.h, we have defined it in environ.h.
-            Otherwise you would need to include Paul Hsieh's pstdint.h,
-            a portable version of stdint.h, which is included here and
-            can be found at http://www.azillionmonkeys.com/qed/pstdint.h           
+        Tom Powers has written a set of notes for developing the library
+        and executables under MS Visual Studio 2008.  The documentation
+        is included with project files in vs2008.  See the developer
+        notes there.  You can download the vs2008 package separately
+        from the download page or from code.google.com/p/leptonica.
+
 10. Provides for your own memory management (allocator, deallocator).
     For pix, which tend to be large, the alloc/dealloc functions
     can be set programmatically.  For all other structs and arrays,
@@ -744,19 +763,15 @@
     downloaded and built from:
         http://jbig2dec.sourceforge.net/
 
-25. If you use Leptonica with other imaging libraries, you have three
-    choices with respect to the Pix data structure.  It is
-    easiest if you can use the Pix directly.  Next easiest is to
-    make a Pix from a local image data structure or the unbundled
-    image parameters; see the file pix.h for the constraints on the
-    image data that will permit you to avoid data replication.
-    By far, the most work is to provide new high-level shims from some
-    other image data structure to the low-level functions in the library,
-    which take only built-in C data types.  It would be an inordinately
-    large task to do this for the entire library.
+25. If you use Leptonica with other imaging libraries, you will need
+    functions to convert between the Pix and other image data
+    structures.  To make a Pix from other image data structures, you
+    will need to understand pixel packing, pixel padding, component
+    ordering and byte ordering on raster lines.  See the file pix.h
+    for the specification of image data in the pix.
 
 26. New versions of the Leptonica library are released approximately
-    8 times a year, and version numbers are provided for each release in
+    6 times a year, and version numbers are provided for each release in
     the makefile and in allheaders.h.  All even versions from 1.42 to 1.60
     are archived at http://code.google.com/p/leptonica, as well as all
     versions after 1.60.
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/Makefile.am leptonlib-1.066/src/Makefile.am
--- leptonlib-1.66/src/Makefile.am	2010-08-03 01:27:48.000000000 +0300
+++ leptonlib-1.066/src/Makefile.am	2010-09-30 11:32:11.000000000 +0300
@@ -67,9 +67,10 @@
  seedfill.c seedfilllow.c \
  sel1.c sel2.c selgen.c \
  shear.c skew.c spixio.c \
- stack.c textops.c \
+ stack.c sudoku.c textops.c \
  tiffio.c tiffiostub.c \
  utils.c viewfiles.c \
+ webpio.c webpiostub.c \
  warper.c watershed.c writefile.c \
  zlibmem.c zlibmemstub.c
 
@@ -77,7 +78,7 @@
  arrayaccess.h bbuffer.h bmf.h bmp.h ccbord.h dewarp.h environ.h \
  gplot.h heap.h imageio.h jbclass.h leptprotos.h list.h \
  morph.h pix.h ptra.h queue.h readbarcode.h regutils.h \
- stack.h watershed.h
+ stack.h sudoku.h watershed.h
 
 EXTRA_DIST = Makefile.mingw arrayaccess.h.vc arrayaccess.h.vc60 \
  endiantest.c hmttemplate1.txt hmttemplate2.txt leptonica-license.txt \
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/Makefile.in leptonlib-1.066/src/Makefile.in
--- leptonlib-1.66-orig/src/Makefile.in	2010-08-03 02:12:51.000000000 +0300
+++ leptonlib-1.66/src/Makefile.in	2010-10-16 16:40:24.000000000 +0300
@@ -105,9 +105,10 @@
 	runlength.$(OBJEXT) sarray.$(OBJEXT) scale.$(OBJEXT) \
 	scalelow.$(OBJEXT) seedfill.$(OBJEXT) seedfilllow.$(OBJEXT) \
 	sel1.$(OBJEXT) sel2.$(OBJEXT) selgen.$(OBJEXT) shear.$(OBJEXT) \
-	skew.$(OBJEXT) spixio.$(OBJEXT) stack.$(OBJEXT) \
+	skew.$(OBJEXT) spixio.$(OBJEXT) stack.$(OBJEXT) sudoku.$(OBJEXT) \
 	textops.$(OBJEXT) tiffio.$(OBJEXT) tiffiostub.$(OBJEXT) \
 	utils.$(OBJEXT) viewfiles.$(OBJEXT) warper.$(OBJEXT) \
+	webpio.$(OBJEXT) webpiostub.$(OBJEXT) \
 	watershed.$(OBJEXT) writefile.$(OBJEXT) zlibmem.$(OBJEXT) \
 	zlibmemstub.$(OBJEXT)
 liblept_a_OBJECTS = $(am_liblept_a_OBJECTS)
@@ -304,9 +305,10 @@
  seedfill.c seedfilllow.c \
  sel1.c sel2.c selgen.c \
  shear.c skew.c spixio.c \
- stack.c textops.c \
+ stack.c sudoku.c textops.c \
  tiffio.c tiffiostub.c \
  utils.c viewfiles.c \
+ webpio.c webpiostub.c \
  warper.c watershed.c writefile.c \
  zlibmem.c zlibmemstub.c
 
@@ -314,7 +316,7 @@
  arrayaccess.h bbuffer.h bmf.h bmp.h ccbord.h dewarp.h environ.h \
  gplot.h heap.h imageio.h jbclass.h leptprotos.h list.h \
  morph.h pix.h ptra.h queue.h readbarcode.h regutils.h \
- stack.h watershed.h
+ stack.h sudoku.h watershed.h webpimg.h
 
 EXTRA_DIST = Makefile.mingw arrayaccess.h.vc arrayaccess.h.vc60 \
  endiantest.c hmttemplate1.txt hmttemplate2.txt leptonica-license.txt \
@@ -389,7 +389,7 @@
        $(RANLIB) liblept.a
 
 liblept.so: $(liblept_a_OBJECTS) $(liblept_a_DEPENDENCIES) 
-	$(CC) -shared -o $@ $(liblept_a_OBJECTS) -lgif -ltiff -ljpeg -lpng -lm -Wl,-soname -Wl,$@
+	$(CC) -shared -o $@ $(liblept_a_OBJECTS) -lwebp -lgif -ltiff -ljpeg -lpng -lm -Wl,-soname -Wl,$@
 
 mostlyclean-compile:
        -rm -f *.$(OBJEXT)
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/alltypes.h leptonlib-1.066/src/alltypes.h
--- leptonlib-1.66/src/alltypes.h	2010-07-09 03:45:09.000000000 +0300
+++ leptonlib-1.066/src/alltypes.h	2010-08-16 09:02:35.000000000 +0300
@@ -35,6 +35,7 @@
 #include "queue.h"
 #include "regutils.h"
 #include "stack.h"
+#include "sudoku.h"
 #include "watershed.h"
 
     /* i/o */
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/arrayaccess.h leptonlib-1.066/src/arrayaccess.h
--- leptonlib-1.66/src/arrayaccess.h	2010-07-31 04:05:27.000000000 +0300
+++ leptonlib-1.066/src/arrayaccess.h	2010-09-10 23:32:58.000000000 +0300
@@ -47,7 +47,11 @@
  */
 
 
-#if 1   /* Inline Accessors */
+    /* Use the inline accessors (except with _MSC_VER), because they
+     * are faster.  */
+#define  USE_INLINE_ACCESSORS    1
+
+#if USE_INLINE_ACCESSORS
 #ifndef _MSC_VER
 
     /*--------------------------------------------------*
@@ -155,14 +159,14 @@
 
 
 #endif  /* ! _MSC_VER */
-#endif  /* Inline Accessors */
+#endif  /* USE_INLINE_ACCESSORS */
 
 
 
     /*--------------------------------------------------*
      *  Slower, using function calls for all accessors  *
      *--------------------------------------------------*/
-#if 0 || defined(_MSC_VER)
+#if !USE_INLINE_ACCESSORS || defined(_MSC_VER)
 #define  GET_DATA_BIT(pdata, n)               l_getDataBit(pdata, n)
 #define  SET_DATA_BIT(pdata, n)               l_setDataBit(pdata, n)
 #define  CLEAR_DATA_BIT(pdata, n)             l_clearDataBit(pdata, n)
@@ -184,7 +188,7 @@
 
 #define  GET_DATA_FOUR_BYTES(pdata, n)         l_getDataFourBytes(pdata, n)
 #define  SET_DATA_FOUR_BYTES(pdata, n, val)    l_setDataFourBytes(pdata, n, val)
-#endif
+#endif  /* !USE_INLINE_ACCESSORS || _MSC_VER */
 
 
 #endif /* LEPTONICA_ARRAY_ACCESS_H */
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/bmpio.c leptonlib-1.066/src/bmpio.c
--- leptonlib-1.66/src/bmpio.c	2010-07-20 00:02:17.000000000 +0300
+++ leptonlib-1.066/src/bmpio.c	2010-09-16 08:18:29.000000000 +0300
@@ -57,7 +57,7 @@
 l_uint32   ival;
 l_int16    bfType, bfSize, bfFill1, bfReserved1, bfReserved2;
 l_int16    offset, bfFill2, biPlanes, depth, d;
-l_int32    biSize, width, height, xres, yres, compression;
+l_int32    biSize, width, height, xres, yres, compression, ignore;
 l_int32    imagebytes, biClrUsed, biClrImportant;
 l_uint8   *colormapBuf;
 l_int32    colormapEntries;
@@ -76,46 +76,46 @@
         return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
 
         /* Read bitmap file header */
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     bfType = convertOnBigEnd16(sval);
     if (bfType != BMP_ID)
         return (PIX *)ERROR_PTR("not bmf format", procName, NULL);
 
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     bfSize = convertOnBigEnd16(sval);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     bfFill1 = convertOnBigEnd16(sval);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     bfReserved1 = convertOnBigEnd16(sval);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     bfReserved2 = convertOnBigEnd16(sval);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     offset = convertOnBigEnd16(sval);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     bfFill2 = convertOnBigEnd16(sval);
 
         /* Read bitmap info header */
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     biSize = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     width = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     height = convertOnBigEnd32(ival);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     biPlanes = convertOnBigEnd16(sval);
-    fread((char *)&sval, 1, 2, fp);
+    ignore = fread((char *)&sval, 1, 2, fp);
     depth = convertOnBigEnd16(sval);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     compression = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     imagebytes = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     xres = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     yres = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     biClrUsed = convertOnBigEnd32(ival);
-    fread((char *)&ival, 1, 4, fp);
+    ignore = fread((char *)&ival, 1, 4, fp);
     biClrImportant = convertOnBigEnd32(ival);
 
     if (compression != 0)
@@ -242,7 +242,7 @@
             }
             if (extrabytes) {
                 for (k = 0; k < extrabytes; k++)
-                    fread(&pel, 1, 1, fp);
+                    ignore = fread(&pel, 1, 1, fp);
             }
             line -= pixWpl;
         }
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/colormap.c leptonlib-1.066/src/colormap.c
--- leptonlib-1.66/src/colormap.c	2010-07-22 14:44:24.000000000 +0300
+++ leptonlib-1.066/src/colormap.c	2010-09-15 22:36:42.000000000 +0300
@@ -1171,7 +1171,7 @@
 PIXCMAP *
 pixcmapReadStream(FILE  *fp)
 {
-l_int32   rval, gval, bval;
+l_int32   rval, gval, bval, ignore;
 l_int32   i, index, ret, depth, ncolors;
 PIXCMAP  *cmap;
 
@@ -1186,14 +1186,14 @@
         (depth != 1 && depth != 2 && depth != 4 && depth != 8) ||
         (ncolors < 2 || ncolors > 256))
         return (PIXCMAP *)ERROR_PTR("invalid cmap size", procName, NULL);
-    fscanf(fp, "Color    R-val    G-val    B-val\n");
-    fscanf(fp, "--------------------------------\n");
+    ignore = fscanf(fp, "Color    R-val    G-val    B-val\n");
+    ignore = fscanf(fp, "--------------------------------\n");
 
     if ((cmap = pixcmapCreate(depth)) == NULL)
         return (PIXCMAP *)ERROR_PTR("cmap not made", procName, NULL);
     for (i = 0; i < ncolors; i++) {
-        fscanf(fp, "%3d       %3d      %3d      %3d\n",
-                &index, &rval, &gval, &bval);
+        ignore = fscanf(fp, "%3d       %3d      %3d      %3d\n",
+                        &index, &rval, &gval, &bval);
         pixcmapAddColor(cmap, rval, gval, bval);
     }
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/environ.h leptonlib-1.066/src/environ.h
--- leptonlib-1.66-orig/src/environ.h   2010-08-01 23:20:20.000000000 +0300
+++ leptonlib-1.66/src/environ.h        2010-10-16 23:06:51.000000000 +0300
@@ -94,6 +94,7 @@
 #define  HAVE_LIBZ        1
 #define  HAVE_LIBGIF      0
 #define  HAVE_LIBUNGIF    0
+#define  HAVE_LIBWEBP     1
 #endif  /* ~HAVE_CONFIG_H */
 
 /*
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/gifio.c leptonlib-1.066/src/gifio.c
--- leptonlib-1.66/src/gifio.c	2010-08-02 08:36:18.000000000 +0300
+++ leptonlib-1.066/src/gifio.c	2010-09-08 00:13:10.000000000 +0300
@@ -16,8 +16,11 @@
 /*
  *  gifio.c
  *
- *    Read/write gif to file
+ *    Read gif from file
  *          PIX        *pixReadStreamGif()
+ *          static PIX *pixInterlaceGIF()
+ *
+ *    Write gif to file
  *          l_int32     pixWriteStreamGif()
  *
  *    Read/write from/to memory
@@ -51,6 +54,12 @@
 
 #include "gif_lib.h"
 
+    /* GIF supports 4-way horizontal interlacing */
+static PIX * pixInterlaceGIF(PIX  *pixs);
+static const l_int32 InterlacedOffset[] = {0, 4, 2, 1};
+static const l_int32 InterlacedJumps[] = {8, 8, 4, 2};
+
+
 /*---------------------------------------------------------------------*
  *                       Reading gif from file                         *
  *---------------------------------------------------------------------*/
@@ -67,7 +76,7 @@
 l_int32          rval, gval, bval;
 l_uint32        *data, *line;
 GifFileType     *gif;
-PIX             *pixd;
+PIX             *pixd, *pixdi;
 PIXCMAP         *cmap;
 ColorMapObject  *gif_cmap;
 SavedImage       si;
@@ -154,7 +163,7 @@
     data = pixGetData(pixd);
     for (i = 0; i < h; i++) {
         line = data + i * wpl;
-	if (d == 1) {
+        if (d == 1) {
             for (j = 0; j < w; j++) {
                 if (si.RasterBits[i * w + j])
                     SET_DATA_BIT(line, j);
@@ -174,11 +183,47 @@
         }
     }
 
+    if (gif->Image.Interlace) {
+        pixdi = pixInterlaceGIF(pixd);
+        pixTransferAllData(pixd, &pixdi, 0, 0);
+    }
+
     DGifCloseFile(gif);
     return pixd;
 }
 
 
+static PIX *
+pixInterlaceGIF(PIX  *pixs)
+{
+l_int32    w, h, d, wpl, j, k, srow, drow;
+l_uint32  *datas, *datad, *lines, *lined;
+PIX       *pixd;
+
+    PROCNAME("pixInterlaceGIF");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+
+    pixGetDimensions(pixs, &w, &h, &d);
+    wpl = pixGetWpl(pixs);
+    pixd = pixCreateTemplate(pixs);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    for (k = 0, srow = 0; k < 4; k++) {
+        for (drow = InterlacedOffset[k]; drow < h;
+             drow += InterlacedJumps[k], srow++) {
+            lines = datas + srow * wpl;
+            lined = datad + drow * wpl;
+            for (j = 0; j < w; j++)
+                memcpy(lined, lines, 4 * wpl);
+        }
+    }
+
+    return pixd;
+}
+
+
 /*---------------------------------------------------------------------*
  *                         Writing gif to file                         *
  *---------------------------------------------------------------------*/
@@ -267,7 +312,7 @@
         return ERROR_INT("failed to create GIF color map", procName, 1);
     }
     for (i = 0; i < gif_ncolor; i++) {
-	rval = gval = bval = 0;
+        rval = gval = bval = 0;
         if (ncolor > 0) {
             if (pixcmapGetColor(cmap, i, &rval, &gval, &bval) != 0) {
                 pixDestroy(&pixd);
@@ -443,7 +488,7 @@
     *psize = nbytes;
     return 0;
 }
-    
+
 
 /* -----------------------------------------------------------------*/
 #endif    /* HAVE_LIBGIF || HAVE_LIBUNGIF  */
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/gplot.c leptonlib-1.066/src/gplot.c
--- leptonlib-1.66/src/gplot.c	2010-08-02 20:01:27.000000000 +0300
+++ leptonlib-1.066/src/gplot.c	2010-09-15 22:36:44.000000000 +0300
@@ -349,7 +349,8 @@
 l_int32
 gplotMakeOutput(GPLOT  *gplot)
 {
-char  buf[L_BUF_SIZE];
+char     buf[L_BUF_SIZE];
+l_int32  ignore;
 
     PROCNAME("gplotMakeOutput");
 
@@ -372,7 +373,7 @@
        snprintf(buf, L_BUF_SIZE,
                "wgnuplot -persist %s", gplot->cmdname);
 #endif  /* _WIN32 */
-    system(buf);
+    ignore = system(buf);
     return 0;
 }
 
@@ -676,8 +677,8 @@
 gplotRead(const char  *filename)
 {
 char     buf[L_BUF_SIZE];
-char    *rootname, *title, *xlabel, *ylabel;
-l_int32  outformat, ret, version;
+char    *rootname, *title, *xlabel, *ylabel, *ignores;
+l_int32  outformat, ret, version, ignore;
 FILE    *fp;
 GPLOT   *gplot;
 
@@ -699,16 +700,16 @@
         return (GPLOT *)ERROR_PTR("invalid gplot version", procName, NULL);
     }
 
-    fscanf(fp, "Rootname: %s\n", buf);
+    ignore = fscanf(fp, "Rootname: %s\n", buf);
     rootname = stringNew(buf);
-    fscanf(fp, "Output format: %d\n", &outformat);
-    fgets(buf, L_BUF_SIZE, fp);   /* Title: ... */
+    ignore = fscanf(fp, "Output format: %d\n", &outformat);
+    ignores = fgets(buf, L_BUF_SIZE, fp);   /* Title: ... */
     title = stringNew(buf + 7);
     title[strlen(title) - 1] = '\0';
-    fgets(buf, L_BUF_SIZE, fp);   /* X axis label: ... */
+    ignores = fgets(buf, L_BUF_SIZE, fp);   /* X axis label: ... */
     xlabel = stringNew(buf + 14);
     xlabel[strlen(xlabel) - 1] = '\0';
-    fgets(buf, L_BUF_SIZE, fp);   /* Y axis label: ... */
+    ignores = fgets(buf, L_BUF_SIZE, fp);   /* Y axis label: ... */
     ylabel = stringNew(buf + 14);
     ylabel[strlen(ylabel) - 1] = '\0';
 
@@ -726,23 +727,23 @@
     sarrayDestroy(&gplot->plottitles);
     numaDestroy(&gplot->plotstyles);
 
-    fscanf(fp, "Commandfile name: %s\n", buf);
+    ignore = fscanf(fp, "Commandfile name: %s\n", buf);
     stringReplace(&gplot->cmdname, buf);
-    fscanf(fp, "\nCommandfile data:");
+    ignore = fscanf(fp, "\nCommandfile data:");
     gplot->cmddata = sarrayReadStream(fp);
-    fscanf(fp, "\nDatafile names:");
+    ignore = fscanf(fp, "\nDatafile names:");
     gplot->datanames = sarrayReadStream(fp);
-    fscanf(fp, "\nPlot data:");
+    ignore = fscanf(fp, "\nPlot data:");
     gplot->plotdata = sarrayReadStream(fp);
-    fscanf(fp, "\nPlot titles:");
+    ignore = fscanf(fp, "\nPlot titles:");
     gplot->plottitles = sarrayReadStream(fp);
-    fscanf(fp, "\nPlot styles:");
+    ignore = fscanf(fp, "\nPlot styles:");
     gplot->plotstyles = numaReadStream(fp);
 
-    fscanf(fp, "Number of plots: %d\n", &gplot->nplots);
-    fscanf(fp, "Output file name: %s\n", buf);
+    ignore = fscanf(fp, "Number of plots: %d\n", &gplot->nplots);
+    ignore = fscanf(fp, "Output file name: %s\n", buf);
     stringReplace(&gplot->outname, buf);
-    fscanf(fp, "Axis scaling: %d\n", &gplot->scaling);
+    ignore = fscanf(fp, "Axis scaling: %d\n", &gplot->scaling);
 
     fclose(fp);
     return gplot;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/graymorph.c leptonlib-1.066/src/graymorph.c
--- leptonlib-1.66/src/graymorph.c	2007-06-09 08:43:52.000000000 +0300
+++ leptonlib-1.066/src/graymorph.c	2010-09-15 15:19:17.000000000 +0300
@@ -17,26 +17,42 @@
 /*
  *  graymorph.c
  *
- *      Top-level binary morphological operations
- *
+ *      Top-level binary morphological operations (van Herk / Gil-Werman)
  *            PIX     *pixErodeGray()
  *            PIX     *pixDilateGray()
  *            PIX     *pixOpenGray()
  *            PIX     *pixCloseGray()
  *
+ *      Special operations for 1x3, 3x1 and 3x3 Sels  (direct)
+ *            PIX     *pixErodeGray3()
+ *            PIX     *pixDilateGray3()
+ *            PIX     *pixOpenGray3()
+ *            PIX     *pixCloseGray3()
+ *
  *
  *      Method: Algorithm by van Herk and Gil and Werman, 1992
  *
- *      Measured speed is about 1 output pixel per 120 PIII clock cycles,
- *      for a horizontal or vertical erosion or dilation.  The 
- *      computation time doubles for opening or closing, or for a
- *      square SE, as expected, and is independent of the size of the SE.
+ *      Measured speed of the vH/G-W implementation is about 1 output
+ *      pixel per 120 PIII clock cycles, for a horizontal or vertical
+ *      erosion or dilation.  The computation time doubles for opening
+ *      or closing, or for a square SE, as expected, and is independent
+ *      of the size of the SE.
+ *
+ *      A faster implementation can be made directly for brick Sels
+ *      of maximum size 3.  We unroll the computation for sets of 8 bytes.
+ *      It needs to be called explicitly; the general functions do not
+ *      default for the size 3 brick Sels.
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "allheaders.h"
 
+static PIX *pixErodeGray3h(PIX *pixs);
+static PIX *pixErodeGray3v(PIX *pixs);
+static PIX *pixDilateGray3h(PIX *pixs);
+static PIX *pixDilateGray3v(PIX *pixs);
+
 
 /*-----------------------------------------------------------------*
  *              Top-level gray morphological operations            *
@@ -109,8 +125,7 @@
     if ((pixt = pixCreateTemplate(pixb)) == NULL)
         return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
     
-    w = pixGetWidth(pixt);
-    h = pixGetHeight(pixt);
+    pixGetDimensions(pixt, &w, &h, NULL);
     datab = pixGetData(pixb);
     datat = pixGetData(pixt);
     wplb = pixGetWpl(pixb);
@@ -219,8 +234,7 @@
     if ((pixt = pixCreateTemplate(pixb)) == NULL)
         return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
     
-    w = pixGetWidth(pixt);
-    h = pixGetHeight(pixt);
+    pixGetDimensions(pixt, &w, &h, NULL);
     datab = pixGetData(pixb);
     datat = pixGetData(pixt);
     wplb = pixGetWpl(pixb);
@@ -330,8 +344,7 @@
     if ((pixt = pixCreateTemplate(pixb)) == NULL)
         return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
     
-    w = pixGetWidth(pixt);
-    h = pixGetHeight(pixt);
+    pixGetDimensions(pixt, &w, &h, NULL);
     datab = pixGetData(pixb);
     datat = pixGetData(pixt);
     wplb = pixGetWpl(pixb);
@@ -457,8 +470,7 @@
     if ((pixt = pixCreateTemplate(pixb)) == NULL)
         return (PIX *)ERROR_PTR("pixt not made", procName, NULL);
     
-    w = pixGetWidth(pixt);
-    h = pixGetHeight(pixt);
+    pixGetDimensions(pixt, &w, &h, NULL);
     datab = pixGetData(pixb);
     datat = pixGetData(pixt);
     wplb = pixGetWpl(pixb);
@@ -514,4 +526,505 @@
     return pixd;
 }
 
+
+/*-----------------------------------------------------------------*
+ *           Special operations for 1x3, 3x1 and 3x3 Sels          *
+ *-----------------------------------------------------------------*/
+/*!
+ *  pixErodeGray3()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *              hsize  (1 or 3)
+ *              vsize  (1 or 3)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for 1x3, 3x1 or 3x3 brick sel (all hits)
+ *      (2) If hsize = vsize = 1, just returns a copy.
+ *      (3) It would be nice not to add a border, but it is required
+ *          if we want the same results as from the general case.
+ *          We add 4 bytes on the left to speed up the copying, and
+ *          8 bytes at the right and bottom to allow unrolling of
+ *          the computation of 8 pixels.
+ */
+PIX *
+pixErodeGray3(PIX     *pixs,
+              l_int32  hsize,
+              l_int32  vsize)
+{
+PIX  *pixt, *pixb, *pixbd, *pixd;
+
+    PROCNAME("pixErodeGray3");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
+    if ((hsize != 1 && hsize != 3) ||
+        (vsize != 1 && vsize != 3))
+        return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
+
+    if (hsize == 1 && vsize == 1)
+        return pixCopy(NULL, pixs);
+
+    pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 255);
+
+    if (vsize == 1)
+        pixbd = pixErodeGray3h(pixb);
+    else if (hsize == 1)
+        pixbd = pixErodeGray3v(pixb);
+    else {  /* vize == hsize == 3 */
+        pixt = pixErodeGray3h(pixb);
+        pixbd = pixErodeGray3v(pixt);
+        pixDestroy(&pixt);
+    }
+
+    pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
+    pixDestroy(&pixb);
+    pixDestroy(&pixbd);
+    return pixd;
+}
+
+
+/*!
+ *  pixErodeGray3h()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for horizontal 3x1 brick Sel;
+ *          also used as the first step for the 3x3 brick Sel.
+ */
+static PIX *
+pixErodeGray3h(PIX  *pixs)
+{
+l_uint32  *datas, *datad, *lines, *lined;
+l_int32    w, h, wpl, i, j;
+l_int32    val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, minval;
+PIX       *pixd;
+
+    PROCNAME("pixErodeGray3h");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+
+    pixd = pixCreateTemplateNoInit(pixs);
+    pixSetBorderVal(pixd, 4, 8, 2, 8, 0);  /* only to silence valgrind */
+    pixGetDimensions(pixs, &w, &h, NULL);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    wpl = pixGetWpl(pixs);
+    for (i = 0; i < h; i++) {
+        lines = datas + i * wpl;
+        lined = datad + i * wpl;
+        for (j = 1; j < w - 8; j += 8) {
+            val0 = GET_DATA_BYTE(lines, j - 1);
+            val1 = GET_DATA_BYTE(lines, j);
+            val2 = GET_DATA_BYTE(lines, j + 1);
+            val3 = GET_DATA_BYTE(lines, j + 2);
+            val4 = GET_DATA_BYTE(lines, j + 3);
+            val5 = GET_DATA_BYTE(lines, j + 4);
+            val6 = GET_DATA_BYTE(lines, j + 5);
+            val7 = GET_DATA_BYTE(lines, j + 6);
+            val8 = GET_DATA_BYTE(lines, j + 7);
+            val9 = GET_DATA_BYTE(lines, j + 8);
+            minval = L_MIN(val1, val2);
+            SET_DATA_BYTE(lined, j, L_MIN(val0, minval));
+            SET_DATA_BYTE(lined, j + 1, L_MIN(minval, val3));
+            minval = L_MIN(val3, val4);
+            SET_DATA_BYTE(lined, j + 2, L_MIN(val2, minval));
+            SET_DATA_BYTE(lined, j + 3, L_MIN(minval, val5));
+            minval = L_MIN(val5, val6);
+            SET_DATA_BYTE(lined, j + 4, L_MIN(val4, minval));
+            SET_DATA_BYTE(lined, j + 5, L_MIN(minval, val7));
+            minval = L_MIN(val7, val8);
+            SET_DATA_BYTE(lined, j + 6, L_MIN(val6, minval));
+            SET_DATA_BYTE(lined, j + 7, L_MIN(minval, val9));
+        }
+    }
+    return pixd;
+}
+
+
+/*!
+ *  pixErodeGray3v()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for vertical 1x3 brick Sel;
+ *          also used as the second step for the 3x3 brick Sel.
+ *      (2) Surprisingly, this is faster than setting up the
+ *          lineptrs array and accessing into it; e.g.,
+ *              val4 = GET_DATA_BYTE(lines8[i + 3], j);
+ */
+static PIX *
+pixErodeGray3v(PIX  *pixs)
+{
+l_uint32  *datas, *datad, *linesi, *linedi;
+l_int32    w, h, wpl, i, j;
+l_int32    val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, minval;
+PIX       *pixd;
+
+    PROCNAME("pixErodeGray3v");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+
+    pixd = pixCreateTemplateNoInit(pixs);
+    pixGetDimensions(pixs, &w, &h, NULL);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    wpl = pixGetWpl(pixs);
+    for (j = 0; j < w; j++) {
+        for (i = 1; i < h - 8; i += 8) {
+            linesi = datas + i * wpl;
+            linedi = datad + i * wpl;
+            val0 = GET_DATA_BYTE(linesi - wpl, j);
+            val1 = GET_DATA_BYTE(linesi, j);
+            val2 = GET_DATA_BYTE(linesi + wpl, j);
+            val3 = GET_DATA_BYTE(linesi + 2 * wpl, j);
+            val4 = GET_DATA_BYTE(linesi + 3 * wpl, j);
+            val5 = GET_DATA_BYTE(linesi + 4 * wpl, j);
+            val6 = GET_DATA_BYTE(linesi + 5 * wpl, j);
+            val7 = GET_DATA_BYTE(linesi + 6 * wpl, j);
+            val8 = GET_DATA_BYTE(linesi + 7 * wpl, j);
+            val9 = GET_DATA_BYTE(linesi + 8 * wpl, j);
+            minval = L_MIN(val1, val2);
+            SET_DATA_BYTE(linedi, j, L_MIN(val0, minval));
+            SET_DATA_BYTE(linedi + wpl, j, L_MIN(minval, val3));
+            minval = L_MIN(val3, val4);
+            SET_DATA_BYTE(linedi + 2 * wpl, j, L_MIN(val2, minval));
+            SET_DATA_BYTE(linedi + 3 * wpl, j, L_MIN(minval, val5));
+            minval = L_MIN(val5, val6);
+            SET_DATA_BYTE(linedi + 4 * wpl, j, L_MIN(val4, minval));
+            SET_DATA_BYTE(linedi + 5 * wpl, j, L_MIN(minval, val7));
+            minval = L_MIN(val7, val8);
+            SET_DATA_BYTE(linedi + 6 * wpl, j, L_MIN(val6, minval));
+            SET_DATA_BYTE(linedi + 7 * wpl, j, L_MIN(minval, val9));
+        }
+    }
+    return pixd;
+}
+
+
+/*!
+ *  pixDilateGray3()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *              hsize  (1 or 3)
+ *              vsize  (1 or 3)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for 1x3, 3x1 or 3x3 brick sel (all hits)
+ *      (2) If hsize = vsize = 1, just returns a copy.
+ */
+PIX *
+pixDilateGray3(PIX     *pixs,
+               l_int32  hsize,
+               l_int32  vsize)
+{
+PIX  *pixt, *pixb, *pixbd, *pixd;
+
+    PROCNAME("pixDilateGray3");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
+    if ((hsize != 1 && hsize != 3) ||
+        (vsize != 1 && vsize != 3))
+        return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
+
+    if (hsize == 1 && vsize == 1)
+        return pixCopy(NULL, pixs);
+
+    pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0);
+
+    if (vsize == 1)
+        pixbd = pixDilateGray3h(pixb);
+    else if (hsize == 1)
+        pixbd = pixDilateGray3v(pixb);
+    else {  /* vize == hsize == 3 */
+        pixt = pixDilateGray3h(pixb);
+        pixbd = pixDilateGray3v(pixt);
+        pixDestroy(&pixt);
+    }
+
+    pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
+    pixDestroy(&pixb);
+    pixDestroy(&pixbd);
+    return pixd;
+}
+
+
+/*!
+ *  pixDilateGray3h()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for horizontal 3x1 brick Sel;
+ *          also used as the first step for the 3x3 brick Sel.
+ */
+static PIX *
+pixDilateGray3h(PIX  *pixs)
+{
+l_uint32  *datas, *datad, *lines, *lined;
+l_int32    w, h, wpl, i, j;
+l_int32    val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval;
+PIX       *pixd;
+
+    PROCNAME("pixDilateGray3h");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+
+    pixd = pixCreateTemplateNoInit(pixs);
+    pixSetBorderVal(pixd, 4, 8, 2, 8, 0);  /* only to silence valgrind */
+    pixGetDimensions(pixs, &w, &h, NULL);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    wpl = pixGetWpl(pixs);
+    for (i = 0; i < h; i++) {
+        lines = datas + i * wpl;
+        lined = datad + i * wpl;
+        for (j = 1; j < w - 8; j += 8) {
+            val0 = GET_DATA_BYTE(lines, j - 1);
+            val1 = GET_DATA_BYTE(lines, j);
+            val2 = GET_DATA_BYTE(lines, j + 1);
+            val3 = GET_DATA_BYTE(lines, j + 2);
+            val4 = GET_DATA_BYTE(lines, j + 3);
+            val5 = GET_DATA_BYTE(lines, j + 4);
+            val6 = GET_DATA_BYTE(lines, j + 5);
+            val7 = GET_DATA_BYTE(lines, j + 6);
+            val8 = GET_DATA_BYTE(lines, j + 7);
+            val9 = GET_DATA_BYTE(lines, j + 8);
+            maxval = L_MAX(val1, val2);
+            SET_DATA_BYTE(lined, j, L_MAX(val0, maxval));
+            SET_DATA_BYTE(lined, j + 1, L_MAX(maxval, val3));
+            maxval = L_MAX(val3, val4);
+            SET_DATA_BYTE(lined, j + 2, L_MAX(val2, maxval));
+            SET_DATA_BYTE(lined, j + 3, L_MAX(maxval, val5));
+            maxval = L_MAX(val5, val6);
+            SET_DATA_BYTE(lined, j + 4, L_MAX(val4, maxval));
+            SET_DATA_BYTE(lined, j + 5, L_MAX(maxval, val7));
+            maxval = L_MAX(val7, val8);
+            SET_DATA_BYTE(lined, j + 6, L_MAX(val6, maxval));
+            SET_DATA_BYTE(lined, j + 7, L_MAX(maxval, val9));
+        }
+    }
+    return pixd;
+}
+
+
+/*!
+ *  pixDilateGray3v()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for vertical 1x3 brick Sel;
+ *          also used as the second step for the 3x3 brick Sel.
+ */
+static PIX *
+pixDilateGray3v(PIX  *pixs)
+{
+l_uint32  *datas, *datad, *linesi, *linedi;
+l_int32    w, h, wpl, i, j;
+l_int32    val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval;
+PIX       *pixd;
+
+    PROCNAME("pixDilateGray3v");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+
+    pixd = pixCreateTemplateNoInit(pixs);
+    pixGetDimensions(pixs, &w, &h, NULL);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    wpl = pixGetWpl(pixs);
+    for (j = 0; j < w; j++) {
+        for (i = 1; i < h - 8; i += 8) {
+            linesi = datas + i * wpl;
+            linedi = datad + i * wpl;
+            val0 = GET_DATA_BYTE(linesi - wpl, j);
+            val1 = GET_DATA_BYTE(linesi, j);
+            val2 = GET_DATA_BYTE(linesi + wpl, j);
+            val3 = GET_DATA_BYTE(linesi + 2 * wpl, j);
+            val4 = GET_DATA_BYTE(linesi + 3 * wpl, j);
+            val5 = GET_DATA_BYTE(linesi + 4 * wpl, j);
+            val6 = GET_DATA_BYTE(linesi + 5 * wpl, j);
+            val7 = GET_DATA_BYTE(linesi + 6 * wpl, j);
+            val8 = GET_DATA_BYTE(linesi + 7 * wpl, j);
+            val9 = GET_DATA_BYTE(linesi + 8 * wpl, j);
+            maxval = L_MAX(val1, val2);
+            SET_DATA_BYTE(linedi, j, L_MAX(val0, maxval));
+            SET_DATA_BYTE(linedi + wpl, j, L_MAX(maxval, val3));
+            maxval = L_MAX(val3, val4);
+            SET_DATA_BYTE(linedi + 2 * wpl, j, L_MAX(val2, maxval));
+            SET_DATA_BYTE(linedi + 3 * wpl, j, L_MAX(maxval, val5));
+            maxval = L_MAX(val5, val6);
+            SET_DATA_BYTE(linedi + 4 * wpl, j, L_MAX(val4, maxval));
+            SET_DATA_BYTE(linedi + 5 * wpl, j, L_MAX(maxval, val7));
+            maxval = L_MAX(val7, val8);
+            SET_DATA_BYTE(linedi + 6 * wpl, j, L_MAX(val6, maxval));
+            SET_DATA_BYTE(linedi + 7 * wpl, j, L_MAX(maxval, val9));
+        }
+    }
+    return pixd;
+}
+
+
+/*!
+ *  pixOpenGray3()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *              hsize  (1 or 3)
+ *              vsize  (1 or 3)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for 1x3, 3x1 or 3x3 brick sel (all hits)
+ *      (2) If hsize = vsize = 1, just returns a copy.
+ *      (3) It would be nice not to add a border, but it is required
+ *          to get the same results as for the general case.
+ */
+PIX *
+pixOpenGray3(PIX     *pixs,
+             l_int32  hsize,
+             l_int32  vsize)
+{
+PIX  *pixt, *pixb, *pixbd, *pixd;
+
+    PROCNAME("pixOpenGray3");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
+    if ((hsize != 1 && hsize != 3) ||
+        (vsize != 1 && vsize != 3))
+        return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
+
+    if (hsize == 1 && vsize == 1)
+        return pixCopy(NULL, pixs);
+
+    pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 255);  /* set to max */
+
+    if (vsize == 1) {
+        pixt = pixErodeGray3h(pixb);
+        pixSetBorderVal(pixt, 4, 8, 2, 8, 0);  /* set to min */
+        pixbd = pixDilateGray3h(pixt);
+        pixDestroy(&pixt);
+    }
+    else if (hsize == 1) {
+        pixt = pixErodeGray3v(pixb);
+        pixSetBorderVal(pixt, 4, 8, 2, 8, 0);
+        pixbd = pixDilateGray3v(pixt);
+        pixDestroy(&pixt);
+    }
+    else {  /* vize == hsize == 3 */
+        pixt = pixErodeGray3h(pixb);
+        pixbd = pixErodeGray3v(pixt);
+        pixDestroy(&pixt);
+        pixSetBorderVal(pixbd, 4, 8, 2, 8, 0);
+        pixt = pixDilateGray3h(pixbd);
+        pixDestroy(&pixbd);
+        pixbd = pixDilateGray3v(pixt);
+        pixDestroy(&pixt);
+    }
+
+    pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
+    pixDestroy(&pixb);
+    pixDestroy(&pixbd);
+    return pixd;
+}
+
+
+/*!
+ *  pixCloseGray3()
+ *
+ *      Input:  pixs (8 bpp, not cmapped)
+ *              hsize  (1 or 3)
+ *              vsize  (1 or 3)
+ *      Return: pixd, or null on error
+ *
+ *  Notes:
+ *      (1) Special case for 1x3, 3x1 or 3x3 brick sel (all hits)
+ *      (2) If hsize = vsize = 1, just returns a copy.
+ */
+PIX *
+pixCloseGray3(PIX     *pixs,
+              l_int32  hsize,
+              l_int32  vsize)
+{
+PIX  *pixt, *pixb, *pixbd, *pixd;
+
+    PROCNAME("pixCloseGray3");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
+    if ((hsize != 1 && hsize != 3) ||
+        (vsize != 1 && vsize != 3))
+        return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
+
+    if (hsize == 1 && vsize == 1)
+        return pixCopy(NULL, pixs);
+
+    pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0);  /* set to min */
+
+    if (vsize == 1) {
+        pixt = pixDilateGray3h(pixb);
+        pixSetBorderVal(pixt, 4, 8, 2, 8, 255);  /* set to max */
+        pixbd = pixErodeGray3h(pixt);
+        pixDestroy(&pixt);
+    }
+    else if (hsize == 1) {
+        pixt = pixDilateGray3v(pixb);
+        pixSetBorderVal(pixt, 4, 8, 2, 8, 255);
+        pixbd = pixErodeGray3v(pixt);
+        pixDestroy(&pixt);
+    }
+    else {  /* vize == hsize == 3 */
+        pixt = pixDilateGray3h(pixb);
+        pixbd = pixDilateGray3v(pixt);
+        pixDestroy(&pixt);
+        pixSetBorderVal(pixbd, 4, 8, 2, 8, 255);
+        pixt = pixErodeGray3h(pixbd);
+        pixDestroy(&pixbd);
+        pixbd = pixErodeGray3v(pixt);
+        pixDestroy(&pixt);
+    }
+
+    pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
+    pixDestroy(&pixb);
+    pixDestroy(&pixbd);
+    return pixd;
+}
+
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/jpegio.c leptonlib-1.066/src/jpegio.c
--- leptonlib-1.66/src/jpegio.c	2010-03-17 22:38:20.000000000 +0200
+++ leptonlib-1.066/src/jpegio.c	2010-09-08 22:43:57.000000000 +0300
@@ -773,21 +773,37 @@
  *  
  *      Input:  inarray (binary jpeg)
  *              size (of the data array)
- *             &index (<return> location of image metadata)
+ *              &index (<return> location of image metadata)
  *      Return: 0 if OK, 1 on error.  Caller must check this!
  *  
  *  Notes:
- *      (1) The parameters listed here appear to be the only jpeg flags
+ *      (1) The metadata in jpeg files is a mess.  There are markers
+ *          for the chunks that are always preceeded by 0xff.
+ *          It is possible to have 0xff in the binary data that is
+ *          not a marker, and this is always 'escaped' by a following
+ *          0x0 byte.  The two bytes following the marker give the
+ *          chunk size, inclusive of those two bytes.  The jpeg parser
+ *          runs through the file, looking for special markers such
+ *          as 0xc0 and 0xc2 that indicate the beginning of a metadata
+ *          frame that gives the image size, depth, etc.
+ *      (2) The markers listed here appear to be the only ones that
  *          we need to worry about.  It would have been nice to have
- *          avoided the switch with all these parameters, but
+ *          avoided the switch with all these markers, but
  *          unfortunately the parser for the jpeg header is set
- *          to accept any old flag that's not on the approved list!
+ *          to accept any byte marker that's not on the approved list!
  *          So we have to look for a flag that's not on the list
- *          (and is not 0), and then interpret the size of the
- *          data chunk and skip it.  Sometimes such a chunk contains
- *          a thumbnail version of the image, so if we don't skip it,
- *          we will find a pair of bytes such as 0xffc0, followed
- *          by small w and h dimensions. 
+ *          (and is not 0 or followed by 0xff), and then interpret
+ *          the size of the data chunk and skip it.  Why do this?
+ *          Such a chunk may contain a thumbnail version of the image,
+ *          so if we don't skip it, we will find a pair of bytes such
+ *          as 0xffc0 within the chunk, followed by the metadata
+ *          (e.g., w and h dimensions) for the thumbnail.  Not what we want.
+ *      (3) We recently found jpeg files with the sequence 0xffXXff,
+ *          where XX is apparently a random marker not on the 'approved'
+ *          list.  These clearly need to be escaped, because there are
+ *          no chunks of size as great as 0xff00 that can be skipped
+ *          (remember: for chunks that must be skipped, the 2 bytes
+ *          after the marker give the chunk size).
  */
 static l_int32
 locateJpegImageParameters(l_uint8  *inarray,
@@ -804,15 +820,18 @@
     if (!pindex)
         return ERROR_INT("&index not defined", procName, 1);
 
-    index = *pindex;
+    index = 0;  /* start at the beginning of the data */
     while (1) {
         if (getNextJpegMarker(inarray, size, &index))
             break;
         if ((val = inarray[index]) == 0)  /* ignore if "escaped" */
             continue;
+        if (inarray[index + 1] == 0xff)  /* ignore if 'ff' immediately after */
+            continue;
 /*        fprintf(stderr, " marker %x at %o, %d\n", val, index, index); */
         switch(val)
         {
+            /* These are valid metadata start locations */
         case 0xc0:  /* M_SOF0 */
         case 0xc1:  /* M_SOF1 */
         case 0xc2:  /* M_SOF2 */
@@ -828,6 +847,8 @@
             *pindex = index + 1;  /* found it */
             return 0;
 
+            /* Go on -- these are on the 'approved' list and are
+             * not chunks that must be skipped */
         case 0x01:  /* M_TEM */
         case 0xd0:  /* M_RST0 */
         case 0xd1:  /* M_RST1 */
@@ -843,6 +864,7 @@
         case 0xee:  /* M_APP14 */
             break;
 
+            /* Everything else is assumed to be a chunk that must be skipped */
         default:
             skiplength = getTwoByteParameter(inarray, index + 1);
             index += skiplength;
@@ -859,10 +881,10 @@
  *
  *      Input:  array (jpeg data)
  *              size (from current point to the end)
- *             &index (<return> the last position searched.  If it
- *                     is not at the end of the array, we return
- *                     the first byte that is not 0xff, after
- *                     having encountered at least one 0xff.)
+ *              &index (input current and <return> the last position searched.
+ *                      If it is not at the end of the array, we return
+ *                      the first byte that is not 0xff, after
+ *                      having encountered at least one 0xff.)
  *      Return: 0 if a marker is found, 1 if the end of the array is reached
  *      
  *  Notes:
@@ -891,7 +913,7 @@
     if (!pindex)
         return ERROR_INT("&index not defined", procName, 1);
 
-    index = *pindex;
+    index = *pindex;  /* initial location in array */
 
     while (index < size) {  /* skip to 0xff */
        val = array[index++];    
@@ -1111,4 +1133,3 @@
 /* --------------------------------------------*/
 #endif  /* HAVE_LIBJPEG */
 /* --------------------------------------------*/
-
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/kernel.c leptonlib-1.066/src/kernel.c
--- leptonlib-1.66/src/kernel.c	2010-01-22 03:16:29.000000000 +0200
+++ leptonlib-1.066/src/kernel.c	2010-09-15 22:36:47.000000000 +0300
@@ -522,7 +522,7 @@
 L_KERNEL *
 kernelReadStream(FILE  *fp)
 {
-l_int32    sy, sx, cy, cx, i, j, ret, version;
+l_int32    sy, sx, cy, cx, i, j, ret, version, ignore;
 L_KERNEL  *kel;
 
     PROCNAME("kernelReadStream");
@@ -546,10 +546,10 @@
 
     for (i = 0; i < sy; i++) {
         for (j = 0; j < sx; j++)
-            fscanf(fp, "%15f", &kel->data[i][j]);
-        fscanf(fp, "\n");
+            ignore = fscanf(fp, "%15f", &kel->data[i][j]);
+        ignore = fscanf(fp, "\n");
     }
-    fscanf(fp, "\n");
+    ignore = fscanf(fp, "\n");
 
     return kel;
 }
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/leptprotos.h leptonlib-1.066/src/leptprotos.h
--- leptonlib-1.66/src/leptprotos.h	2010-08-08 04:26:00.000000000 +0300
+++ leptonlib-1.066/src/leptprotos.h	2010-09-23 09:31:36.000000000 +0300
@@ -615,6 +615,10 @@
 LEPT_DLL extern PIX * pixDilateGray ( PIX *pixs, l_int32 hsize, l_int32 vsize );
 LEPT_DLL extern PIX * pixOpenGray ( PIX *pixs, l_int32 hsize, l_int32 vsize );
 LEPT_DLL extern PIX * pixCloseGray ( PIX *pixs, l_int32 hsize, l_int32 vsize );
+LEPT_DLL extern PIX * pixErodeGray3 ( PIX *pixs, l_int32 hsize, l_int32 vsize );
+LEPT_DLL extern PIX * pixDilateGray3 ( PIX *pixs, l_int32 hsize, l_int32 vsize );
+LEPT_DLL extern PIX * pixOpenGray3 ( PIX *pixs, l_int32 hsize, l_int32 vsize );
+LEPT_DLL extern PIX * pixCloseGray3 ( PIX *pixs, l_int32 hsize, l_int32 vsize );
 LEPT_DLL extern void dilateGrayLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 size, l_int32 direction, l_uint8 *buffer, l_uint8 *maxarray );
 LEPT_DLL extern void erodeGrayLow ( l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 size, l_int32 direction, l_uint8 *buffer, l_uint8 *minarray );
 LEPT_DLL extern PIX * pixDitherToBinary ( PIX *pixs );
@@ -1097,15 +1101,17 @@
 LEPT_DLL extern PIX * pixClipRectangle ( PIX *pixs, BOX *box, BOX **pboxc );
 LEPT_DLL extern PIX * pixClipMasked ( PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_uint32 outval );
 LEPT_DLL extern PIX * pixResizeToMatch ( PIX *pixs, PIX *pixt, l_int32 w, l_int32 h );
-LEPT_DLL extern NUMA * pixExtractOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor );
-LEPT_DLL extern l_float32 pixAverageOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor );
-LEPT_DLL extern NUMA * pixAverageIntensityProfile ( PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 factor1, l_int32 factor2 );
-LEPT_DLL extern NUMA * pixReversalProfile ( PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 minreversal, l_int32 factor1, l_int32 factor2 );
 LEPT_DLL extern l_int32 pixClipToForeground ( PIX *pixs, PIX **ppixd, BOX **pbox );
 LEPT_DLL extern l_int32 pixClipBoxToForeground ( PIX *pixs, BOX *boxs, PIX **ppixd, BOX **pboxd );
 LEPT_DLL extern l_int32 pixScanForForeground ( PIX *pixs, BOX *box, l_int32 scanflag, l_int32 *ploc );
 LEPT_DLL extern l_int32 pixClipBoxToEdges ( PIX *pixs, BOX *boxs, l_int32 lowthresh, l_int32 highthresh, l_int32 maxwidth, l_int32 factor, PIX **ppixd, BOX **pboxd );
 LEPT_DLL extern l_int32 pixScanForEdge ( PIX *pixs, BOX *box, l_int32 lowthresh, l_int32 highthresh, l_int32 maxwidth, l_int32 factor, l_int32 scanflag, l_int32 *ploc );
+LEPT_DLL extern NUMA * pixExtractOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor );
+LEPT_DLL extern l_float32 pixAverageOnLine ( PIX *pixs, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_int32 factor );
+LEPT_DLL extern NUMA * pixAverageIntensityProfile ( PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 factor1, l_int32 factor2 );
+LEPT_DLL extern NUMA * pixReversalProfile ( PIX *pixs, l_float32 fract, l_int32 dir, l_int32 first, l_int32 last, l_int32 minreversal, l_int32 factor1, l_int32 factor2 );
+LEPT_DLL extern PIX * pixRankRowTransform ( PIX *pixs );
+LEPT_DLL extern PIX * pixRankColumnTransform ( PIX *pixs );
 LEPT_DLL extern PIXA * pixaCreate ( l_int32 n );
 LEPT_DLL extern PIXA * pixaCreateFromPix ( PIX *pixs, l_int32 n, l_int32 cellw, l_int32 cellh );
 LEPT_DLL extern PIXA * pixaCreateFromBoxa ( PIX *pixs, BOXA *boxa, l_int32 *pcropwarn );
@@ -1774,6 +1780,14 @@
 LEPT_DLL extern l_int32 lstackExtendArray ( L_STACK *lstack );
 LEPT_DLL extern l_int32 lstackGetCount ( L_STACK *lstack );
 LEPT_DLL extern l_int32 lstackPrint ( FILE *fp, L_STACK *lstack );
+LEPT_DLL extern l_int32 * sudokuReadFile ( const char *filename );
+LEPT_DLL extern l_int32 * sudokuReadString ( const char *str );
+LEPT_DLL extern L_SUDOKU * sudokuCreate ( l_int32 *array );
+LEPT_DLL extern void sudokuDestroy ( L_SUDOKU **psud );
+LEPT_DLL extern l_int32 sudokuSolve ( L_SUDOKU *sud );
+LEPT_DLL extern l_int32 sudokuTestUniqueness ( l_int32 *array, l_int32 *punique );
+LEPT_DLL extern L_SUDOKU * sudokuGenerate ( l_int32 *array, l_int32 seed, l_int32 minelems, l_int32 maxtries );
+LEPT_DLL extern l_int32 sudokuOutput ( L_SUDOKU *sud, l_int32 arraytype );
 LEPT_DLL extern PIX * pixAddSingleTextblock ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 location, l_int32 *poverflow );
 LEPT_DLL extern l_int32 pixSetTextblock ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 x0, l_int32 y0, l_int32 wtext, l_int32 firstindent, l_int32 *poverflow );
 LEPT_DLL extern l_int32 pixSetTextline ( PIX *pixs, L_BMF *bmf, const char *textstr, l_uint32 val, l_int32 x0, l_int32 y0, l_int32 *pwidth, l_int32 *poverflow );
@@ -1851,11 +1865,17 @@
 LEPT_DLL extern char * genTempFilename ( const char *dir, const char *tail, l_int32 usepid );
 LEPT_DLL extern char * mungePathnameForWindows ( const char *namein );
 LEPT_DLL extern l_int32 extractNumberFromFilename ( const char *fname, l_int32 numpre, l_int32 numpost );
+LEPT_DLL extern l_int32 genRandomIntegerInRange ( l_int32 range, l_int32 seed, l_int32 *pval );
 LEPT_DLL extern char * getLeptonlibVersion (  );
 LEPT_DLL extern char * getImagelibVersions (  );
 LEPT_DLL extern void startTimer ( void );
 LEPT_DLL extern l_float32 stopTimer ( void );
 LEPT_DLL extern l_int32 pixHtmlViewer ( const char *dirin, const char *dirout, const char *rootname, l_int32 thumbwidth, l_int32 viewwidth, l_int32 copyorig );
+LEPT_DLL extern PIX * pixReadWebP ( const char *filename );
+LEPT_DLL extern PIX * pixReadStreamWebP ( FILE *fp );
+LEPT_DLL extern l_int32 pixWriteWebP ( const char *filename, PIX *pix, l_int32 quantparam );
+LEPT_DLL extern l_int32 pixWriteStreamWebP ( FILE *fp, PIX *pix, l_int32 quantparam );
+LEPT_DLL extern l_int32 pixWriteWebPwithTargetPSNR ( const char *filename, PIX *pix, l_float64 target_psnr, l_int32 *qp_ptr );
 LEPT_DLL extern PIX * pixSimpleCaptcha ( PIX *pixs, l_int32 border, l_int32 nterms, l_uint32 seed, l_uint32 color, l_int32 cmapflag );
 LEPT_DLL extern PIX * pixRandomHarmonicWarp ( PIX *pixs, l_float32 xmag, l_float32 ymag, l_float32 xfreq, l_float32 yfreq, l_int32 nx, l_int32 ny, l_uint32 seed, l_int32 grayval );
 LEPT_DLL extern PIX * pixWarpStereoscopic ( PIX *pixs, l_int32 zbend, l_int32 zshiftt, l_int32 zshiftb, l_int32 ybendt, l_int32 ybendb, l_int32 redleft );
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/makefile leptonlib-1.066/src/makefile
--- leptonlib-1.66/src/makefile	2010-08-01 01:42:45.000000000 +0300
+++ leptonlib-1.066/src/makefile	2010-09-24 07:27:46.000000000 +0300
@@ -99,8 +99,8 @@
 #        ERROR_* logging, and to remove all DEBUG information dependent
 #        on whether or not NO_CONSOLE_IO has been defined.
 #     - use -D_CYGWIN_ENVIRON (and without -fPIC) for cygwin
-CC =		gcc -ansi -D_BSD_SOURCE -DANSI -fPIC
-#CC =		g++ -D_BSD_SOURCE -fPIC
+#CC =		gcc -ansi -D_BSD_SOURCE -DANSI -fPIC
+CC =		g++ -D_BSD_SOURCE -fPIC
 #CC =		g++ -Wunused -D_BSD_SOURCE -fPIC
 #CC =		gcc -ansi -DNO_CONSOLE_IO -D_BSD_SOURCE -DANSI -fPIC
 #CC =		gcc -ansi -D_CYGWIN_ENVIRON -DANSI
@@ -138,7 +138,7 @@
 #   Links are created among the files <libname>.X.Y,
 #   <libname>.X, and <libname>, where Y is the minor revision number.
 MAJOR_REV = 1
-MINOR_REV = 66
+MINOR_REV = 66a
 
 #########################################################
 
@@ -195,9 +195,11 @@
 		scale.c scalelow.c \
 		seedfill.c seedfilllow.c \
 		sel1.c sel2.c selgen.c \
-		shear.c skew.c spixio.c stack.c \
+		shear.c skew.c spixio.c \
+		stack.c sudoku.c \
 		textops.c tiffio.c tiffiostub.c \
 		utils.c viewfiles.c \
+		webpio.c webpiostub.c \
 		warper.c watershed.c writefile.c \
 		zlibmem.c zlibmemstub.c
 
@@ -210,7 +212,7 @@
 		leptprotos.h list.h \
 		morph.h pix.h ptra.h queue.h \
 		readbarcode.h regutils.h stack.h \
-		watershed.h
+		sudoku.h watershed.h
 
 ##################################################################
 
@@ -256,7 +258,7 @@
 #  xtractprotos
 
 xtractprotos:	dirs leptlib
-	cd ../prog; make xtractprotos
+	cd ../prog; make xtractprotos; cp xtractprotos ../src
 
 xtractprotos.o:	xtractprotos.c
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/makefile.mingw leptonlib-1.066/src/makefile.mingw
--- leptonlib-1.66/src/makefile.mingw	2010-08-01 01:43:54.000000000 +0300
+++ leptonlib-1.066/src/makefile.mingw	2010-09-16 08:46:35.000000000 +0300
@@ -125,7 +125,7 @@
 # Links are created among the files <libname>.X.Y,
 # <libname>.X, and <libname>, where Y is the minor revision number.
 MAJOR_REV = 1
-MINOR_REV = 66
+MINOR_REV = 66a
 
 #########################################################
 
@@ -183,9 +183,11 @@
 		scale.c scalelow.c \
 		seedfill.c seedfilllow.c \
 		sel1.c sel2.c selgen.c \
-		shear.c skew.c spixio.c stack.c \
+		shear.c skew.c spixio.c \
+		stack.c sudoku.c \
 		textops.c tiffio.c tiffiostub.c \
 		utils.c viewfiles.c \
+		vp8io.c vp8iostub.c \
 		warper.c watershed.c writefile.c \
 		zlibmem.c zlibmemstub.c
 
@@ -198,7 +200,7 @@
 		leptprotos.h list.h \
 		morph.h pix.h ptra.h queue.h \
 		readbarcode.h regutils.h stack.h \
-		watershed.h
+		sudoku.h watershed.h
 
 ##################################################################
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/numabasic.c leptonlib-1.066/src/numabasic.c
--- leptonlib-1.66/src/numabasic.c	2010-07-20 00:01:55.000000000 +0300
+++ leptonlib-1.066/src/numabasic.c	2010-09-16 07:54:01.000000000 +0300
@@ -954,7 +954,7 @@
 NUMA *
 numaReadStream(FILE  *fp)
 {
-l_int32    i, n, index, ret, version;
+l_int32    i, n, index, ret, version, ignore;
 l_float32  val, startx, delx;
 NUMA      *na;
 
@@ -968,7 +968,7 @@
         return (NUMA *)ERROR_PTR("not a numa file", procName, NULL);
     if (version != NUMA_VERSION_NUMBER)
         return (NUMA *)ERROR_PTR("invalid numa version", procName, NULL);
-    fscanf(fp, "Number of numbers = %d\n", &n);
+    ignore = fscanf(fp, "Number of numbers = %d\n", &n);
 
     if ((na = numaCreate(n)) == NULL)
         return (NUMA *)ERROR_PTR("na not made", procName, NULL);
@@ -1415,7 +1415,7 @@
 NUMAA *
 numaaReadStream(FILE  *fp)
 {
-l_int32    i, n, index, ret, version;
+l_int32    i, n, index, ret, version, ignore;
 NUMA      *na;
 NUMAA     *naa;
 
@@ -1429,12 +1429,12 @@
         return (NUMAA *)ERROR_PTR("not a numa file", procName, NULL);
     if (version != NUMA_VERSION_NUMBER)
         return (NUMAA *)ERROR_PTR("invalid numaa version", procName, NULL);
-    fscanf(fp, "Number of numa = %d\n\n", &n);
+    ignore = fscanf(fp, "Number of numa = %d\n\n", &n);
     if ((naa = numaaCreate(n)) == NULL)
         return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
 
     for (i = 0; i < n; i++) {
-        fscanf(fp, "Numa[%d]:", &index);
+        ignore = fscanf(fp, "Numa[%d]:", &index);
         if ((na = numaReadStream(fp)) == NULL)
             return (NUMAA *)ERROR_PTR("na not made", procName, NULL);
         numaaAddNuma(naa, na, L_INSERT);
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/pageseg.c leptonlib-1.066/src/pageseg.c
--- leptonlib-1.66/src/pageseg.c	2010-08-02 08:51:01.000000000 +0300
+++ leptonlib-1.066/src/pageseg.c	2010-09-08 22:45:39.000000000 +0300
@@ -159,7 +159,7 @@
         PTAA     *ptaa;
         ptaa = pixGetOuterBordersPtaa(pixtb);
         tempname = genTempFilename("/tmp", "tb_outlines.ptaa", 0);
-	ptaaWrite(tempname, ptaa, 1);
+        ptaaWrite(tempname, ptaa, 1);
         FREE(tempname);
         pixt1 = pixRenderRandomCmapPtaa(pixtb, ptaa, 1, 16, 1);
         cmap = pixGetColormap(pixt1);
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/parseprotos.c leptonlib-1.066/src/parseprotos.c
--- leptonlib-1.66/src/parseprotos.c	2009-07-12 04:12:56.000000000 +0300
+++ leptonlib-1.066/src/parseprotos.c	2010-09-09 10:09:13.000000000 +0300
@@ -158,12 +158,22 @@
                 start, stop, charindex); */
         str = captureProtoSignature(sa, start, stop, charindex);
 
-            /* Make sure it is not static.  Note that 'extern' has
-             * been prepended to the prototype, so the 'static'
-             * keyword, if it exists, would be the second word. */
+            /* Make sure that the signature found by cpp is neither
+             * static nor extern.  We get 'extern' declarations from
+             * header files, and with some versions of cpp running on
+             * #include <sys/stat.h> we get something of the form:
+             *    extern ... (( ... )) ... ( ... ) { ...
+             * For this, the 1st '(' is the lp, the 2nd ')' is the rp,
+             * and there is a lot of garbage between the rp and the lb.
+             * It is easiest to simply reject any signature that starts
+             * with 'extern'.  Note also that an 'extern' token has been
+             * prepended to each prototype, so the 'static' or
+             * 'extern' keywords we are looking for, if they exist,
+             * would be the second word. */
         satest = sarrayCreateWordsFromString(str);
         secondword = sarrayGetString(satest, 1, 0);
-        if (strcmp(secondword, "static")) {  /* not static */
+        if (strcmp(secondword, "static") &&  /* not static */
+            strcmp(secondword, "extern")) {  /* not extern */
             if (prestring) {  /* prepend it to the prototype */
                 newstr = stringJoin(prestring, str);
                 sarrayAddString(saout, newstr, L_INSERT);
@@ -454,7 +464,11 @@
             continue;
         }
 
-            /* OK, it should be a function definition */
+            /* OK, it should be a function definition.  We haven't
+             * checked that there is only white space between the
+             * rp and lb, but we've only seen problems with two
+             * extern inlines in sys/stat.h, and this is handled
+             * later by eliminating any prototype beginning with 'extern'. */
         *pstart = next;
         *pstop = next + soffsetrp;
         *pcharindex = boffsetrp;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/pix1.c leptonlib-1.066/src/pix1.c
--- leptonlib-1.66/src/pix1.c	2010-07-31 04:40:58.000000000 +0300
+++ leptonlib-1.066/src/pix1.c	2010-09-15 09:04:16.000000000 +0300
@@ -16,13 +16,14 @@
 /*
  *  pix1.c
  *
- *    The pixN.c {N = 1,2,3,4} files are sorted by the type of operation.
+ *    The pixN.c {N = 1,2,3,4,5} files are sorted by the type of operation.
  *    The primary functions in these files are:
  *
  *        pix1.c: constructors, destructors and field accessors
  *        pix2.c: pixel poking of image, pad and border pixels
  *        pix3.c: masking and logical ops, counting, mirrored tiling
- *        pix4.c: histograms, fg/bg estimation, rectangle extraction
+ *        pix4.c: histograms, statistics, fg/bg estimation
+ *        pix5.c: property measurements, rectangle extraction
  *
  *
  *    This file has the basic constructors, destructors and field accessors
@@ -269,7 +270,7 @@
           l_int32  height,
           l_int32  depth)
 {
-PIX       *pixd;
+PIX  *pixd;
 
     PROCNAME("pixCreate");
 
@@ -326,7 +327,7 @@
 PIX *
 pixCreateTemplate(PIX  *pixs)
 {
-PIX     *pixd;
+PIX  *pixd;
 
     PROCNAME("pixCreateTemplate");
 
@@ -385,8 +386,8 @@
                 l_int32  height,
                 l_int32  depth)
 {
-l_int32    wpl;
-PIX       *pixd;
+l_int32  wpl;
+PIX     *pixd;
 
     PROCNAME("pixCreateHeader");
 
@@ -409,7 +410,6 @@
 
     pixd->refcount = 1;
     pixd->informat = IFF_UNKNOWN;
-
     return pixd;
 }
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/pix5.c leptonlib-1.066/src/pix5.c
--- leptonlib-1.66/src/pix5.c	2010-07-20 00:01:57.000000000 +0300
+++ leptonlib-1.066/src/pix5.c	2010-09-15 09:43:51.000000000 +0300
@@ -20,8 +20,9 @@
  *
  *      (1) Measurement of 1 bpp image properties
  *      (2) Extract rectangular region
- *      (3) Extract pixel averages and reversals along lines
- *      (4) Clip to foreground
+ *      (3) Clip to foreground
+ *      (4) Extract pixel averages and reversals along lines
+ *      (5) Rank row and column transforms
  *
  *    Measurement of properties
  *           l_int32     pixaFindDimensions()
@@ -42,18 +43,22 @@
  *           PIX        *pixClipMasked()
  *           PIX        *pixResizeToMatch()
  *
- *    Extract pixel averages and reversals along lines
- *           NUMA       *pixExtractOnLine()
- *           l_float32   pixAverageOnLine();
- *           NUMA       *pixAverageIntensityProfile()
- *           NUMA       *pixReversalProfile()
- *
  *    Clip to foreground
  *           PIX        *pixClipToForeground()
  *           l_int32     pixClipBoxToForeground()
  *           l_int32     pixScanForForeground()
  *           l_int32     pixClipBoxToEdges()
  *           l_int32     pixScanForEdge()
+ *
+ *    Extract pixel averages and reversals along lines
+ *           NUMA       *pixExtractOnLine()
+ *           l_float32   pixAverageOnLine();
+ *           NUMA       *pixAverageIntensityProfile()
+ *           NUMA       *pixReversalProfile()
+ *
+ *    Rank row and column transforms
+ *           PIX        *pixRankRowTransform()
+ *           PIX        *pixRankColumnTransform()
  */
 
 #include <stdio.h>
@@ -875,399 +880,6 @@
 
 
 /*---------------------------------------------------------------------*
- *           Extract pixel averages and reversals along lines          *
- *---------------------------------------------------------------------*/
-/*!
- *  pixExtractOnLine()
- *
- *      Input:  pixs (1 bpp or 8 bpp; no colormap)
- *              x1, y1 (starting pt for line)
- *              x2, y2 (end pt for line)
- *              factor (sampling; >= 1)
- *      Return: na (of pixel values along line), or null on error.
- *
- *  Notes:
- *      (1) The line must be either horizontal or vertical, so either
- *          y1 == y2 (horizontal) or x1 == x2 (vertical).
- *      (2) If horizontal, x1 must be <= x2.
- *          If vertical, y1 must be <= y2.
- *      (3) Input end points are clipped to the pix.
- *      (4) Can be used with numaCountReverals(), for example, to
- *          characterize the intensity smoothness along a line.
- */
-NUMA *
-pixExtractOnLine(PIX     *pixs,
-                 l_int32  x1,
-                 l_int32  y1,
-                 l_int32  x2,
-                 l_int32  y2,
-                 l_int32  factor)
-{
-l_int32   i, w, h, d, direction;
-l_uint32  val;
-NUMA     *na;
-
-    PROCNAME("pixExtractOnLine");
-
-    if (!pixs)
-        return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
-    pixGetDimensions(pixs, &w, &h, &d);
-    if (d != 1 && d != 8)
-        return (NUMA *)ERROR_PTR("d not 1 or 8 bpp", procName, NULL);
-    if (pixGetColormap(pixs))
-        return (NUMA *)ERROR_PTR("pixs has a colormap", procName, NULL);
-    if (x1 > x2 || y1 > y2)
-        return (NUMA *)ERROR_PTR("x1 > x2 or y1 > y2", procName, NULL);
-    if (y1 == y2) {
-        x1 = L_MAX(0, x1);
-        x2 = L_MIN(w - 1, x2);
-        y1 = L_MAX(0, L_MIN(y1, h - 1));
-        direction = L_HORIZONTAL_LINE;
-    }
-    else if (x1 == x2) {
-        y1 = L_MAX(0, y1);
-        y2 = L_MIN(h - 1, y2);
-        x1 = L_MAX(0, L_MIN(x1, w - 1));
-        direction = L_VERTICAL_LINE;
-    }
-    if (y1 == y2)
-        direction = L_HORIZONTAL_LINE;
-    else if (x1 == x2)
-        direction = L_VERTICAL_LINE;
-    else
-        return (NUMA *)ERROR_PTR("line neither horiz nor vert", procName, NULL);
-    if (factor < 1) {
-        L_WARNING("factor must be >= 1; setting to 1", procName);
-        factor = 1;
-    }
-
-    na = numaCreate(0);
-    if (direction == L_HORIZONTAL_LINE) {
-        numaSetXParameters(na, x1, factor);
-        for (i = x1; i <= x2; i += factor) {
-            pixGetPixel(pixs, i, y1, &val);
-            numaAddNumber(na, val);
-        }
-    } else if (direction == L_VERTICAL_LINE) {
-        numaSetXParameters(na, y1, factor);
-        for (i = y1; i <= y2; i += factor) {
-            pixGetPixel(pixs, x1, i, &val);
-            numaAddNumber(na, val);
-        }
-    }
-
-    return na;
-}
-
-
-/*!
- *  pixAverageOnLine()
- *
- *      Input:  pixs (1 bpp or 8 bpp; no colormap)
- *              x1, y1 (starting pt for line)
- *              x2, y2 (end pt for line)
- *              factor (sampling; >= 1)
- *      Return: average of pixel values along line, or null on error.
- *
- *  Notes:
- *      (1) The line must be either horizontal or vertical, so either
- *          y1 == y2 (horizontal) or x1 == x2 (vertical).
- *      (2) If horizontal, x1 must be <= x2.
- *          If vertical, y1 must be <= y2.
- *          characterize the intensity smoothness along a line.
- *      (3) Input end points are clipped to the pix.
- */
-l_float32
-pixAverageOnLine(PIX     *pixs,
-                 l_int32  x1,
-                 l_int32  y1,
-                 l_int32  x2,
-                 l_int32  y2,
-                 l_int32  factor)
-{
-l_int32    i, j, w, h, d, direction, count, wpl;
-l_uint32  *data, *line;
-l_float32  sum;
-
-    PROCNAME("pixAverageOnLine");
-
-    if (!pixs)
-        return ERROR_INT("pixs not defined", procName, 1);
-    pixGetDimensions(pixs, &w, &h, &d);
-    if (d != 1 && d != 8)
-        return ERROR_INT("d not 1 or 8 bpp", procName, 1);
-    if (pixGetColormap(pixs))
-        return ERROR_INT("pixs has a colormap", procName, 1);
-    if (x1 > x2 || y1 > y2)
-        return ERROR_INT("x1 > x2 or y1 > y2", procName, 1);
-    if (y1 == y2) {
-        x1 = L_MAX(0, x1);
-        x2 = L_MIN(w - 1, x2);
-        y1 = L_MAX(0, L_MIN(y1, h - 1));
-        direction = L_HORIZONTAL_LINE;
-    }
-    else if (x1 == x2) {
-        y1 = L_MAX(0, y1);
-        y2 = L_MIN(h - 1, y2);
-        x1 = L_MAX(0, L_MIN(x1, w - 1));
-        direction = L_VERTICAL_LINE;
-    }
-    else
-        return ERROR_INT("line neither horiz nor vert", procName, 1);
-    if (factor < 1) {
-        L_WARNING("factor must be >= 1; setting to 1", procName);
-        factor = 1;
-    }
-
-    data = pixGetData(pixs);
-    wpl = pixGetWpl(pixs);
-    sum = 0;
-    if (direction == L_HORIZONTAL_LINE) {
-        line = data + y1 * wpl;
-        for (j = x1, count = 0; j <= x2; count++, j += factor) {
-            if (d == 1)
-                sum += GET_DATA_BIT(line, j);
-            else  /* d == 8 */
-                sum += GET_DATA_BYTE(line, j);
-        }
-    }
-    else if (direction == L_VERTICAL_LINE) {
-        for (i = y1, count = 0; i <= y2; count++, i += factor) {
-            line = data + i * wpl;
-            if (d == 1)
-                sum += GET_DATA_BIT(line, x1);
-            else  /* d == 8 */
-                sum += GET_DATA_BYTE(line, x1);
-        }
-    }
-
-    return sum / (l_float32)count;
-}
-
-
-/*!
- *  pixAverageIntensityProfile()
- *
- *      Input:  pixs (any depth; colormap OK)
- *              fract (fraction of image width or height to be used)
- *              dir (averaging direction: L_HORIZONTAL_LINE or L_VERTICAL_LINE)
- *              first, last (span of rows or columns to measure)
- *              factor1 (sampling along fast scan direction; >= 1)
- *              factor2 (sampling along slow scan direction; >= 1)
- *      Return: na (of reversal profile), or null on error.
- *
- *  Notes:
- *      (1) If d != 1 bpp, colormaps are removed and the result
- *          is converted to 8 bpp.
- *      (2) If @dir == L_HORIZONTAL_LINE, the intensity is averaged
- *          along each horizontal raster line (sampled by @factor1),
- *          and the profile is the array of these averages in the
- *          vertical direction between @first and @last raster lines,
- *          and sampled by @factor2.
- *      (3) If @dir == L_VERTICAL_LINE, the intensity is averaged
- *          along each vertical line (sampled by @factor1),
- *          and the profile is the array of these averages in the
- *          horizontal direction between @first and @last columns,
- *          and sampled by @factor2.
- *      (4) The averages are measured over the central @fract of the image.
- *          Use @fract == 1.0 to average across the entire width or height.
- */
-NUMA *
-pixAverageIntensityProfile(PIX       *pixs,
-                           l_float32  fract,
-                           l_int32    dir,
-                           l_int32    first,
-                           l_int32    last,
-                           l_int32    factor1,
-                           l_int32    factor2)
-{
-l_int32    i, j, w, h, d, start, end;
-l_float32  ave;
-NUMA      *nad;
-PIX       *pixr, *pixg;
-
-    PROCNAME("pixAverageIntensityProfile");
-
-    if (!pixs)
-        return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
-    if (fract < 0.0 || fract > 1.0)
-        return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
-    if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
-        return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
-    if (first < 0) first = 0;
-    if (last < first)
-        return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
-    if (factor1 < 1) {
-        L_WARNING("factor1 must be >= 1; setting to 1", procName);
-        factor1 = 1;
-    }
-    if (factor2 < 1) {
-        L_WARNING("factor2 must be >= 1; setting to 1", procName);
-        factor2 = 1;
-    }
-
-        /* Use 1 or 8 bpp, without colormap */
-    if (pixGetColormap(pixs))
-        pixr = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
-    else
-        pixr = pixClone(pixs);
-    pixGetDimensions(pixr, &w, &h, &d);
-    if (d == 1)
-        pixg = pixClone(pixr);
-    else
-        pixg = pixConvertTo8(pixr, 0);
-
-    nad = numaCreate(0);  /* output: samples in slow scan direction */
-    numaSetXParameters(nad, 0, factor2);
-    if (dir == L_HORIZONTAL_LINE) {
-        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
-        end = w - start;
-        if (last > h - 1) {
-            L_WARNING("last > h - 1; clipping", procName);
-            last = h - 1;
-        }
-        for (i = first; i <= last; i += factor2) {
-            ave = pixAverageOnLine(pixg, start, i, end, i, factor1);
-            numaAddNumber(nad, ave);
-        }
-    } else if (dir == L_VERTICAL_LINE) {
-        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
-        end = h - start;
-        if (last > w - 1) {
-            L_WARNING("last > w - 1; clipping", procName);
-            last = w - 1;
-        }
-        for (j = first; j <= last; j += factor2) {
-            ave = pixAverageOnLine(pixg, j, start, j, end, factor1);
-            numaAddNumber(nad, ave);
-        }
-    }
-
-    pixDestroy(&pixr);
-    pixDestroy(&pixg);
-    return nad;
-}
-
-
-/*!
- *  pixReversalProfile()
- *
- *      Input:  pixs (any depth; colormap OK)
- *              fract (fraction of image width or height to be used)
- *              dir (profile direction: L_HORIZONTAL_LINE or L_VERTICAL_LINE)
- *              first, last (span of rows or columns to measure)
- *              minreversal (minimum change in intensity to trigger a reversal)
- *              factor1 (sampling along raster line (fast scan); >= 1)
- *              factor2 (sampling of raster lines (slow scan); >= 1)
- *      Return: na (of reversal profile), or null on error.
- *
- *  Notes:
- *      (1) If d != 1 bpp, colormaps are removed and the result
- *          is converted to 8 bpp.
- *      (2) If @dir == L_HORIZONTAL_LINE, the the reversals are counted
- *          along each horizontal raster line (sampled by @factor1),
- *          and the profile is the array of these sums in the
- *          vertical direction between @first and @last raster lines,
- *          and sampled by @factor2.
- *      (3) If @dir == L_VERTICAL_LINE, the the reversals are counted
- *          along each vertical column (sampled by @factor1),
- *          and the profile is the array of these sums in the
- *          horizontal direction between @first and @last columns,
- *          and sampled by @factor2.
- *      (4) For each row or column, the reversals are summed over the
- *          central @fract of the image.  Use @fract == 1.0 to sum
- *          across the entire width (of row) or height (of column).
- *      (5) @minreversal is the relative change in intensity that is
- *          required to resolve peaks and valleys.  A typical number for
- *          locating text in 8 bpp might be 50.  For 1 bpp, minreversal
- *          must be 1.
- *      (6) The reversal profile is simply the number of reversals
- *          in a row or column, vs the row or column index.
- */
-NUMA *
-pixReversalProfile(PIX       *pixs,
-                   l_float32  fract,
-                   l_int32    dir,
-                   l_int32    first,
-                   l_int32    last,
-                   l_int32    minreversal,
-                   l_int32    factor1,
-                   l_int32    factor2)
-{
-l_int32   i, j, w, h, d, start, end, nr;
-NUMA     *naline, *nad;
-PIX      *pixr, *pixg;
-
-    PROCNAME("pixReversalProfile");
-
-    if (!pixs)
-        return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
-    if (fract < 0.0 || fract > 1.0)
-        return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
-    if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
-        return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
-    if (first < 0) first = 0;
-    if (last < first)
-        return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
-    if (factor1 < 1) {
-        L_WARNING("factor1 must be >= 1; setting to 1", procName);
-        factor1 = 1;
-    }
-    if (factor2 < 1) {
-        L_WARNING("factor2 must be >= 1; setting to 1", procName);
-        factor2 = 1;
-    }
-
-        /* Use 1 or 8 bpp, without colormap */
-    if (pixGetColormap(pixs))
-        pixr = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
-    else
-        pixr = pixClone(pixs);
-    pixGetDimensions(pixr, &w, &h, &d);
-    if (d == 1) {
-        pixg = pixClone(pixr);
-        minreversal = 1;  /* enforce this */
-    }
-    else
-        pixg = pixConvertTo8(pixr, 0);
-
-    nad = numaCreate(0);  /* output: samples in slow scan direction */
-    numaSetXParameters(nad, 0, factor2);
-    if (dir == L_HORIZONTAL_LINE) {
-        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
-        end = w - start;
-        if (last > h - 1) {
-            L_WARNING("last > h - 1; clipping", procName);
-            last = h - 1;
-        }
-        for (i = first; i <= last; i += factor2) {
-            naline = pixExtractOnLine(pixg, start, i, end, i, factor1);
-            numaCountReversals(naline, minreversal, &nr, NULL);
-            numaAddNumber(nad, nr);
-            numaDestroy(&naline);
-        }
-    } else if (dir == L_VERTICAL_LINE) {
-        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
-        end = h - start;
-        if (last > w - 1) {
-            L_WARNING("last > w - 1; clipping", procName);
-            last = w - 1;
-        }
-        for (j = first; j <= last; j += factor2) {
-            naline = pixExtractOnLine(pixg, j, start, j, end, factor1);
-            numaCountReversals(naline, minreversal, &nr, NULL);
-            numaAddNumber(nad, nr);
-            numaDestroy(&naline);
-        }
-    }
-
-    pixDestroy(&pixr);
-    pixDestroy(&pixg);
-    return nad;
-}
-
-
-/*---------------------------------------------------------------------*
  *                           Clip to Foreground                        *
  *---------------------------------------------------------------------*/
 /*!
@@ -1846,3 +1458,504 @@
     return 1;  /* edge not found */
 }
 
+
+/*---------------------------------------------------------------------*
+ *           Extract pixel averages and reversals along lines          *
+ *---------------------------------------------------------------------*/
+/*!
+ *  pixExtractOnLine()
+ *
+ *      Input:  pixs (1 bpp or 8 bpp; no colormap)
+ *              x1, y1 (starting pt for line)
+ *              x2, y2 (end pt for line)
+ *              factor (sampling; >= 1)
+ *      Return: na (of pixel values along line), or null on error.
+ *
+ *  Notes:
+ *      (1) The line must be either horizontal or vertical, so either
+ *          y1 == y2 (horizontal) or x1 == x2 (vertical).
+ *      (2) If horizontal, x1 must be <= x2.
+ *          If vertical, y1 must be <= y2.
+ *      (3) Input end points are clipped to the pix.
+ *      (4) Can be used with numaCountReverals(), for example, to
+ *          characterize the intensity smoothness along a line.
+ */
+NUMA *
+pixExtractOnLine(PIX     *pixs,
+                 l_int32  x1,
+                 l_int32  y1,
+                 l_int32  x2,
+                 l_int32  y2,
+                 l_int32  factor)
+{
+l_int32   i, w, h, d, direction;
+l_uint32  val;
+NUMA     *na;
+
+    PROCNAME("pixExtractOnLine");
+
+    if (!pixs)
+        return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
+    pixGetDimensions(pixs, &w, &h, &d);
+    if (d != 1 && d != 8)
+        return (NUMA *)ERROR_PTR("d not 1 or 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (NUMA *)ERROR_PTR("pixs has a colormap", procName, NULL);
+    if (x1 > x2 || y1 > y2)
+        return (NUMA *)ERROR_PTR("x1 > x2 or y1 > y2", procName, NULL);
+    if (y1 == y2) {
+        x1 = L_MAX(0, x1);
+        x2 = L_MIN(w - 1, x2);
+        y1 = L_MAX(0, L_MIN(y1, h - 1));
+        direction = L_HORIZONTAL_LINE;
+    }
+    else if (x1 == x2) {
+        y1 = L_MAX(0, y1);
+        y2 = L_MIN(h - 1, y2);
+        x1 = L_MAX(0, L_MIN(x1, w - 1));
+        direction = L_VERTICAL_LINE;
+    }
+    if (y1 == y2)
+        direction = L_HORIZONTAL_LINE;
+    else if (x1 == x2)
+        direction = L_VERTICAL_LINE;
+    else
+        return (NUMA *)ERROR_PTR("line neither horiz nor vert", procName, NULL);
+    if (factor < 1) {
+        L_WARNING("factor must be >= 1; setting to 1", procName);
+        factor = 1;
+    }
+
+    na = numaCreate(0);
+    if (direction == L_HORIZONTAL_LINE) {
+        numaSetXParameters(na, x1, factor);
+        for (i = x1; i <= x2; i += factor) {
+            pixGetPixel(pixs, i, y1, &val);
+            numaAddNumber(na, val);
+        }
+    } else if (direction == L_VERTICAL_LINE) {
+        numaSetXParameters(na, y1, factor);
+        for (i = y1; i <= y2; i += factor) {
+            pixGetPixel(pixs, x1, i, &val);
+            numaAddNumber(na, val);
+        }
+    }
+
+    return na;
+}
+
+
+/*!
+ *  pixAverageOnLine()
+ *
+ *      Input:  pixs (1 bpp or 8 bpp; no colormap)
+ *              x1, y1 (starting pt for line)
+ *              x2, y2 (end pt for line)
+ *              factor (sampling; >= 1)
+ *      Return: average of pixel values along line, or null on error.
+ *
+ *  Notes:
+ *      (1) The line must be either horizontal or vertical, so either
+ *          y1 == y2 (horizontal) or x1 == x2 (vertical).
+ *      (2) If horizontal, x1 must be <= x2.
+ *          If vertical, y1 must be <= y2.
+ *          characterize the intensity smoothness along a line.
+ *      (3) Input end points are clipped to the pix.
+ */
+l_float32
+pixAverageOnLine(PIX     *pixs,
+                 l_int32  x1,
+                 l_int32  y1,
+                 l_int32  x2,
+                 l_int32  y2,
+                 l_int32  factor)
+{
+l_int32    i, j, w, h, d, direction, count, wpl;
+l_uint32  *data, *line;
+l_float32  sum;
+
+    PROCNAME("pixAverageOnLine");
+
+    if (!pixs)
+        return ERROR_INT("pixs not defined", procName, 1);
+    pixGetDimensions(pixs, &w, &h, &d);
+    if (d != 1 && d != 8)
+        return ERROR_INT("d not 1 or 8 bpp", procName, 1);
+    if (pixGetColormap(pixs))
+        return ERROR_INT("pixs has a colormap", procName, 1);
+    if (x1 > x2 || y1 > y2)
+        return ERROR_INT("x1 > x2 or y1 > y2", procName, 1);
+    if (y1 == y2) {
+        x1 = L_MAX(0, x1);
+        x2 = L_MIN(w - 1, x2);
+        y1 = L_MAX(0, L_MIN(y1, h - 1));
+        direction = L_HORIZONTAL_LINE;
+    }
+    else if (x1 == x2) {
+        y1 = L_MAX(0, y1);
+        y2 = L_MIN(h - 1, y2);
+        x1 = L_MAX(0, L_MIN(x1, w - 1));
+        direction = L_VERTICAL_LINE;
+    }
+    else
+        return ERROR_INT("line neither horiz nor vert", procName, 1);
+    if (factor < 1) {
+        L_WARNING("factor must be >= 1; setting to 1", procName);
+        factor = 1;
+    }
+
+    data = pixGetData(pixs);
+    wpl = pixGetWpl(pixs);
+    sum = 0;
+    if (direction == L_HORIZONTAL_LINE) {
+        line = data + y1 * wpl;
+        for (j = x1, count = 0; j <= x2; count++, j += factor) {
+            if (d == 1)
+                sum += GET_DATA_BIT(line, j);
+            else  /* d == 8 */
+                sum += GET_DATA_BYTE(line, j);
+        }
+    }
+    else if (direction == L_VERTICAL_LINE) {
+        for (i = y1, count = 0; i <= y2; count++, i += factor) {
+            line = data + i * wpl;
+            if (d == 1)
+                sum += GET_DATA_BIT(line, x1);
+            else  /* d == 8 */
+                sum += GET_DATA_BYTE(line, x1);
+        }
+    }
+
+    return sum / (l_float32)count;
+}
+
+
+/*!
+ *  pixAverageIntensityProfile()
+ *
+ *      Input:  pixs (any depth; colormap OK)
+ *              fract (fraction of image width or height to be used)
+ *              dir (averaging direction: L_HORIZONTAL_LINE or L_VERTICAL_LINE)
+ *              first, last (span of rows or columns to measure)
+ *              factor1 (sampling along fast scan direction; >= 1)
+ *              factor2 (sampling along slow scan direction; >= 1)
+ *      Return: na (of reversal profile), or null on error.
+ *
+ *  Notes:
+ *      (1) If d != 1 bpp, colormaps are removed and the result
+ *          is converted to 8 bpp.
+ *      (2) If @dir == L_HORIZONTAL_LINE, the intensity is averaged
+ *          along each horizontal raster line (sampled by @factor1),
+ *          and the profile is the array of these averages in the
+ *          vertical direction between @first and @last raster lines,
+ *          and sampled by @factor2.
+ *      (3) If @dir == L_VERTICAL_LINE, the intensity is averaged
+ *          along each vertical line (sampled by @factor1),
+ *          and the profile is the array of these averages in the
+ *          horizontal direction between @first and @last columns,
+ *          and sampled by @factor2.
+ *      (4) The averages are measured over the central @fract of the image.
+ *          Use @fract == 1.0 to average across the entire width or height.
+ */
+NUMA *
+pixAverageIntensityProfile(PIX       *pixs,
+                           l_float32  fract,
+                           l_int32    dir,
+                           l_int32    first,
+                           l_int32    last,
+                           l_int32    factor1,
+                           l_int32    factor2)
+{
+l_int32    i, j, w, h, d, start, end;
+l_float32  ave;
+NUMA      *nad;
+PIX       *pixr, *pixg;
+
+    PROCNAME("pixAverageIntensityProfile");
+
+    if (!pixs)
+        return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (fract < 0.0 || fract > 1.0)
+        return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
+    if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
+        return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
+    if (first < 0) first = 0;
+    if (last < first)
+        return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
+    if (factor1 < 1) {
+        L_WARNING("factor1 must be >= 1; setting to 1", procName);
+        factor1 = 1;
+    }
+    if (factor2 < 1) {
+        L_WARNING("factor2 must be >= 1; setting to 1", procName);
+        factor2 = 1;
+    }
+
+        /* Use 1 or 8 bpp, without colormap */
+    if (pixGetColormap(pixs))
+        pixr = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
+    else
+        pixr = pixClone(pixs);
+    pixGetDimensions(pixr, &w, &h, &d);
+    if (d == 1)
+        pixg = pixClone(pixr);
+    else
+        pixg = pixConvertTo8(pixr, 0);
+
+    nad = numaCreate(0);  /* output: samples in slow scan direction */
+    numaSetXParameters(nad, 0, factor2);
+    if (dir == L_HORIZONTAL_LINE) {
+        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
+        end = w - start;
+        if (last > h - 1) {
+            L_WARNING("last > h - 1; clipping", procName);
+            last = h - 1;
+        }
+        for (i = first; i <= last; i += factor2) {
+            ave = pixAverageOnLine(pixg, start, i, end, i, factor1);
+            numaAddNumber(nad, ave);
+        }
+    } else if (dir == L_VERTICAL_LINE) {
+        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
+        end = h - start;
+        if (last > w - 1) {
+            L_WARNING("last > w - 1; clipping", procName);
+            last = w - 1;
+        }
+        for (j = first; j <= last; j += factor2) {
+            ave = pixAverageOnLine(pixg, j, start, j, end, factor1);
+            numaAddNumber(nad, ave);
+        }
+    }
+
+    pixDestroy(&pixr);
+    pixDestroy(&pixg);
+    return nad;
+}
+
+
+/*!
+ *  pixReversalProfile()
+ *
+ *      Input:  pixs (any depth; colormap OK)
+ *              fract (fraction of image width or height to be used)
+ *              dir (profile direction: L_HORIZONTAL_LINE or L_VERTICAL_LINE)
+ *              first, last (span of rows or columns to measure)
+ *              minreversal (minimum change in intensity to trigger a reversal)
+ *              factor1 (sampling along raster line (fast scan); >= 1)
+ *              factor2 (sampling of raster lines (slow scan); >= 1)
+ *      Return: na (of reversal profile), or null on error.
+ *
+ *  Notes:
+ *      (1) If d != 1 bpp, colormaps are removed and the result
+ *          is converted to 8 bpp.
+ *      (2) If @dir == L_HORIZONTAL_LINE, the the reversals are counted
+ *          along each horizontal raster line (sampled by @factor1),
+ *          and the profile is the array of these sums in the
+ *          vertical direction between @first and @last raster lines,
+ *          and sampled by @factor2.
+ *      (3) If @dir == L_VERTICAL_LINE, the the reversals are counted
+ *          along each vertical column (sampled by @factor1),
+ *          and the profile is the array of these sums in the
+ *          horizontal direction between @first and @last columns,
+ *          and sampled by @factor2.
+ *      (4) For each row or column, the reversals are summed over the
+ *          central @fract of the image.  Use @fract == 1.0 to sum
+ *          across the entire width (of row) or height (of column).
+ *      (5) @minreversal is the relative change in intensity that is
+ *          required to resolve peaks and valleys.  A typical number for
+ *          locating text in 8 bpp might be 50.  For 1 bpp, minreversal
+ *          must be 1.
+ *      (6) The reversal profile is simply the number of reversals
+ *          in a row or column, vs the row or column index.
+ */
+NUMA *
+pixReversalProfile(PIX       *pixs,
+                   l_float32  fract,
+                   l_int32    dir,
+                   l_int32    first,
+                   l_int32    last,
+                   l_int32    minreversal,
+                   l_int32    factor1,
+                   l_int32    factor2)
+{
+l_int32   i, j, w, h, d, start, end, nr;
+NUMA     *naline, *nad;
+PIX      *pixr, *pixg;
+
+    PROCNAME("pixReversalProfile");
+
+    if (!pixs)
+        return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (fract < 0.0 || fract > 1.0)
+        return (NUMA *)ERROR_PTR("fract < 0.0 or > 1.0", procName, NULL);
+    if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
+        return (NUMA *)ERROR_PTR("invalid direction", procName, NULL);
+    if (first < 0) first = 0;
+    if (last < first)
+        return (NUMA *)ERROR_PTR("last must be >= first", procName, NULL);
+    if (factor1 < 1) {
+        L_WARNING("factor1 must be >= 1; setting to 1", procName);
+        factor1 = 1;
+    }
+    if (factor2 < 1) {
+        L_WARNING("factor2 must be >= 1; setting to 1", procName);
+        factor2 = 1;
+    }
+
+        /* Use 1 or 8 bpp, without colormap */
+    if (pixGetColormap(pixs))
+        pixr = pixRemoveColormap(pixs, REMOVE_CMAP_TO_GRAYSCALE);
+    else
+        pixr = pixClone(pixs);
+    pixGetDimensions(pixr, &w, &h, &d);
+    if (d == 1) {
+        pixg = pixClone(pixr);
+        minreversal = 1;  /* enforce this */
+    }
+    else
+        pixg = pixConvertTo8(pixr, 0);
+
+    nad = numaCreate(0);  /* output: samples in slow scan direction */
+    numaSetXParameters(nad, 0, factor2);
+    if (dir == L_HORIZONTAL_LINE) {
+        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)w);
+        end = w - start;
+        if (last > h - 1) {
+            L_WARNING("last > h - 1; clipping", procName);
+            last = h - 1;
+        }
+        for (i = first; i <= last; i += factor2) {
+            naline = pixExtractOnLine(pixg, start, i, end, i, factor1);
+            numaCountReversals(naline, minreversal, &nr, NULL);
+            numaAddNumber(nad, nr);
+            numaDestroy(&naline);
+        }
+    } else if (dir == L_VERTICAL_LINE) {
+        start = (l_int32)(0.5 * (1.0 - fract) * (l_float32)h);
+        end = h - start;
+        if (last > w - 1) {
+            L_WARNING("last > w - 1; clipping", procName);
+            last = w - 1;
+        }
+        for (j = first; j <= last; j += factor2) {
+            naline = pixExtractOnLine(pixg, j, start, j, end, factor1);
+            numaCountReversals(naline, minreversal, &nr, NULL);
+            numaAddNumber(nad, nr);
+            numaDestroy(&naline);
+        }
+    }
+
+    pixDestroy(&pixr);
+    pixDestroy(&pixg);
+    return nad;
+}
+
+
+/*---------------------------------------------------------------------*
+ *                     Rank row and column transforms                  *
+ *---------------------------------------------------------------------*/
+/*!
+ *  pixRankRowTransform()
+ *
+ *      Input:  pixs (8 bpp; no colormap)
+ *      Return: pixd (with pixels sorted in each row, from
+ *                    min to max value)
+ *
+ * Notes:
+ *     (1) The time is O(n) in the number of pixels and runs about
+ *         100 Mpixels/sec on a 3 GHz machine.
+ */
+PIX *
+pixRankRowTransform(PIX  *pixs)
+{
+l_int32    i, j, k, m, w, h, wpl, index, val; 
+l_int32    histo[256];
+l_uint32  *datas, *datad, *lines, *lined;
+PIX       *pixd;
+
+    PROCNAME("pixRankRowTransform");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (PIX *)ERROR_PTR("pixs has a colormap", procName, NULL);
+
+    pixGetDimensions(pixs, &w, &h, NULL);
+    pixd = pixCreateTemplateNoInit(pixs);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    wpl = pixGetWpl(pixs);
+    for (i = 0; i < h; i++) {
+        memset(histo, 0, 1024);
+        lines = datas + i * wpl;
+        lined = datad + i * wpl;
+        for (j = 0; j < w; j++) {
+            val = GET_DATA_BYTE(lines, j);
+            histo[val]++;
+        }
+        for (m = 0, j = 0; m < 256; m++) {
+            for (k = 0; k < histo[m]; k++, j++)
+                SET_DATA_BYTE(lined, j, m);
+        }
+    }
+
+    return pixd;
+}
+
+
+/*!
+ *  pixRankColumnTransform()
+ *
+ *      Input:  pixs (8 bpp; no colormap)
+ *      Return: pixd (with pixels sorted in each column, from
+ *                    min to max value)
+ *
+ * Notes:
+ *     (1) The time is O(n) in the number of pixels and runs about
+ *         50 Mpixels/sec on a 3 GHz machine.
+ */
+PIX *
+pixRankColumnTransform(PIX  *pixs)
+{
+l_int32    i, j, k, m, w, h, wpl, val; 
+l_int32    histo[256];
+l_uint32  *datas, *datad;
+void     **lines8, **lined8;
+PIX       *pixd;
+
+    PROCNAME("pixRankColumnTransform");
+
+    if (!pixs)
+        return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
+    if (pixGetDepth(pixs) != 8)
+        return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
+    if (pixGetColormap(pixs))
+        return (PIX *)ERROR_PTR("pixs has a colormap", procName, NULL);
+
+    pixGetDimensions(pixs, &w, &h, NULL);
+    pixd = pixCreateTemplateNoInit(pixs);
+    datas = pixGetData(pixs);
+    datad = pixGetData(pixd);
+    wpl = pixGetWpl(pixs);
+    lines8 = pixGetLinePtrs(pixs, NULL);
+    lined8 = pixGetLinePtrs(pixd, NULL);
+    for (j = 0; j < w; j++) {
+        memset(histo, 0, 1024);
+        for (i = 0; i < h; i++) {
+            val = GET_DATA_BYTE(lines8[i], j);
+            histo[val]++;
+        }
+        for (m = 0, i = 0; m < 256; m++) {
+            for (k = 0; k < histo[m]; k++, i++)
+                SET_DATA_BYTE(lined8[i], j, m);
+        }
+    }
+
+    FREE(lines8);
+    FREE(lined8);
+    return pixd;
+}
+
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/pixcomp.c leptonlib-1.066/src/pixcomp.c
--- leptonlib-1.66/src/pixcomp.c	2010-03-24 18:13:02.000000000 +0200
+++ leptonlib-1.066/src/pixcomp.c	2010-09-15 22:36:50.000000000 +0300
@@ -1261,7 +1261,8 @@
             return (PIXAC *)ERROR_PTR("res reading", procName, NULL);
         if ((data = (l_uint8 *)CALLOC(1, size)) == NULL)
             return (PIXAC *)ERROR_PTR("calloc fail for data", procName, NULL);
-        fread(data, size, 1, fp);
+        if (fread(data, 1, size, fp) != size)
+            return (PIXAC *)ERROR_PTR("error reading data", procName, NULL);
         pixc->w = w;
         pixc->h = h;
         pixc->d = d;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/pngio.c leptonlib-1.066/src/pngio.c
--- leptonlib-1.66/src/pngio.c	2010-05-05 20:56:47.000000000 +0300
+++ leptonlib-1.066/src/pngio.c	2010-09-16 08:16:17.000000000 +0300
@@ -405,7 +405,8 @@
         return ERROR_INT("file too small to be png", procName, 1);
     if ((data = (l_uint8 *)CALLOC(40, sizeof(l_uint8))) == NULL)
         return ERROR_INT("CALLOC fail for data", procName, 1);
-    fread(data, 40, 1, fp);
+    if (fread(data, 1, 40, fp) != 40)
+        return ERROR_INT("error reading data", procName, 1);
     ret = sreadHeaderPng(data, pwidth, pheight, pbps, pspp, piscmap);
     FREE(data);
     return ret;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/pnmio.c leptonlib-1.066/src/pnmio.c
--- leptonlib-1.66/src/pnmio.c	2009-11-22 03:37:39.000000000 +0200
+++ leptonlib-1.066/src/pnmio.c	2010-09-15 22:36:39.000000000 +0300
@@ -98,7 +98,7 @@
 {
 l_uint8    val8, rval8, gval8, bval8;
 l_uint16   val16;
-l_int32    w, h, d, bpl, wpl, i, j, type;
+l_int32    w, h, d, bpl, wpl, i, j, type, ignore;
 l_int32    val, rval, gval, bval;
 l_uint32   rgbval;
 l_uint32  *line, *data;
@@ -144,7 +144,8 @@
         for (i = 0; i < h; i++) {
             line = data + i * wpl;
             for (j = 0; j < bpl; j++) {
-                fread(&val8, 1, 1, fp);
+                if (fread(&val8, 1, 1, fp) != 1)
+                    return (PIX *)ERROR_PTR( "read error in 4", procName, pix);
                 SET_DATA_BYTE(line, j, val8);
             }
         }
@@ -158,7 +159,8 @@
             line = data + i * wpl;
             if (d != 16) {
                 for (j = 0; j < w; j++) {
-                    fread(&val8, 1, 1, fp);
+                    if (fread(&val8, 1, 1, fp) != 1)
+                        return (PIX *)ERROR_PTR( "error in 5", procName, pix);
                     if (d == 2)
                         SET_DATA_DIBIT(line, j, val8);
                     else if (d == 4)
@@ -169,7 +171,8 @@
             }
             else {  /* d == 16 */
                 for (j = 0; j < w; j++) {
-                    fread(&val16, 2, 1, fp);
+                    if (fread(&val16, 2, 1, fp) != 1)
+                        return (PIX *)ERROR_PTR( "16 bpp error", procName, pix);
                     SET_DATA_TWO_BYTES(line, j, val16);
                 }
             }
@@ -181,9 +184,12 @@
     for (i = 0; i < h; i++) {
         line = data + i * wpl;
         for (j = 0; j < wpl; j++) {
-            fread(&rval8, 1, 1, fp);
-            fread(&gval8, 1, 1, fp);
-            fread(&bval8, 1, 1, fp);
+            if (fread(&rval8, 1, 1, fp) != 1)
+                return (PIX *)ERROR_PTR( "read error type 6", procName, pix);
+            if (fread(&gval8, 1, 1, fp) != 1)
+                return (PIX *)ERROR_PTR( "read error type 6", procName, pix);
+            if (fread(&bval8, 1, 1, fp) != 1)
+                return (PIX *)ERROR_PTR( "read error type 6", procName, pix);
             composeRGBPixel(rval8, gval8, bval8, &rgbval);
             line[j] = rgbval;
         }
@@ -204,11 +210,6 @@
  *              &bps (<optional return>, bits/sample)
  *              &spp (<optional return>, samples/pixel)
  *      Return: 0 if OK, 1 on error
- *
- *  Notes:
- *      (1) To get only the header data, set @getpix == 0.
- *          However, if this is called as part of reading a pix from a file,
- *          set @getpix == 1 to return the pix without the image data.
  */
 l_int32
 freadHeaderPnm(FILE     *fp,
@@ -220,7 +221,7 @@
                l_int32  *pbps,
                l_int32  *pspp)
 {
-l_int32  w, h, d, type;
+l_int32  w, h, d, type, ignore;
 l_int32  maxval;
 
     PROCNAME("freadHeaderPnm");
@@ -230,14 +231,14 @@
     if (!pwidth || !pheight || !pdepth || !ptype)
         return ERROR_INT("input ptr(s) not defined", procName, 1);
 
-    fscanf(fp, "P%d\n", &type);
+    ignore = fscanf(fp, "P%d\n", &type);
     if (type < 1 || type > 6)
         return ERROR_INT("invalid pnm file", procName, 1);
 
     if (pnmSkipCommentLines(fp))
         return ERROR_INT("no data in file", procName, 1);
 
-    fscanf(fp, "%d %d\n", &w, &h);
+    ignore = fscanf(fp, "%d %d\n", &w, &h);
     if (w <= 0 || h <= 0 || w > MAX_PNM_WIDTH || h > MAX_PNM_HEIGHT)
         return ERROR_INT("invalid sizes", procName, 1);
 
@@ -245,7 +246,7 @@
     if (type == 1 || type == 4)
         d = 1;
     else if (type == 2 || type == 5) {
-        fscanf(fp, "%d\n", &maxval);
+        ignore = fscanf(fp, "%d\n", &maxval);
         if (maxval == 3)
             d = 2;
         else if (maxval == 15)
@@ -260,7 +261,7 @@
         }
     }
     else {  /* type == 3 || type == 6; this is rgb  */
-        fscanf(fp, "%d\n", &maxval);
+        ignore = fscanf(fp, "%d\n", &maxval);
         if (maxval != 255)
             L_WARNING_INT("unexpected maxval = %d", procName, maxval);
         d = 32;
@@ -275,7 +276,7 @@
     if (!ppix)
         return 0;
 
-    if ((*ppix = pixCreate(w, h, d)) == NULL)
+    if ((*ppix = pixCreate(w, h, d)) == NULL)  /* return pix initialized to 0 */
         return ERROR_INT( "pix not made", procName, 1);
     return 0;
 }
@@ -701,7 +702,7 @@
 pnmReadNextAsciiValue(FILE  *fp,
                       l_int32 *pval)
 {
-l_int32   c;
+l_int32   c, ignore;
 
     PROCNAME("pnmReadNextAsciiValue");
 
@@ -716,7 +717,7 @@
     } while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
 
     fseek(fp, -1L, SEEK_CUR);        /* back up one byte */
-    fscanf(fp, "%d", pval);
+    ignore = fscanf(fp, "%d", pval);
     return 0;
 }
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/ptabasic.c leptonlib-1.066/src/ptabasic.c
--- leptonlib-1.66/src/ptabasic.c	2010-07-19 03:55:35.000000000 +0300
+++ leptonlib-1.066/src/ptabasic.c	2010-09-16 07:55:25.000000000 +0300
@@ -527,11 +527,13 @@
         return (PTA *)ERROR_PTR("pta not made", procName, NULL);
     for (i = 0; i < n; i++) {
         if (type == 0) {  /* data is float */
-            fscanf(fp, "   (%f, %f)\n", &x, &y);
+            if (fscanf(fp, "   (%f, %f)\n", &x, &y) != 2)
+                return (PTA *)ERROR_PTR("error reading floats", procName, NULL);
             ptaAddPt(pta, x, y);
         }
         else {   /* data is integer */
-            fscanf(fp, "   (%d, %d)\n", &ix, &iy);
+            if (fscanf(fp, "   (%d, %d)\n", &ix, &iy) != 2)
+                return (PTA *)ERROR_PTR("error reading ints", procName, NULL);
             ptaAddPt(pta, ix, iy);
         }
     }
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/regutils.c leptonlib-1.066/src/regutils.c
--- leptonlib-1.66/src/regutils.c	2010-08-02 08:35:07.000000000 +0300
+++ leptonlib-1.066/src/regutils.c	2010-09-10 23:33:08.000000000 +0300
@@ -577,22 +577,25 @@
 static char *
 getRootNameFromArgv0(const char  *argv0)
 {
-l_int32  len;
+l_int32  len, suffix_len;
 char    *root;
 
     PROCNAME("getRootNameFromArgv0");
 
 #ifdef _WIN32
-    if ((len = strlen(argv0)) < 9)
-        return (char *)ERROR_PTR("invalid argv0; too small", procName, NULL);
+    suffix_len = strlen("_reg.exe");
     splitPathAtDirectory(argv0, NULL, &root);
-    root[len - 8] = '\0';
+    if ((len = strlen(root)) <= suffix_len) {
+        FREE(root);
+        return (char *)ERROR_PTR("invalid argv0; too small", procName, NULL);
+    }
 #else
-    if ((len = strlen(argv0)) < 5)
+    suffix_len = strlen("_reg");
+    if ((len = strlen(argv0)) <= suffix_len)
         return (char *)ERROR_PTR("invalid argv0", procName, NULL);
     root = stringNew(argv0);
-    root[len - 4] = '\0';
 #endif  /*  _WIN32 */
+    root[len - suffix_len] = '\0';
     return root;
 }
 
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/sarray.c leptonlib-1.066/src/sarray.c
--- leptonlib-1.66/src/sarray.c	2010-08-07 00:15:12.000000000 +0300
+++ leptonlib-1.066/src/sarray.c	2010-09-16 08:11:10.000000000 +0300
@@ -1441,7 +1441,7 @@
 sarrayReadStream(FILE  *fp)
 {
 char    *stringbuf;
-l_int32  i, n, size, index, bufsize, ret, version;
+l_int32  i, n, size, index, bufsize, version, ignore;
 SARRAY  *sa;
 
     PROCNAME("sarrayReadStream");
@@ -1449,12 +1449,12 @@
     if (!fp)
         return (SARRAY *)ERROR_PTR("stream not defined", procName, NULL);
 
-    ret = fscanf(fp, "\nSarray Version %d\n", &version);
-    if (ret != 1)
+    if (fscanf(fp, "\nSarray Version %d\n", &version) != 1)
         return (SARRAY *)ERROR_PTR("not an sarray file", procName, NULL);
     if (version != SARRAY_VERSION_NUMBER)
         return (SARRAY *)ERROR_PTR("invalid sarray version", procName, NULL);
-    fscanf(fp, "Number of strings = %d\n", &n);
+    if (fscanf(fp, "Number of strings = %d\n", &n) != 1)
+        return (SARRAY *)ERROR_PTR("error on # strings", procName, NULL);
 
     if ((sa = sarrayCreate(n)) == NULL)
         return (SARRAY *)ERROR_PTR("sa not made", procName, NULL);
@@ -1464,7 +1464,8 @@
 
     for (i = 0; i < n; i++) {
 	    /* Get the size of the stored string */
-        fscanf(fp, "%d[%d]:", &index, &size);
+        if (fscanf(fp, "%d[%d]:", &index, &size) != 2)
+            return (SARRAY *)ERROR_PTR("error on string size", procName, NULL);
 	    /* Expand the string buffer if necessary */
 	if (size > bufsize - 5) {
             FREE(stringbuf);
@@ -1472,13 +1473,14 @@
             stringbuf = (char *)CALLOC(bufsize, sizeof(char));
 	}
 	    /* Read the stored string, plus leading spaces and trailing \n */
-	fread(stringbuf, 1, size + 3, fp);
+	if (fread(stringbuf, 1, size + 3, fp) != size + 3)
+            return (SARRAY *)ERROR_PTR("error reading string", procName, NULL);
 	    /* Remove the \n that was added by sarrayWriteStream() */
 	stringbuf[size + 2] = '\0';
 	    /* Copy it in, skipping the 2 leading spaces */
         sarrayAddString(sa, stringbuf + 2, L_COPY);
     }
-    fscanf(fp, "\n");
+    ignore = fscanf(fp, "\n");
 
     FREE(stringbuf);
     return sa;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/sel1.c leptonlib-1.066/src/sel1.c
--- leptonlib-1.66/src/sel1.c	2010-06-07 20:41:54.000000000 +0300
+++ leptonlib-1.066/src/sel1.c	2010-09-16 08:20:01.000000000 +0300
@@ -1349,7 +1349,7 @@
 {
 char    *selname;
 char     linebuf[L_BUF_SIZE];
-l_int32  sy, sx, cy, cx, i, j, ret, version;
+l_int32  sy, sx, cy, cx, i, j, version, ignore;
 SEL     *sel;
 
     PROCNAME("selReadStream");
@@ -1357,13 +1357,13 @@
     if (!fp)
         return (SEL *)ERROR_PTR("stream not defined", procName, NULL);
 
-    ret = fscanf(fp, "  Sel Version %d\n", &version);
-    if (ret != 1)
+    if (fscanf(fp, "  Sel Version %d\n", &version) != 1)
         return (SEL *)ERROR_PTR("not a sel file", procName, NULL);
     if (version != SEL_VERSION_NUMBER)
         return (SEL *)ERROR_PTR("invalid sel version", procName, NULL);
 
-    fgets(linebuf, L_BUF_SIZE, fp);
+    if (fgets(linebuf, L_BUF_SIZE, fp) == NULL)
+        return (SEL *)ERROR_PTR("error reading into linebuf", procName, NULL);
     selname = stringNew(linebuf);
     sscanf(linebuf, "  ------  %s  ------", selname);
 
@@ -1376,12 +1376,12 @@
     selSetOrigin(sel, cy, cx);
 
     for (i = 0; i < sy; i++) {
-        fscanf(fp, "    ");
+        ignore = fscanf(fp, "    ");
         for (j = 0; j < sx; j++)
-            fscanf(fp, "%1d", &sel->data[i][j]);
-        fscanf(fp, "\n");
+            ignore = fscanf(fp, "%1d", &sel->data[i][j]);
+        ignore = fscanf(fp, "\n");
     }
-    fscanf(fp, "\n");
+    ignore = fscanf(fp, "\n");
 
     FREE(selname);
     return sel;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/spixio.c leptonlib-1.066/src/spixio.c
--- leptonlib-1.66/src/spixio.c	2010-06-25 19:03:09.000000000 +0300
+++ leptonlib-1.066/src/spixio.c	2010-09-16 08:14:40.000000000 +0300
@@ -157,7 +157,8 @@
         return ERROR_INT("file too small to be spix", procName, 1);
     if ((data = (l_uint32 *)CALLOC(6, sizeof(l_uint32))) == NULL)
         return ERROR_INT("CALLOC fail for data", procName, 1);
-    fread(data, 6, 4, fp);
+    if (fread(data, 4, 6, fp) != 6)
+        return ERROR_INT("error reading data", procName, 1);
     ret = sreadHeaderSpix(data, pwidth, pheight, pbps, pspp, piscmap);
     FREE(data);
     return ret;
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/sudoku.c leptonlib-1.066/src/sudoku.c
--- leptonlib-1.66/src/sudoku.c	1970-01-01 02:00:00.000000000 +0200
+++ leptonlib-1.066/src/sudoku.c	2010-09-15 16:45:30.000000000 +0300
@@ -0,0 +1,855 @@
+/*====================================================================*
+ -  Copyright (C) 2001 Leptonica.  All rights reserved.
+ -  This software is distributed in the hope that it will be
+ -  useful, but with NO WARRANTY OF ANY KIND.
+ -  No author or distributor accepts responsibility to anyone for the
+ -  consequences of using this software, or for whether it serves any
+ -  particular purpose or works at all, unless he or she says so in
+ -  writing.  Everyone is granted permission to copy, modify and
+ -  redistribute this source code, for commercial or non-commercial
+ -  purposes, with the following restrictions: (1) the origin of this
+ -  source code must not be misrepresented; (2) modified versions must
+ -  be plainly marked as such; and (3) this notice may not be removed
+ -  or altered from any source or modified source distribution.
+ *====================================================================*/
+
+
+/*
+ *  sudoku.c
+ *
+ *      Solve a sudoku by brute force search
+ *
+ *      Read input data from file or string
+ *          l_int32         *sudokuReadFile()
+ *          l_int32         *sudokuReadString()
+ *
+ *      Create/destroy
+ *          L_SUDOKU        *sudokuCreate()
+ *          void             sudokuDestroy()
+ *
+ *      Solve the puzzle
+ *          l_int32          sudokuSolve()
+ *          static l_int32   sudokuValidState()
+ *          static l_int32   sudokuNewGuess()
+ *          static l_int32   sudokuTestState()
+ *
+ *      Test for uniqueness
+ *          l_int32          sudokuTestUniqueness()
+ *          static l_int32   sudokuCompareState()
+ *          static l_int32  *sudokuRotateArray()
+ *
+ *      Generation
+ *          L_SUDOKU        *sudokuGenerate()
+ *
+ *      Output
+ *          l_int32          sudokuOutput()
+ *
+ *  Solving sudokus is a somewhat addictive pastime.  The rules are
+ *  simple but it takes just enough concentration to make it rewarding
+ *  when you find a number.  And you get 50 to 60 such rewards each time
+ *  you complete one.  The downside is that you could have been doing
+ *  something more creative, like keying out a new plant, staining
+ *  the deck, or even writing a computer program to discourage your
+ *  wife from doing sudokus.
+ *
+ *  My original plan for the sudoku solver was somewhat grandiose.
+ *  The program would model the way a person solves the problem.
+ *  It would examine each empty position and determine how many possible
+ *  numbers could fit.  The empty positions would be entered in a priority
+ *  queue keyed on the number of possible numbers that could fit.
+ *  If there existed a position where only a single number would work,
+ *  it would greedily take it.  Otherwise it would consider a
+ *  positions that could accept two and make a guess, with backtracking
+ *  if an impossible state were reached.  And so on.
+ *
+ *  Then one of my colleagues announced she had solved the problem
+ *  by brute force and it was fast.  At that point the original plan was
+ *  dead in the water, because the two top requirements for a leptonica
+ *  algorithm are (1) as simple as possible and (2) fast.  The brute
+ *  force approach starts at the UL corner, and in succession at each
+ *  blank position it finds the first valid number (testing in
+ *  sequence from 1 to 9).  When no number will fit a blank position
+ *  it backtracks, choosing the next valid number in the previous
+ *  blank position.
+ *
+ *  This is an inefficient method for pruning the space of solutions
+ *  (imagine backtracking from the LR corner back to the UL corner
+ *  and starting over with a new guess), but it nevertheless gets
+ *  the job done quickly.  I have made no effort to optimize
+ *  it, because it is fast: a 5-star (highest difficulty) sudoku might
+ *  require a million guesses and take 0.05 sec.  (This BF implementation
+ *  does about 20M guesses/sec at 3 GHz.)
+ *
+ *  Proving uniqueness of a sudoku solution is tricker than finding
+ *  a solution (or showing that no solution exists).  A good indication
+ *  that a solution is unique is if we get the same result solving
+ *  by brute force when the puzzle is also rotated by 90, 180 and 270
+ *  degrees.  If there are multiple solutions, it seems unlikely
+ *  that you would get the same solution four times in a row, using a
+ *  brute force method that increments guesses and scans LR/TB.
+ *  The function sudokuTestUniqueness() does this.
+ *
+ *  And given a function that can determine uniqueness, it is
+ *  easy to generate valid sudokus.  We provide sudokuGenerate(),
+ *  which starts with some valid initial solution, and randomly
+ *  removes numbers, stopping either when a minimum number of non-zero
+ *  elements are left, or when it becomes difficult to remove another
+ *  element without destroying the uniqueness of the solution.
+ *
+ *  For further reading, see the Wikipedia articles:
+ *     (1) http://en.wikipedia.org/wiki/Algorithmics_of_sudoku
+ *     (2) http://en.wikipedia.org/wiki/Sudoku
+ *
+ *  How many 9x9 sudokus are there?  Here are the numbers.
+ *   - From ref(1), there are about 6 x 10^27 "latin squares", where
+ *     each row and column has all 9 digits.
+ *   - There are 7.2 x 10^21 actual solutions, having the added
+ *     constraint in each of the 9 3x3 squares.  (The constraint
+ *     reduced the number by the fraction 1.2 x 10^(-6).)
+ *   - There are a mere 5.5 billion essentially different solutions (EDS),
+ *     when symmetries (rotation, reflection, permutation and relabelling)
+ *     are removed.
+ *   - Thus there are 1.3 x 10^12 solutions that can be derived by
+ *     symmetry from each EDS.  Can we account for these?
+ *   - Sort-of.  From an EDS, you can derive (3!)^8 = 1.7 million solutions
+ *     by simply permuting rows and columns.  (Do you see why it is
+ *     not (3!)^6 ?)
+ *   - Also from an EDS, you can derive 9! solutions by relabelling,
+ *     and 4 solutions by rotation, for a total of 1.45 million solutions
+ *     by relabelling and rotation.  Then taking the product, by symmetry
+ *     we can derive 1.7M x 1.45M = 2.45 trillion solutions from each EDS.
+ *     (Something is off by about a factor of 2 -- close enough.)
+ *
+ *  Another interesting fact is that there are apparently 48K EDS sudokus
+ *  (with unique solutions) that have only 17 givens.  No sudokus are known
+ *  with less than 17, but there exists no proof that this is the minimum.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "allheaders.h"
+
+
+static l_int32 sudokuValidState(l_int32  *state);
+static l_int32 sudokuNewGuess(L_SUDOKU  *sud);
+static l_int32 sudokuTestState(l_int32  *state, l_int32  index);
+static l_int32 sudokuCompareState(L_SUDOKU  *sud1, L_SUDOKU  *sud2,
+                                  l_int32  quads, l_int32  *psame);
+static l_int32 *sudokuRotateArray(l_int32  *array, l_int32  quads);
+
+    /* An example of a valid solution */
+static const char valid_solution[] = "3 8 7 2 6 4 1 9 5 "
+                                     "2 6 5 8 9 1 4 3 7 "
+                                     "1 4 9 5 3 7 6 8 2 "
+                                     "5 2 3 7 1 6 8 4 9 "
+                                     "7 1 6 9 4 8 2 5 3 "
+                                     "8 9 4 3 5 2 7 1 6 "
+                                     "9 7 2 1 8 5 3 6 4 "
+                                     "4 3 1 6 7 9 5 2 8 "
+                                     "6 5 8 4 2 3 9 7 1 ";
+
+
+/*---------------------------------------------------------------------*
+ *               Read input data from file or string                   *
+ *---------------------------------------------------------------------*/
+/*!
+ *  sudokuReadFile()
+ *
+ *      Input:  filename (of formatted sudoku file)
+ *      Return: array (of 81 numbers), or null on error
+ *
+ *  Notes:
+ *      (1) The file format has:
+ *          * any number of comment lines beginning with '#'
+ *          * a set of 9 lines, each having 9 digits (0-9) separated
+ *            by a space
+ */
+l_int32 *
+sudokuReadFile(const char  *filename)
+{
+char     *str, *strj;
+l_uint8  *data;
+l_int32   i, j, nlines, nbytes, val, index, error;
+l_int32  *array;
+SARRAY   *saline, *sa1, *sa2;
+
+    PROCNAME("sudokuReadFile");
+
+    if (!filename)
+        return (l_int32 *)ERROR_PTR("filename not defined", procName, NULL);
+    data = arrayRead(filename, &nbytes);
+    sa1 = sarrayCreateLinesFromString((char *)data, 0);
+    sa2 = sarrayCreate(9);
+
+        /* Filter out the comment lines; verify that there are 9 data lines */
+    nlines = sarrayGetCount(sa1);
+    for (i = 0; i < nlines; i++) {
+        str = sarrayGetString(sa1, i, L_NOCOPY);
+        if (str[0] != '#')
+            sarrayAddString(sa2, str, L_COPY);
+    }
+    FREE(data);
+    sarrayDestroy(&sa1);
+    nlines = sarrayGetCount(sa2);
+    if (nlines != 9) {
+        sarrayDestroy(&sa2);
+        L_ERROR_INT("file has %d lines", procName, nlines);
+        return (l_int32 *)ERROR_PTR("invalid file", procName, NULL);
+    }
+
+        /* Read the data into the array, verifying that each data
+         * line has 9 numbers. */
+    error = FALSE;
+    array = (l_int32 *)CALLOC(81, sizeof(l_int32));
+    for (i = 0, index = 0; i < 9; i++) {
+        str = sarrayGetString(sa2, i, L_NOCOPY);
+        saline = sarrayCreateWordsFromString(str);
+        if (sarrayGetCount(saline) != 9) {
+            error = TRUE;
+            sarrayDestroy(&saline);
+            break;
+        }
+        for (j = 0; j < 9; j++) {
+            strj = sarrayGetString(saline, j, L_NOCOPY);
+            if (sscanf(strj, "%d", &val) != 1)
+                error = TRUE;
+            else
+                array[index++] = val;
+        }
+        sarrayDestroy(&saline);
+        if (error) break;
+    }
+    sarrayDestroy(&sa2);
+
+    if (error) {
+        FREE(array);
+        return (l_int32 *)ERROR_PTR("invalid data", procName, NULL);
+    }
+
+    return array;
+}
+
+
+/*!
+ *  sudokuReadString()
+ *
+ *      Input:  str (of input data)
+ *      Return: array (of 81 numbers), or null on error
+ *
+ *  Notes:
+ *      (1) The string is formatted as 81 single digits, each separated
+ *          by 81 spaces.
+ */
+l_int32 *
+sudokuReadString(const char  *str)
+{
+l_int32   i;
+l_int32  *array;
+
+    PROCNAME("sudokuReadString");
+
+    if (!str)
+        return (l_int32 *)ERROR_PTR("str not defined", procName, NULL);
+
+        /* Read in the initial solution */
+    array = (l_int32 *)CALLOC(81, sizeof(l_int32));
+    for (i = 0; i < 81; i++) {
+        if (sscanf(str + 2 * i, "%d ", &array[i]) != 1)
+            return (l_int32 *)ERROR_PTR("invalid format", procName, NULL);
+    }
+
+    return array;
+}
+
+
+/*---------------------------------------------------------------------*
+ *                        Create/destroy sudoku                        *
+ *---------------------------------------------------------------------*/
+/*!
+ *  sudokuCreate()
+ *
+ *      Input:  array (of 81 numbers, 9 rows of 9 numbers each)
+ *      Return: l_sudoku, or null on error
+ *
+ *  Notes:
+ *      (1) The input array has 0 for the unknown values, and 1-9
+ *          for the known initial values.  It is generated from
+ *          a file using sudokuReadInput(), which checks that the file
+ *          data has 81 numbers in 9 rows.
+ */
+L_SUDOKU *
+sudokuCreate(l_int32  *array)
+{
+l_int32    i, val, locs_index;
+L_SUDOKU  *sud;
+
+    PROCNAME("sudokuCreate");
+
+    if (!array)
+        return (L_SUDOKU *)ERROR_PTR("array not defined", procName, NULL);
+
+    locs_index = 0;  /* into locs array */
+    if ((sud = (L_SUDOKU *)CALLOC(1, sizeof(L_SUDOKU))) == NULL)
+        return (L_SUDOKU *)ERROR_PTR("sud not made", procName, NULL);
+    if ((sud->locs = (l_int32 *)CALLOC(81, sizeof(l_int32))) == NULL)
+        return (L_SUDOKU *)ERROR_PTR("su state array not made", procName, NULL);
+    if ((sud->init = (l_int32 *)CALLOC(81, sizeof(l_int32))) == NULL)
+        return (L_SUDOKU *)ERROR_PTR("su init array not made", procName, NULL);
+    if ((sud->state = (l_int32 *)CALLOC(81, sizeof(l_int32))) == NULL)
+        return (L_SUDOKU *)ERROR_PTR("su state array not made", procName, NULL);
+    for (i = 0; i < 81; i++) {
+        val = array[i];
+        sud->init[i] = val;
+        sud->state[i] = val;
+        if (val == 0)
+            sud->locs[locs_index++] = i;
+    }
+    sud->num = locs_index;
+    sud->failure = FALSE;
+    sud->finished = FALSE;
+    return sud;
+}
+
+
+/*!
+ *  sudokuDestroy()
+ *
+ *      Input:  &l_sudoku (<to be nulled>)
+ *      Return: void
+ */
+void
+sudokuDestroy(L_SUDOKU  **psud)
+{
+L_SUDOKU  *sud;
+
+    PROCNAME("sudokuDestroy");
+
+    if (psud == NULL) {
+        L_WARNING("ptr address is NULL", procName);
+        return;
+    }
+    if ((sud = *psud) == NULL)
+        return;
+
+    FREE(sud->locs);
+    FREE(sud->init);
+    FREE(sud->state);
+    FREE(sud);
+
+    *psud = NULL;
+    return;
+}
+
+
+/*---------------------------------------------------------------------*
+ *                           Solve the puzzle                          *
+ *---------------------------------------------------------------------*/
+/*!
+ *  sudokuSolve()
+ *
+ *      Input:  l_sudoku (starting in initial state)
+ *      Return: 1 on success, 0 on failure to solve (note reversal of
+ *              typical unix returns)
+ */
+l_int32
+sudokuSolve(L_SUDOKU  *sud)
+{
+    PROCNAME("sudokuSolve");
+
+    if (!sud)
+        return ERROR_INT("sud not defined", procName, 0);
+
+    if (!sudokuValidState(sud->init))
+        return ERROR_INT("initial state not valid", procName, 0);
+
+    while (1) {
+        if (sudokuNewGuess(sud))
+            break;
+        if (sud->finished == TRUE)
+            break;
+    }
+
+    if (sud->failure == TRUE) {
+        fprintf(stderr, "Failure after %d guesses\n", sud->nguess);
+        return 0;
+    }
+
+    fprintf(stderr, "Solved after %d guesses\n", sud->nguess);
+    return 1;
+}
+
+
+/*!
+ *  sudokuValidState()
+ *
+ *      Input:  state (array of size 81)
+ *      Return: 1 if valid, 0 if invalid
+ *
+ *  Notes:
+ *      (1) This can be used on either the initial state (init)
+ *          or on the current state (state) of the l_soduku.
+ *          All values of 0 are ignored.
+ */
+static l_int32
+sudokuValidState(l_int32  *state)
+{
+l_int32  i;
+
+    PROCNAME("sudokuValidState");
+
+    if (!state)
+        return ERROR_INT("state not defined", procName, 0);
+
+    for (i = 0; i < 81; i++) {
+        if (!sudokuTestState(state, i))
+            return 0;
+    }
+
+    return 1;
+}
+
+
+/*!
+ *  sudokuNewGuess()
+ *
+ *      Input:  l_sudoku
+ *      Return: 0 if OK; 1 if no solution is possible
+ *
+ *  Notes:
+ *      (1) This attempts to increment the number in the current
+ *          location.  If it can't, it backtracks (sets the number
+ *          in the current location to zero and decrements the
+ *          current location).  If it can, it tests that number,
+ *          and if the number is valid, moves forward to the next
+ *          empty location (increments the current location).
+ *      (2) If there is no solution, backtracking will eventually
+ *          exhaust possibilities for the first location.
+ */
+static l_int32
+sudokuNewGuess(L_SUDOKU  *sud)
+{
+l_int32   index, val, valid;
+l_int32  *locs, *state;
+
+    locs = sud->locs;
+    state = sud->state;
+    index = locs[sud->current];  /* 0 to 80 */
+    val = state[index];
+    if (val == 9) {  /* backtrack or give up */
+        if (sud->current == 0) {
+            sud->failure = TRUE;
+            return 1;
+        }
+        state[index] = 0;
+        sud->current--;
+    }
+    else {  /* increment current value and test */
+        sud->nguess++;
+        state[index]++;
+        valid = sudokuTestState(state, index);
+        if (valid) {
+            if (sud->current == sud->num - 1) {  /* we're done */
+                sud->finished = TRUE;
+                return 0;
+            }
+            else  /* advance to next position */
+                sud->current++;
+        }
+    }
+
+    return 0;
+}
+
+
+/*!
+ *  sudokuTestState()
+ *
+ *      Input:  state (current state: array of 81 values)
+ *              index (into state element that we are testing)
+ *      Return: 1 if valid; 0 if invalid (no error checking)
+ */
+static l_int32
+sudokuTestState(l_int32  *state,
+                l_int32   index)
+{
+l_int32  i, j, val, row, rowstart, rowend, col;
+l_int32  blockrow, blockcol, blockstart, rowindex, locindex;
+
+    if ((val = state[index]) == 0)  /* automatically valid */
+        return 1;
+
+        /* Test row.  Test val is at (x, y) = (index % 9, index / 9)  */
+    row = index / 9;
+    rowstart = 9 * row;
+    for (i = rowstart; i < index; i++) {
+        if (state[i] == val)
+            return 0;
+    }
+    rowend = rowstart + 9;
+    for (i = index + 1; i < rowend; i++) {
+        if (state[i] == val)
+            return 0;
+    }
+
+        /* Test column */
+    col = index % 9;
+    for (j = col; j < index; j += 9) {
+        if (state[j] == val)
+            return 0;
+    }
+    for (j = index + 9; j < 81; j += 9) {
+        if (state[j] == val)
+            return 0;
+    }
+
+        /* Test local 3x3 block */
+    blockrow = 3 * (row / 3);
+    blockcol = 3 * (col / 3);
+    blockstart = 9 * blockrow + blockcol;
+    for (i = 0; i < 3; i++) {
+        rowindex = blockstart + 9 * i;
+        for (j = 0; j < 3; j++) {
+            locindex = rowindex + j;
+            if (index == locindex) continue;
+            if (state[locindex] == val)
+                return 0;
+        }
+    }
+
+    return 1;
+}
+
+
+/*---------------------------------------------------------------------*
+ *                         Test for uniqueness                         *
+ *---------------------------------------------------------------------*/
+/*!
+ *  sudokuTestUniqueness()
+ *
+ *      Input:  array (of 81 numbers, 9 lines of 9 numbers each)
+ *              &punique (<return> 1 if unique, 0 if not)
+ *      Return: 0 if OK, 1 on error
+ *
+ *  Notes:
+ *      (1) This applies the brute force method to all four 90 degree
+ *          rotations.  If there is more than one solution, it is highly
+ *          unlikely that all four results will be the same;
+ *          consequently, if they are the same, the solution is
+ *          most likely to be unique.
+ */
+l_int32
+sudokuTestUniqueness(l_int32  *array,
+                     l_int32  *punique)
+{
+l_int32    same1, same2, same3;
+l_int32   *array1, *array2, *array3;
+L_SUDOKU  *sud, *sud1, *sud2, *sud3;
+
+    PROCNAME("sudokuTestUniqueness");
+
+    if (!punique)
+        return ERROR_INT("&unique not defined", procName, 1);
+    *punique = 0;
+    if (!array)
+        return ERROR_INT("array not defined", procName, 1);
+
+    sud = sudokuCreate(array);
+    sudokuSolve(sud);
+    array1 = sudokuRotateArray(array, 1);
+    sud1 = sudokuCreate(array1);
+    sudokuSolve(sud1);
+    array2 = sudokuRotateArray(array, 2);
+    sud2 = sudokuCreate(array2);
+    sudokuSolve(sud2);
+    array3 = sudokuRotateArray(array, 3);
+    sud3 = sudokuCreate(array3);
+    sudokuSolve(sud3);
+
+    sudokuCompareState(sud, sud1, 1, &same1);
+    sudokuCompareState(sud, sud2, 2, &same2);
+    sudokuCompareState(sud, sud3, 3, &same3);
+    *punique = (same1 && same2 && same3);
+
+    sudokuDestroy(&sud);
+    sudokuDestroy(&sud1);
+    sudokuDestroy(&sud2);
+    sudokuDestroy(&sud3);
+    FREE(array1);
+    FREE(array2);
+    FREE(array3);
+    return 0;
+}
+
+
+/*!
+ *  sudokuCompareState()
+ *
+ *      Input:  sud1, sud2
+ *              quads (rotation of sud2 input with respect to sud1,
+ *                    in units of 90 degrees cw)
+ *              &same (<return> 1 if all 4 results are identical; 0 otherwise)
+ *      Return: 0 if OK, 1 on error
+ *
+ *  Notes:
+ *      (1) The input to sud2 has been rotated by @quads relative to the
+ *          input to sud1.  Therefore, we must rotate the solution to
+ *          sud1 by the same amount before comparing it to the
+ *          solution to sud2.
+ */
+static l_int32
+sudokuCompareState(L_SUDOKU  *sud1,
+                   L_SUDOKU  *sud2,
+                   l_int32    quads,
+                   l_int32   *psame)
+{
+l_int32   i, same;
+l_int32  *array;
+
+    PROCNAME("sudokuCompareState");
+
+    if (!psame)
+        return ERROR_INT("&same not defined", procName, 1);
+    *psame = 0;
+    if (!sud1)
+        return ERROR_INT("sud1 not defined", procName, 1);
+    if (!sud2)
+        return ERROR_INT("sud1 not defined", procName, 1);
+    if (quads < 1 || quads > 3)
+        return ERROR_INT("valid quads in {1,2,3}", procName, 1);
+
+    same = TRUE;
+    if ((array = sudokuRotateArray(sud1->state, quads)) == NULL)
+        return ERROR_INT("array not made", procName, 1);
+    for (i = 0; i < 81; i++) {
+        if (array[i] != sud2->state[i]) {
+            same = FALSE;
+            break;
+        }
+    }
+    *psame = same;
+    FREE(array);
+    return 0;
+}
+
+
+/*!
+ *  sudokuRotateArray()
+ *
+ *      Input:  array (of 81 numbers; 9 lines of 9 numbers each)
+ *              quads (1-3; number of 90 degree cw rotations)
+ *      Return: rarray (rotated array), or null on error
+ */
+static l_int32 *
+sudokuRotateArray(l_int32  *array,
+                  l_int32   quads)
+{
+l_int32   i, j, sindex, dindex;
+l_int32  *rarray;
+
+    PROCNAME("sudokuRotateArray");
+
+    if (!array)
+        return (l_int32 *)ERROR_PTR("array not defined", procName, NULL);
+    if (quads < 1 || quads > 3)
+        return (l_int32 *)ERROR_PTR("valid quads in {1,2,3}", procName, NULL);
+
+    rarray = (l_int32 *)CALLOC(81, sizeof(l_int32));
+    if (quads == 1) {
+        for (j = 0, dindex = 0; j < 9; j++) {
+             for (i = 8; i >= 0; i--) {
+                 sindex = 9 * i + j;
+                 rarray[dindex++] = array[sindex];
+             }
+        }
+    }
+    else if (quads == 2) {
+        for (i = 8, dindex = 0; i >= 0; i--) {
+             for (j = 8; j >= 0; j--) {
+                 sindex = 9 * i + j;
+                 rarray[dindex++] = array[sindex];
+             }
+        }
+    }
+    else {  /* quads == 3 */
+        for (j = 8, dindex = 0; j >= 0; j--) {
+             for (i = 0; i < 9; i++) {
+                 sindex = 9 * i + j;
+                 rarray[dindex++] = array[sindex];
+             }
+        }
+    }
+
+    return rarray;
+}
+
+
+/*---------------------------------------------------------------------*
+ *                              Generation                             *
+ *---------------------------------------------------------------------*/
+/*!
+ *  sudokuGenerate()
+ *
+ *      Input:  array (of 81 numbers, 9 rows of 9 numbers each)
+ *              seed (random number)
+ *              minelems (min non-zero elements allowed; <= 80)
+ *              maxtries (max tries to remove a number and get a valid sudoku)
+ *      Return: l_sudoku, or null on error
+ *
+ *  Notes:
+ *      (1) This is a brute force generator.  It starts with a completed
+ *          sudoku solution and, by removing elements (setting them to 0),
+ *          generates a valid (unique) sudoku initial condition.
+ *      (2) The process stops when either @minelems, the minimum
+ *          number of non-zero elements, is reached, or when the
+ *          number of attempts to remove the next element exceeds @maxtries.
+ *      (3) No sudoku is known with less than 17 nonzero elements.
+ */
+L_SUDOKU *
+sudokuGenerate(l_int32  *array,
+               l_int32   seed,
+               l_int32   minelems,
+               l_int32   maxtries)
+{
+l_int32    index, sector, nzeros, removefirst, tries, val, oldval, unique;
+L_SUDOKU  *sud, *testsud;
+
+    PROCNAME("sudokuGenerate");
+
+    if (!array)
+        return (L_SUDOKU *)ERROR_PTR("array not defined", procName, NULL);
+    if (minelems > 80)
+        return (L_SUDOKU *)ERROR_PTR("minelems must be < 81", procName, NULL);
+
+        /* Remove up to 30 numbers at random from the solution.
+         * Test if the solution is valid -- the initial 'solution' may
+         * have been invalid.  Then test if the sudoku with 30 zeroes
+         * is unique -- it almost always will be. */
+    srand(seed);
+    nzeros = 0;
+    sector = 0;
+    removefirst = L_MIN(30, 81 - minelems);
+    while (nzeros < removefirst) {
+        genRandomIntegerInRange(9, 0, &val);
+        index = 27 * (sector / 3) + 3 * (sector % 3) +
+                9 * (val / 3) + (val % 3);
+        if (array[index] == 0) continue;
+        array[index] = 0;
+        nzeros++;
+        sector++;
+        sector %= 9;
+    }
+    testsud = sudokuCreate(array);
+    sudokuSolve(testsud);
+    if (testsud->failure) {
+        sudokuDestroy(&testsud);
+        L_ERROR("invalid initial solution", procName);
+        return NULL;
+    }
+    sudokuTestUniqueness(testsud->init, &unique);
+    sudokuDestroy(&testsud);
+    if (!unique) {
+        L_ERROR("non-unique result with 30 zeroes", procName);
+        return NULL;
+    }
+
+        /* Remove more numbers, testing at each removal for uniqueness. */
+    tries = 0;
+    sector = 0;
+    while (1) {
+        if (tries > maxtries) break;
+        if (81 - nzeros <= minelems) break;
+
+        if (tries == 0) {
+            fprintf(stderr, "Trying %d zeros\n", nzeros);
+            tries = 1;
+        }
+
+            /* Choose an element to be zeroed.  We choose one
+             * at random in succession from each of the nine sectors. */
+        genRandomIntegerInRange(9, 0, &val);
+        index = 27 * (sector / 3) + 3 * (sector % 3) +
+                9 * (val / 3) + (val % 3);
+        sector++;
+        sector %= 9;
+        if (array[index] == 0) continue;
+
+            /* Save the old value in case we need to revert */
+        oldval = array[index];
+
+            /* Is there a solution?  If not, try again. */
+        array[index] = 0;
+        testsud = sudokuCreate(array);
+        sudokuSolve(testsud);
+        if (testsud->failure == TRUE) {
+            sudokuDestroy(&testsud);
+            array[index] = oldval;  /* revert */
+            tries++;
+            continue;
+        }
+
+            /* Is the solution unique?  If not, try again. */
+        sudokuTestUniqueness(testsud->init, &unique);
+        sudokuDestroy(&testsud);
+        if (!unique) {  /* revert and try again */
+            array[index] = oldval;
+            tries++;
+        }
+        else {  /* accept this */
+            tries = 0;
+            fprintf(stderr, "Have %d zeros\n", nzeros);
+            nzeros++;
+        }
+    }
+    fprintf(stderr, "Final: nelems = %d\n", 81 - nzeros);
+
+        /* Show that we can recover the solution */
+    sud = sudokuCreate(array);
+    sudokuOutput(sud, L_SUDOKU_INIT);
+    sudokuSolve(sud);
+    sudokuOutput(sud, L_SUDOKU_STATE);
+
+    return sud;
+}
+
+
+/*---------------------------------------------------------------------*
+ *                               Output                                *
+ *---------------------------------------------------------------------*/
+/*!
+ *  sudokuOutput()
+ *
+ *      Input:  l_sudoku (at any stage)
+ *              arraytype (L_SUDOKU_INIT, L_SUDOKU_STATE)
+ *      Return: void
+ *
+ *  Notes:
+ *      (1) Prints either the initial array or the current state
+ *          of the solution.
+ */
+l_int32
+sudokuOutput(L_SUDOKU  *sud,
+             l_int32    arraytype)
+{
+l_int32   i, j;
+l_int32  *array;
+
+    PROCNAME("sudokuOutput");
+
+    if (!sud)
+        return ERROR_INT("sud not defined", procName, 1);
+    if (arraytype == L_SUDOKU_INIT)
+        array = sud->init;
+    else if (arraytype == L_SUDOKU_STATE)
+        array = sud->state;
+    else
+        return ERROR_INT("invalid arraytype", procName, 1);
+
+    for (i = 0; i < 9; i++) {
+        for (j = 0; j < 9; j++)
+            fprintf(stderr, "%d ", array[9 * i + j]);
+        fprintf(stderr, "\n");
+    }
+
+    return 0;
+}
+
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/sudoku.h leptonlib-1.066/src/sudoku.h
--- leptonlib-1.66/src/sudoku.h	1970-01-01 02:00:00.000000000 +0200
+++ leptonlib-1.066/src/sudoku.h	2010-09-09 22:51:31.000000000 +0300
@@ -0,0 +1,62 @@
+/*====================================================================*
+ -  Copyright (C) 2001 Leptonica.  All rights reserved.
+ -  This software is distributed in the hope that it will be
+ -  useful, but with NO WARRANTY OF ANY KIND.
+ -  No author or distributor accepts responsibility to anyone for the
+ -  consequences of using this software, or for whether it serves any
+ -  particular purpose or works at all, unless he or she says so in
+ -  writing.  Everyone is granted permission to copy, modify and
+ -  redistribute this source code, for commercial or non-commercial
+ -  purposes, with the following restrictions: (1) the origin of this
+ -  source code must not be misrepresented; (2) modified versions must
+ -  be plainly marked as such; and (3) this notice may not be removed
+ -  or altered from any source or modified source distribution.
+ *====================================================================*/
+
+#ifndef SUDOKU_H_INCLUDED
+#define SUDOKU_H_INCLUDED
+
+/*
+ *  sudoku.h
+ *
+ *    The L_Sudoku holds all the information of the current state.
+ *
+ *    The input to sudokuCreate() is a file with any number of lines
+ *    starting with '#', followed by 9 lines consisting of 9 numbers
+ *    in each line.  These have the known values and use 0 for the unknowns.
+ *    Blank lines are ignored.
+ *
+ *    The @locs array holds the indices of the unknowns, numbered
+ *    left-to-right and top-to-bottom from 0 to 80.  The array size
+ *    is initialized to @num.  @current is the index into the @locs
+ *    array of the current guess: locs[current].
+ *
+ *    The @state array is used to determine the validity of each guess.
+ *    It is of size 81, and is initialized by setting the unknowns to 0
+ *    and the knowns to their input values.
+ */
+struct L_Sudoku
+{
+    l_int32        num;         /* number of unknowns                     */
+    l_int32       *locs;        /* location of unknowns                   */
+    l_int32        current;     /* index into @locs of current location   */
+    l_int32       *init;        /* initial state, with 0 representing     */
+                                /* the unknowns                           */
+    l_int32       *state;       /* present state, including inits and     */
+                                /* guesses of unknowns up to @current     */
+    l_int32        nguess;      /* shows current number of guesses        */
+    l_int32        finished;    /* set to 1 when solved                   */
+    l_int32        failure;     /* set to 1 if no solution is possible    */
+};
+typedef struct L_Sudoku  L_SUDOKU;
+
+
+    /* For printing out array data */
+enum {
+    L_SUDOKU_INIT = 0,
+    L_SUDOKU_STATE = 1
+};
+
+#endif /* SUDOKU_H_INCLUDED */
+
+
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/utils.c leptonlib-1.066/src/utils.c
--- leptonlib-1.66/src/utils.c	2010-08-08 03:29:17.000000000 +0300
+++ leptonlib-1.066/src/utils.c	2010-09-16 08:14:02.000000000 +0300
@@ -91,6 +91,9 @@
  *           char      *mungePathnameForWindows()
  *           l_int32    extractNumberFromFilename()
  *
+ *       Generate random integer in given range
+ *           l_int32    genRandomIntegerInRange()
+ *
  *       Version number
  *           char      *getLeptonlibVersion()
  *           char      *getImagelibVersions()
@@ -1345,6 +1348,7 @@
 arrayReadStream(FILE     *fp, 
                 l_int32  *pnbytes)
 {
+l_int32   ignore;
 l_uint8  *data;
 
     PROCNAME("arrayReadStream");
@@ -1358,7 +1362,7 @@
     *pnbytes = fnbytesInFile(fp);
     if ((data = (l_uint8 *)CALLOC(1, *pnbytes + 1)) == NULL)
         return (l_uint8 *)ERROR_PTR("CALLOC fail for data", procName, NULL);
-    fread(data, *pnbytes, 1, fp);
+    ignore = fread(data, 1, *pnbytes, fp);
     return data;
 }
 
@@ -2063,6 +2067,41 @@
 }
 
 
+/*---------------------------------------------------------------------*
+ *                Generate random integer in given range               *
+ *---------------------------------------------------------------------*/
+/*!
+ *  genRandomIntegerInRange()
+ *
+ *      Input:  range (size of range; must be >= 2)
+ *              seed (use 0 to skip; otherwise call srand)
+ *              val (<return> random integer in range {0 ... range-1}
+ *      Return: 0 if OK, 1 on error
+ *
+ *  Notes:
+ *      (1) For example, to choose a rand integer between 0 and 99,
+ *          use @range = 100.
+ */
+l_int32
+genRandomIntegerInRange(l_int32   range,
+                        l_int32   seed,
+                        l_int32  *pval)
+{
+    PROCNAME("genRandomIntegerInRange");
+
+    if (!pval)
+        return ERROR_INT("&val not defined", procName, 1);
+    *pval = 0;
+    if (range < 2)
+        return ERROR_INT("range must be >= 2", procName, 1);
+
+    if (seed > 0) srand(seed);
+    *pval = (l_int32)((l_float64)range *
+                       ((l_float64)rand() / (l_float64)RAND_MAX));
+    return 0;
+}
+
+
 /*---------------------------------------------------------------------*
  *                          Version number                             *
  *---------------------------------------------------------------------*/
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/viewfiles.c leptonlib-1.066/src/viewfiles.c
--- leptonlib-1.66/src/viewfiles.c	2009-07-25 20:22:47.000000000 +0300
+++ leptonlib-1.066/src/viewfiles.c	2010-09-16 08:20:32.000000000 +0300
@@ -76,7 +76,7 @@
 char       charbuf[L_BUF_SIZE];
 char       htmlstring[] = "<html>";
 char       framestring[] = "</frameset></html>";
-l_int32    i, nfiles, index, w, nimages;
+l_int32    i, nfiles, index, w, nimages, ignore;
 l_float32  factor;
 PIX       *pix, *pixthumb, *pixview;
 SARRAY    *safiles, *sathumbs, *saviews, *sahtml, *salink;
@@ -105,7 +105,7 @@
 
         /* Make the output directory if it doesn't already exist */
     sprintf(charbuf, "mkdir -p %s", dirout);
-    system(charbuf);
+    ignore = system(charbuf);
 
         /* Capture the filenames in the input directory */
     if ((safiles = getFilenamesInDirectory(dirin)) == NULL)
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/webpimg.h leptonlib-1.066/src/webpimg.h
--- leptonlib-1.66/src/webpimg.h	1970-01-01 02:00:00.000000000 +0200
+++ leptonlib-1.066/src/webpimg.h	2010-09-29 21:19:39.000000000 +0300
@@ -0,0 +1,181 @@
+/*===========================================================================*
+ - Copyright 2010 Google Inc.
+ -
+ - This code is licensed under the same terms as WebM:
+ - Software License Agreement:  http://www.webmproject.org/license/software/
+ - Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
+ *===========================================================================*/
+
+/*
+ * Encoding/Decoding of WebP still image compression format.
+ *
+ * 1. WebPDecode: Takes an array of bytes (string) corresponding to the WebP
+ *                encoded image and generates output in the YUV format with
+ *                the color components U, V subsampled to 1/2 resolution along
+ *                each dimension.
+ *
+ * 2. YUV420toRGBA: Converts from YUV (with color subsampling) such as produced
+ *                  by the WebPDecode routine into 32 bits per pixel RGBA data
+ *                  array. This data array can be directly used by the Leptonica
+ *                  Pix in-memory image format.
+ *
+ * 3. WebPEncode: Takes a Y, U, V data buffers (with color components U and V
+ *                subsampled to 1/2 resolution) and generates the WebP string
+ *
+ * 4. RGBAToYUV420: Generates Y, U, V data (with color subsampling) from 32 bits
+ *                  per pixel RGBA data buffer. The resulting YUV data can be
+ *                  directly fed into the WebPEncode routine.
+ *
+ * 5. AdjustColorspace:
+ *
+ * 6. AdjustColorspaceBack:
+ */
+
+#ifndef THIRD_PARTY_VP8_VP8IMG_H_
+#define THIRD_PARTY_VP8_VP8IMG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif  /* __cplusplus */
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef enum WebPResultType {
+  webp_success = 0,
+  webp_failure = -1
+} WebPResult;
+
+/* Takes an array of bytes (string) corresponding to the WebP
+ * encoded image and generates output in the YUV format with
+ * the color components U, V subsampled to 1/2 resolution along
+ * each dimension.
+ * Input:
+ *      1. data: the WebP data stream (array of bytes)
+ *      2. data_size: count of bytes in the WebP data stream
+ *
+ * Output:
+ *      3. p_Y/p_U/p_V : pointer to the Y/U/V data buffer (this routine will
+ *                       allocate memory for the buffer, fill the buffer with
+ *                       appropriate data and transfer owner ship of the buffer
+ *                       to caller. Caller is reponsible for freeing the memory).
+ *                       Note that the memory for Y, U, V buffers is alloacted
+ *                       in one chunk, hence one should call free(*p_Y) only.
+ *                       Do not try to free the U and V buffers.
+ *
+ *      6. p_width: this routine returns the width of the decoded image here
+ *      7. p_height: this routine returns the width of the decoded image here
+ * Return: success/failure
+ */
+WebPResult WebPDecode(const uint8* data,
+                      int data_size,
+                      uint8** p_Y,
+                      uint8** p_U,
+                      uint8** p_V,
+                      int* p_width,
+                      int* p_height);
+
+/* WebPEncode: Takes a Y, U, V data buffers (with color components U and V
+ *             subsampled to 1/2 resolution) and generates the WebP string.
+ * Input:
+ *      1, 2, 3. Y, U, V: The input YUV data buffers
+ *      4, 5. y_width, y_height: The width and height of the image whose data
+ *                               is in Y, U, V. This matches the Y plane. The U
+ *                               and V planes typically have 1/2 width and
+ *                               height.
+ *      6. y_stride: The width (in bytes) of one row of Y data. This may not
+ *                   match width if there is end of row padding (e.g., for 32
+ *                   bit row aligment).
+ *      7. QP: the quantization parameter. This parameter controls the
+ *             compression vs quality tradeoff. Use smaller numbers for better
+ *             quality (compression will be lesser) and vice versa. 20 is a
+ *             good optimal value.
+ * Output:
+ *      8. p_out: the output array of bytes corresponding to the encoded WebP
+ *                image. This routine allocates memory for the buffer, fills it
+ *                with appropriate values and transfers ownership to caller.
+ *                Caller responsible for freeing of memory.
+ * Return: success/failure
+ */
+WebPResult WebPEncode(const uint8* Y,
+                      const uint8* U,
+                      const uint8* V,
+                      int y_width,
+                      int y_height,
+                      int y_stride,
+                      int uv_width,
+                      int uv_height,
+                      int uv_stride,
+                      int QP,
+                      unsigned char** p_out,
+                      int* p_out_size_bytes,
+                      double* psnr);
+
+/* Converts from YUV (with color subsampling) such as produced by the WebPDecode
+ * routine into 32 bits per pixel RGBA data array. This data array can be
+ * directly used by the Leptonica Pix in-memory image format.
+ * Input:
+ *      1, 2, 3. Y, U, V: the input data buffers
+ *      4. pixwpl: the desired words per line corresponding to the supplied
+ *                 output pixdata.
+ *      5. width, height: the dimensions of the image whose data resides in Y,
+ *                        U, V.
+ * Output:
+ *     6. pixdata: the output data buffer. Caller should allocate
+ *                 height * pixwpl bytes of memory before calling this routine.
+ */
+void YUV420toRGBA(uint8* Y,
+                  uint8* U,
+                  uint8* V,
+                  int words_per_line,
+                  int width,
+                  int height,
+                  uint32* pixdata);
+
+/* Generates Y, U, V data (with color subsampling) from 32 bits
+ * per pixel RGBA data buffer. The resulting YUV data can be directly fed into
+ * the WebPEncode routine.
+ * Input:
+ *    1. pix data input rgba data buffer
+ *    2. words per line corresponding to pixdata
+ *    3, 4. image width and height respectively
+ * Output:
+ *    5, 6, 7. Output YUV data buffers
+ */
+void RGBAToYUV420(uint32* pixdata,
+                  int words_per_line,
+                  int width,
+                  int height,
+                  uint8* Y,
+                  uint8* U,
+                  uint8* V);
+
+/* This function adjust from YUV420J (jpeg decoding) to YUV420 (webp input)
+ * Hints: http://en.wikipedia.org/wiki/YCbCr
+ */
+void AdjustColorspace(uint8* Y, uint8* U, uint8* V, int width, int height);
+
+/* Inverse function: convert from YUV420 to YUV420J */
+void AdjustColorspaceBack(uint8* Y, uint8* U, uint8* V, int width, int height);
+
+/* Checks WebP image header and outputs height and width information of
+ * the image
+ *
+ * Input:
+ *      1. data: the WebP data stream (array of bytes)
+ *      2. data_size: count of bytes in the WebP data stream
+ *
+ * Outut:
+ *      width/height: width and height of the image
+ *
+ * Return: success/failure
+ */
+WebPResult WebPGetInfo(const uint8* data,
+                       int data_size,
+                       int *width,
+                       int *height);
+
+#ifdef __cplusplus
+}
+#endif  /* __cplusplus */
+
+#endif  /* THIRD_PARTY_VP8_VP8IMG_H_ */
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/webpio.c leptonlib-1.066/src/webpio.c
--- leptonlib-1.66/src/webpio.c	1970-01-01 02:00:00.000000000 +0200
+++ leptonlib-1.066/src/webpio.c	2010-09-29 21:19:39.000000000 +0300
@@ -0,0 +1,397 @@
+/*====================================================================*
+ -  Copyright (C) 2001 Leptonica.  All rights reserved.
+ -  This software is distributed in the hope that it will be
+ -  useful, but with NO WARRANTY OF ANY KIND.
+ -  No author or distributor accepts responsibility to anyone for the
+ -  consequences of using this software, or for whether it serves any
+ -  particular purpose or works at all, unless he or she says so in
+ -  writing.  Everyone is granted permission to copy, modify and
+ -  redistribute this source code, for commercial or non-commercial
+ -  purposes, with the following restrictions: (1) the origin of this
+ -  source code must not be misrepresented; (2) modified versions must
+ -  be plainly marked as such; and (3) this notice may not be removed
+ -  or altered from any source or modified source distribution.
+ -  Author: krish@google.com (krish Chaudhury)
+ *====================================================================*/
+
+/*
+ *  webpio.c
+ *
+ *    Read WebP from file
+ *          PIX             *pixReadWebP()  [ special top level ]
+ *          PIX             *pixReadStreamWebP()
+ *
+ *    Write WebP to file
+ *          l_int32          pixWriteWebP()  [ special top level ]
+ *          l_int32          pixWriteStreamWebP()
+ *
+ *    Write WebP to file with target psnr
+ *          l_int32          pixWriteWebPwithTargetPSNR
+ *
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "allheaders.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config_auto.h"
+#endif  /* HAVE_CONFIG_H */
+
+/* --------------------------------------------*/
+#if  HAVE_LIBWEBP   /* defined in environ.h */
+/* --------------------------------------------*/
+
+#include "webpimg.h"
+
+/*---------------------------------------------------------------------*
+ *                              Reading WebP                            *
+ *---------------------------------------------------------------------*/
+/*!
+ *  pixReadWebP()
+ *
+ *      Input:  filename corresponding to WebP image
+ *      Return: pix (8 or 32 bpp), or null on error
+ */
+PIX *
+pixReadWebP(const char  *filename)
+{
+FILE  *fp;
+PIX   *pix;
+
+    PROCNAME("pixReadWebP");
+
+    if (!filename)
+        return (PIX *)ERROR_PTR("filename not defined", procName, NULL);
+
+    if ((fp = fopenReadStream(filename)) == NULL)
+        return (PIX *)ERROR_PTR("image file not found", procName, NULL);
+    pix = pixReadStreamWebP(fp);
+    fclose(fp);
+
+    if (!pix)
+        return (PIX *)ERROR_PTR("image not returned", procName, NULL);
+    return pix;
+}
+
+
+/*!
+ *  pixReadStreamWebP()
+ *
+ *      Input:  stream corresponding to WebP image
+ *      Return: pix(8 or 32 bpp), or null on error
+ *
+ *  Notes:
+ *      (1) Use 'free', and not leptonica's 'FREE', for all heap data
+ *          that is returned from the WebP library.
+ */
+PIX *
+pixReadStreamWebP(FILE  *fp)
+{
+l_int32    w, h, wpl, ret, nbytes;
+l_uint8   *filedata;
+l_uint8   *Y = NULL;
+l_uint8   *U = NULL;
+l_uint8   *V = NULL;
+l_uint32  *data;
+PIX       *pix;
+
+    PROCNAME("pixReadStreamWebP");
+
+    if (!fp)
+        return (PIX *)ERROR_PTR("fp not defined", procName, NULL);
+
+        /* Read data from file and decode into Y,U,V arrays */
+    rewind(fp);
+    if ((filedata = arrayReadStream(fp, &nbytes)) == NULL)
+        return (PIX *)ERROR_PTR("filedata not read", procName, NULL);
+    ret = WebPDecode(filedata, nbytes, &Y, &U, &V, &w, &h);
+    FREE(filedata);
+    if (ret != webp_success) {
+        if (Y) free(Y);
+        return (PIX *)ERROR_PTR("WebP decode failed", procName, NULL);
+    }
+
+        /* Write from Y,U,V arrays to pix data */
+    pix = pixCreate(w, h, 32);
+    wpl = pixGetWpl(pix);
+    data = pixGetData(pix);
+    YUV420toRGBA(Y, U, V, wpl, w, h, data);
+
+    if (Y) free(Y);
+    return pix;
+}
+
+/*---------------------------------------------------------------------*
+ *                             Writing WebP                             *
+ *---------------------------------------------------------------------*/
+/*!
+ *  pixWriteWebP()
+ *
+ *      Input:  filename
+ *              pix
+ *              quantparam (quantization parameter), controls quality of
+ *              generated WebP, smaller quantparam == better quality.
+ *              Send -1 to get default value.
+ *      Return: 0 if OK, 1 on error
+ */
+l_int32
+pixWriteWebP(const char  *filename,
+             PIX         *pix,
+             l_int32      quantparam)
+{
+FILE  *fp;
+
+    PROCNAME("pixWriteWebP");
+
+    if (!pix)
+        return ERROR_INT("pix not defined", procName, 1);
+    if (!filename)
+        return ERROR_INT("filename not defined", procName, 1);
+
+    if ((fp = fopen(filename, "wb+")) == NULL)
+        return ERROR_INT("stream not opened", procName, 1);
+
+    if (pixWriteStreamWebP(fp, pix, quantparam) != 0) {
+        fclose(fp);
+        return ERROR_INT("pix not written to stream", procName, 1);
+    }
+
+    fclose(fp);
+    return 0;
+}
+
+
+/*!
+ *  pixWriteStreampWebP()
+ *
+ *      Input:  stream
+ *              pix  (32 bpp)
+ *              quantparam (quantization parameter; use -1 for default)
+ *      Return: 0 if OK, 1 on error
+ *
+ *  Notes:
+ *      (1) The @quantparam controls the quality of the generated WebP;
+ *          a smaller quantparam gives better quality.  The following
+ *          table shows a rough correspondence between @quantparam
+ *          and the jpeg quality parameter:
+ *
+ *              quantparam               jpeg quality
+ *              ----------               ------------
+ *              20                         60
+ *              15                         75
+ *              12                         90
+ */
+l_int32
+pixWriteStreamWebP(FILE    *fp,
+                   PIX     *pixs,
+                   l_int32  quantparam)
+{
+l_int32    w, h, d, wpl, uv_width, uv_height, nbytes, ret;
+l_uint8   *Y = NULL;
+l_uint8   *U = NULL;
+l_uint8   *V = NULL;
+l_uint8   *filedata = NULL;
+l_uint32  *data;
+PIX       *pix = NULL;
+
+    PROCNAME("pixWriteStreamWebP");
+
+    if (!fp)
+        return ERROR_INT("stream not open", procName, 1);
+    if (!pixs)
+        return ERROR_INT("pixs not defined", procName, 1);
+    if (quantparam <= 0) quantparam = 20;
+
+    if ((pix = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR)) == NULL) {
+        return ERROR_INT("cannot remove color map", procName, 1);
+    }
+    pixGetDimensions(pix, &w, &h, &d);
+    wpl = pixGetWpl(pix);
+    data = pixGetData(pix);
+    if (d != 32 || w <= 0 || h <= 0 || wpl <= 0 || !data) {
+        pixDestroy(&pix);
+        return ERROR_INT("bad or empty input pix", procName, 1);
+    }
+
+        /* Read data into Y,U,V arrays */
+    uv_width = (w + 1) >> 1;
+    uv_height = (h + 1) >> 1;
+    nbytes = w * h + 2 * uv_width * uv_height;
+    if ((Y = (l_uint8 *)CALLOC(nbytes, sizeof(l_uint8))) == NULL) {
+        pixDestroy(&pix);
+        return ERROR_INT("YUV buffer alloc failed", procName, 1);
+    }
+    U = Y + w * h;
+    V = U + uv_width * uv_height;
+    RGBAToYUV420(data, wpl, w, h, Y, U, V);
+
+        /* Encode Y,U,V and write data to file */
+    ret = WebPEncode(Y, U, V, w, h, w, uv_width, uv_height, uv_width,
+                     quantparam, &filedata, &nbytes, NULL);
+    FREE(Y);
+    if (ret != webp_success) {
+        if (filedata) free(filedata);
+        pixDestroy(&pix);
+        return ERROR_INT("WebPEncode failed", procName, 1);
+    }
+
+    rewind(fp);
+    if (fwrite(filedata, 1, nbytes, fp) != nbytes) {
+        pixDestroy(&pix);
+        return ERROR_INT("Write error", procName, 1);
+    }
+    free(filedata);
+    pixDestroy(&pix);
+
+    return 0;
+}
+
+
+/*!
+ *  pixWriteWebPwithTargetPSNR()
+ *
+ *      Input:  filename
+ *              pix  (32 bpp rgb)
+ *              target_psnr (target psnr to control the quality [1 ... 99])
+ *              pqp (<optional return> final qp value used to obtain
+ *                   the target_psnr; can be null)
+ *      Return: 0 if OK, 1 on error
+ *
+ *  Notes:
+ *      (1) The parameter to control quality while encoding WebP is qp.
+ *          This function does a line search over the qp values between
+ *          MIN_QP and MAX_QP to achieve the target PSNR as closely as
+ *          possible.
+ */
+l_int32
+pixWriteWebPwithTargetPSNR(const char  *filename,
+                           PIX         *pixs,
+                           l_float64    target_psnr,
+                           l_int32     *pqp)
+{
+l_uint8   *Y = NULL;
+l_uint8   *U = NULL;
+l_uint8   *V = NULL;
+l_uint8   *filedata = NULL;
+l_uint8   *tmp_filedata = NULL;
+l_int32    MIN_QP = 10;  /* min allowed value of qp */
+l_int32    MAX_QP = 63;  /* max allowed value of qp */
+l_int32    w, h, d, wpl, uv_width, uv_height, nbytes, ret;
+l_int32    qp, delta_qp, qp_test, accept;
+l_int32    tmp_nbytes = 0;
+l_uint32  *data;
+l_float64  psnr, psnr_test;
+FILE      *fp;
+PIX       *pix = NULL;
+
+    PROCNAME("pixWriteWebPwithTargetPSNR");
+
+    if (!filename)
+        return ERROR_INT("filename not defined", procName, 1);
+    if (!pixs)
+        return ERROR_INT("pixs not defined", procName, 1);
+    if (target_psnr <= 0 || target_psnr >= 100)
+        return ERROR_INT("Target psnr out of range", procName, 1);
+
+    if ((pix = pixRemoveColormap(pixs, REMOVE_CMAP_TO_FULL_COLOR)) == NULL) {
+        return ERROR_INT("cannot remove color map", procName, 1);
+    }
+    pixGetDimensions(pix, &w, &h, &d);
+    wpl = pixGetWpl(pix);
+    data = pixGetData(pix);
+    if (d != 32 || w <= 0 || h <= 0 || wpl <= 0 || !data) {
+        pixDestroy(&pix);
+        return ERROR_INT("bad or empty input pix", procName, 1);
+    }
+
+        /* Set the initial value of the QP parameter.  In each iteration
+         * it will then increase or decrease the QP value, based on
+         * whether the achieved psnr is higher or lower than the target_psnr */
+    qp = 30;
+
+        /* Read data into Y,U,V arrays */
+    uv_width = (w + 1) >> 1;
+    uv_height = (h + 1) >> 1;
+    nbytes = w * h + 2 * uv_width * uv_height;
+    if ((Y = (l_uint8 *)CALLOC(nbytes, sizeof(l_uint8))) == NULL) {
+        pixDestroy(&pix);
+        return ERROR_INT("YUV buffer alloc failed", procName, 1);
+    }
+    U = Y + w * h;
+    V = U + uv_width * uv_height;
+    RGBAToYUV420(data, wpl, w, h, Y, U, V);
+
+        /* Encode Y,U,V and write data to file */
+    ret = WebPEncode(Y, U, V, w, h, w, uv_width, uv_height, uv_width, qp,
+                     &filedata, &nbytes, &psnr);
+    if (ret != webp_success) {
+        FREE(Y);
+        if (filedata) free(filedata);
+        pixDestroy(&pix);
+        return ERROR_INT("WebPEncode failed", procName, 1);
+    }
+
+        /* Rationale about the delta_qp being limited: we expect the optimal
+         * qp to be not too far from target qp in practice. So instead of a full
+         * dichotomy for the whole [MIN_QP, MAX_QP] range we cap |delta_qp|
+         * to only explore quickly around the starting value and maximize the
+         * return in investment. */
+    delta_qp = (psnr > target_psnr) ? L_MAX((MAX_QP - qp) / 4, 1) :
+        L_MIN((MIN_QP - qp) / 4, -1);
+
+    while (delta_qp != 0) {
+            /* Advance qp and clip to valid range */
+        qp_test = L_MIN(L_MAX(qp + delta_qp, MIN_QP), MAX_QP);
+            /* Re-adjust delta value after QP-clipping. */
+        delta_qp = qp_test - qp;
+
+        ret = WebPEncode(Y, U, V, w, h, w, uv_width, uv_height, uv_width,
+                         qp_test, &tmp_filedata, &tmp_nbytes, &psnr_test);
+
+        if (ret != webp_success) {
+            FREE(Y);
+            free(filedata);
+            if (tmp_filedata) free(tmp_filedata);
+            pixDestroy(&pix);
+            return ERROR_INT("WebPEncode failed", procName, 1);
+        }
+
+            /* Accept or reject new settings */
+        accept = (psnr_test > target_psnr) ^ (delta_qp < 0);
+        if (accept) {
+            free(filedata);
+            filedata = tmp_filedata;
+            nbytes = tmp_nbytes;
+            qp = qp_test;
+            psnr = psnr_test;
+        }
+        else {
+            delta_qp /= 2;
+            free(tmp_filedata);
+        }
+    }
+    if (pqp) *pqp = qp;
+    FREE(Y);
+
+    if ((fp = fopen(filename, "wb+")) == NULL) {
+        free(filedata);
+        pixDestroy(&pix);
+        return ERROR_INT("stream not opened", procName, 1);
+    }
+    ret = (fwrite(filedata, 1, nbytes, fp) != nbytes);
+    fclose(fp);
+    free(filedata);
+    if (ret) {
+        pixDestroy(&pix);
+        return ERROR_INT("Write error", procName, 1);
+    }
+
+    pixDestroy(&pix);
+    return 0;
+}
+
+/* --------------------------------------------*/
+#endif  /* HAVE_LIBWEBP */
+/* --------------------------------------------*/
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/webpiostub.c leptonlib-1.066/src/webpiostub.c
--- leptonlib-1.66/src/webpiostub.c	1970-01-01 02:00:00.000000000 +0200
+++ leptonlib-1.066/src/webpiostub.c	2010-09-24 07:27:09.000000000 +0300
@@ -0,0 +1,61 @@
+/*====================================================================*
+ -  Copyright (C) 2001 Leptonica.  All rights reserved.
+ -  This software is distributed in the hope that it will be
+ -  useful, but with NO WARRANTY OF ANY KIND.
+ -  No author or distributor accepts responsibility to anyone for the
+ -  consequences of using this software, or for whether it serves any
+ -  particular purpose or works at all, unless he or she says so in
+ -  writing.  Everyone is granted permission to copy, modify and
+ -  redistribute this source code, for commercial or non-commercial
+ -  purposes, with the following restrictions: (1) the origin of this
+ -  source code must not be misrepresented; (2) modified versions must
+ -  be plainly marked as such; and (3) this notice may not be removed
+ -  or altered from any source or modified source distribution.
+ *====================================================================*/
+
+/*
+ *  webpiostub.c
+ *
+ *     Stubs for vp8io.c functions
+ */
+
+#include <stdio.h>
+#include "allheaders.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config_auto.h"
+#endif  /* HAVE_CONFIG_H */
+
+/* --------------------------------------------*/
+#if  !HAVE_LIBWEBP   /* defined in environ.h */
+/* --------------------------------------------*/
+
+PIX * pixReadWebP(const char *filename)
+{
+    return (PIX * )ERROR_PTR("function not present", "pixReadWebP", NULL);
+}
+
+PIX * pixReadStreamWebP(FILE *fp)
+{
+    return (PIX * )ERROR_PTR("function not present", "pixReadStreamWebP", NULL);
+}
+
+l_int32 pixWriteWebP(const char *filename, PIX *pix, l_int32 quantparam)
+{
+    return ERROR_INT("function not present", "pixWriteWebP", 1);
+}
+
+l_int32 pixWriteStreamWebP(FILE *fp, PIX *pix, l_int32 quantparam)
+{
+    return ERROR_INT("function not present", "pixWriteStreamWebP", 1);
+}
+
+l_int32 pixWriteWebPwithTargetPSNR(const char *filename, PIX *pix,
+                                  l_float64 target_psnr, l_int32 *qp_ptr)
+{
+    return ERROR_INT("function not present", "pixWriteWebPwithTargetPSNR", 1);
+}
+
+/* --------------------------------------------*/
+#endif  /* !HAVE_LIBWEBP */
+/* --------------------------------------------*/
diff -urNad -x '*.png' -x '*.jpg' leptonlib-1.66/src/writefile.c leptonlib-1.066/src/writefile.c
--- leptonlib-1.66/src/writefile.c	2010-08-02 08:37:19.000000000 +0300
+++ leptonlib-1.066/src/writefile.c	2010-09-16 08:21:11.000000000 +0300
@@ -55,10 +55,6 @@
 #define  WRITE_AS_NAMED    1
     /* ----------------------------------------------------------- */
 
-#ifdef _WIN32
-#define MAX_PATH     260  /* actually in <WinDef.h>; brings in other files */
-#endif  /* _WIN32 */
-
     /* MS VC++ can't handle array initialization with static consts ! */
 #define L_BUF_SIZE   512
 
@@ -687,13 +683,13 @@
 char           *tempname;
 char            buffer[L_BUF_SIZE];
 static l_int32  index = 0;  /* caution: not .so or thread safe */
-l_int32         w, h, d;
+l_int32         w, h, d, ignore;
 l_float32       ratw, rath, ratmin;
 PIX            *pixt;
 #ifndef _WIN32
 l_int32         wt, ht;
 #else
-char            pathname[MAX_PATH];
+char            pathname[_MAX_PATH];
 #endif  /* _WIN32 */
 
     PROCNAME("pixDisplayWithTitle");
@@ -734,7 +730,7 @@
 
     if (index == 0) {
         snprintf(buffer, L_BUF_SIZE, "rm -f /tmp/junk_display.*");
-        system(buffer);
+        ignore = system(buffer);
     }
 
     index++;
@@ -777,7 +773,7 @@
                  "xzgv --geometry %dx%d+%d+%d %s &", wt + 10, ht + 10,
                  x, y, tempname);
     }
-    system(buffer);
+    ignore = system(buffer);
 
 #else  /* _WIN32 */
 
@@ -790,7 +786,7 @@
     else
         snprintf(buffer, L_BUF_SIZE, "i_view32.exe \"%s\" /pos=(%d,%d)",
                  pathname, x, y);
-    system(buffer);
+    ignore = system(buffer);
 
 #endif  /* _WIN32 */
 
@@ -815,10 +811,11 @@
 l_int32
 pixDisplayMultiple(const char  *filepattern)
 {
-char   buffer[L_BUF_SIZE];
+char     buffer[L_BUF_SIZE];
+l_int32  ignore;
 #ifdef _WIN32
-char   pathname[MAX_PATH];
-char  *dir, *tail;
+char     pathname[_MAX_PATH];
+char    *dir, *tail;
 #endif  /* _WIN32 */
 
     PROCNAME("pixDisplayMultiple");
@@ -839,7 +836,7 @@
     FREE(tail);
 #endif  /* _WIN32 */
 
-    system(buffer);
+    ignore = system(buffer);
     return 0;
 }
 
@@ -903,6 +900,7 @@
                       l_int32  format)
 {
 char            buffer[L_BUF_SIZE];
+l_int32         ignore;
 l_float32       scale;
 PIX            *pixt, *pix8;
 static l_int32  index = 0;  /* caution: not .so or thread safe */
@@ -924,7 +922,7 @@
     if (index == 0) {
         snprintf(buffer, L_BUF_SIZE,
            "rm -f /tmp/junk_write_display.*.png /tmp/junk_write_display.*.jpg");
-        system(buffer);
+        ignore = system(buffer);
     }
     index++;
 
