first working version from Android Studio

This commit is contained in:
Vincent KHERBACHE
2015-01-29 23:47:56 +01:00
commit e55edb3754
5195 changed files with 1523796 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.googlecode.tesseract.android"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="20" />
</manifest>

View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Image adaptive mapping methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class AdaptiveMap {
static {
System.loadLibrary("lept");
}
// Background normalization constants
/** Image reduction value; possible values are 1, 2, 4, 8 */
private final static int NORM_REDUCTION = 16;
/** Desired tile size; actual size may vary */
private final static int NORM_SIZE = 3;
/** Background brightness value; values over 200 may result in clipping */
private final static int NORM_BG_VALUE = 200;
/**
* Normalizes an image's background using default parameters.
*
* @param pixs A source pix image.
* @return the source pix image with a normalized background
*/
public static Pix backgroundNormMorph(Pix pixs) {
return backgroundNormMorph(pixs, NORM_REDUCTION, NORM_SIZE, NORM_BG_VALUE);
}
/**
* Normalizes an image's background to a specified value.
* <p>
* Notes:
* <ol>
* <li>This is a top-level interface for normalizing the image intensity by
* mapping the image so that the background is near the input value 'bgval'.
* <li>The input image is either grayscale or rgb.
* <li>For each component in the input image, the background value is
* estimated using a grayscale closing; hence the 'Morph' in the function
* name.
* <li>An optional binary mask can be specified, with the foreground pixels
* typically over image regions. The resulting background map values will be
* determined by surrounding pixels that are not under the mask foreground.
* The origin (0,0) of this mask is assumed to be aligned with the origin of
* the input image. This binary mask must not fully cover pixs, because then
* there will be no pixels in the input image available to compute the
* background.
* <li>The map is computed at reduced size (given by 'reduction') from the
* input pixs and optional pixim. At this scale, pixs is closed to remove
* the background, using a square Sel of odd dimension. The product of
* reduction * size should be large enough to remove most of the text
* foreground.
* <li>No convolutional smoothing needs to be done on the map before
* inverting it.
* <li>A 'bgval' target background value for the normalized image. This
* should be at least 128. If set too close to 255, some clipping will occur
* in the result.
* </ol>
*
* @param pixs A source pix image.
* @param normReduction Reduction at which morphological closings are done.
* @param normSize Size of square Sel for the closing.
* @param normBgValue Target background value.
* @return the source pix image with a normalized background
*/
public static Pix backgroundNormMorph(
Pix pixs, int normReduction, int normSize, int normBgValue) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
long nativePix = nativeBackgroundNormMorph(
pixs.mNativePix, normReduction, normSize, normBgValue);
if (nativePix == 0)
throw new RuntimeException("Failed to normalize image background");
return new Pix(nativePix);
}
/**
* Adaptively attempts to expand the contrast to the full dynamic range in
* each tile.
* <p>
* Notes:
* <ol>
* <li>If the contrast in a tile is smaller than minDiff, it uses the min
* and max pixel values from neighboring tiles. It also can use
* convolution to smooth the min and max values from neighboring tiles.
* After all that processing, it is possible that the actual pixel values
* in the tile are outside the computed [min ... max] range for local
* contrast normalization. Such pixels are taken to be at either 0 (if
* below the min) or 255 (if above the max).
* <li>sizeX and sizeY give the tile size; they are typically at least 20.
* <li>minDiff is used to eliminate results for tiles where it is likely
* that either fg or bg is missing. A value around 50 or more is
* reasonable.
* <li>The full width and height of the convolution kernel are (2 * smoothx
* + 1) and (2 * smoothy + 1). Some smoothing is typically useful, and we
* limit the smoothing half-widths to the range from 0 to 8. Use 0 for no
* smoothing.
* <li>A linear TRC (gamma = 1.0) is applied to increase the contrast in
* each tile. The result can subsequently be globally corrected, by
* applying pixGammaTRC() with arbitrary values of gamma and the 0 and 255
* points of the mapping.
* </ol>
*
* @param pixs A source pix image
* @param sizeX Tile width
* @param sizeY Tile height
* @param minDiff Minimum difference to accept as valid
* @param smoothX Half-width of convolution kernel applied to min and max
* arrays
* @param smoothY Half-height of convolution kernel applied to min and max
* arrays
*/
public static Pix pixContrastNorm(
Pix pixs, int sizeX, int sizeY, int minDiff, int smoothX, int smoothY) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
long nativePix = nativePixContrastNorm(
pixs.mNativePix, sizeX, sizeY, minDiff, smoothX, smoothY);
if (nativePix == 0)
throw new RuntimeException("Failed to normalize image contrast");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeBackgroundNormMorph(
long nativePix, int reduction, int size, int bgval);
private static native long nativePixContrastNorm(
long nativePix, int sizeX, int sizeY, int minDiff, int smoothX, int smoothY);
}

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Image binarization methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Binarize {
static {
System.loadLibrary("lept");
}
// Otsu thresholding constants
/** Desired tile X dimension; actual size may vary */
public final static int OTSU_SIZE_X = 32;
/** Desired tile Y dimension; actual size may vary */
public final static int OTSU_SIZE_Y = 32;
/** Desired X smoothing value */
public final static int OTSU_SMOOTH_X = 2;
/** Desired Y smoothing value */
public final static int OTSU_SMOOTH_Y = 2;
/** Fraction of the max Otsu score, typically 0.1 */
public final static float OTSU_SCORE_FRACTION = 0.1f;
/**
* Performs locally-adaptive Otsu threshold binarization with default
* parameters.
*
* @param pixs An 8 bpp PIX source image.
* @return A 1 bpp thresholded PIX image.
*/
public static Pix otsuAdaptiveThreshold(Pix pixs) {
return otsuAdaptiveThreshold(
pixs, OTSU_SIZE_X, OTSU_SIZE_Y, OTSU_SMOOTH_X, OTSU_SMOOTH_Y, OTSU_SCORE_FRACTION);
}
/**
* Performs locally-adaptive Otsu threshold binarization.
* <p>
* Notes:
* <ol>
* <li>The Otsu method finds a single global threshold for an image. This
* function allows a locally adapted threshold to be found for each tile
* into which the image is broken up.
* <li>The array of threshold values, one for each tile, constitutes a
* highly downscaled image. This array is optionally smoothed using a
* convolution. The full width and height of the convolution kernel are (2 *
* smoothX + 1) and (2 * smoothY + 1).
* <li>The minimum tile dimension allowed is 16. If such small tiles are
* used, it is recommended to use smoothing, because without smoothing, each
* small tile determines the splitting threshold independently. A tile that
* is entirely in the image bg will then hallucinate fg, resulting in a very
* noisy binarization. The smoothing should be large enough that no tile is
* only influenced by one type (fg or bg) of pixels, because it will force a
* split of its pixels.
* <li>To get a single global threshold for the entire image, use input
* values of sizeX and sizeY that are larger than the image. For this
* situation, the smoothing parameters are ignored.
* <li>The threshold values partition the image pixels into two classes: one
* whose values are less than the threshold and another whose values are
* greater than or equal to the threshold. This is the same use of
* 'threshold' as in pixThresholdToBinary().
* <li>The scorefract is the fraction of the maximum Otsu score, which is
* used to determine the range over which the histogram minimum is searched.
* See numaSplitDistribution() for details on the underlying method of
* choosing a threshold.
* <li>This uses enables a modified version of the Otsu criterion for
* splitting the distribution of pixels in each tile into a fg and bg part.
* The modification consists of searching for a minimum in the histogram
* over a range of pixel values where the Otsu score is within a defined
* fraction, scoreFraction, of the max score. To get the original Otsu
* algorithm, set scoreFraction == 0.
* </ol>
*
* @param pixs An 8 bpp PIX source image.
* @param sizeX Desired tile X dimension; actual size may vary.
* @param sizeY Desired tile Y dimension; actual size may vary.
* @param smoothX Half-width of convolution kernel applied to threshold
* array: use 0 for no smoothing.
* @param smoothY Half-height of convolution kernel applied to threshold
* array: use 0 for no smoothing.
* @param scoreFraction Fraction of the max Otsu score; typ. 0.1 (use 0.0
* for standard Otsu).
* @return A 1 bpp thresholded PIX image.
*/
public static Pix otsuAdaptiveThreshold(
Pix pixs, int sizeX, int sizeY, int smoothX, int smoothY, float scoreFraction) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (pixs.getDepth() != 8)
throw new IllegalArgumentException("Source pix depth must be 8bpp");
long nativePix = nativeOtsuAdaptiveThreshold(
pixs.mNativePix, sizeX, sizeY, smoothX, smoothY, scoreFraction);
if (nativePix == 0)
throw new RuntimeException("Failed to perform Otsu adaptive threshold on image");
return new Pix(nativePix);
}
/**
* Performs Sauvola binarization.
* <p>
* Notes:
* <ol>
* <li> The window width and height are 2 * whsize + 1. The minimum
* value for whsize is 2; typically it is >= 7.
* <li> For nx == ny == 1, this defaults to pixSauvolaBinarize().
* <li> Why a tiled version?
* (a) Because the mean value accumulator is a uint32, overflow
* can occur for an image with more than 16M pixels.
* (b) The mean value accumulator array for 16M pixels is 64 MB.
* The mean square accumulator array for 16M pixels is 128 MB.
* Using tiles reduces the size of these arrays.
* (c) Each tile can be processed independently, in parallel,
* on a multicore processor.
* <li> The Sauvola threshold is determined from the formula:
* t = m * (1 - k * (1 - s / 128))
* where:
* t = local threshold
* m = local mean
* k = @factor (>= 0) [ typ. 0.35 ]
* s = local standard deviation, which is maximized at
* 127.5 when half the samples are 0 and half are 255.
* <li> The basic idea of Niblack and Sauvola binarization is that
* the local threshold should be less than the median value, and the larger
* the variance, the closer to the median it should be chosen. Typical
* values for k are between 0.2 and 0.5.
* </ol>
*
* @param pixs An 8 bpp PIX source image.
* @param whsize Window half-width for measuring local statistics
* @param factor Factor for reducing threshold due to variance; >= 0
* @param nx Subdivision into tiles; >= 1
* @param ny Subdivision into tiles; >= 1
* @return A 1 bpp thresholded PIX image.
*/
public static Pix sauvolaBinarizeTiled(Pix pixs, int whsize, float factor, int nx, int ny) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (pixs.getDepth() != 8)
throw new IllegalArgumentException("Source pix depth must be 8bpp");
long nativePix = nativeSauvolaBinarizeTiled(pixs.mNativePix, whsize, factor, nx, ny);
if (nativePix == 0)
throw new RuntimeException("Failed to perform Otsu adaptive threshold on image");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeOtsuAdaptiveThreshold(
long nativePix, int sizeX, int sizeY, int smoothX, int smoothY, float scoreFract);
private static native long nativeSauvolaBinarizeTiled(
long nativePix, int whsize, float factor, int nx, int ny);
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Wrapper for Leptonica's native BOX.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Box {
static {
System.loadLibrary("lept");
}
/** The index of the X coordinate within the geometry array. */
public static final int INDEX_X = 0;
/** The index of the Y coordinate within the geometry array. */
public static final int INDEX_Y = 1;
/** The index of the width within the geometry array. */
public static final int INDEX_W = 2;
/** The index of the height within the geometry array. */
public static final int INDEX_H = 3;
/**
* A pointer to the native Box object. This is used internally by native
* code.
*/
final long mNativeBox;
private boolean mRecycled = false;
/**
* Creates a new Box wrapper for the specified native BOX.
*
* @param nativeBox A pointer to the native BOX.
*/
Box(long nativeBox) {
mNativeBox = nativeBox;
mRecycled = false;
}
/**
* Creates a box with the specified geometry. All dimensions should be
* non-negative and specified in pixels.
*
* @param x X-coordinate of the top-left corner of the box.
* @param y Y-coordinate of the top-left corner of the box.
* @param w Width of the box.
* @param h Height of the box.
*/
public Box(int x, int y, int w, int h) {
if (x < 0 || y < 0 || w < 0 || h < 0) {
throw new IllegalArgumentException("All box dimensions must be non-negative");
}
long nativeBox = nativeCreate(x, y, w, h);
if (nativeBox == 0) {
throw new OutOfMemoryError();
}
mNativeBox = nativeBox;
mRecycled = false;
}
/**
* Returns the box's x-coordinate in pixels.
*
* @return The box's x-coordinate in pixels.
*/
public int getX() {
return nativeGetX(mNativeBox);
}
/**
* Returns the box's y-coordinate in pixels.
*
* @return The box's y-coordinate in pixels.
*/
public int getY() {
return nativeGetY(mNativeBox);
}
/**
* Returns the box's width in pixels.
*
* @return The box's width in pixels.
*/
public int getWidth() {
return nativeGetWidth(mNativeBox);
}
/**
* Returns the box's height in pixels.
*
* @return The box's height in pixels.
*/
public int getHeight() {
return nativeGetHeight(mNativeBox);
}
/**
* Returns an array containing the coordinates of this box. See INDEX_*
* constants for indices.
*
* @return an array of box oordinates
*/
public int[] getGeometry() {
int[] geometry = new int[4];
if (getGeometry(geometry)) {
return geometry;
}
return null;
}
/**
* Fills an array containing the coordinates of this box. See INDEX_*
* constants for indices.
*
* @param geometry A 4+ element integer array to fill with coordinates.
* @return <code>true</code> on success
*/
public boolean getGeometry(int[] geometry) {
if (geometry.length < 4) {
throw new IllegalArgumentException("Geometry array must be at least 4 elements long");
}
return nativeGetGeometry(mNativeBox, geometry);
}
/**
* Releases resources and frees any memory associated with this Box.
*/
public void recycle() {
if (!mRecycled) {
nativeDestroy(mNativeBox);
mRecycled = true;
}
}
@Override
protected void finalize() throws Throwable {
recycle();
super.finalize();
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeCreate(int x, int y, int w, int h);
private static native int nativeGetX(long nativeBox);
private static native int nativeGetY(long nativeBox);
private static native int nativeGetWidth(long nativeBox);
private static native int nativeGetHeight(long nativeBox);
private static native void nativeDestroy(long nativeBox);
private static native boolean nativeGetGeometry(long nativeBox, int[] geometry);
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2014 Robert Theis
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Extract rectangular regions.
*/
public class Clip {
static {
System.loadLibrary("lept");
}
/**
* Extract a region from a Pix.
* <p>
* Notes:
* <p>
* This should be simple, but there are choices to be made. The box is
* defined relative to the pix coordinates. However, if the box is not
* contained within the pix, we have two choices:
* <p>
* <p> (1) clip the box to the pix
* <p> (2) make a new pix equal to the full box dimensions,
* but let rasterop do the clipping and positioning
* of the src with respect to the dest
* <p>
* Choice (2) immediately brings up the problem of what pixel values
* to use that were not taken from the src. For example, on a grayscale
* image, do you want the pixels not taken from the src to be black
* or white or something else? To implement choice 2, one needs to
* specify the color of these extra pixels.
* <p>
* So we adopt (1), and clip the box first, if necessary,
* before making the dest pix and doing the rasterop. But there
* is another issue to consider. If you want to paste the
* clipped pix back into pixs, it must be properly aligned, and
* it is necessary to use the clipped box for alignment.
*
* @param source Source pix
* @param box Requested clipping region
* @return clipped pix, or null if rectangle doesn't intersect source pix
*/
public static Pix clipRectangle(Pix source, Box box) {
int result = nativeClipRectangle(source.getNativePix(), box.mNativeBox);
if (result != 0) {
return new Pix(result);
}
return null;
}
// ***************
// * NATIVE CODE *
// ***************
private static native int nativeClipRectangle(long nativePix, long nativeBox);
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Leptonica constants.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Constants {
/*-------------------------------------------------------------------------*
* Access and storage flags *
*-------------------------------------------------------------------------*/
/*
* For Pix, Box, Pta and Numa, there are 3 standard methods for handling the
* retrieval or insertion of a struct: (1) direct insertion (Don't do this
* if there is another handle somewhere to this same struct!) (2) copy
* (Always safe, sets up a refcount of 1 on the new object. Can be
* undesirable if very large, such as an image or an array of images.) (3)
* clone (Makes another handle to the same struct, and bumps the refcount up
* by 1. Safe to do unless you're changing data through one of the handles
* but don't want those changes to be seen by the other handle.) For Pixa
* and Boxa, which are structs that hold an array of clonable structs, there
* is an additional method: (4) copy-clone (Makes a new higher-level struct
* with a refcount of 1, but clones all the structs in the array.) Unlike
* the other structs, when retrieving a string from an Sarray, you are
* allowed to get a handle without a copy or clone (i.e., that you don't
* own!). You must not free or insert such a string! Specifically, for an
* Sarray, the copyflag for retrieval is either: TRUE (or 1 or L_COPY) or
* FALSE (or 0 or L_NOCOPY) For insertion, the copyflag is either: TRUE (or
* 1 or L_COPY) or FALSE (or 0 or L_INSERT) Note that L_COPY is always 1,
* and L_INSERT and L_NOCOPY are always 0.
*/
/* Stuff it in; no copy, clone or copy-clone */
public static final int L_INSERT = 0;
/* Make/use a copy of the object */
public static final int L_COPY = 1;
/* Make/use clone (ref count) of the object */
public static final int L_CLONE = 2;
/*
* Make a new object and fill with with clones of each object in the
* array(s)
*/
public static final int L_COPY_CLONE = 3;
/*--------------------------------------------------------------------------*
* Sort flags *
*--------------------------------------------------------------------------*/
/* Sort in increasing order */
public static final int L_SORT_INCREASING = 1;
/* Sort in decreasing order */
public static final int L_SORT_DECREASING = 2;
/* Sort box or c.c. by horiz location */
public static final int L_SORT_BY_X = 3;
/* Sort box or c.c. by vert location */
public static final int L_SORT_BY_Y = 4;
/* Sort box or c.c. by width */
public static final int L_SORT_BY_WIDTH = 5;
/* Sort box or c.c. by height */
public static final int L_SORT_BY_HEIGHT = 6;
/* Sort box or c.c. by min dimension */
public static final int L_SORT_BY_MIN_DIMENSION = 7;
/* Sort box or c.c. by max dimension */
public static final int L_SORT_BY_MAX_DIMENSION = 8;
/* Sort box or c.c. by perimeter */
public static final int L_SORT_BY_PERIMETER = 9;
/* Sort box or c.c. by area */
public static final int L_SORT_BY_AREA = 10;
/* Sort box or c.c. by width/height ratio */
public static final int L_SORT_BY_ASPECT_RATIO = 11;
/* ------------------ Image file format types -------------- */
/*
* The IFF_DEFAULT flag is used to write the file out in the same (input)
* file format that the pix was read from. If the pix was not read from
* file, the input format field will be IFF_UNKNOWN and the output file
* format will be chosen to be compressed and lossless; namely, IFF_TIFF_G4
* for d = 1 and IFF_PNG for everything else. IFF_JP2 is for jpeg2000, which
* is not supported in leptonica.
*/
public static final int IFF_UNKNOWN = 0;
public static final int IFF_BMP = 1;
public static final int IFF_JFIF_JPEG = 2;
public static final int IFF_PNG = 3;
public static final int IFF_TIFF = 4;
public static final int IFF_TIFF_PACKBITS = 5;
public static final int IFF_TIFF_RLE = 6;
public static final int IFF_TIFF_G3 = 7;
public static final int IFF_TIFF_G4 = 8;
public static final int IFF_TIFF_LZW = 9;
public static final int IFF_TIFF_ZIP = 10;
public static final int IFF_PNM = 11;
public static final int IFF_PS = 12;
public static final int IFF_GIF = 13;
public static final int IFF_JP2 = 14;
public static final int IFF_DEFAULT = 15;
public static final int IFF_SPIX = 16;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Image bit-depth conversion methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Convert {
static {
System.loadLibrary("lept");
}
/**
* Converts an image of any bit depth to 8-bit grayscale.
*
* @param pixs Source pix of any bit-depth.
* @return a new Pix image or <code>null</code> on error
*/
public static Pix convertTo8(Pix pixs) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
long nativePix = nativeConvertTo8(pixs.mNativePix);
if (nativePix == 0)
throw new RuntimeException("Failed to natively convert pix");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeConvertTo8(long nativePix);
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2014 Robert Theis
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Edge detection.
*/
public class Edge {
static {
System.loadLibrary("lept");
}
// Edge orientation flags
/** Filters for horizontal edges */
public static final int L_HORIZONTAL_EDGES = 0;
/** Filters for vertical edges */
public static final int L_VERTICAL_EDGES = 1;
/** Filters for all edges */
public static final int L_ALL_EDGES = 2;
/**
* Performs a Sobel edge detecting filter.
* <p>
* To use both the vertical and horizontal filters, set the orientation
* flag to L_ALL_EDGES; this sums the abs. value of their outputs,
* clipped to 255.
* <p>
* Notes:
* <ol>
* <li> Invert pixd to see larger gradients as darker (grayscale).
* <li> To generate a binary image of the edges, threshold the result
* using pixThresholdToBinary(). If the high edge values are to be fg (1),
* invert after running pixThresholdToBinary().
* <li> Label the pixels as follows:
* <p>
* <p> 1 4 7
* <p> 2 5 8
* <p> 3 6 9
* <p>
* Read the data incrementally across the image and unroll the loop.
* <li> This runs at about 45 Mpix/sec on a 3 GHz processor.
* </ol>
*
* @param pixs Source pix (8 bpp; no colormap)
* @param orientFlag Edge orientation flag (L_HORIZONTAL_EDGES,
* L_VERTICAL_EDGES, L_ALL_EDGES)
* @return a new Pix image (8bpp, edges are brighter), or null on error
*/
public static Pix pixSobelEdgeFilter(Pix pixs, int orientFlag) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (pixs.getDepth() != 8)
throw new IllegalArgumentException("Source pix depth must be 8bpp");
if (orientFlag < 0 || orientFlag > 2)
throw new IllegalArgumentException("Invalid orientation flag");
long nativePix = nativePixSobelEdgeFilter(pixs.mNativePix, orientFlag);
if (nativePix == 0)
throw new RuntimeException("Failed to perform Sobel edge filter on image");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativePixSobelEdgeFilter(long nativePix, int orientFlag);
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Image sharpening methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Enhance {
static {
System.loadLibrary("lept");
}
/**
* Performs unsharp masking (edge enhancement).
* <p>
* Notes:
* <ul>
* <li>We use symmetric smoothing filters of odd dimension, typically use
* sizes of 3, 5, 7, etc. The <code>halfwidth</code> parameter for these is
* (size - 1)/2; i.e., 1, 2, 3, etc.</li>
* <li>The <code>fract</code> parameter is typically taken in the range: 0.2
* &lt; <code>fract</code> &lt; 0.7</li>
* </ul>
*
* @param halfwidth The half-width of the smoothing filter.
* @param fraction The fraction of edge to be added back into the source
* image.
* @return an edge-enhanced Pix image or copy if no enhancement requested
*/
public static Pix unsharpMasking(Pix pixs, int halfwidth, float fraction) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
long nativePix = nativeUnsharpMasking(pixs.mNativePix, halfwidth, fraction);
if (nativePix == 0) {
throw new OutOfMemoryError();
}
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeUnsharpMasking(long nativePix, int halfwidth, float fract);
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2014 Robert Theis
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
public class GrayQuant {
static {
System.loadLibrary("lept");
}
/**
* Perform simple (pixelwise) binarization with fixed threshold
* <p>
* Notes:
* <ol>
* <li> If the source pixel is less than the threshold value, the dest will
* be 1; otherwise, it will be 0
* </ol>
*
* @param pixs Source pix (4 or 8 bpp)
* @param thresh Threshold value
* @return a new Pix image, 1 bpp
*/
public static Pix pixThresholdToBinary(Pix pixs, int thresh) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
int depth = pixs.getDepth();
if (depth != 4 && depth != 8)
throw new IllegalArgumentException("Source pix depth must be 4 or 8 bpp");
if (depth == 4 && thresh > 16)
throw new IllegalArgumentException("4 bpp thresh not in {0-16}");
if (depth == 8 && thresh > 256)
throw new IllegalArgumentException("8 bpp thresh not in {0-256}");
long nativePix = nativePixThresholdToBinary(pixs.mNativePix, thresh);
if (nativePix == 0)
throw new RuntimeException("Failed to perform binarization");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativePixThresholdToBinary(long nativePix, int thresh);
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* JPEG input and output methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class JpegIO {
static {
System.loadLibrary("lept");
}
/** Default quality is 85%, which is reasonably good. */
public static final int DEFAULT_QUALITY = 85;
/** Progressive encoding is disabled by default to increase compatibility. */
public static final boolean DEFAULT_PROGRESSIVE = false;
/**
* Returns a compressed JPEG byte representation of this Pix using default
* parameters.
*
* @param pixs
* @return a compressed JPEG byte array representation of the Pix
*/
public static byte[] compressToJpeg(Pix pixs) {
return compressToJpeg(pixs, DEFAULT_QUALITY, DEFAULT_PROGRESSIVE);
}
/**
* Returns a compressed JPEG byte representation of this Pix.
*
* @param pixs A source pix image.
* @param quality The quality of the compressed image. Valid range is 0-100.
* @param progressive Whether to use progressive compression.
* @return a compressed JPEG byte array representation of the Pix
*/
public static byte[] compressToJpeg(Pix pixs, int quality, boolean progressive) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (quality < 0 || quality > 100)
throw new IllegalArgumentException("Quality must be between 0 and 100 (inclusive)");
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
final Bitmap bmp = WriteFile.writeBitmap(pixs);
bmp.compress(CompressFormat.JPEG, quality, byteStream);
bmp.recycle();
final byte[] encodedData = byteStream.toByteArray();
try {
byteStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return encodedData;
}
// ***************
// * NATIVE CODE *
// ***************
private static native byte[] nativeCompressToJpeg(
long nativePix, int quality, boolean progressive);
}

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2014 Robert Theis
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Composite image processing operations.
*/
public class MorphApp {
static {
System.loadLibrary("lept");
}
// Morphological tophat flags
public static final int L_TOPHAT_WHITE = 0;
public static final int L_TOPHAT_BLACK = 1;
/**
* Performs a tophat transform.
* <p>
* Notes:
* <ol>
* <li> Sel is a brick with all elements being hits
* <li> If hsize = vsize = 1, returns an image with all 0 data.
* <li> The L_TOPHAT_WHITE flag emphasizes small bright regions, whereas
* the L_TOPHAT_BLACK flag emphasizes small dark regions. The L_TOPHAT_WHITE
* tophat can be accomplished by doing a L_TOPHAT_BLACK tophat on the
* inverse, or v.v.
* </ol>
*
* @param pixs Source pix (8bpp)
* @param hsize (of Sel; must be odd; origin implicitly in center)
* @param vsize (ditto)
* @param type L_TOPHAT_WHITE: image - opening or L_TOPHAT_BLACK: closing - image
* @return a new Pix image
*/
public static Pix pixTophat(Pix pixs, int hsize, int vsize, int type) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (pixs.getDepth() != 8)
throw new IllegalArgumentException("Source pix depth must be 8bpp");
if (hsize < 1 || vsize < 1)
throw new IllegalArgumentException("hsize or vsize < 1");
if (type < 0 || type > 1)
throw new IllegalArgumentException("Type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE");
long nativePix = nativePixTophat(pixs.mNativePix, hsize, vsize, type);
if (nativePix == 0)
throw new RuntimeException("Failed to perform Tophat on image");
return new Pix(nativePix);
}
/**
* Performs a tophat-like operation.
* <p>
* Notes:
* <ol>
* <li> Don't be fooled. This is NOT a tophat. It is a tophat-like
* operation, where the result is similar to what you'd get if you used an
* erosion instead of an opening, or a dilation instead of a closing.
*
* <li> Instead of opening or closing at full resolution, it does a fast
* downscale/minmax operation, then a quick small smoothing at low res, a
* replicative expansion of the "background" to full res, and finally a
* removal of the background level from the input image. The smoothing
* step may not be important.
*
* <li> It does not remove noise as well as a tophat, but it is 5 to 10
* times faster. If you need the preciseness of the tophat, don't use this.
* <li> The L_TOPHAT_WHITE flag emphasizes small bright regions, whereas
* the L_TOPHAT_BLACK flag emphasizes small dark regions.
* </ol>
*
* @param pixs Source pix (8bpp)
* @param xsize width of max/min op, smoothing; any integer >= 1
* @param ysize height of max/min op, smoothing; any integer >= 1
* @param type L_TOPHAT_WHITE: image - min, or L_TOPHAT_BLACK: max - image
* @return a new Pix image
*/
public static Pix pixFastTophat(Pix pixs, int xsize, int ysize, int type) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (pixs.getDepth() != 8)
throw new IllegalArgumentException("Source pix depth must be 8bpp");
if (xsize < 1 || ysize < 1)
throw new IllegalArgumentException("size < 1");
if (type < 0 || type > 1)
throw new IllegalArgumentException("Type must be L_TOPHAT_BLACK or L_TOPHAT_WHITE");
long nativePix = nativePixFastTophat(pixs.mNativePix, xsize, ysize, type);
if (nativePix == 0)
throw new RuntimeException("Failed to perform pixFastTophat on image");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativePixTophat(long nativePix, int hsize, int vsize, int type);
private static native long nativePixFastTophat(long nativePix, int xsize, int ysize, int type);
}

View File

@@ -0,0 +1,299 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
import android.graphics.Rect;
/**
* Java representation of a native Leptonica PIX object.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Pix {
static {
System.loadLibrary("lept");
}
/** Index of the image width within the dimensions array. */
public static final int INDEX_W = 0;
/** Index of the image height within the dimensions array. */
public static final int INDEX_H = 1;
/** Index of the image bit-depth within the dimensions array. */
public static final int INDEX_D = 2;
/** Package-accessible pointer to native pix */
final long mNativePix;
private boolean mRecycled;
/**
* Creates a new Pix wrapper for the specified native PIX object. Never call
* this twice on the same native pointer, because finalize() will attempt to
* free native memory twice.
*
* @param nativePix A pointer to the native PIX object.
*/
public Pix(long nativePix) {
mNativePix = nativePix;
mRecycled = false;
}
public Pix(int width, int height, int depth) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("Pix width and height must be > 0");
} else if (depth != 1 && depth != 2 && depth != 4 && depth != 8 && depth != 16
&& depth != 24 && depth != 32) {
throw new IllegalArgumentException("Depth must be one of 1, 2, 4, 8, 16, or 32");
}
mNativePix = nativeCreatePix(width, height, depth);
mRecycled = false;
}
/**
* Returns a pointer to the native Pix object. This is used by native code
* and is only valid within the same process in which the Pix was created.
*
* @return a native pointer to the Pix object
*/
public long getNativePix() {
return mNativePix;
}
/**
* Return the raw bytes of the native PIX object. You can reconstruct the
* Pix from this data using createFromPix().
*
* @return a copy of this PIX object's raw data
*/
public byte[] getData() {
int size = nativeGetDataSize(mNativePix);
byte[] buffer = new byte[size];
if (!nativeGetData(mNativePix, buffer)) {
throw new RuntimeException("native getData failed");
}
return buffer;
}
/**
* Returns an array of this image's dimensions. See Pix.INDEX_* for indices.
*
* @return an array of this image's dimensions or <code>null</code> on
* failure
*/
public int[] getDimensions() {
int[] dimensions = new int[4];
if (getDimensions(dimensions)) {
return dimensions;
}
return null;
}
/**
* Fills an array with this image's dimensions. The array must be at least 3
* elements long.
*
* @param dimensions An integer array with at least three elements.
* @return <code>true</code> on success
*/
public boolean getDimensions(int[] dimensions) {
return nativeGetDimensions(mNativePix, dimensions);
}
/**
* Returns a clone of this Pix. This does NOT create a separate copy, just a
* new pointer that can be recycled without affecting other clones.
*
* @return a clone (shallow copy) of the Pix
*/
@Override
public Pix clone() {
long nativePix = nativeClone(mNativePix);
if (nativePix == 0) {
throw new OutOfMemoryError();
}
return new Pix(nativePix);
}
/**
* Returns a deep copy of this Pix that can be modified without affecting
* the original Pix.
*
* @return a copy of the Pix
*/
public Pix copy() {
long nativePix = nativeCopy(mNativePix);
if (nativePix == 0) {
throw new OutOfMemoryError();
}
return new Pix(nativePix);
}
/**
* Inverts this Pix in-place.
*
* @return <code>true</code> on success
*/
public boolean invert() {
return nativeInvert(mNativePix);
}
/**
* Releases resources and frees any memory associated with this Pix. You may
* not modify or access the pix after calling this method.
*/
public void recycle() {
if (!mRecycled) {
nativeDestroy(mNativePix);
mRecycled = true;
}
}
@Override
protected void finalize() throws Throwable {
recycle();
super.finalize();
}
/**
* Creates a new Pix from raw Pix data obtained from getData().
*
* @param pixData Raw pix data obtained from getData().
* @param width The width of the original Pix.
* @param height The height of the original Pix.
* @param depth The bit-depth of the original Pix.
* @return a new Pix or <code>null</code> on error
*/
public static Pix createFromPix(byte[] pixData, int width, int height, int depth) {
long nativePix = nativeCreateFromData(pixData, width, height, depth);
if (nativePix == 0) {
throw new OutOfMemoryError();
}
return new Pix(nativePix);
}
/**
* Returns a Rect with the width and height of this Pix.
*
* @return a Rect with the width and height of this Pix
*/
public Rect getRect() {
int w = getWidth();
int h = getHeight();
return new Rect(0, 0, w, h);
}
/**
* Returns the width of this Pix.
*
* @return the width of this Pix
*/
public int getWidth() {
return nativeGetWidth(mNativePix);
}
/**
* Returns the height of this Pix.
*
* @return the height of this Pix
*/
public int getHeight() {
return nativeGetHeight(mNativePix);
}
/**
* Returns the depth of this Pix.
*
* @return the depth of this Pix
*/
public int getDepth() {
return nativeGetDepth(mNativePix);
}
/**
* Returns the {@link android.graphics.Color} at the specified location.
*
* @param x The x coordinate (0...width-1) of the pixel to return.
* @param y The y coordinate (0...height-1) of the pixel to return.
* @return The argb {@link android.graphics.Color} at the specified
* coordinate.
* @throws IllegalArgumentException If x, y exceeds the image bounds.
*/
public int getPixel(int x, int y) {
if (x < 0 || x >= getWidth()) {
throw new IllegalArgumentException("Supplied x coordinate exceeds image bounds");
} else if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("Supplied x coordinate exceeds image bounds");
}
return nativeGetPixel(mNativePix, x, y);
}
/**
* Sets the {@link android.graphics.Color} at the specified location.
*
* @param x The x coordinate (0...width-1) of the pixel to set.
* @param y The y coordinate (0...height-1) of the pixel to set.
* @param color The argb {@link android.graphics.Color} to set at the
* specified coordinate.
* @throws IllegalArgumentException If x, y exceeds the image bounds.
*/
public void setPixel(int x, int y, int color) {
if (x < 0 || x >= getWidth()) {
throw new IllegalArgumentException("Supplied x coordinate exceeds image bounds");
} else if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException("Supplied x coordinate exceeds image bounds");
}
nativeSetPixel(mNativePix, x, y, color);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeCreatePix(int w, int h, int d);
private static native long nativeCreateFromData(byte[] data, int w, int h, int d);
private static native boolean nativeGetData(long nativePix, byte[] data);
private static native int nativeGetDataSize(long nativePix);
private static native long nativeClone(long nativePix);
private static native long nativeCopy(long nativePix);
private static native boolean nativeInvert(long nativePix);
private static native void nativeDestroy(long nativePix);
private static native boolean nativeGetDimensions(long nativePix, int[] dimensions);
private static native int nativeGetWidth(long nativePix);
private static native int nativeGetHeight(long nativePix);
private static native int nativeGetDepth(long nativePix);
private static native int nativeGetPixel(long nativePix, int x, int y);
private static native void nativeSetPixel(long nativePix, int x, int y, int color);
}

View File

@@ -0,0 +1,450 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
import android.graphics.Rect;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Java representation of a native PIXA object. This object contains multiple
* PIX objects and their associated bounding BOX objects.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Pixa implements Iterable<Pix> {
static {
System.loadLibrary("lept");
}
/** A pointer to the native PIXA object. This is used internally by native code. */
final long mNativePixa;
/** The specified width of this Pixa. */
final int mWidth;
/** The specified height of this Pixa. */
final int mHeight;
private boolean mRecycled;
/**
* Creates a new Pixa with the specified minimum capacity. The Pixa will
* expand automatically as new Pix are added.
*
* @param size The minimum capacity of this Pixa.
* @return a new Pixa or <code>null</code> on error
*/
public static Pixa createPixa(int size) {
return createPixa(size, 0, 0);
}
/**
* Creates a new Pixa with the specified minimum capacity. The Pixa will
* expand automatically as new Pix are added.
* <p>
* If non-zero, the specified width and height will be used to specify the
* bounds of output images. *
*
* @param size The minimum capacity of this Pixa.
* @param width (Optional) The width of this Pixa, use 0 for default.
* @param height (Optional) The height of this Pixa, use 0 for default.
* @return a new Pixa or <code>null</code> on error
*/
public static Pixa createPixa(int size, int width, int height) {
long nativePixa = nativeCreate(size);
if (nativePixa == 0) {
throw new OutOfMemoryError();
}
return new Pixa(nativePixa, width, height);
}
/**
* Creates a wrapper for the specified native Pixa pointer.
*
* @param nativePixa Native pointer to a PIXA object.
* @param width The width of the PIXA.
* @param height The height of the PIXA.
*/
public Pixa(long nativePixa, int width, int height) {
mNativePixa = nativePixa;
mWidth = width;
mHeight = height;
mRecycled = false;
}
/**
* Returns a pointer to the native PIXA object. This is used by native code.
*
* @return a pointer to the native PIXA object
*/
public long getNativePixa() {
return mNativePixa;
}
/**
* Creates a shallow copy of this Pixa. Contained Pix are cloned, and the
* resulting Pixa may be recycled separately from the original.
*
* @return a shallow copy of this Pixa
*/
public Pixa copy() {
int nativePixa = nativeCopy(mNativePixa);
if (nativePixa == 0) {
throw new OutOfMemoryError();
}
return new Pixa(nativePixa, mWidth, mHeight);
}
/**
* Sorts this Pixa using the specified field and order. See
* Constants.L_SORT_BY_* and Constants.L_SORT_INCREASING or
* Constants.L_SORT_DECREASING.
*
* @param field The field to sort by. See Constants.L_SORT_BY_*.
* @param order The order in which to sort. Must be either
* Constants.L_SORT_INCREASING or Constants.L_SORT_DECREASING.
* @return a sorted copy of this Pixa
*/
public Pixa sort(int field, int order) {
int nativePixa = nativeSort(mNativePixa, field, order);
if (nativePixa == 0) {
throw new OutOfMemoryError();
}
return new Pixa(nativePixa, mWidth, mHeight);
}
/**
* Returns the number of elements in this Pixa.
*
* @return the number of elements in this Pixa
*/
public int size() {
return nativeGetCount(mNativePixa);
}
/**
* Recycles this Pixa and frees natively allocated memory. You may not
* access or modify the Pixa after calling this method.
* <p>
* Any Pix obtained from this Pixa or copies of this Pixa will still be
* accessible until they are explicitly recycled or finalized by the garbage
* collector.
*/
public synchronized void recycle() {
if (!mRecycled) {
nativeDestroy(mNativePixa);
mRecycled = true;
}
}
@Override
protected void finalize() throws Throwable {
recycle();
super.finalize();
}
/**
* Merges the contents of another Pixa into this one.
*
* @param otherPixa
* @return <code>true</code> on success
*/
public boolean join(Pixa otherPixa) {
return nativeJoin(mNativePixa, otherPixa.mNativePixa);
}
/**
* Adds a Pix to this Pixa.
*
* @param pix The Pix to add.
* @param mode The mode in which to add this Pix, typically
* Constants.L_CLONE.
*/
public void addPix(Pix pix, int mode) {
nativeAddPix(mNativePixa, pix.mNativePix, mode);
}
/**
* Adds a Box to this Pixa.
*
* @param box The Box to add.
* @param mode The mode in which to add this Box, typically
* Constants.L_CLONE.
*/
public void addBox(Box box, int mode) {
nativeAddBox(mNativePixa, box.mNativeBox, mode);
}
/**
* Adds a Pix and associated Box to this Pixa.
*
* @param pix The Pix to add.
* @param box The Box to add.
* @param mode The mode in which to add this Pix and Box, typically
* Constants.L_CLONE.
*/
public void add(Pix pix, Box box, int mode) {
nativeAdd(mNativePixa, pix.mNativePix, box.mNativeBox, mode);
}
/**
* Returns the Box at the specified index, or <code>null</code> on error.
*
* @param index The index of the Box to return.
* @return the Box at the specified index, or <code>null</code> on error
*/
public Box getBox(int index) {
long nativeBox = nativeGetBox(mNativePixa, index);
if (nativeBox == 0) {
return null;
}
return new Box(nativeBox);
}
/**
* Returns the Pix at the specified index, or <code>null</code> on error.
*
* @param index The index of the Pix to return.
* @return the Pix at the specified index, or <code>null</code> on error
*/
public Pix getPix(int index) {
int nativePix = nativeGetPix(mNativePixa, index);
if (nativePix == 0) {
return null;
}
return new Pix(nativePix);
}
/**
* Returns the width of this Pixa, or 0 if one was not set when it was
* created.
*
* @return the width of this Pixa, or 0 if one was not set when it was
* created
*/
public int getWidth() {
return mWidth;
}
/**
* Returns the height of this Pixa, or 0 if one was not set when it was
* created.
*
* @return the height of this Pixa, or 0 if one was not set when it was
* created
*/
public int getHeight() {
return mHeight;
}
/**
* Returns a bounding Rect for this Pixa, which may be (0,0,0,0) if width
* and height were not specified on creation.
*
* @return a bounding Rect for this Pixa
*/
public Rect getRect() {
return new Rect(0, 0, mWidth, mHeight);
}
/**
* Returns a bounding Rect for the Box at the specified index.
*
* @param index The index of the Box to get the bounding Rect of.
* @return a bounding Rect for the Box at the specified index
*/
public Rect getBoxRect(int index) {
int[] dimensions = getBoxGeometry(index);
if (dimensions == null) {
return null;
}
int x = dimensions[Box.INDEX_X];
int y = dimensions[Box.INDEX_Y];
int w = dimensions[Box.INDEX_W];
int h = dimensions[Box.INDEX_H];
Rect bound = new Rect(x, y, x + w, y + h);
return bound;
}
/**
* Returns a geometry array for the Box at the specified index. See
* Box.INDEX_* for indices.
*
* @param index The index of the Box to get the geometry of.
* @return a bounding Rect for the Box at the specified index
*/
public int[] getBoxGeometry(int index) {
int[] dimensions = new int[4];
if (getBoxGeometry(index, dimensions)) {
return dimensions;
}
return null;
}
/**
* Fills an array with the geometry of the Box at the specified index. See
* Box.INDEX_* for indices.
*
* @param index The index of the Box to get the geometry of.
* @param dimensions The array to fill with Box geometry. Must be at least 4
* elements.
* @return <code>true</code> on success
*/
public boolean getBoxGeometry(int index, int[] dimensions) {
return nativeGetBoxGeometry(mNativePixa, index, dimensions);
}
/**
* Returns an ArrayList of Box bounding Rects.
*
* @return an ArrayList of Box bounding Rects
*/
public ArrayList<Rect> getBoxRects() {
final int pixaCount = nativeGetCount(mNativePixa);
final int[] buffer = new int[4];
final ArrayList<Rect> rects = new ArrayList<Rect>(pixaCount);
for (int i = 0; i < pixaCount; i++) {
getBoxGeometry(i, buffer);
final int x = buffer[Box.INDEX_X];
final int y = buffer[Box.INDEX_Y];
final Rect bound = new Rect(x, y, x + buffer[Box.INDEX_W], y + buffer[Box.INDEX_H]);
rects.add(bound);
}
return rects;
}
/**
* Replaces the Pix and Box at the specified index with the specified Pix
* and Box, both of which may be recycled after calling this method.
*
* @param index The index of the Pix to replace.
* @param pix The Pix to replace the existing Pix.
* @param box The Box to replace the existing Box.
*/
public void replacePix(int index, Pix pix, Box box) {
nativeReplacePix(mNativePixa, index, pix.mNativePix, box.mNativeBox);
}
/**
* Merges the Pix at the specified indices and removes the Pix at the second
* index.
*
* @param indexA The index of the first Pix.
* @param indexB The index of the second Pix, which will be removed after
* merging.
*/
public void mergeAndReplacePix(int indexA, int indexB) {
nativeMergeAndReplacePix(mNativePixa, indexA, indexB);
}
/**
* Writes the components of this Pix to a bitmap-formatted file using a
* random color map.
*
* @param file The file to write to.
* @return <code>true</code> on success
*/
public boolean writeToFileRandomCmap(File file) {
return nativeWriteToFileRandomCmap(mNativePixa, file.getAbsolutePath(), mWidth, mHeight);
}
public Iterator<Pix> iterator() {
return new PixIterator();
}
private class PixIterator implements Iterator<Pix> {
private int mIndex;
private PixIterator() {
mIndex = 0;
}
public boolean hasNext() {
final int size = size();
return (size > 0 && mIndex < size);
}
public Pix next() {
return getPix(mIndex++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
// ***************
// * NATIVE CODE *
// ***************
private static native int nativeCreate(int size);
private static native int nativeCopy(long nativePixa);
private static native int nativeSort(long nativePixa, int field, int order);
private static native boolean nativeJoin(long nativePixa, long otherPixa);
private static native int nativeGetCount(long nativePixa);
private static native void nativeDestroy(long nativePixa);
private static native void nativeAddPix(long nativePixa, long nativePix, int mode);
private static native void nativeAddBox(long nativePixa, long nativeBox, int mode);
private static native void nativeAdd(long nativePixa, long nativePix, long nativeBox, int mode);
private static native boolean nativeWriteToFileRandomCmap(
long nativePixa, String fileName, int width, int height);
private static native void nativeReplacePix(
long nativePixa, int index, long nativePix, long nativeBox);
private static native void nativeMergeAndReplacePix(long nativePixa, int indexA, int indexB);
private static native long nativeGetBox(long nativePix, int index);
private static native int nativeGetPix(long nativePix, int index);
private static native boolean nativeGetBoxGeometry(long nativePixa, int index, int[] dimensions);
}

View File

@@ -0,0 +1,194 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.File;
/**
* Image input and output methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class ReadFile {
static {
System.loadLibrary("lept");
}
/**
* Creates a 32bpp Pix object from encoded data. Supported formats are BMP
* and JPEG.
*
* @param encodedData JPEG or BMP encoded byte data.
* @return a 32bpp Pix object
*/
public static Pix readMem(byte[] encodedData) {
if (encodedData == null)
throw new IllegalArgumentException("Image data byte array must be non-null");
final BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
final Bitmap bmp = BitmapFactory.decodeByteArray(encodedData, 0, encodedData.length,
opts);
final Pix pix = readBitmap(bmp);
bmp.recycle();
return pix;
}
/**
* Creates an 8bpp Pix object from raw 8bpp grayscale pixels.
*
* @param pixelData 8bpp grayscale pixel data.
* @param width The width of the input image.
* @param height The height of the input image.
* @return an 8bpp Pix object
*/
public static Pix readBytes8(byte[] pixelData, int width, int height) {
if (pixelData == null)
throw new IllegalArgumentException("Byte array must be non-null");
if (width <= 0)
throw new IllegalArgumentException("Image width must be greater than 0");
if (height <= 0)
throw new IllegalArgumentException("Image height must be greater than 0");
if (pixelData.length < width * height)
throw new IllegalArgumentException("Array length does not match dimensions");
long nativePix = nativeReadBytes8(pixelData, width, height);
if (nativePix == 0)
throw new RuntimeException("Failed to read pix from memory");
return new Pix(nativePix);
}
/**
* Replaces the bytes in an 8bpp Pix object with raw grayscale 8bpp pixels.
* Width and height be identical to the input Pix.
*
* @param pixs The Pix whose bytes will be replaced.
* @param pixelData 8bpp grayscale pixel data.
* @param width The width of the input image.
* @param height The height of the input image.
* @return an 8bpp Pix object
*/
public static boolean replaceBytes8(Pix pixs, byte[] pixelData, int width, int height) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (pixelData == null)
throw new IllegalArgumentException("Byte array must be non-null");
if (width <= 0)
throw new IllegalArgumentException("Image width must be greater than 0");
if (height <= 0)
throw new IllegalArgumentException("Image height must be greater than 0");
if (pixelData.length < width * height)
throw new IllegalArgumentException("Array length does not match dimensions");
if (pixs.getWidth() != width)
throw new IllegalArgumentException("Source pix width does not match image width");
if (pixs.getHeight() != height)
throw new IllegalArgumentException("Source pix width does not match image width");
return nativeReplaceBytes8(pixs.mNativePix, pixelData, width, height);
}
/**
* Creates a Pixa object from encoded files in a directory. Supported
* formats are BMP and JPEG.
*
* @param dir The directory containing the files.
* @param prefix The prefix of the files to load into a Pixa.
* @return a Pixa object containing one Pix for each file
*/
public static Pixa readFiles(File dir, String prefix) {
if (dir == null)
throw new IllegalArgumentException("Directory must be non-null");
if (!dir.exists())
throw new IllegalArgumentException("Directory does not exist");
if (!dir.canRead())
throw new IllegalArgumentException("Cannot read directory");
// TODO: Remove or fix this.
throw new RuntimeException("readFiles() is not current supported");
}
/**
* Creates a Pix object from encoded file data. Supported formats are BMP
* and JPEG.
*
* @param file The JPEG or BMP-encoded file to read in as a Pix.
* @return a Pix object
*/
public static Pix readFile(File file) {
if (file == null)
throw new IllegalArgumentException("File must be non-null");
if (!file.exists())
throw new IllegalArgumentException("File does not exist");
if (!file.canRead())
throw new IllegalArgumentException("Cannot read file");
final BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
final Bitmap bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), opts);
final Pix pix = readBitmap(bmp);
bmp.recycle();
return pix;
}
/**
* Creates a Pix object from Bitmap data. Currently supports only
* ARGB_8888-formatted bitmaps.
*
* @param bmp The Bitmap object to convert to a Pix.
* @return a Pix object
*/
public static Pix readBitmap(Bitmap bmp) {
if (bmp == null)
throw new IllegalArgumentException("Bitmap must be non-null");
if (bmp.getConfig() != Bitmap.Config.ARGB_8888)
throw new IllegalArgumentException("Bitmap config must be ARGB_8888");
long nativePix = nativeReadBitmap(bmp);
if (nativePix == 0)
throw new RuntimeException("Failed to read pix from bitmap");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeReadMem(byte[] data, int size);
private static native long nativeReadBytes8(byte[] data, int w, int h);
private static native boolean nativeReplaceBytes8(long nativePix, byte[] data, int w, int h);
private static native long nativeReadFiles(String dirname, String prefix);
private static native long nativeReadFile(String filename);
private static native long nativeReadBitmap(Bitmap bitmap);
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* @author alanv@google.com (Alan Viverette)
*/
public class Rotate {
static {
System.loadLibrary("lept");
}
// Rotation default
/** Default rotation quality is high. */
public static final boolean ROTATE_QUALITY = true;
/**
* Performs rotation using the default parameters.
*
* @param pixs The source pix.
* @param degrees The number of degrees to rotate; clockwise is positive.
* @return the rotated source image
*/
public static Pix rotate(Pix pixs, float degrees) {
return rotate(pixs, degrees, false);
}
/**
* Performs rotation with resizing using the default parameters.
*
* @param pixs The source pix.
* @param degrees The number of degrees to rotate; clockwise is positive.
* @param quality Whether to use high-quality rotation.
* @return the rotated source image
*/
public static Pix rotate(Pix pixs, float degrees, boolean quality) {
return rotate(pixs, degrees, quality, true);
}
/**
* Performs basic image rotation about the center.
* <p>
* Notes:
* <ol>
* <li>Rotation is about the center of the image.
* <li>For very small rotations, just return a clone.
* <li>Rotation brings either white or black pixels in from outside the
* image.
* <li>Above 20 degrees, if rotation by shear is requested, we rotate by
* sampling.
* <li>Colormaps are removed for rotation by area map and shear.
* <li>The dest can be expanded so that no image pixels are lost. To invoke
* expansion, input the original width and height. For repeated rotation,
* use of the original width and height allows the expansion to stop at the
* maximum required size, which is a square with side = sqrt(w*w + h*h).
* </ol>
*
* @param pixs The source pix.
* @param degrees The number of degrees to rotate; clockwise is positive.
* @param quality Whether to use high-quality rotation.
* @param Whether to expand the output so that no pixels are lost.
* <strong>Note:</strong> 1bpp images are always resized when
* quality is {@code true}.
* @return the rotated source image
*/
public static Pix rotate(Pix pixs, float degrees, boolean quality, boolean resize) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
long nativePix = nativeRotate(pixs.mNativePix, degrees, quality, resize);
if (nativePix == 0)
return null;
return new Pix(nativePix);
}
/**
* Performs top-level rotation by multiples of 90 degrees.
*
* @param pixs The source pix (all depths)
* @param quads 0-3; number of 90 degree cw rotations
* @return the rotated source image
*/
public static Pix rotateOrth(Pix pixs, int quads) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (quads < 0 || quads > 3)
throw new IllegalArgumentException("quads not in {0,1,2,3}");
int nativePix = nativeRotateOrth(pixs.mNativePix, quads);
if (nativePix == 0)
return null;
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native int nativeRotateOrth(long nativePix, int quads);
private static native long nativeRotate(long nativePix, float degrees, boolean quality,
boolean resize);
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Image scaling methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Scale {
static {
System.loadLibrary("lept");
}
public enum ScaleType {
/* Scale in X and Y independently, so that src matches dst exactly. */
FILL,
/*
* Compute a scale that will maintain the original src aspect ratio, but
* will also ensure that src fits entirely inside dst. May shrink or
* expand src to fit dst.
*/
FIT,
/*
* Compute a scale that will maintain the original src aspect ratio, but
* will also ensure that src fits entirely inside dst. May shrink src to
* fit dst, but will not expand it.
*/
FIT_SHRINK,
}
/**
* Scales the Pix to a specified width and height using a specified scaling
* type (fill, stretch, etc.). Returns a scaled image or a clone of the Pix
* if no scaling is required.
*
* @param pixs
* @param width
* @param height
* @param type
* @return a scaled image or a clone of the Pix if no scaling is required
*/
public static Pix scaleToSize(Pix pixs, int width, int height, ScaleType type) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
int pixWidth = pixs.getWidth();
int pixHeight = pixs.getHeight();
float scaleX = width / (float) pixWidth;
float scaleY = height / (float) pixHeight;
switch (type) {
case FILL:
// Retains default scaleX and scaleY values
break;
case FIT:
scaleX = Math.min(scaleX, scaleY);
scaleY = scaleX;
break;
case FIT_SHRINK:
scaleX = Math.min(1.0f, Math.min(scaleX, scaleY));
scaleY = scaleX;
break;
}
return scale(pixs, scaleX, scaleY);
}
/**
* Scales the Pix to specified scale. If no scaling is required, returns a
* clone of the source Pix.
*
* @param pixs the source Pix
* @param scale dimension scaling factor
* @return a Pix scaled according to the supplied factors
*/
public static Pix scale(Pix pixs, float scale) {
return scale(pixs, scale, scale);
}
/**
* Scales the Pix to the specified scale without sharpening.
*
* @param pixs the source Pix (1, 2, 4, 8, 16 and 32 bpp)
* @param scale scaling factor for both X and Y
* @return a Pix scaled while maintaining its aspect ratio
*/
public static Pix scaleWithoutSharpening(Pix pixs, float scale) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (scale <= 0.0f)
throw new IllegalArgumentException("Scaling factor must be positive");
return new Pix(nativeScaleGeneral(pixs.mNativePix, scale, scale, 0f, 0));
}
/**
* Scales the Pix to specified x and y scale. If no scaling is required,
* returns a clone of the source Pix.
*
* @param pixs the source Pix
* @param scaleX x-dimension (width) scaling factor
* @param scaleY y-dimension (height) scaling factor
* @return a Pix scaled according to the supplied factors
*/
public static Pix scale(Pix pixs, float scaleX, float scaleY) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (scaleX <= 0.0f)
throw new IllegalArgumentException("X scaling factor must be positive");
if (scaleY <= 0.0f)
throw new IllegalArgumentException("Y scaling factor must be positive");
long nativePix = nativeScale(pixs.mNativePix, scaleX, scaleY);
if (nativePix == 0)
throw new RuntimeException("Failed to natively scale pix");
return new Pix(nativePix);
}
// ***************
// * NATIVE CODE *
// ***************
private static native long nativeScale(long nativePix, float scaleX, float scaleY);
private static native long nativeScaleGeneral(long nativePix, float scaleX, float scaleY, float sharpfract, int sharpwidth);
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
/**
* Image rotation and skew detection methods.
*
* @author alanv@google.com (Alan Viverette)
*/
public class Skew {
static {
System.loadLibrary("lept");
}
// Text alignment defaults
/** Default range for sweep, will detect rotation of + or - 30 degrees. */
public final static float SWEEP_RANGE = 30.0f;
/** Default sweep delta, reasonably accurate within 0.05 degrees. */
public final static float SWEEP_DELTA = 5.0f;
/** Default sweep reduction, one-eighth the size of the original image. */
public final static int SWEEP_REDUCTION = 8;
/** Default sweep reduction, one-fourth the size of the original image. */
public final static int SEARCH_REDUCTION = 4;
/** Default search minimum delta, reasonably accurate within 0.05 degrees. */
public final static float SEARCH_MIN_DELTA = 0.01f;
/**
* Finds and returns the skew angle using default parameters.
*
* @param pixs Input pix (1 bpp).
* @return the detected skew angle, or 0.0 on failure
*/
public static float findSkew(Pix pixs) {
return findSkew(pixs, SWEEP_RANGE, SWEEP_DELTA, SWEEP_REDUCTION, SEARCH_REDUCTION,
SEARCH_MIN_DELTA);
}
/**
* Finds and returns the skew angle, doing first a sweep through a set of
* equal angles, and then doing a binary search until convergence.
* <p>
* Notes:
* <ol>
* <li>In computing the differential line sum variance score, we sum the
* result over scanlines, but we always skip:
* <ul>
* <li>at least one scanline
* <li>not more than 10% of the image height
* <li>not more than 5% of the image width
* </ul>
* </ol>
*
* @param pixs Input pix (1 bpp).
* @param sweepRange Half the full search range, assumed about 0; in
* degrees.
* @param sweepDelta Angle increment of sweep; in degrees.
* @param sweepReduction Sweep reduction factor = 1, 2, 4 or 8.
* @param searchReduction Binary search reduction factor = 1, 2, 4 or 8; and
* must not exceed redsweep.
* @param searchMinDelta Minimum binary search increment angle; in degrees.
* @return the detected skew angle, or 0.0 on failure
*/
public static float findSkew(Pix pixs, float sweepRange, float sweepDelta, int sweepReduction,
int searchReduction, float searchMinDelta) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
return nativeFindSkew(pixs.mNativePix, sweepRange, sweepDelta, sweepReduction,
searchReduction, searchMinDelta);
}
// ***************
// * NATIVE CODE *
// ***************
private static native float nativeFindSkew(long nativePix, float sweepRange, float sweepDelta,
int sweepReduction, int searchReduction, float searchMinDelta);
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.leptonica.android;
import android.graphics.Bitmap;
import java.io.File;
/**
* @author alanv@google.com (Alan Viverette)
*/
public class WriteFile {
static {
System.loadLibrary("lept");
}
/* Default JPEG quality */
public static final int DEFAULT_QUALITY = 85;
/* Default JPEG progressive encoding */
public static final boolean DEFAULT_PROGRESSIVE = true;
/**
* Write an 8bpp Pix to a flat byte array.
*
* @param pixs The 8bpp source image.
* @return a byte array where each byte represents a single 8-bit pixel
*/
public static byte[] writeBytes8(Pix pixs) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
int size = pixs.getWidth() * pixs.getHeight();
if (pixs.getDepth() != 8) {
Pix pix8 = Convert.convertTo8(pixs);
pixs.recycle();
pixs = pix8;
}
byte[] data = new byte[size];
writeBytes8(pixs, data);
return data;
}
/**
* Write an 8bpp Pix to a flat byte array.
*
* @param pixs The 8bpp source image.
* @param data A byte array large enough to hold the pixels of pixs.
* @return the number of bytes written to data
*/
public static int writeBytes8(Pix pixs, byte[] data) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
int size = pixs.getWidth() * pixs.getHeight();
if (data.length < size)
throw new IllegalArgumentException("Data array must be large enough to hold image bytes");
int bytesWritten = nativeWriteBytes8(pixs.mNativePix, data);
return bytesWritten;
}
/**
* Writes all the images in a Pixa array to individual files using the
* specified format. The output file extension will be determined by the
* format.
* <p>
* Output file names will take the format <path>/<prefix><index>.<extension>
*
* @param pixas The source Pixa image array.
* @param path The output directory.
* @param prefix The prefix to give output files.
* @param format The format to use for output files.
* @return <code>true</code> on success
*/
public static boolean writeFiles(Pixa pixas, File path, String prefix, int format) {
if (pixas == null)
throw new IllegalArgumentException("Source pixa must be non-null");
if (path == null)
throw new IllegalArgumentException("Destination path non-null");
if (prefix == null)
throw new IllegalArgumentException("Filename prefix must be non-null");
//String rootname = new File(path, prefix).getAbsolutePath();
throw new RuntimeException("writeFiles() is not currently supported");
}
/**
* Write a Pix to a byte array using the specified encoding from
* Constants.IFF_*.
*
* @param pixs The source image.
* @param format A format from Constants.IFF_*.
* @return a byte array containing encoded bytes
*/
public static byte[] writeMem(Pix pixs, int format) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
throw new RuntimeException("writeMem() is not currently supported");
}
/**
* Writes a Pix to file using the file extension as the output format;
* supported formats are .jpg or .jpeg for JPEG and .bmp for bitmap.
* <p>
* Uses default quality and progressive encoding settings.
*
* @param pixs Source image.
* @param file The file to write.
* @return <code>true</code> on success
*/
public static boolean writeImpliedFormat(Pix pixs, File file) {
return writeImpliedFormat(pixs, file, DEFAULT_QUALITY, DEFAULT_PROGRESSIVE);
}
/**
* Writes a Pix to file using the file extension as the output format;
* supported formats are .jpg or .jpeg for JPEG and .bmp for bitmap.
* <p>
* Notes:
* <ol>
* <li>This determines the output format from the filename extension.
* <li>The last two args are ignored except for requests for jpeg files.
* <li>The jpeg default quality is 75.
* </ol>
*
* @param pixs Source image.
* @param file The file to write.
* @param quality (Only for lossy formats) Quality between 1 - 100, 0 for
* default.
* @param progressive (Only for JPEG) Whether to encode as progressive.
* @return <code>true</code> on success
*/
public static boolean writeImpliedFormat(
Pix pixs, File file, int quality, boolean progressive) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
if (file == null)
throw new IllegalArgumentException("File must be non-null");
return nativeWriteImpliedFormat(
pixs.mNativePix, file.getAbsolutePath(), quality, progressive);
}
/**
* Writes a Pix to an Android Bitmap object. The output Bitmap will always
* be in ARGB_8888 format, but the input Pixs may be any bit-depth.
*
* @param pixs The source image.
* @return a Bitmap containing a copy of the source image, or <code>null
* </code> on failure
*/
public static Bitmap writeBitmap(Pix pixs) {
if (pixs == null)
throw new IllegalArgumentException("Source pix must be non-null");
final int[] dimensions = pixs.getDimensions();
final int width = dimensions[Pix.INDEX_W];
final int height = dimensions[Pix.INDEX_H];
//final int depth = dimensions[Pix.INDEX_D];
final Bitmap.Config config = Bitmap.Config.ARGB_8888;
final Bitmap bitmap = Bitmap.createBitmap(width, height, config);
if (nativeWriteBitmap(pixs.mNativePix, bitmap)) {
return bitmap;
}
bitmap.recycle();
return null;
}
// ***************
// * NATIVE CODE *
// ***************
private static native int nativeWriteBytes8(long nativePix, byte[] data);
private static native boolean nativeWriteFiles(long nativePix, String rootname, int format);
private static native byte[] nativeWriteMem(long nativePix, int format);
private static native boolean nativeWriteImpliedFormat(
long nativePix, String fileName, int quality, boolean progressive);
private static native boolean nativeWriteBitmap(long nativePix, Bitmap bitmap);
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.tesseract.android;
import com.googlecode.tesseract.android.TessBaseAPI.PageIteratorLevel;
public class PageIterator {
static {
System.loadLibrary("lept");
System.loadLibrary("tess");
}
/** Pointer to native page iterator. */
private final long mNativePageIterator;
/* package */PageIterator(long nativePageIterator) {
mNativePageIterator = nativePageIterator;
}
/**
* Resets the iterator to point to the start of the page.
*/
public void begin() {
nativeBegin(mNativePageIterator);
}
/**
* Moves to the start of the next object at the given level in the page
* hierarchy, and returns false if the end of the page was reached.
* <p>
* NOTE that {@link PageIteratorLevel#RIL_SYMBOL} will skip non-text blocks,
* but all other {@link PageIteratorLevel} level values will visit each
* non-text block once. Think of non text blocks as containing a single
* para, with a single line, with a single imaginary word.
* <p>
* Calls to {@link #next} with different levels may be freely intermixed.
* <p>
* This function iterates words in right-to-left scripts correctly, if the
* appropriate language has been loaded into Tesseract.
*
* @param level the page iterator level. See {@link PageIteratorLevel}.
* @return {@code false} if the end of the page was reached, {@code true}
* otherwise.
*/
public boolean next(int level) {
return nativeNext(mNativePageIterator, level);
}
/**
* Get bounding box: x, y, w, h
*
* ============= Accessing data ==============.
* Coordinate system:
* Integer coordinates are at the cracks between the pixels.
* The top-left corner of the top-left pixel in the image is at (0,0).
* The bottom-right corner of the bottom-right pixel in the image is at
* (width, height).
* Every bounding box goes from the top-left of the top-left contained
* pixel to the bottom-right of the bottom-right contained pixel, so
* the bounding box of the single top-left pixel in the image is:
* (0,0)->(1,1).
* If an image rectangle has been set in the API, then returned coordinates
* relate to the original (full) image, rather than the rectangle.
*
* Returns the bounding rectangle of the current object at the given level.
* See comment on coordinate system above.
* The returned bounding box may clip foreground pixels from a grey image.
*
* @param level the page iterator level. See {@link PageIteratorLevel}.
* @return the bounding rectangle of the current object at the given level
*/
public int[] getBoundingBox(int level){
return nativeBoundingBox(mNativePageIterator, level);
}
private static native void nativeBegin(long nativeIterator);
private static native boolean nativeNext(long nativeIterator, int level);
private static native int[] nativeBoundingBox(long nativeIterator, int level);
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.tesseract.android;
import java.util.ArrayList;
import java.util.List;
import android.util.Log;
import android.util.Pair;
import com.googlecode.tesseract.android.TessBaseAPI.PageIteratorLevel;
/**
* Java interface for the ResultIterator. Does not implement all available JNI
* methods, but does implement enough to be useful. Comments are adapted from
* original Tesseract source.
*
* @author alanv@google.com (Alan Viverette)
*/
public class ResultIterator extends PageIterator {
static {
System.loadLibrary("lept");
System.loadLibrary("tess");
}
/** Pointer to native result iterator. */
private final long mNativeResultIterator;
/* package */ResultIterator(long nativeResultIterator) {
super(nativeResultIterator);
mNativeResultIterator = nativeResultIterator;
}
/**
* Returns the text string for the current object at the given level.
*
* @param level the page iterator level. See {@link PageIteratorLevel}.
* @return the text string for the current object at the given level.
*/
public String getUTF8Text(int level) {
return nativeGetUTF8Text(mNativeResultIterator, level);
}
/**
* Returns the mean confidence of the current object at the given level. The
* number should be interpreted as a percent probability (0-100).
*
* @param level the page iterator level. See {@link PageIteratorLevel}.
* @return the mean confidence of the current object at the given level.
*/
public float confidence(int level) {
return nativeConfidence(mNativeResultIterator, level);
}
/**
* Returns all possible matching text strings and their confidence level
* for the current object at the given level.
* <p>
* The default matching text is blank ("").
* The default confidence level is zero (0.0)
*
* @param level the page iterator level. See {@link PageIteratorLevel}.
* @return A list of pairs with the UTF string and the confidence
*/
public List<Pair<String, Double>> getChoicesAndConfidence(int level) {
// Get the native choices
String[] nativeChoices = nativeGetChoices(mNativeResultIterator, level);
// Create the output list
ArrayList<Pair<String, Double>> pairedResults = new ArrayList<Pair<String, Double>>();
for (int i = 0; i < nativeChoices.length; i++ ) {
// The string and the confidence level are separated by a '|'
int separatorPosition = nativeChoices[i].lastIndexOf('|');
// Create a pair with the choices
String utfString = "";
Double confidenceLevel = Double.valueOf(0);
if (separatorPosition > 0) {
// If the string contains a '|' separate the UTF string and the confidence level
utfString = nativeChoices[i].substring(0, separatorPosition);
try {
confidenceLevel = Double.parseDouble(nativeChoices[i].substring(separatorPosition + 1));
} catch (NumberFormatException e) {
Log.e("ResultIterator","Invalid confidence level for " + nativeChoices[i]);
}
} else {
// If the string contains no '|' then save the full native result as the utfString
utfString = nativeChoices[i];
}
// Add the UTF string to the results
pairedResults.add(new Pair<String, Double> (utfString, confidenceLevel));
}
return pairedResults;
}
private static native String[] nativeGetChoices(long nativeResultIterator, int level);
private static native String nativeGetUTF8Text(long nativeResultIterator, int level);
private static native float nativeConfidence(long nativeResultIterator, int level);
}

View File

@@ -0,0 +1,742 @@
/*
* Copyright (C) 2011 Google Inc.
* Copyright (C) 2011 Robert Theis
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.googlecode.tesseract.android;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.Log;
import com.googlecode.leptonica.android.Pixa;
import com.googlecode.leptonica.android.Pix;
import com.googlecode.leptonica.android.ReadFile;
import java.io.File;
/**
* Java interface for the Tesseract OCR engine. Does not implement all available
* JNI methods, but does implement enough to be useful. Comments are adapted
* from original Tesseract source.
*
* @author alanv@google.com (Alan Viverette)
*/
public class TessBaseAPI {
/**
* Used by the native implementation of the class.
*/
private long mNativeData;
static {
System.loadLibrary("lept");
System.loadLibrary("tess");
nativeClassInit();
}
public static final class PageSegMode {
/** Orientation and script detection only. */
public static final int PSM_OSD_ONLY = 0;
/** Automatic page segmentation with orientation and script detection. (OSD) */
public static final int PSM_AUTO_OSD = 1;
/** Fully automatic page segmentation, but no OSD, or OCR. */
public static final int PSM_AUTO_ONLY = 2;
/** Fully automatic page segmentation, but no OSD. */
public static final int PSM_AUTO = 3;
/** Assume a single column of text of variable sizes. */
public static final int PSM_SINGLE_COLUMN = 4;
/** Assume a single uniform block of vertically aligned text. */
public static final int PSM_SINGLE_BLOCK_VERT_TEXT = 5;
/** Assume a single uniform block of text. (Default.) */
public static final int PSM_SINGLE_BLOCK = 6;
/** Treat the image as a single text line. */
public static final int PSM_SINGLE_LINE = 7;
/** Treat the image as a single word. */
public static final int PSM_SINGLE_WORD = 8;
/** Treat the image as a single word in a circle. */
public static final int PSM_CIRCLE_WORD = 9;
/** Treat the image as a single character. */
public static final int PSM_SINGLE_CHAR = 10;
/** Find as much text as possible in no particular order. */
public static final int PSM_SPARSE_TEXT = 11;
/** Sparse text with orientation and script detection. */
public static final int PSM_SPARSE_TEXT_OSD = 12;
/** Number of enum entries. */
public static final int PSM_COUNT = 13;
}
/** Whitelist of characters to recognize. */
public static final String VAR_CHAR_WHITELIST = "tessedit_char_whitelist";
/** Blacklist of characters to not recognize. */
public static final String VAR_CHAR_BLACKLIST = "tessedit_char_blacklist";
/** Save blob choices allowing us to get alternative results. */
public static final String VAR_SAVE_BLOB_CHOICES = "save_blob_choices";
/** String value used to assign a boolean variable to true. */
public static final String VAR_TRUE = "T";
/** String value used to assign a boolean variable to false. */
public static final String VAR_FALSE = "F";
/** Run Tesseract only - fastest */
public static final int OEM_TESSERACT_ONLY = 0;
/** Run Cube only - better accuracy, but slower */
public static final int OEM_CUBE_ONLY = 1;
/** Run both and combine results - best accuracy */
public static final int OEM_TESSERACT_CUBE_COMBINED = 2;
/** Default OCR engine mode. */
public static final int OEM_DEFAULT = 3;
/**
* Elements of the page hierarchy, used in {@link ResultIterator} to provide
* functions that operate on each level without having to have 5x as many
* functions.
* <p>
* NOTE: At present {@link #RIL_PARA} and {@link #RIL_BLOCK} are equivalent
* as there is no paragraph internally yet.
*/
public static final class PageIteratorLevel {
/** Block of text/image/separator line. */
public static final int RIL_BLOCK = 0;
/** Paragraph within a block. */
public static final int RIL_PARA = 1;
/** Line within a paragraph. */
public static final int RIL_TEXTLINE = 2;
/** Word within a text line. */
public static final int RIL_WORD = 3;
/** Symbol/character within a word. */
public static final int RIL_SYMBOL = 4;
};
private ProgressNotifier progressNotifier;
/**
* Interface that may be implemented by calling object in order to receive
* progress callbacks during OCR.
*/
public interface ProgressNotifier {
void onProgressValues(ProgressValues progressValues);
}
/**
* Represents values indicating recognition progress and status.
*/
public class ProgressValues {
private int percent;
private int boundingBoxLeft;
private int boundingBoxRight;
private int boundingBoxTop;
private int boundingBoxBottom;
public ProgressValues(int percent, int left, int right, int top, int bottom) {
this.percent = percent;
this.boundingBoxLeft = left;
this.boundingBoxRight = right;
this.boundingBoxTop = top;
this.boundingBoxBottom = bottom;
}
public int getPercent() {
return percent;
}
public int getBoundingBoxLeft() {
return boundingBoxLeft;
}
public int getBoundingBoxRight() {
return boundingBoxRight;
}
public int getBoundingBoxTop() {
return boundingBoxTop;
}
public int getBoundingBoxBottom() {
return boundingBoxBottom;
}
}
/**
* Constructs an instance of TessBaseAPI.
*/
public TessBaseAPI() {
nativeConstruct();
}
/**
* Constructs an instance of TessBaseAPI with a callback method for
* receiving progress updates during OCR.
*
* @param progressNotifier Callback to receive progress notifications
*/
public TessBaseAPI(ProgressNotifier progressNotifier) {
this.progressNotifier = progressNotifier;
nativeConstruct();
}
/**
* Called by the GC to clean up the native data that we set up when we
* construct the object.
*
* Altered from original version to avoid a crash-causing bug in OCR Test application.
*/
@Override
protected void finalize() throws Throwable {
// TODO Find out why finalize() is getting called when we change languages, even though
// we're still using the object. Is bypassing nativeFinalize() OK if we still call
// baseApi.end() in the Activity's onDestroy()?
try {
Log.d("TessBaseAPI.java", "finalize(): NOT calling nativeFinalize() due to premature garbage collection");
//nativeFinalize();
} finally {
Log.d("TessBaseAPI.java", "finalize(): calling super.finalize()");
super.finalize();
}
}
/**
* Initializes the Tesseract engine with a specified language model. Returns
* <code>true</code> on success.
* <p>
* Instances are now mostly thread-safe and totally independent, but some
* global parameters remain. Basically it is safe to use multiple
* TessBaseAPIs in different threads in parallel, UNLESS you use SetVariable
* on some of the Params in classify and textord. If you do, then the effect
* will be to change it for all your instances.
* <p>
* The datapath must be the name of the parent directory of tessdata and
* must end in / . Any name after the last / will be stripped. The language
* is (usually) an ISO 639-3 string or <code>null</code> will default to eng.
* It is entirely safe (and eventually will be efficient too) to call Init
* multiple times on the same instance to change language, or just to reset
* the classifier.
* <p>
* The language may be a string of the form [~]<lang>[+[~]<lang>]* indicating
* that multiple languages are to be loaded. Eg hin+eng will load Hindi and
* English. Languages may specify internally that they want to be loaded
* with one or more other languages, so the ~ sign is available to override
* that. Eg if hin were set to load eng by default, then hin+~eng would force
* loading only hin. The number of loaded languages is limited only by
* memory, with the caveat that loading additional languages will impact
* both speed and accuracy, as there is more work to do to decide on the
* applicable language, and there is more chance of hallucinating incorrect
* words.
* <p>
* <b>WARNING:</b> On changing languages, all Tesseract parameters are reset
* back to their default values. (Which may vary between languages.)
* <p>
* If you have a rare need to set a Variable that controls initialization
* for a second call to Init you should explicitly call End() and then use
* SetVariable before Init. This is only a very rare use case, since there
* are very few uses that require any parameters to be set before Init.
*
* @param datapath the parent directory of tessdata ending in a forward
* slash
* @param language (optional) an ISO 639-3 string representing the language(s)
* @return <code>true</code> on success
*/
public boolean init(String datapath, String language) {
if (datapath == null)
throw new IllegalArgumentException("Data path must not be null!");
if (!datapath.endsWith(File.separator))
datapath += File.separator;
File tessdata = new File(datapath + "tessdata");
if (!tessdata.exists() || !tessdata.isDirectory())
throw new IllegalArgumentException("Data path must contain subfolder tessdata!");
return nativeInit(datapath, language);
}
/**
* Initializes the Tesseract engine with the specified language model(s). Returns
* <code>true</code> on success.
*
* @param datapath the parent directory of tessdata ending in a forward
* slash
* @param language (optional) an ISO 639-3 string representing the language(s)
* @param ocrEngineMode the OCR engine mode to be set
* @return <code>true</code> on success
*/
public boolean init(String datapath, String language, int ocrEngineMode) {
if (datapath == null)
throw new IllegalArgumentException("Data path must not be null!");
if (!datapath.endsWith(File.separator))
datapath += File.separator;
File tessdata = new File(datapath + "tessdata");
if (!tessdata.exists() || !tessdata.isDirectory())
throw new IllegalArgumentException("Data path must contain subfolder tessdata!");
return nativeInitOem(datapath, language, ocrEngineMode);
}
/**
* Returns the languages string used in the last valid initialization.
* If the last initialization specified "deu+hin" then that will be
* returned. If hin loaded eng automatically as well, then that will
* not be included in this list. To find the languages actually
* loaded use GetLoadedLanguagesAsVector.
*
* @return the last-used language code
*/
public String getInitLanguagesAsString() {
return nativeGetInitLanguagesAsString();
}
/**
* Frees up recognition results and any stored image data, without actually
* freeing any recognition data that would be time-consuming to reload.
* Afterwards, you must call SetImage or SetRectangle before doing any
* Recognize or Get* operation.
*/
public void clear() {
nativeClear();
}
/**
* Closes down tesseract and free up all memory. End() is equivalent to
* destructing and reconstructing your TessBaseAPI.
* <p>
* Once End() has been used, none of the other API functions may be used
* other than Init and anything declared above it in the class definition.
*/
public void end() {
nativeEnd();
}
/**
* Set the value of an internal "variable" (of either old or new types).
* Supply the name of the variable and the value as a string, just as you
* would in a config file.
* <p>
* Example: <code>setVariable(VAR_TESSEDIT_CHAR_BLACKLIST, "xyz"); to ignore x, y and z. * setVariable(VAR_BLN_NUMERICMODE, "1"); to set numeric-only mode. * </code>
* <p>
* setVariable() may be used before open(), but settings will revert to
* defaults on close().
*
* @param var name of the variable
* @param value value to set
* @return false if the name lookup failed
*/
public boolean setVariable(String var, String value) {
return nativeSetVariable(var, value);
}
/**
* Return the current page segmentation mode.
*
* @return value of the current page segmentation mode
*/
public int getPageSegMode() {
return nativeGetPageSegMode();
}
/**
* Sets the page segmentation mode. This controls how much processing the
* OCR engine will perform before recognizing text.
*
* @param mode the page segmentation mode to set
*/
public void setPageSegMode(int mode) {
nativeSetPageSegMode(mode);
}
/**
* Sets debug mode. This controls how much information is displayed in the
* log during recognition.
*
* @param enabled <code>true</code> to enable debugging mode
*/
public void setDebug(boolean enabled) {
nativeSetDebug(enabled);
}
/**
* Restricts recognition to a sub-rectangle of the image. Call after
* SetImage. Each SetRectangle clears the recogntion results so multiple
* rectangles can be recognized with the same image.
*
* @param rect the bounding rectangle
*/
public void setRectangle(Rect rect) {
setRectangle(rect.left, rect.top, rect.width(), rect.height());
}
/**
* Restricts recognition to a sub-rectangle of the image. Call after
* SetImage. Each SetRectangle clears the recogntion results so multiple
* rectangles can be recognized with the same image.
*
* @param left the left bound
* @param top the right bound
* @param width the width of the bounding box
* @param height the height of the bounding box
*/
public void setRectangle(int left, int top, int width, int height) {
nativeSetRectangle(left, top, width, height);
}
/**
* Provides an image for Tesseract to recognize.
*
* @param file absolute path to the image file
*/
public void setImage(File file) {
Pix image = ReadFile.readFile(file);
if (image == null) {
throw new RuntimeException("Failed to read image file");
}
nativeSetImagePix(image.getNativePix());
}
/**
* Provides an image for Tesseract to recognize. Does not copy the image
* buffer. The source image must persist until after Recognize or
* GetUTF8Chars is called.
*
* @param bmp bitmap representation of the image
*/
public void setImage(Bitmap bmp) {
Pix image = ReadFile.readBitmap(bmp);
if (image == null) {
throw new RuntimeException("Failed to read bitmap");
}
nativeSetImagePix(image.getNativePix());
}
/**
* Provides a Leptonica pix format image for Tesseract to recognize. Clones
* the pix object. The source image may be destroyed immediately after
* SetImage is called, but its contents may not be modified.
*
* @param image Leptonica pix representation of the image
*/
public void setImage(Pix image) {
nativeSetImagePix(image.getNativePix());
}
/**
* Provides an image for Tesseract to recognize. Copies the image buffer.
* The source image may be destroyed immediately after SetImage is called.
* SetImage clears all recognition results, and sets the rectangle to the
* full image, so it may be followed immediately by a GetUTF8Text, and it
* will automatically perform recognition.
*
* @param imagedata byte representation of the image
* @param width image width
* @param height image height
* @param bpp bytes per pixel
* @param bpl bytes per line
*/
public void setImage(byte[] imagedata, int width, int height, int bpp, int bpl) {
nativeSetImageBytes(imagedata, width, height, bpp, bpl);
}
/**
* The recognized text is returned as a String which is coded as UTF8.
*
* @return the recognized text
*/
public String getUTF8Text() {
// Trim because the text will have extra line breaks at the end
String text = nativeGetUTF8Text();
return text.trim();
}
/**
* Returns the mean confidence of text recognition.
*
* @return the mean confidence
*/
public int meanConfidence() {
return nativeMeanConfidence();
}
/**
* Returns all word confidences (between 0 and 100) in an array. The number
* of confidences should correspond to the number of space-delimited words
* in GetUTF8Text().
*
* @return an array of word confidences (between 0 and 100) for each
* space-delimited word returned by GetUTF8Text()
*/
public int[] wordConfidences() {
int[] conf = nativeWordConfidences();
// We shouldn't return null confidences
if (conf == null)
conf = new int[0];
return conf;
}
/**
* Return a copy of the internal thresholded image from Tesseract.
* Only available after setImage.
*
* @return Pix containing the thresholded image
*/
public Pix getThresholdedImage() {
return new Pix(nativeGetThresholdedImage());
}
/**
* Returns the result of page layout analysis as a Pixa, in reading order.
*
* @return Pixa contaning page layout bounding boxes
*/
public Pixa getRegions() {
return new Pixa(nativeGetRegions(), 0, 0);
}
/**
* Returns the textlines as a Pixa.
*
* Block IDs are not returned.
*
* @return Pixa containing textlines
*/
public Pixa getTextlines() {
return new Pixa(nativeGetTextlines(), 0, 0);
}
/**
* Returns the strips as a Pixa.
*
* Block IDs are not returned.
*
* @return Pixa containing strips
*/
public Pixa getStrips() {
return new Pixa(nativeGetStrips(), 0, 0);
}
/**
* Returns the word bounding boxes as a Pixa, in reading order.
*
* @return Pixa containing word bounding boxes
*/
public Pixa getWords() {
return new Pixa(nativeGetWords(), 0, 0);
}
/**
* Gets the individual connected (text) components (created after pages
* segmentation step, but before recognition) as a Pixa, in reading order.
* Can be called before or after Recognize.
*
* @return Pixa containing connected components bounding boxes
*/
public Pixa getConnectedComponents() {
return new Pixa(nativeGetConnectedComponents(), 0, 0);
}
/**
* Returns an iterator allowing you to iterate over the top result for each recognized word or symbol.
*
* @return ResultIterator iterate over the words
*/
public ResultIterator getResultIterator() {
long nativeResultIterator = nativeGetResultIterator();
if (nativeResultIterator == 0) {
return null;
}
return new ResultIterator(nativeResultIterator);
}
/**
* Make a HTML-formatted string with hOCR markup from the internal data
* structures.
*
* @param page is 0-based but will appear in the output as 1-based.
* @return HTML-formatted string with hOCR markup
*/
public String getHOCRText(int page){
return nativeGetHOCRText(page);
}
/**
* Set the name of the input file. Needed only for training and
* reading a UNLV zone file.
*
* @param name input file name
*/
public void setInputName(String name){
nativeSetInputName(name);
}
/**
* Set the name of the output files.
* Needed only for debugging.
* @param name output file name
*/
public void setOutputName(String name){
nativeSetOutputName(name);
}
/**
* Read a "config" file containing a set of variable, value pairs.
* Searches the standard places: <i>tessdata/configs, tessdata/tessconfigs</i>.
*
* @param filename the configuration filename, without path
*/
public void ReadConfigFile(String filename){
nativeReadConfigFile(filename);
}
/**
* The recognized text is returned as coded in the same format as a UTF8
* box file used in training.
*
* @param page is a 0-based page index that will appear in the box file.
*/
public String getBoxText(int page){
return nativeGetBoxText(page);
}
/**
* Cancel any recognition in progress.
*/
public void stop() {
nativeStop();
}
/**
* Called from native code to update progress of ongoing recognition passes.
*
* @param percent Percent complete
* @param left Left bound of word bounding box
* @param right Right bound of word bounding box
* @param top Top bound of word bounding box
* @param bottom Bottom bound of word bounding box
*/
private void onProgressValues(final int percent, final int left,
final int right, final int top, final int bottom) {
if (progressNotifier != null) {
ProgressValues pv = new ProgressValues(percent, left, right, top, bottom);
progressNotifier.onProgressValues(pv);
}
}
// ******************
// * Native methods *
// ******************
/**
* Initializes static native data. Must be called on object load.
*/
private static native void nativeClassInit();
/**
* Initializes native data. Must be called on object construction.
*/
private native void nativeConstruct();
/**
* Finalizes native data. Must be called on object destruction.
*/
private native void nativeFinalize();
private native boolean nativeInit(String datapath, String language);
private native boolean nativeInitOem(String datapath, String language, int mode);
private native String nativeGetInitLanguagesAsString();
private native void nativeClear();
private native void nativeEnd();
private native void nativeSetImageBytes(
byte[] imagedata, int width, int height, int bpp, int bpl);
private native void nativeSetImagePix(long nativePix);
private native void nativeSetRectangle(int left, int top, int width, int height);
private native String nativeGetUTF8Text();
private native int nativeMeanConfidence();
private native int[] nativeWordConfidences();
private native boolean nativeSetVariable(String var, String value);
private native void nativeSetDebug(boolean debug);
private native int nativeGetPageSegMode();
private native void nativeSetPageSegMode(int mode);
private native long nativeGetThresholdedImage();
private native long nativeGetRegions();
private native long nativeGetTextlines();
private native long nativeGetStrips();
private native long nativeGetWords();
private native long nativeGetConnectedComponents();
private native long nativeGetResultIterator();
private native String nativeGetBoxText(int page_number);
private native String nativeGetHOCRText(int page_number);
private native void nativeSetInputName(String name);
private native void nativeSetOutputName(String name);
private native void nativeReadConfigFile(String fileName);
private native int nativeStop();
}

View File

@@ -0,0 +1,6 @@
LOCAL_PATH := $(call my-dir)
TESSERACT_PATH := $(LOCAL_PATH)/com_googlecode_tesseract_android/src
LEPTONICA_PATH := $(LOCAL_PATH)/com_googlecode_leptonica_android/src
# Just build the Android.mk files in the subdirs
include $(call all-subdir-makefiles)

View File

@@ -0,0 +1,6 @@
APP_STL := gnustl_static
APP_ABI := armeabi armeabi-v7a x86 mips # arm64-v8a x86_64 mips64
APP_OPTIM := release
APP_PLATFORM := android-8
APP_CPPFLAGS += -fexceptions -frtti
NDK_TOOLCHAIN_VERSION := 4.8

View File

@@ -0,0 +1,49 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := liblept
# leptonica (minus freetype)
BLACKLIST_SRC_FILES := \
%endiantest.c \
%freetype.c \
%xtractprotos.c
LEPTONICA_SRC_FILES := \
$(subst $(LOCAL_PATH)/,,$(wildcard $(LEPTONICA_PATH)/src/*.c))
LOCAL_SRC_FILES := \
$(filter-out $(BLACKLIST_SRC_FILES),$(LEPTONICA_SRC_FILES))
LOCAL_CFLAGS := \
-DHAVE_CONFIG_H
LOCAL_LDLIBS := \
-lz
# jni
LOCAL_SRC_FILES += \
box.cpp \
pix.cpp \
pixa.cpp \
utilities.cpp \
readfile.cpp \
writefile.cpp \
jni.cpp
LOCAL_C_INCLUDES += \
$(LOCAL_PATH) \
$(LEPTONICA_PATH)/src
LOCAL_LDLIBS += \
-ljnigraphics \
-llog
# common
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2011, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
jlong Java_com_googlecode_leptonica_android_Box_nativeCreate(JNIEnv *env, jclass clazz, jint x,
jint y, jint w, jint h) {
BOX *box = boxCreate((l_int32) x, (l_int32) y, (l_int32) w, (l_int32) h);
return (jlong) box;
}
void Java_com_googlecode_leptonica_android_Box_nativeDestroy(JNIEnv *env, jclass clazz,
jlong nativeBox) {
BOX *box = (BOX *) nativeBox;
boxDestroy(&box);
}
jint Java_com_googlecode_leptonica_android_Box_nativeGetX(JNIEnv *env, jclass clazz, jlong nativeBox) {
BOX *box = (BOX *) nativeBox;
return (jint) box->x;
}
jint Java_com_googlecode_leptonica_android_Box_nativeGetY(JNIEnv *env, jclass clazz, jlong nativeBox) {
BOX *box = (BOX *) nativeBox;
return (jint) box->y;
}
jint Java_com_googlecode_leptonica_android_Box_nativeGetWidth(JNIEnv *env, jclass clazz,
jlong nativeBox) {
BOX *box = (BOX *) nativeBox;
return (jint) box->w;
}
jint Java_com_googlecode_leptonica_android_Box_nativeGetHeight(JNIEnv *env, jclass clazz,
jlong nativeBox) {
BOX *box = (BOX *) nativeBox;
return (jint) box->h;
}
jboolean Java_com_googlecode_leptonica_android_Box_nativeGetGeometry(JNIEnv *env, jclass clazz,
jlong nativeBox,
jintArray dimensions) {
BOX *box = (BOX *) nativeBox;
jint *dimensionArray = env->GetIntArrayElements(dimensions, NULL);
l_int32 x, y, w, h;
if (boxGetGeometry(box, &x, &y, &w, &h)) {
return JNI_FALSE;
}
dimensionArray[0] = x;
dimensionArray[1] = y;
dimensionArray[2] = w;
dimensionArray[3] = h;
env->ReleaseIntArrayElements(dimensions, dimensionArray, 0);
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2010, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LEPTONICA_JNI_COMMON_H
#define LEPTONICA_JNI_COMMON_H
#include <jni.h>
#include <assert.h>
#include <allheaders.h>
#include <android/log.h>
#include <asm/byteorder.h>
#ifdef __BIG_ENDIAN
#define SK_A32_SHIFT 0
#define SK_R32_SHIFT 8
#define SK_G32_SHIFT 16
#define SK_B32_SHIFT 24
#else
#define SK_A32_SHIFT 24
#define SK_R32_SHIFT 16
#define SK_G32_SHIFT 8
#define SK_B32_SHIFT 0
#endif /* __BIG_ENDIAN */
#define LOG_TAG "Leptonica(native)"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOG_ASSERT(_cond, ...) if (!_cond) __android_log_assert("conditional", LOG_TAG, __VA_ARGS__)
#endif

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2010, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LEPTONICA_JNI_CONFIG_AUTO_H
#define LEPTONICA_JNI_CONFIG_AUTO_H
#define HAVE_LIBJPEG 0
#define HAVE_LIBTIFF 0
#define HAVE_LIBPNG 0
#define HAVE_LIBZ 1
#define HAVE_LIBGIF 0
#define HAVE_LIBUNGIF 0
#define HAVE_FMEMOPEN 0
#endif

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2011, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv *env;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
return -1;
}
assert(env != NULL);
return JNI_VERSION_1_6;
}

View File

@@ -0,0 +1,253 @@
/*
* Copyright 2011, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
jlong Java_com_googlecode_leptonica_android_Pix_nativeCreatePix(JNIEnv *env, jclass clazz, jint w,
jint h, jint d) {
PIX *pix = pixCreate((l_int32) w, (l_int32) h, (l_int32) d);
return (jlong) pix;
}
jlong Java_com_googlecode_leptonica_android_Pix_nativeCreateFromData(JNIEnv *env, jclass clazz,
jbyteArray data, jint w,
jint h, jint d) {
PIX *pix = pixCreateNoInit((l_int32) w, (l_int32) h, (l_int32) d);
jbyte *data_buffer = env->GetByteArrayElements(data, NULL);
l_uint8 *byte_buffer = (l_uint8 *) data_buffer;
size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix);
memcpy(pixGetData(pix), byte_buffer, size);
env->ReleaseByteArrayElements(data, data_buffer, JNI_ABORT);
return (jlong) pix;
}
jboolean Java_com_googlecode_leptonica_android_Pix_nativeGetData(JNIEnv *env, jclass clazz,
jlong nativePix, jbyteArray data) {
PIX *pix = (PIX *) nativePix;
jbyte *data_buffer = env->GetByteArrayElements(data, NULL);
l_uint8 *byte_buffer = (l_uint8 *) data_buffer;
size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix);
memcpy(byte_buffer, pixGetData(pix), size);
env->ReleaseByteArrayElements(data, data_buffer, 0);
return JNI_TRUE;
}
jint Java_com_googlecode_leptonica_android_Pix_nativeGetDataSize(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pix = (PIX *) nativePix;
size_t size = 4 * pixGetWpl(pix) * pixGetHeight(pix);
return (jint) size;
}
jlong Java_com_googlecode_leptonica_android_Pix_nativeClone(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pixs = (PIX *) nativePix;
PIX *pixd = pixClone(pixs);
return (jlong) pixd;
}
jlong Java_com_googlecode_leptonica_android_Pix_nativeCopy(JNIEnv *env, jclass clazz, jlong nativePix) {
PIX *pixs = (PIX *) nativePix;
PIX *pixd = pixCopy(NULL, pixs);
return (jlong) pixd;
}
jboolean Java_com_googlecode_leptonica_android_Pix_nativeInvert(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pixs = (PIX *) nativePix;
if (pixInvert(pixs, pixs)) {
return JNI_FALSE;
}
return JNI_TRUE;
}
void Java_com_googlecode_leptonica_android_Pix_nativeDestroy(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pix = (PIX *) nativePix;
pixDestroy(&pix);
}
jboolean Java_com_googlecode_leptonica_android_Pix_nativeGetDimensions(JNIEnv *env, jclass clazz,
jlong nativePix,
jintArray dimensions) {
PIX *pix = (PIX *) nativePix;
jint *dimensionArray = env->GetIntArrayElements(dimensions, NULL);
l_int32 w, h, d;
if (pixGetDimensions(pix, &w, &h, &d)) {
return JNI_FALSE;
}
dimensionArray[0] = w;
dimensionArray[1] = h;
dimensionArray[2] = d;
env->ReleaseIntArrayElements(dimensions, dimensionArray, 0);
return JNI_TRUE;
}
jint Java_com_googlecode_leptonica_android_Pix_nativeGetWidth(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pix = (PIX *) nativePix;
return (jint) pixGetWidth(pix);
}
jint Java_com_googlecode_leptonica_android_Pix_nativeGetHeight(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pix = (PIX *) nativePix;
return (jint) pixGetHeight(pix);
}
jint Java_com_googlecode_leptonica_android_Pix_nativeGetDepth(JNIEnv *env, jclass clazz,
jlong nativePix) {
PIX *pix = (PIX *) nativePix;
return (jint) pixGetDepth(pix);
}
void Java_com_googlecode_leptonica_android_Pix_nativeSetPixel(JNIEnv *env, jclass clazz,
jlong nativePix, jint xCoord,
jint yCoord, jint argbColor) {
PIX *pix = (PIX *) nativePix;
l_int32 d = pixGetDepth(pix);
l_int32 x = (l_int32) xCoord;
l_int32 y = (l_int32) yCoord;
// These shift values are based on RGBA_8888
l_uint8 r = (argbColor >> SK_R32_SHIFT) & 0xFF;
l_uint8 g = (argbColor >> SK_G32_SHIFT) & 0xFF;
l_uint8 b = (argbColor >> SK_B32_SHIFT) & 0xFF;
l_uint8 a = (argbColor >> SK_A32_SHIFT) & 0xFF;
l_uint8 gray = ((r + g + b) / 3) & 0xFF;
l_uint32 color;
switch (d) {
case 1: // 1-bit binary
color = gray > 128 ? 1 : 0;
break;
case 2: // 2-bit grayscale
color = gray >> 6;
break;
case 4: // 4-bit grayscale
color = gray >> 4;
break;
case 8: // 8-bit grayscale
color = gray;
break;
case 24: // 24-bit RGB
SET_DATA_BYTE(&color, COLOR_RED, r);
SET_DATA_BYTE(&color, COLOR_GREEN, g);
SET_DATA_BYTE(&color, COLOR_BLUE, b);
break;
case 32: // 32-bit ARGB
SET_DATA_BYTE(&color, COLOR_RED, r);
SET_DATA_BYTE(&color, COLOR_GREEN, g);
SET_DATA_BYTE(&color, COLOR_BLUE, b);
SET_DATA_BYTE(&color, L_ALPHA_CHANNEL, a);
break;
default: // unsupported
LOGE("Not a supported color depth: %d", d);
color = 0;
break;
}
pixSetPixel(pix, x, y, color);
}
jint Java_com_googlecode_leptonica_android_Pix_nativeGetPixel(JNIEnv *env, jclass clazz,
jlong nativePix, jint xCoord,
jint yCoord) {
PIX *pix = (PIX *) nativePix;
l_int32 d = pixGetDepth(pix);
l_int32 x = (l_int32) xCoord;
l_int32 y = (l_int32) yCoord;
l_uint32 pixel;
l_uint32 color;
l_uint8 a, r, g, b;
pixGetPixel(pix, x, y, &pixel);
switch (d) {
case 1: // 1-bit binary
a = 0xFF;
r = g = b = (pixel == 0 ? 0x00 : 0xFF);
break;
case 2: // 2-bit grayscale
a = 0xFF;
r = g = b = (pixel << 6 | pixel << 4 | pixel);
break;
case 4: // 4-bit grayscale
a = 0xFF;
r = g = b = (pixel << 4 | pixel);
break;
case 8: // 8-bit grayscale
a = 0xFF;
r = g = b = pixel;
break;
case 24: // 24-bit RGB
a = 0xFF;
r = (pixel >> L_RED_SHIFT) & 0xFF;
g = (pixel >> L_GREEN_SHIFT) & 0xFF;
b = (pixel >> L_BLUE_SHIFT) & 0xFF;
break;
case 32: // 32-bit RGBA
r = (pixel >> L_RED_SHIFT) & 0xFF;
g = (pixel >> L_GREEN_SHIFT) & 0xFF;
b = (pixel >> L_BLUE_SHIFT) & 0xFF;
a = (pixel >> L_ALPHA_SHIFT) & 0xFF;
break;
default: // Not supported
LOGE("Not a supported color depth: %d", d);
a = r = g = b = 0x00;
break;
}
color = a << SK_A32_SHIFT;
color |= r << SK_R32_SHIFT;
color |= g << SK_G32_SHIFT;
color |= b << SK_B32_SHIFT;
return (jint) color;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -0,0 +1,215 @@
/*
* Copyright 2011, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
jlong Java_com_googlecode_leptonica_android_Pixa_nativeCreate(JNIEnv *env, jclass clazz, jint size) {
PIXA *pixa = pixaCreate((l_int32) size);
return (jlong) pixa;
}
jlong Java_com_googlecode_leptonica_android_Pixa_nativeCopy(JNIEnv *env, jclass clazz,
jlong nativePixa) {
PIXA *pixas = (PIXA *) nativePixa;
PIXA *pixad = pixaCopy(pixas, L_CLONE);
return (jlong) pixad;
}
jlong Java_com_googlecode_leptonica_android_Pixa_nativeSort(JNIEnv *env, jclass clazz,
jlong nativePixa, jint field, jint order) {
PIXA *pixas = (PIXA *) nativePixa;
PIXA *pixad = pixaSort(pixas, field, order, NULL, L_CLONE);
return (jlong) pixad;
}
void Java_com_googlecode_leptonica_android_Pixa_nativeDestroy(JNIEnv *env, jclass clazz,
jlong nativePixa) {
PIXA *pixa = (PIXA *) nativePixa;
pixaDestroy(&pixa);
}
jboolean Java_com_googlecode_leptonica_android_Pixa_nativeJoin(JNIEnv *env, jclass clazz,
jlong nativePixa, jlong otherPixa) {
PIXA *pixa = (PIXA *) nativePixa;
PIXA *pixas = (PIXA *) otherPixa;
if (pixaJoin(pixa, pixas, 0, 0)) {
return JNI_FALSE;
}
return JNI_TRUE;
}
jint Java_com_googlecode_leptonica_android_Pixa_nativeGetCount(JNIEnv *env, jclass clazz,
jlong nativePixa) {
PIXA *pixa = (PIXA *) nativePixa;
return (jint) pixaGetCount(pixa);
}
void Java_com_googlecode_leptonica_android_Pixa_nativeAddPix(JNIEnv *env, jclass clazz,
jlong nativePixa, jlong nativePix,
jint mode) {
PIXA *pixa = (PIXA *) nativePixa;
PIX *pix = (PIX *) nativePix;
pixaAddPix(pixa, pix, mode);
}
void Java_com_googlecode_leptonica_android_Pixa_nativeAddBox(JNIEnv *env, jclass clazz,
jlong nativePixa, jlong nativeBox,
jint mode) {
PIXA *pixa = (PIXA *) nativePixa;
BOX *box = (BOX *) nativeBox;
pixaAddBox(pixa, box, mode);
}
void Java_com_googlecode_leptonica_android_Pixa_nativeAdd(JNIEnv *env, jclass clazz,
jlong nativePixa, jlong nativePix,
jlong nativeBox, jint mode) {
PIXA *pixa = (PIXA *) nativePixa;
PIX *pix = (PIX *) nativePix;
BOX *box = (BOX *) nativeBox;
pixaAddPix(pixa, pix, mode);
pixaAddBox(pixa, box, mode);
}
void Java_com_googlecode_leptonica_android_Pixa_nativeReplacePix(JNIEnv *env, jclass clazz,
jlong nativePixa, jint index,
jlong nativePix, jlong nativeBox) {
PIXA *pixa = (PIXA *) nativePixa;
PIX *pix = (PIX *) nativePix;
BOX *box = (BOX *) nativeBox;
pixaReplacePix(pixa, index, pix, box);
}
void Java_com_googlecode_leptonica_android_Pixa_nativeMergeAndReplacePix(JNIEnv *env, jclass clazz,
jlong nativePixa,
jint indexA, jint indexB) {
PIXA *pixa = (PIXA *) nativePixa;
l_int32 op;
l_int32 x, y, w, h;
l_int32 dx, dy, dw, dh;
PIX *pixs, *pixd;
BOX *boxA, *boxB, *boxd;
boxA = pixaGetBox(pixa, indexA, L_CLONE);
boxB = pixaGetBox(pixa, indexB, L_CLONE);
boxd = boxBoundingRegion(boxA, boxB);
boxGetGeometry(boxd, &x, &y, &w, &h);
pixd = pixCreate(w, h, 1);
op = PIX_SRC | PIX_DST;
pixs = pixaGetPix(pixa, indexA, L_CLONE);
boxGetGeometry(boxA, &dx, &dy, &dw, &dh);
pixRasterop(pixd, dx - x, dy - y, dw, dh, op, pixs, 0, 0);
pixDestroy(&pixs);
boxDestroy(&boxA);
pixs = pixaGetPix(pixa, indexB, L_CLONE);
boxGetGeometry(boxB, &dx, &dy, &dw, &dh);
pixRasterop(pixd, dx - x, dy - y, dw, dh, op, pixs, 0, 0);
pixDestroy(&pixs);
boxDestroy(&boxB);
pixaReplacePix(pixa, indexA, pixd, boxd);
}
jboolean Java_com_googlecode_leptonica_android_Pixa_nativeWriteToFileRandomCmap(JNIEnv *env,
jclass clazz,
jlong nativePixa,
jstring fileName,
jint width,
jint height) {
PIX *pixtemp;
PIXA *pixa = (PIXA *) nativePixa;
const char *c_fileName = env->GetStringUTFChars(fileName, NULL);
if (c_fileName == NULL) {
LOGE("could not extract fileName string!");
return JNI_FALSE;
}
if (pixaGetCount(pixa) > 0) {
pixtemp = pixaDisplayRandomCmap(pixa, (l_int32) width, (l_int32) height);
} else {
pixtemp = pixCreate((l_int32) width, (l_int32) height, 1);
}
pixWrite(c_fileName, pixtemp, IFF_BMP);
pixDestroy(&pixtemp);
env->ReleaseStringUTFChars(fileName, c_fileName);
return JNI_TRUE;
}
jint Java_com_googlecode_leptonica_android_Pixa_nativeGetPix(JNIEnv *env, jclass clazz,
jlong nativePixa, jint index) {
PIXA *pixa = (PIXA *) nativePixa;
PIX *pix = pixaGetPix(pixa, (l_int32) index, L_CLONE);
return (jlong) pix;
}
jlong Java_com_googlecode_leptonica_android_Pixa_nativeGetBox(JNIEnv *env, jclass clazz,
jlong nativePixa, jint index) {
PIXA *pixa = (PIXA *) nativePixa;
BOX *box = pixaGetBox(pixa, (l_int32) index, L_CLONE);
return (jlong) box;
}
jboolean Java_com_googlecode_leptonica_android_Pixa_nativeGetBoxGeometry(JNIEnv *env, jclass clazz,
jlong nativePixa,
jint index,
jintArray dimensions) {
PIXA *pixa = (PIXA *) nativePixa;
jint *dimensionArray = env->GetIntArrayElements(dimensions, NULL);
l_int32 x, y, w, h;
if (pixaGetBoxGeometry(pixa, (l_int32) index, &x, &y, &w, &h)) {
return JNI_FALSE;
}
dimensionArray[0] = x;
dimensionArray[1] = y;
dimensionArray[2] = w;
dimensionArray[3] = h;
env->ReleaseIntArrayElements(dimensions, dimensionArray, 0);
return JNI_TRUE;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -0,0 +1,194 @@
/*
* Copyright 2011, Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#include <string.h>
#include <android/bitmap.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/************
* ReadFile *
************/
jlong Java_com_googlecode_leptonica_android_ReadFile_nativeReadMem(JNIEnv *env, jclass clazz,
jbyteArray image, jint length) {
jbyte *image_buffer = env->GetByteArrayElements(image, NULL);
int buffer_length = env->GetArrayLength(image);
PIX *pix = pixReadMem((const l_uint8 *) image_buffer, buffer_length);
env->ReleaseByteArrayElements(image, image_buffer, JNI_ABORT);
return (jlong) pix;
}
jlong Java_com_googlecode_leptonica_android_ReadFile_nativeReadBytes8(JNIEnv *env, jclass clazz,
jbyteArray data, jint w,
jint h) {
PIX *pix = pixCreateNoInit((l_int32) w, (l_int32) h, 8);
l_uint8 **lineptrs = pixSetupByteProcessing(pix, NULL, NULL);
jbyte *data_buffer = env->GetByteArrayElements(data, NULL);
l_uint8 *byte_buffer = (l_uint8 *) data_buffer;
for (int i = 0; i < h; i++) {
memcpy(lineptrs[i], (byte_buffer + (i * w)), w);
}
env->ReleaseByteArrayElements(data, data_buffer, JNI_ABORT);
pixCleanupByteProcessing(pix, lineptrs);
l_int32 d;
pixGetDimensions(pix, &w, &h, &d);
LOGE("Created image width w=%d, h=%d, d=%d", w, h, d);
return (jlong) pix;
}
jboolean Java_com_googlecode_leptonica_android_ReadFile_nativeReplaceBytes8(JNIEnv *env,
jclass clazz,
jlong nativePix,
jbyteArray data,
jint srcw, jint srch) {
PIX *pix = (PIX *) nativePix;
l_int32 w, h, d;
pixGetDimensions(pix, &w, &h, &d);
if (d != 8 || (l_int32) srcw != w || (l_int32) srch != h) {
LOGE("Failed to replace bytes at w=%d, h=%d, d=%d with w=%d, h=%d", w, h, d, srcw, srch);
return JNI_FALSE;
}
l_uint8 **lineptrs = pixSetupByteProcessing(pix, NULL, NULL);
jbyte *data_buffer = env->GetByteArrayElements(data, NULL);
l_uint8 *byte_buffer = (l_uint8 *) data_buffer;
for (int i = 0; i < h; i++) {
memcpy(lineptrs[i], (byte_buffer + (i * w)), w);
}
env->ReleaseByteArrayElements(data, data_buffer, JNI_ABORT);
pixCleanupByteProcessing(pix, lineptrs);
return JNI_TRUE;
}
jlong Java_com_googlecode_leptonica_android_ReadFile_nativeReadFiles(JNIEnv *env, jclass clazz,
jstring dirName, jstring prefix) {
PIXA *pixad = NULL;
const char *c_dirName = env->GetStringUTFChars(dirName, NULL);
if (c_dirName == NULL) {
LOGE("could not extract dirName string!");
return (jlong) NULL;
}
const char *c_prefix = env->GetStringUTFChars(prefix, NULL);
if (c_prefix == NULL) {
LOGE("could not extract prefix string!");
return (jlong) NULL;
}
pixad = pixaReadFiles(c_dirName, c_prefix);
env->ReleaseStringUTFChars(dirName, c_dirName);
env->ReleaseStringUTFChars(prefix, c_prefix);
return (jlong) pixad;
}
jlong Java_com_googlecode_leptonica_android_ReadFile_nativeReadFile(JNIEnv *env, jclass clazz,
jstring fileName) {
PIX *pixd = NULL;
const char *c_fileName = env->GetStringUTFChars(fileName, NULL);
if (c_fileName == NULL) {
LOGE("could not extract fileName string!");
return (jlong) NULL;
}
pixd = pixRead(c_fileName);
env->ReleaseStringUTFChars(fileName, c_fileName);
return (jlong) pixd;
}
jlong Java_com_googlecode_leptonica_android_ReadFile_nativeReadBitmap(JNIEnv *env, jclass clazz,
jobject bitmap) {
l_int32 w, h, d;
AndroidBitmapInfo info;
void* pixels;
int ret;
if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return (jlong) NULL;
}
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Bitmap format is not RGBA_8888 !");
return (jlong) NULL;
}
if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
return (jlong) NULL;
}
PIX *pixd = pixCreate(info.width, info.height, 8);
l_uint32 *src = (l_uint32 *) pixels;
l_int32 srcWpl = (info.stride / 4);
l_uint32 *dst = pixGetData(pixd);
l_int32 dstWpl = pixGetWpl(pixd);
l_uint8 a, r, g, b, pixel8;
for (int y = 0; y < info.height; y++) {
l_uint32 *dst_line = dst + (y * dstWpl);
l_uint32 *src_line = src + (y * srcWpl);
for (int x = 0; x < info.width; x++) {
// Get pixel from RGBA_8888
r = *src_line >> SK_R32_SHIFT;
g = *src_line >> SK_G32_SHIFT;
b = *src_line >> SK_B32_SHIFT;
a = *src_line >> SK_A32_SHIFT;
pixel8 = (l_uint8)((r + g + b) / 3);
// Set pixel to LUMA_8
SET_DATA_BYTE(dst_line, x, pixel8);
// Move to the next pixel
src_line++;
}
}
AndroidBitmap_unlockPixels(env, bitmap);
return (jlong) pixd;
}
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -0,0 +1,8 @@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = config README.html leptonica-license.txt moller52.jpg version-notes.html make-for-auto make-for-local autobuild
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = lept.pc
SUBDIRS = src prog

View File

@@ -0,0 +1,815 @@
# Makefile.in generated by automake 1.11.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = .
DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/lept.pc.in \
$(top_srcdir)/config/config.h.in $(top_srcdir)/configure \
config/config.guess config/config.sub config/depcomp \
config/install-sh config/ltmain.sh config/missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = config_auto.h
CONFIG_CLEAN_FILES = lept.pc
CONFIG_CLEAN_VPATH_FILES =
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-dvi-recursive install-exec-recursive \
install-html-recursive install-info-recursive \
install-pdf-recursive install-ps-recursive install-recursive \
installcheck-recursive installdirs-recursive pdf-recursive \
ps-recursive uninstall-recursive
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
am__installdirs = "$(DESTDIR)$(pkgconfigdir)"
DATA = $(pkgconfig_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
distdir dist dist-all distcheck
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
am__remove_distdir = \
if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
APPLE_UNIVERSAL_BUILD = @APPLE_UNIVERSAL_BUILD@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENDIANNESS = @ENDIANNESS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GDI_LIBS = @GDI_LIBS@
GIFLIB_LIBS = @GIFLIB_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JPEG_LIBS = @JPEG_LIBS@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBJP2K_LIBS = @LIBJP2K_LIBS@
LIBM = @LIBM@
LIBOBJS = @LIBOBJS@
LIBPNG_LIBS = @LIBPNG_LIBS@
LIBS = @LIBS@
LIBTIFF_LIBS = @LIBTIFF_LIBS@
LIBTOOL = @LIBTOOL@
LIBWEBP_LIBS = @LIBWEBP_LIBS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = config README.html leptonica-license.txt moller52.jpg version-notes.html make-for-auto make-for-local autobuild
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = lept.pc
SUBDIRS = src prog
all: config_auto.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
am--refresh: Makefile
@:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config_auto.h: stamp-h1
@if test ! -f $@; then rm -f stamp-h1; else :; fi
@if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
stamp-h1: $(top_srcdir)/config/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config_auto.h
$(top_srcdir)/config/config.h.in: $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f config_auto.h stamp-h1
lept.pc: $(top_builddir)/config.status $(srcdir)/lept.pc.in
cd $(top_builddir) && $(SHELL) ./config.status $@
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool config.lt
install-pkgconfigDATA: $(pkgconfig_DATA)
@$(NORMAL_INSTALL)
test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
done
uninstall-pkgconfigDATA:
@$(NORMAL_UNINSTALL)
@list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
@fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
@fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
*k*) failcom='fail=yes';; \
esac; \
done; \
dot_seen=no; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
rev=''; for subdir in $$list; do \
if test "$$subdir" = "."; then :; else \
rev="$$subdir $$rev"; \
fi; \
done; \
rev="$$rev ."; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
-test -n "$(am__skip_mode_fix)" \
|| find "$(distdir)" -type d ! -perm -755 \
-exec chmod u+rwx,go+rx {} \; -o \
! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
! -type d ! -perm -400 -exec chmod a+r {} \; -o \
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
$(am__remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
$(am__remove_distdir)
dist-lzma: distdir
tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
$(am__remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
$(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
$(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
$(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
$(am__remove_distdir)
dist dist-all: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
$(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
case '$(DIST_ARCHIVES)' in \
*.tar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
*.tar.lzma*) \
lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
xz -dc $(distdir).tar.xz | $(am__untar) ;;\
*.tar.Z*) \
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
*.shar.gz*) \
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
*.zip*) \
unzip $(distdir).zip ;;\
esac
chmod -R a-w $(distdir); chmod a+w $(distdir)
mkdir $(distdir)/_build
mkdir $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure --srcdir=.. --prefix="$$dc_install_base" \
$(AM_DISTCHECK_CONFIGURE_FLAGS) \
$(DISTCHECK_CONFIGURE_FLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
distuninstallcheck \
&& chmod -R a-w "$$dc_install_base" \
&& ({ \
(cd ../.. && umask 077 && mkdir "$$dc_destdir") \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
&& $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
} || { rm -rf "$$dc_destdir"; exit 1; }) \
&& rm -rf "$$dc_destdir" \
&& $(MAKE) $(AM_MAKEFLAGS) dist \
&& rm -rf $(DIST_ARCHIVES) \
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
$(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
distuninstallcheck:
@test -n '$(distuninstallcheck_dir)' || { \
echo 'ERROR: trying to run $@ with an empty' \
'$$(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
$(am__cd) '$(distuninstallcheck_dir)' || { \
echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
exit 1; \
}; \
test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left after uninstall:" ; \
if test -n "$(DESTDIR)"; then \
echo " (check DESTDIR support)"; \
fi ; \
$(distuninstallcheck_listfiles) ; \
exit 1; } >&2
distcleancheck: distclean
@if test '$(srcdir)' = . ; then \
echo "ERROR: distcleancheck can only run from a VPATH build" ; \
exit 1 ; \
fi
@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
|| { echo "ERROR: files left in build directory after distclean:" ; \
$(distcleancheck_listfiles) ; \
exit 1; } >&2
check-am: all-am
check: check-recursive
all-am: Makefile $(DATA) config_auto.h
installdirs: installdirs-recursive
installdirs-am:
for dir in "$(DESTDIR)$(pkgconfigdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am
distclean: distclean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-hdr \
distclean-libtool distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am: install-pkgconfigDATA
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am: uninstall-pkgconfigDATA
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \
ctags-recursive install-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
all all-am am--refresh check check-am clean clean-generic \
clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \
dist-gzip dist-lzip dist-lzma dist-shar dist-tarZ dist-xz \
dist-zip distcheck distclean distclean-generic distclean-hdr \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-pkgconfigDATA install-ps \
install-ps-am install-strip installcheck installcheck-am \
installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
uninstall uninstall-am uninstall-pkgconfigDATA
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
#!/bin/sh
#
# autobuild
libtoolize -c -f
aclocal
autoheader
autoconf
automake -a -c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
/* config/config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `fmemopen' function. */
#undef HAVE_FMEMOPEN
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have giflib. */
#undef HAVE_LIBGIF
/* Define to 1 if you have libopenjp2. */
#undef HAVE_LIBJP2K
/* Define to 1 if you have jpeg. */
#undef HAVE_LIBJPEG
/* Define to 1 if you have libpng. */
#undef HAVE_LIBPNG
/* Define to 1 if you have libtiff. */
#undef HAVE_LIBTIFF
/* Define to 1 if you have libwebp. */
#undef HAVE_LIBWEBP
/* Define to 1 if you have zlib. */
#undef HAVE_LIBZ
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View File

@@ -0,0 +1,104 @@
/* config/config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the `fmemopen' function. */
#undef HAVE_FMEMOPEN
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have giflib. */
#undef HAVE_LIBGIF
/* Define to 1 if you have libopenjpeg. */
#undef HAVE_LIBJP2K
/* Define to 1 if you have jpeg. */
#undef HAVE_LIBJPEG
/* Define to 1 if you have libpng. */
#undef HAVE_LIBPNG
/* Define to 1 if you have libtiff. */
#undef HAVE_LIBTIFF
/* Define to 1 if you have libwebp. */
#undef HAVE_LIBWEBP
/* Define to 1 if you have zlib. */
#undef HAVE_LIBZ
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,688 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2011-12-04.11; # UTC
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
# 2011 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
case $1 in
'')
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by `PROGRAMS ARGS'.
object Object file output by `PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "depcomp $scriptversion"
exit $?
;;
esac
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
## The second -e expression handles DOS-style file names with drive letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the `deleted header file' problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
tr ' ' '
' < "$tmpdepfile" |
## Some versions of gcc put a space before the `:'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like `#:fec' to the end of the
# dependency line.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
tr '
' ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' '
' < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts `$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
# Each line is of the form `foo.o: dependent.h'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
# The sourcefile does not contain any dependencies, so just
# store a dummy comment line, to avoid errors with the Makefile
# "include basename.Plo" scheme.
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
icc)
# Intel's C compiler understands `-MD -MF file'. However on
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
# ICC 7.0 will fill foo.d with something like
# foo.o: sub/foo.c
# foo.o: sub/foo.h
# which is wrong. We want:
# sub/foo.o: sub/foo.c
# sub/foo.o: sub/foo.h
# sub/foo.c:
# sub/foo.h:
# ICC 7.1 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using \ :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
# Add `dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in `foo.d' instead, so we check for that too.
# Subdirectories are respected.
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
test "x$dir" = "x$object" && dir=
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
if test "$libtool" = yes; then
# With Tru64 cc, shared objects can also be used to make a
# static library. This mechanism is used in libtool 1.4 series to
# handle both shared and static libraries in a single compilation.
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
#
# With libtool 1.5 this exception was removed, and libtool now
# generates 2 separate objects for the 2 libraries. These two
# compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
tmpdepfile2=$dir$base.o.d # libtool 1.5
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.o.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
tmpdepfile4=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -eq 0; then :
else
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
# That's a tab and a space in the [].
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
else
echo "#dummy" > "$depfile"
fi
rm -f "$tmpdepfile"
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test "$stat" = 0; then :
else
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/ \1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/ /
G
p
}' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for `:'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
"$@" $dashmflag |
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
tr ' ' '
' < "$tmpdepfile" | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
sed '1,2d' "$tmpdepfile" | tr ' ' '
' | \
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove `-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E |
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
echo " " >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -0,0 +1,527 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-01-19.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for `test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,331 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
scriptversion=2012-01-06.13; # UTC
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
run=:
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
else
configure_ac=configure.in
fi
msg="missing on your system"
case $1 in
--run)
# Try to run requested program, and just exit if it succeeds.
run=
shift
"$@" && exit 0
# Exit code 63 means version mismatch. This often happens
# when the user try to use an ancient version of a tool on
# a file that requires a minimum version. In this case we
# we should proceed has if the program had been absent, or
# if --run hadn't been passed.
if test $? = 63; then
run=:
msg="probably too old"
fi
;;
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
autom4te touch the output file, or create a stub one
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
\`g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing $scriptversion (GNU Automake)"
exit $?
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
esac
# normalize program name to check for.
program=`echo "$1" | sed '
s/^gnu-//; t
s/^gnu//; t
s/^g//; t'`
# Now exit if we have it, but it failed. Also exit now if we
# don't have it and --version was passed (most likely to detect
# the program). This is about non-GNU programs, so use $1 not
# $program.
case $1 in
lex*|yacc*)
# Not GNU programs, they don't have --version.
;;
*)
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
# We have it, but it failed.
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
# running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
;;
esac
# If it does not exist, or fails to run (possibly an outdated version),
# try to emulate it.
case $program in
aclocal*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`${configure_ac}'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`acconfig.h' or \`${configure_ac}'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case $f in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
autom4te*)
echo 1>&2 "\
WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo "#! /bin/sh"
echo "# Created by GNU Automake missing as a replacement of"
echo "# $ $@"
echo "exit 0"
chmod +x $file
exit 1
fi
;;
bison*|yacc*)
echo 1>&2 "\
WARNING: \`$1' $msg. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if test ! -f y.tab.h; then
echo >y.tab.h
fi
if test ! -f y.tab.c; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex*|flex*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
eval LASTARG=\${$#}
case $LASTARG in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if test -f "$SRCFILE"; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if test ! -f lex.yy.c; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
help2man*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
\`Help2man' package in order for those modifications to take
effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -f "$file"; then
touch $file
else
test -z "$file" || exec >$file
echo ".ab help2man is required to generate this page"
exit $?
fi
;;
makeinfo*)
echo 1>&2 "\
WARNING: \`$1' is $msg. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
if test -z "$file"; then
# ... or it is the one specified with @setfilename ...
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '
/^@setfilename/{
s/.* \([^ ]*\) *$/\1/
p
q
}' $infile`
# ... or it is derived from the source name (dir/f.texi becomes f.info)
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
fi
# If the file does not exist, the user really needs makeinfo;
# let's fail without touching anything.
test -f $file || exit 1
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
AC_PREREQ([2.50])
AC_INIT([leptonica], [1.71])
AC_CONFIG_AUX_DIR([config])
AM_CONFIG_HEADER([config_auto.h:config/config.h.in])
AC_CONFIG_SRCDIR([src/adaptmap.c])
AC_CONFIG_MACRO_DIR([m4])
LT_INIT
AM_INIT_AUTOMAKE
AC_LANG(C)
AC_CANONICAL_HOST
# Checks for programs.
AC_PROG_AWK
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_LN_S
AC_PROG_MAKE_SET
# Checks for arguments.
AC_ARG_WITH([zlib], AS_HELP_STRING([--without-zlib], [do not include zlib support]))
AC_ARG_WITH([libpng], AS_HELP_STRING([--without-libpng], [do not include libpng support]))
AC_ARG_WITH([jpeg], AS_HELP_STRING([--without-jpeg], [do not include jpeg support]))
AC_ARG_WITH([giflib], AS_HELP_STRING([--without-giflib], [do not include giflib support]))
AC_ARG_WITH([libtiff], AS_HELP_STRING([--without-libtiff], [do not include libtiff support]))
AC_ARG_WITH([libwebp], AS_HELP_STRING([--without-libwebp], [do not include libwebp support]))
AC_ARG_WITH([libopenjpeg], AS_HELP_STRING([--without-libopenjpeg], [do not include libopenjpeg support]))
AC_ARG_ENABLE([programs], AS_HELP_STRING([--disable-programs], [do not build additional programs]))
AM_CONDITIONAL([ENABLE_PROGRAMS], [test "x$enable_programs" != xno])
# Checks for libraries.
LT_LIB_M
AS_IF([test "x$with_zlib" != xno],
AC_CHECK_LIB([z], [deflate],
AC_DEFINE([HAVE_LIBZ], 1, [Define to 1 if you have zlib.]) AC_SUBST([ZLIB_LIBS], [-lz]),
AS_IF([test "x$with_zlib" = xyes], AC_MSG_ERROR([zlib support requested but library not found]))
)
)
AS_IF([test "x$with_libpng" != xno],
AC_CHECK_LIB([png], [png_read_png],
AC_DEFINE([HAVE_LIBPNG], 1, [Define to 1 if you have libpng.]) AC_SUBST([LIBPNG_LIBS], [-lpng]),
AS_IF([test "x$with_libpng" = xyes], AC_MSG_ERROR([libpng support requested but library not found]))
)
)
AS_IF([test "x$with_jpeg" != xno],
AC_CHECK_LIB([jpeg], [jpeg_read_scanlines],
AC_DEFINE([HAVE_LIBJPEG], 1, [Define to 1 if you have jpeg.]) AC_SUBST([JPEG_LIBS], [-ljpeg]),
AS_IF([test "x$with_jpeg" = xyes], AC_MSG_ERROR([jpeg support requested but library not found]))
)
)
AS_IF([test "x$with_giflib" != xno],
AC_CHECK_LIB([gif], [DGifOpenFileHandle],
AC_DEFINE([HAVE_LIBGIF], 1, [Define to 1 if you have giflib.]) AC_SUBST([GIFLIB_LIBS], [-lgif]),
AS_IF([test "x$with_giflib" = xyes], AC_MSG_ERROR([giflib support requested but library not found]))
)
)
AS_IF([test "x$with_libtiff" != xno],
AC_CHECK_LIB([tiff], [TIFFOpen],
AC_DEFINE([HAVE_LIBTIFF], 1, [Define to 1 if you have libtiff.]) AC_SUBST([LIBTIFF_LIBS], [-ltiff]),
AS_IF([test "x$with_libtiff" = xyes], AC_MSG_ERROR([libtiff support requested but library not found])),
${ZLIB_LIBS} ${JPEG_LIBS}
)
)
AS_IF([test "x$with_libwebp" != xno],
AC_CHECK_LIB([webp], [WebPGetInfo],
AC_DEFINE([HAVE_LIBWEBP], 1, [Define to 1 if you have libwebp.]) AC_SUBST([LIBWEBP_LIBS], [-lwebp]),
AS_IF([test "x$with_libwebp" = xyes], AC_MSG_ERROR([libwebp support requested but library not found]))
)
)
AS_IF([test "x$with_libopenjp2" != xno],
AC_CHECK_LIB([openjp2], [opj_create_decompress],
AC_DEFINE([HAVE_LIBJP2K], 1, [Define to 1 if you have libopenjp2.]) AC_SUBST([LIBJP2K_LIBS], [-lopenjp2]),
AS_IF([test "x$with_libopenjp2" = xyes], AC_MSG_ERROR([libopenjp2 support requested but library not found]))
)
)
case "$host_os" in
mingw32*) AC_SUBST([GDI_LIBS], [-lgdi32]) ;;
esac
# Enable less verbose output when building.
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
AC_C_BIGENDIAN
AC_SUBST([APPLE_UNIVERSAL_BUILD], [0])
AC_SUBST([ENDIANNESS], [L_LITTLE_ENDIAN])
case "$ac_cv_c_bigendian" in
yes) AC_SUBST([ENDIANNESS], [L_BIG_ENDIAN]) ;;
universal) AC_SUBST([APPLE_UNIVERSAL_BUILD], [1]) ;;
esac
# Add the -Wl and --as-needed flags to gcc compiler
AC_MSG_CHECKING([whether compiler supports -Wl,--as-needed])
OLD_LDFLAGS="${LDFLAGS}"
LDFLAGS="-Wl,--as-needed ${LDFLAGS}"
AC_LINK_IFELSE([AC_LANG_PROGRAM()],
AC_MSG_RESULT([yes]),
LDFLAGS="${OLD_LDFLAGS}"; AC_MSG_RESULT([no])
)
# Checks for library functions.
AC_CHECK_FUNCS([fmemopen])
AC_CONFIG_FILES([Makefile src/endianness.h src/Makefile prog/Makefile lept.pc])
AC_OUTPUT

View File

@@ -0,0 +1,50 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* endiantest.c
*
* This test was contributed by Bill Janssen. When used with the
* gnu compiler, it allows efficient computation of the endian
* flag as part of the normal compilation process. As a result,
* it is not necessary to set this flag either manually or
* through the configure Makefile generator.
*/
#include <stdio.h>
int main()
{
/* fprintf(stderr, "doing the test\n"); */
long v = 0x04030201;
if (*((unsigned char *)(&v)) == 0x04)
printf("L_BIG_ENDIAN\n");
else
printf("L_LITTLE_ENDIAN\n");
return 0;
}

View File

@@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@/leptonica
Name: leptonica
Description: An open source C library for efficient image processing and image analysis operations
Version: @VERSION@
Libs: -L${libdir} -llept
Libs.private: @ZLIB_LIBS@ @LIBPNG_LIBS@ @JPEG_LIBS@ @GIFLIB_LIBS@ @LIBTIFF_LIBS@ @LIBWEBP_LIBS@
Cflags: -I${includedir}

View File

@@ -0,0 +1,26 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/

View File

@@ -0,0 +1,8 @@
#!/bin/sh
#
# make-for-auto
#
# Run this to make with autoconf if you've previously run make-for-local
mv src/makefile src/makefile.static
mv prog/makefile prog/makefile.static

View File

@@ -0,0 +1,8 @@
#!/bin/sh
#
# make-for-local
#
# Run this first if you want to use these static makefiles
cp src/makefile.static src/makefile
cp prog/makefile.static prog/makefile

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -0,0 +1,123 @@
AUTOMAKE_OPTIONS = parallel-tests
AM_CFLAGS = $(DEBUG_FLAGS)
AM_CPPFLAGS = -I$(top_srcdir)/src
LDADD = $(top_builddir)/src/liblept.la $(LIBM)
INSTALL_PROGS = convertfilestopdf convertfilestops \
convertformat \
convertsegfilestopdf convertsegfilestops \
converttopdf converttops fileinfo \
printimage printsplitimage printtiff \
splitimage2pdf xtractprotos
AUTO_REG_PROGS = alphaops_reg alphaxform_reg \
bilateral2_reg binarize_reg blackwhite_reg \
blend3_reg blend4_reg \
colorcontent_reg coloring_reg \
colormask_reg colorquant_reg \
colorspace_reg compare_reg \
convolve_reg dewarp_reg \
dna_reg dwamorph1_reg enhance_reg \
files_reg findcorners_reg findpattern_reg \
fpix1_reg fpix2_reg \
graymorph2_reg hardlight_reg \
insert_reg ioformats_reg \
jpegio_reg kernel_reg label_reg \
maze_reg multitype_reg \
nearline_reg newspaper_reg \
overlap_reg paint_reg paintmask_reg \
pdfseg_reg pixa2_reg \
pixserial_reg pngio_reg \
projection_reg psio_reg psioseg_reg \
pta_reg rankbin_reg rankhisto_reg \
rasteropip_reg \
rotate1_reg rotate2_reg rotateorth_reg \
scale_reg seedspread_reg \
selio_reg shear1_reg shear2_reg \
skew_reg splitcomp_reg subpixel_reg \
threshnorm_reg translate_reg \
warper_reg writetext_reg xformbox_reg
MANUAL_REG_PROGS = alltests_reg adaptnorm_reg affine_reg \
bilateral1_reg bilinear_reg \
binmorph1_reg binmorph2_reg binmorph3_reg \
binmorph4_reg binmorph5_reg \
blend1_reg blend2_reg boxa1_reg \
ccthin1_reg ccthin2_reg cmapquant_reg \
colorize_reg colorseg_reg compfilter_reg \
conncomp_reg conversion_reg distance_reg \
dwamorph2_reg equal_reg expand_reg extrema_reg \
fhmtauto_reg flipdetect_reg fmorphauto_reg \
gifio_reg grayfill_reg graymorph1_reg \
grayquant_reg heap_reg \
jp2kio_reg locminmax_reg \
logicops_reg lowaccess_reg morphseq_reg \
numa1_reg numa2_reg pixa1_reg \
pixadisp_reg pixalloc_reg pixcomp_reg \
pixmem_reg pixtile_reg projective_reg \
ptra1_reg ptra2_reg \
rank_reg rasterop_reg smallpix_reg \
smoothedge_reg string_reg \
webpio_reg wordboxes_reg
OTHER_PROGS = adaptmaptest adaptmap_dark \
arabic_lines arithtest \
barcodetest baselinetest \
binarizefiles binarize_set bincompare \
blendcmaptest buffertest \
byteatest ccbordtest cctest1 \
colormorphtest colorsegtest colorspacetest \
comparepages comparetest concatpdf \
contrasttest converttogray \
convolvetest cornertest \
croptest croptext \
dewarprules dewarptest1 dewarptest2 \
dewarptest3 dewarptest4 \
digitprep1 displayboxa \
displaypix displaypixa \
dithertest dwalineargen \
edgetest falsecolortest \
fcombautogen fhmtautogen \
findpattern1 findpattern2 findpattern3 \
flipselgen fmorphautogen \
fpixcontours gammatest genfonts \
graphicstest graymorphtest \
histotest iotest italictest \
jbcorrelation jbrankhaus jbwords \
lineremoval listtest \
livre_adapt livre_hmt \
livre_makefigs livre_orient \
livre_pageseg livre_seedgen livre_tophat \
maketile misctest1 \
modifyhuesat morphtest1 mtifftest \
numaranktest otsutest1 otsutest2 \
pagesegtest1 pagesegtest2 \
partitiontest pdfiotest \
pixaatest plottest \
quadtreetest ranktest \
recogsort recogtest1 \
reducetest removecmap \
renderfonts rotatefastalt \
rotateorthtest1 rotatetest1 \
runlengthtest scaleandtile \
scaletest1 scaletest2 \
seedfilltest sharptest \
sheartest showedges \
skewtest snapcolortest \
sorttest sudokutest trctest \
viewertest warpertest \
watershedtest wordsinorder \
writemtiff yuvtest
if ENABLE_PROGRAMS
bin_PROGRAMS = $(INSTALL_PROGS)
noinst_PROGRAMS = $(AUTO_REG_PROGS) $(MANUAL_REG_PROGS) $(OTHER_PROGS)
endif
check_PROGRAMS = $(AUTO_REG_PROGS)
TESTS = $(AUTO_REG_PROGS)
TESTS_ENVIRONMENT = $(srcdir)/reg_wrapper.sh
EXTRA_DIST = reg_wrapper.sh
dwamorph1_reg_SOURCES = dwamorph1_reg.c dwalinear.3.c dwalinearlow.3.c
dwamorph2_reg_SOURCES = dwamorph2_reg.c dwalinear.3.c dwalinearlow.3.c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* adaptmap_dark.c
*
* Demonstrates the effect of the fg threshold on adaptive mapping
* and cleaning for images with dark and variable background.
*
* The example pages are text and image. For both, because the
* background is both dark and variable, using a lower threshold
* gives much better results.
*
* For text, cleaning the background to white after adaptively
* remapping to make the background uniform is preferable.
* The final cleaning step uses pixGammaTRC() where the white value
* (here, 180) is set below the remapped gray value (here, 200).
*
* For the image, however, it is best to stop after remapping
* the background. Going further and moving pixels near the
* background color to white removes the details in the lighter
* regions of the image. In practice, parts of a scanned page
* that are image (as opposed to text) don't necessarily have
* background pixels that should be white. These regions can be
* protected by masks from operations, such as pixGammaTRC(),
* where the white value is less than 255.
*/
#include "string.h"
#include "allheaders.h"
void GenCleans(const char *fname, l_int32 *pindex, l_int32 thresh, L_BMF *bmf);
l_int32 main(int argc,
char **argv)
{
l_int32 index;
L_BMF *bmf;
PROCNAME("adaptmap_dark");
bmf = bmfCreate("fonts", 10);
index = 0;
lept_mkdir("lept");
/* Using a variety of different thresholds */
GenCleans("cavalerie.29.jpg", &index, 80, bmf);
GenCleans("cavalerie.29.jpg", &index, 60, bmf);
GenCleans("cavalerie.29.jpg", &index, 40, bmf);
GenCleans("cavalerie.11.jpg", &index, 80, bmf);
GenCleans("cavalerie.11.jpg", &index, 60, bmf);
GenCleans("cavalerie.11.jpg", &index, 40, bmf);
/* Write the nup files in /tmp/adapt2 */
convertToNUpFiles("/tmp/lept", "adapt_", 2, 1, 500, 6, 2, NULL, "adapt2");
/* Gather up into a pdf */
L_INFO("Writing to /tmp/lept/adapt_cleaning.pdf\n", procName);
convertFilesToPdf("/tmp/lept", "adapt_", 100, 1.0, L_JPEG_ENCODE,
75, "Adaptive cleaning", "/tmp/lept/adapt_cleaning.pdf");
bmfDestroy(&bmf);
lept_rmdir("adapt2");
return 0;
}
void
GenCleans(const char *fname,
l_int32 *pindex,
l_int32 thresh,
L_BMF *bmf)
{
l_int32 index, blackval, whiteval;
char buf[256];
PIX *pix1, *pix2, *pix3, *pix4, *pix5;
blackval = 70;
whiteval = 180;
index = *pindex;
pix1 = pixRead(fname);
snprintf(buf, sizeof(buf), "/tmp/lept/adapt_%03d.jpg", index++);
pixWrite(buf, pix1, IFF_JFIF_JPEG);
pix2 = pixBackgroundNorm(pix1, NULL, NULL, 10, 15, thresh, 25, 200, 2, 1);
snprintf(buf, sizeof(buf), "Norm color: fg thresh = %d", thresh);
fprintf(stderr, "%s\n", buf);
pix3 = pixAddSingleTextline(pix2, bmf, buf, 0x00ff0000, L_ADD_BELOW);
snprintf(buf, sizeof(buf), "/tmp/lept/adapt_%03d.jpg", index++);
pixWrite(buf, pix3, IFF_JFIF_JPEG);
pixDestroy(&pix3);
pix3 = pixGammaTRC(NULL, pix2, 1.0, blackval, whiteval);
snprintf(buf, sizeof(buf), "Clean color: fg thresh = %d", thresh);
pix4 = pixAddSingleTextblock(pix3, bmf, buf, 0x00ff0000, L_ADD_BELOW, NULL);
snprintf(buf, sizeof(buf), "/tmp/lept/adapt_%03d.jpg", index++);
pixWrite(buf, pix4, IFF_JFIF_JPEG);
pixDestroy(&pix2);
pixDestroy(&pix3);
pixDestroy(&pix4);
pix2 = pixConvertRGBToGray(pix1, 0.33, 0.34, 0.33);
pix3 = pixBackgroundNorm(pix2, NULL, NULL, 10, 15, thresh, 25, 200, 2, 1);
pix4 = pixGammaTRC(NULL, pix3, 1.0, blackval, whiteval);
snprintf(buf, sizeof(buf), "Clean gray: fg thresh = %d", thresh);
pix5 = pixAddSingleTextblock(pix4, bmf, buf, 0x00ff0000, L_ADD_BELOW, NULL);
snprintf(buf, sizeof(buf), "/tmp/lept/adapt_%03d.jpg", index++);
pixWrite(buf, pix5, IFF_JFIF_JPEG);
pixDestroy(&pix2);
pixDestroy(&pix3);
pixDestroy(&pix4);
pixDestroy(&pix5);
pixDestroy(&pix1);
*pindex = index;
return;
}

View File

@@ -0,0 +1,218 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* adaptmaptest.c
*
* Generates adaptive mappings in both gray and color, testing
* individual parts.
*
* e.g., use with wet-day.jpg
*/
#include "allheaders.h"
#define SIZE_X 10
#define SIZE_Y 30
#define BINTHRESH 50
#define MINCOUNT 30
#define BGVAL 200
#define SMOOTH_X 2
#define SMOOTH_Y 1
/* Location of image region in wet-day.jpg */
#define XS 151
#define YS 225
#define WS 913
#define HS 1285
int main(int argc,
char **argv)
{
l_int32 w, h, d;
PIX *pixs, *pixc, *pixg, *pixgm, *pixmi, *pixd, *pixd2;
PIX *pixmr, *pixmg, *pixmb, *pixmri, *pixmgi, *pixmbi;
PIX *pixim;
PIXA *pixa;
char *filein;
static char mainName[] = "adaptmaptest";
if (argc != 2)
return ERROR_INT(" Syntax: adaptmaptest filein", mainName, 1);
filein = argv[1];
if ((pixs = pixRead(filein)) == NULL)
return ERROR_INT("pix not made", mainName, 1);
pixGetDimensions(pixs, &w, &h, &d);
if (d != 8 && d != 32)
return ERROR_INT("pix not 8 or 32 bpp", mainName, 1);
pixDisplayWrite(NULL, -1);
pixa = pixaCreate(0);
pixSaveTiled(pixs, pixa, 1.0, 1, 20, 32);
pixDisplayWrite(pixs, 1);
if (d == 32) {
pixc = pixClone(pixs);
pixg = pixConvertRGBToGray(pixs, 0.33, 0.34, 0.33);
} else {
pixc = pixConvertTo32(pixs);
pixg = pixClone(pixs);
}
pixSaveTiled(pixg, pixa, 1.0, 0, 20, 32);
pixDisplayWrite(pixg, 1);
#if 1
/* Process in grayscale */
startTimer();
pixim = NULL;
pixim = pixCreate(w, h, 1);
pixRasterop(pixim, XS, YS, WS, HS, PIX_SET, NULL, 0, 0);
pixGetBackgroundGrayMap(pixg, pixim, SIZE_X, SIZE_Y,
BINTHRESH, MINCOUNT, &pixgm);
fprintf(stderr, "time for gray adaptmap gen: %7.3f\n", stopTimer());
pixWrite("/tmp/pixgm1.png", pixgm, IFF_PNG);
pixSaveTiled(pixgm, pixa, 1.0, 1, 20, 32);
pixDisplayWrite(pixgm, 1);
startTimer();
pixmi = pixGetInvBackgroundMap(pixgm, BGVAL, SMOOTH_X, SMOOTH_Y);
fprintf(stderr, "time for gray inv map generation: %7.3f\n", stopTimer());
pixWrite("/tmp/pixmi1.png", pixmi, IFF_PNG);
pixSaveTiled(pixmi, pixa, 1.0, 0, 20, 32);
pixDisplayWrite(pixmi, 1);
startTimer();
pixd = pixApplyInvBackgroundGrayMap(pixg, pixmi, SIZE_X, SIZE_Y);
fprintf(stderr, "time to apply gray inv map: %7.3f\n", stopTimer());
pixWrite("/tmp/pixd1.jpg", pixd, IFF_JFIF_JPEG);
pixSaveTiled(pixd, pixa, 1.0, 0, 20, 32);
pixDisplayWrite(pixd, 1);
pixd2 = pixGammaTRCMasked(NULL, pixd, pixim, 1.0, 0, 190);
pixInvert(pixim, pixim);
pixGammaTRCMasked(pixd2, pixd2, pixim, 1.0, 60, 190);
pixWrite("/tmp/pixo1.jpg", pixd2, IFF_JFIF_JPEG);
pixSaveTiled(pixd2, pixa, 1.0, 0, 20, 32);
pixDisplayWrite(pixd2, 1);
pixDestroy(&pixim);
pixDestroy(&pixgm);
pixDestroy(&pixmi);
pixDestroy(&pixd);
pixDestroy(&pixd2);
#endif
#if 1
/* Process in color */
startTimer();
pixmr = pixmg = pixmb = NULL;
pixim = pixCreate(w, h, 1);
pixRasterop(pixim, XS, YS, WS, HS, PIX_SET, NULL, 0, 0);
pixGetBackgroundRGBMap(pixc, pixim, NULL, SIZE_X, SIZE_Y,
BINTHRESH, MINCOUNT,
&pixmr, &pixmg, &pixmb);
fprintf(stderr, "time for color adaptmap gen: %7.3f\n", stopTimer());
pixWrite("/tmp/pixmr.png", pixmr, IFF_PNG);
pixWrite("/tmp/pixmg.png", pixmg, IFF_PNG);
pixWrite("/tmp/pixmb.png", pixmb, IFF_PNG);
startTimer();
pixmri = pixGetInvBackgroundMap(pixmr, BGVAL, SMOOTH_X, SMOOTH_Y);
pixmgi = pixGetInvBackgroundMap(pixmg, BGVAL, SMOOTH_X, SMOOTH_Y);
pixmbi = pixGetInvBackgroundMap(pixmb, BGVAL, SMOOTH_X, SMOOTH_Y);
fprintf(stderr, "time for color inv map generation: %7.3f\n", stopTimer());
pixWrite("/tmp/pixmri.png", pixmri, IFF_PNG);
pixWrite("/tmp/pixmgi.png", pixmgi, IFF_PNG);
pixWrite("/tmp/pixmbi.png", pixmbi, IFF_PNG);
startTimer();
pixd = pixApplyInvBackgroundRGBMap(pixc, pixmri, pixmgi, pixmbi,
SIZE_X, SIZE_Y);
fprintf(stderr, "time to apply color inv maps: %7.3f\n", stopTimer());
pixWrite("/tmp/pixd2.jpg", pixd, IFF_JFIF_JPEG);
pixSaveTiled(pixd, pixa, 1.0, 1, 20, 32);
pixDisplayWrite(pixd, 1);
pixd2 = pixGammaTRCMasked(NULL, pixd, pixim, 1.0, 0, 190);
pixInvert(pixim, pixim);
pixGammaTRCMasked(pixd2, pixd2, pixim, 1.0, 60, 190);
pixWrite("/tmp/pixo2.jpg", pixd2, IFF_JFIF_JPEG);
pixSaveTiled(pixd2, pixa, 1.0, 0, 20, 32);
pixDisplayWrite(pixd2, 1);
pixDestroy(&pixmr);
pixDestroy(&pixmg);
pixDestroy(&pixmb);
pixDestroy(&pixmri);
pixDestroy(&pixmgi);
pixDestroy(&pixmbi);
pixDestroy(&pixim);
pixDestroy(&pixd);
pixDestroy(&pixd2);
#endif
#if 1
/* Process in either gray or color, depending on the source */
startTimer();
pixim = pixCreate(w, h, 1);
pixRasterop(pixim, XS, YS, WS, HS, PIX_SET, NULL, 0, 0);
/* pixd = pixBackgroundNorm(pixs, pixim, NULL,SIZE_X, SIZE_Y,
BINTHRESH, MINCOUNT,
BGVAL, SMOOTH_X, SMOOTH_Y); */
pixd = pixBackgroundNorm(pixs, pixim, NULL, 5, 10, BINTHRESH, 20,
BGVAL, SMOOTH_X, SMOOTH_Y);
fprintf(stderr, "time for bg normalization: %7.3f\n", stopTimer());
pixWrite("/tmp/pixd3.jpg", pixd, IFF_JFIF_JPEG);
pixSaveTiled(pixd, pixa, 1.0, 1, 20, 32);
pixDisplayWrite(pixd, 1);
pixd2 = pixGammaTRCMasked(NULL, pixd, pixim, 1.0, 0, 190);
pixInvert(pixim, pixim);
pixGammaTRCMasked(pixd2, pixd2, pixim, 1.0, 60, 190);
pixWrite("/tmp/pixo3.jpg", pixd2, IFF_JFIF_JPEG);
pixSaveTiled(pixd2, pixa, 1.0, 0, 20, 32);
pixDisplayWrite(pixd2, 1);
pixDestroy(&pixd);
pixDestroy(&pixd2);
pixDestroy(&pixim);
#endif
/* Display results */
pixd = pixaDisplay(pixa, 0, 0);
pixDisplay(pixd, 100, 100);
pixWrite("/tmp/adapt.jpg", pixd, IFF_JFIF_JPEG);
pixDestroy(&pixd);
pixaDestroy(&pixa);
pixDisplayMultiple("/tmp/display/file*");
pixDestroy(&pixs);
pixDestroy(&pixg);
pixDestroy(&pixc);
return 0;
}

View File

@@ -0,0 +1,158 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* adaptnorm_reg.c
*
* Image normalization for two extreme cases:
* * variable and low contrast
* * good contrast but fast varying background
*/
#include "allheaders.h"
int main(int argc,
char **argv)
{
l_int32 w, h;
l_float32 mps;
PIX *pixs, *pixt, *pixmin, *pixd;
PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
PIX *pixt7, *pixt8, *pixt9, *pixt10, *pixt11, *pixt12;
PIX *pixt13, *pixt14, *pixt15, *pixt16;
PIXA *pixac;
static char mainName[] = "adaptnorm_reg";
/* ---------------------------------------------------------- *
* Normalize by adaptively expanding the dynamic range *
* ---------------------------------------------------------- */
pixac = pixaCreate(0);
pixs = pixRead("lighttext.jpg");
pixGetDimensions(pixs, &w, &h, NULL);
pixSaveTiled(pixs, pixac, 1.0, 1, 20, 8);
startTimer();
pixt1 = pixContrastNorm(NULL, pixs, 10, 10, 40, 2, 2);
mps = 0.000001 * w * h / stopTimer();
fprintf(stderr, "Time: Contrast norm: %7.3f Mpix/sec\n", mps);
pixSaveTiled(pixt1, pixac, 1.0, 1, 40, 8);
pixWrite("/tmp/pixt1.png", pixt1, IFF_PNG);
/* Apply a gamma to clean up the remaining background */
pixt2 = pixGammaTRC(NULL, pixt1, 1.5, 50, 235);
pixSaveTiled(pixt2, pixac, 1.0, 0, 40, 8);
pixWrite("/tmp/pixt2.png", pixt2, IFF_PNG);
/* Here are two possible output display images; a dithered
* 2 bpp image and a 7 level thresholded 4 bpp image */
pixt3 = pixDitherTo2bpp(pixt2, 1);
pixSaveTiled(pixt3, pixac, 1.0, 0, 40, 8);
pixWrite("/tmp/pixt3.png", pixt3, IFF_PNG);
pixt4 = pixThresholdTo4bpp(pixt2, 7, 1);
pixSaveTiled(pixt4, pixac, 1.0, 0, 40, 8);
pixWrite("/tmp/pixt4.png", pixt4, IFF_PNG);
/* Binary image produced from 8 bpp normalized ones,
* before and after the gamma correction. */
pixt5 = pixThresholdToBinary(pixt1, 180);
pixSaveTiled(pixt5, pixac, 1.0, 1, 40, 8);
pixWrite("/tmp/pixt5.png", pixt5, IFF_PNG);
pixt6 = pixThresholdToBinary(pixt2, 200);
pixSaveTiled(pixt6, pixac, 1.0, 0, 40, 8);
pixWrite("/tmp/pixt6.png", pixt6, IFF_PNG);
pixDestroy(&pixs);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
pixd = pixaDisplay(pixac, 0, 0);
pixDisplay(pixd, 100, 100);
pixWrite("/tmp/norm.png", pixd, IFF_PNG);
pixDestroy(&pixd);
pixaDestroy(&pixac);
/* ---------------------------------------------------------- *
* Normalize for rapidly varying background *
* ---------------------------------------------------------- */
pixac = pixaCreate(0);
pixs = pixRead("w91frag.jpg");
pixGetDimensions(pixs, &w, &h, NULL);
pixSaveTiled(pixs, pixac, 1.0, 1, 20, 8);
startTimer();
pixt7 = pixBackgroundNormFlex(pixs, 7, 7, 1, 1, 10);
mps = 0.000001 * w * h / stopTimer();
fprintf(stderr, "Time: Flexible bg norm: %7.3f Mpix/sec\n", mps);
pixSaveTiled(pixt7, pixac, 1.0, 0, 40, 8);
pixWrite("/tmp/pixt7.png", pixt7, IFF_PNG);
/* Now do it again in several steps */
pixt8 = pixScaleSmooth(pixs, 1./7., 1./7.);
pixt = pixScale(pixt8, 7.0, 7.0);
pixSaveTiled(pixt, pixac, 1.0, 1, 20, 8);
pixDestroy(&pixt);
pixLocalExtrema(pixt8, 0, 0, &pixmin, NULL); /* 1's at minima */
pixt9 = pixExpandBinaryReplicate(pixmin, 7);
pixSaveTiled(pixt9, pixac, 1.0, 0, 20, 8);
pixt10 = pixSeedfillGrayBasin(pixmin, pixt8, 10, 4);
pixt11 = pixExtendByReplication(pixt10, 1, 1);
pixt12 = pixGetInvBackgroundMap(pixt11, 200, 1, 1); /* smoothing incl. */
pixt13 = pixApplyInvBackgroundGrayMap(pixs, pixt12, 7, 7);
pixSaveTiled(pixt13, pixac, 1.0, 0, 20, 8);
/* Process the result for gray and binary output */
pixt14 = pixGammaTRCMasked(NULL, pixt7, NULL, 1.0, 100, 175);
pixSaveTiled(pixt14, pixac, 1.0, 1, 20, 8);
pixt15 = pixThresholdTo4bpp(pixt14, 10, 1);
pixSaveTiled(pixt15, pixac, 1.0, 0, 20, 8);
pixt16 = pixThresholdToBinary(pixt14, 190);
pixSaveTiled(pixt16, pixac, 1.0, 0, 20, 8);
pixDestroy(&pixs);
pixDestroy(&pixt7);
pixDestroy(&pixmin);
pixDestroy(&pixt8);
pixDestroy(&pixt9);
pixDestroy(&pixt10);
pixDestroy(&pixt11);
pixDestroy(&pixt12);
pixDestroy(&pixt13);
pixDestroy(&pixt14);
pixDestroy(&pixt15);
pixDestroy(&pixt16);
pixd = pixaDisplay(pixac, 0, 0);
pixDisplay(pixd, 100, 100);
pixWrite("/tmp/flex.png", pixd, IFF_PNG);
pixDestroy(&pixd);
pixaDestroy(&pixac);
return 0;
}

View File

@@ -0,0 +1,392 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* affine_reg.c
*
*/
#include "allheaders.h"
static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad);
l_int32 RenderHashedBoxa(PIX *pixt, BOXA *boxa, l_int32 i);
/* Sample values.
* 1-3: invertability tests
* 4: comparison between sampling and sequential
* 5: test with large distortion
*/
static const l_int32 x1[] = { 300, 300, 300, 95, 32};
static const l_int32 y1[] = {1200, 1200, 1250, 2821, 934};
static const l_int32 x2[] = {1200, 1200, 1125, 1432, 487};
static const l_int32 y2[] = {1100, 1100, 1100, 2682, 934};
static const l_int32 x3[] = { 200, 200, 200, 232, 32};
static const l_int32 y3[] = { 200, 200, 200, 657, 67};
static const l_int32 xp1[] = { 500, 300, 350, 117, 32};
static const l_int32 yp1[] = {1700, 1400, 1400, 2629, 934};
static const l_int32 xp2[] = {850, 1400, 1400, 1464, 487};
static const l_int32 yp2[] = {850, 1500, 1500, 2432, 804};
static const l_int32 xp3[] = { 450, 200, 400, 183, 61};
static const l_int32 yp3[] = { 300, 300, 400, 490, 83};
static const l_int32 SHIFTX = 44;
static const l_int32 SHIFTY = 39;
static const l_float32 SCALEX = 0.83;
static const l_float32 SCALEY = 0.78;
static const l_float32 ROTATION = 0.11; /* radian */
#define ADDED_BORDER_PIXELS 1000
#define ALL 1
int main(int argc,
char **argv)
{
char bufname[256];
l_int32 i, w, h;
l_float32 *mat1, *mat2, *mat3, *mat1i, *mat2i, *mat3i, *matdinv;
l_float32 matd[9], matdi[9];
BOXA *boxa, *boxa2;
PIX *pix, *pixs, *pixb, *pixg, *pixc, *pixcs;
PIX *pixd, *pixt1, *pixt2, *pixt3;
PIXA *pixa;
PTA *ptas, *ptad;
static char mainName[] = "affine_reg";
if (argc != 1)
return ERROR_INT(" Syntax: affine_reg", mainName, 1);
if ((pixs = pixRead("feyn.tif")) == NULL)
return ERROR_INT("pixs not made", mainName, 1);
#if 1
/* Test invertability of sequential. */
pixa = pixaCreate(0);
for (i = 0; i < 3; i++) {
pixb = pixAddBorder(pixs, ADDED_BORDER_PIXELS, 0);
MakePtas(i, &ptas, &ptad);
pixt1 = pixAffineSequential(pixb, ptad, ptas, 0, 0);
pixSaveTiled(pixt1, pixa, 0.3333, 1, 20, 8);
pixt2 = pixAffineSequential(pixt1, ptas, ptad, 0, 0);
pixSaveTiled(pixt2, pixa, 0.3333, 0, 20, 0);
pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS);
pixXor(pixd, pixd, pixs);
pixSaveTiled(pixd, pixa, 0.3333, 0, 20, 0);
sprintf(bufname, "/tmp/seq%d.png", i);
pixWrite(bufname, pixd, IFF_PNG);
pixDestroy(&pixb);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
}
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine1.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 100);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
#endif
#if ALL
/* Test invertability of sampling */
pixa = pixaCreate(0);
for (i = 0; i < 3; i++) {
pixb = pixAddBorder(pixs, ADDED_BORDER_PIXELS, 0);
MakePtas(i, &ptas, &ptad);
pixt1 = pixAffineSampledPta(pixb, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt1, pixa, 0.3333, 1, 20, 8);
pixt2 = pixAffineSampledPta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
pixSaveTiled(pixt2, pixa, 0.3333, 0, 20, 0);
pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS);
pixXor(pixd, pixd, pixs);
pixSaveTiled(pixd, pixa, 0.3333, 0, 20, 0);
if (i == 0) pixWrite("/tmp/samp.png", pixt1, IFF_PNG);
pixDestroy(&pixb);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
}
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine2.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 300);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
#endif
#if ALL
/* Test invertability of interpolation on grayscale */
pixa = pixaCreate(0);
pixg = pixScaleToGray3(pixs);
for (i = 0; i < 3; i++) {
pixb = pixAddBorder(pixg, ADDED_BORDER_PIXELS / 3, 255);
MakePtas(i, &ptas, &ptad);
pixt1 = pixAffinePta(pixb, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt1, pixa, 1.0, 1, 20, 8);
pixt2 = pixAffinePta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
pixSaveTiled(pixt2, pixa, 1.0, 0, 20, 0);
pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS / 3);
pixXor(pixd, pixd, pixg);
pixSaveTiled(pixd, pixa, 1.0, 0, 20, 0);
if (i == 0) pixWrite("/tmp/interp.png", pixt1, IFF_PNG);
pixDestroy(&pixb);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
}
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine3.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 500);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
pixDestroy(&pixg);
#endif
#if ALL
/* Test invertability of interpolation on color */
pixa = pixaCreate(0);
pixc = pixRead("test24.jpg");
pixcs = pixScale(pixc, 0.3, 0.3);
for (i = 0; i < 3; i++) {
pixb = pixAddBorder(pixcs, ADDED_BORDER_PIXELS / 4, 0xffffff00);
MakePtas(i, &ptas, &ptad);
pixt1 = pixAffinePta(pixb, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt1, pixa, 1.0, 1, 20, 32);
pixt2 = pixAffinePta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
pixSaveTiled(pixt2, pixa, 1.0, 0, 20, 0);
pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS / 4);
pixXor(pixd, pixd, pixcs);
pixSaveTiled(pixd, pixa, 1.0, 0, 20, 0);
pixDestroy(&pixb);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
}
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine4.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 500);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
pixDestroy(&pixc);
pixDestroy(&pixcs);
#endif
#if ALL
/* Comparison between sequential and sampling */
MakePtas(3, &ptas, &ptad);
pixa = pixaCreate(0);
/* Use sequential transforms */
pixt1 = pixAffineSequential(pixs, ptas, ptad,
ADDED_BORDER_PIXELS, ADDED_BORDER_PIXELS);
pixSaveTiled(pixt1, pixa, 0.5, 0, 20, 8);
/* Use sampled transform */
pixt2 = pixAffineSampledPta(pixs, ptas, ptad, L_BRING_IN_WHITE);
pixSaveTiled(pixt2, pixa, 0.5, 0, 20, 8);
/* Compare the results */
pixXor(pixt2, pixt2, pixt1);
pixSaveTiled(pixt2, pixa, 0.5, 0, 20, 8);
pixd = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine5.png", pixd, IFF_PNG);
pixDisplay(pixd, 100, 700);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
pixaDestroy(&pixa);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
#endif
#if ALL
/* Get timings and test with large distortion */
MakePtas(4, &ptas, &ptad);
pixa = pixaCreate(0);
pixg = pixScaleToGray3(pixs);
startTimer();
pixt1 = pixAffineSequential(pixg, ptas, ptad, 0, 0);
fprintf(stderr, " Time for pixAffineSequentialPta(): %6.2f sec\n",
stopTimer());
pixSaveTiled(pixt1, pixa, 1.0, 1, 20, 8);
startTimer();
pixt2 = pixAffineSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE);
fprintf(stderr, " Time for pixAffineSampledPta(): %6.2f sec\n", stopTimer());
pixSaveTiled(pixt2, pixa, 1.0, 0, 20, 8);
startTimer();
pixt3 = pixAffinePta(pixg, ptas, ptad, L_BRING_IN_WHITE);
fprintf(stderr, " Time for pixAffinePta(): %6.2f sec\n", stopTimer());
pixSaveTiled(pixt3, pixa, 1.0, 0, 20, 8);
pixXor(pixt1, pixt1, pixt2);
pixSaveTiled(pixt1, pixa, 1.0, 1, 20, 8);
pixXor(pixt2, pixt2, pixt3);
pixSaveTiled(pixt2, pixa, 1.0, 0, 20, 8);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixd = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine6.png", pixd, IFF_PNG);
pixDisplay(pixd, 100, 900);
pixDestroy(&pixd);
pixDestroy(&pixg);
pixaDestroy(&pixa);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
#endif
pixDestroy(&pixs);
#if ALL
/* Set up pix and boxa */
pixa = pixaCreate(0);
pix = pixRead("lucasta.1.300.tif");
pixTranslate(pix, pix, 70, 0, L_BRING_IN_WHITE);
pixt1 = pixCloseBrick(NULL, pix, 14, 5);
pixOpenBrick(pixt1, pixt1, 1, 2);
boxa = pixConnComp(pixt1, NULL, 8);
pixs = pixConvertTo32(pix);
pixGetDimensions(pixs, &w, &h, NULL);
pixc = pixCopy(NULL, pixs);
RenderHashedBoxa(pixc, boxa, 113);
pixSaveTiled(pixc, pixa, 0.5, 1, 30, 32);
pixDestroy(&pix);
pixDestroy(&pixc);
pixDestroy(&pixt1);
/* Set up an affine transform in matd, and apply it to boxa */
mat1 = createMatrix2dTranslate(SHIFTX, SHIFTY);
mat2 = createMatrix2dScale(SCALEX, SCALEY);
mat3 = createMatrix2dRotate(w / 2, h / 2, ROTATION);
l_productMat3(mat3, mat2, mat1, matd, 3);
boxa2 = boxaAffineTransform(boxa, matd);
/* Set up the inverse transform in matdi */
mat1i = createMatrix2dTranslate(-SHIFTX, -SHIFTY);
mat2i = createMatrix2dScale(1.0/ SCALEX, 1.0 / SCALEY);
mat3i = createMatrix2dRotate(w / 2, h / 2, -ROTATION);
l_productMat3(mat1i, mat2i, mat3i, matdi, 3);
/* Invert the original affine transform in matdinv */
affineInvertXform(matd, &matdinv);
fprintf(stderr, "Affine transform, applied to boxa\n");
for (i = 0; i < 9; i++) {
if (i && (i % 3 == 0)) fprintf(stderr, "\n");
fprintf(stderr, " %7.3f ", matd[i]);
}
fprintf(stderr, "\nInverse transform, made by composing inverse parts");
for (i = 0; i < 9; i++) {
if (i % 3 == 0) fprintf(stderr, "\n");
fprintf(stderr, " %7.3f ", matdi[i]);
}
fprintf(stderr, "\nInverse transform, made by inverting the affine xform");
for (i = 0; i < 6; i++) {
if (i % 3 == 0) fprintf(stderr, "\n");
fprintf(stderr, " %7.3f ", matdinv[i]);
}
fprintf(stderr, "\n");
/* Apply the inverted affine transform pixs */
pixd = pixAffine(pixs, matdinv, L_BRING_IN_WHITE);
RenderHashedBoxa(pixd, boxa2, 513);
pixSaveTiled(pixd, pixa, 0.5, 0, 30, 32);
pixDestroy(&pixd);
pixd = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/affine7.png", pixd, IFF_PNG);
pixDisplay(pixd, 100, 900);
pixDestroy(&pixd);
pixDestroy(&pixs);
pixaDestroy(&pixa);
boxaDestroy(&boxa);
boxaDestroy(&boxa2);
lept_free(mat1);
lept_free(mat2);
lept_free(mat3);
lept_free(mat1i);
lept_free(mat2i);
lept_free(mat3i);
#endif
return 0;
}
static void
MakePtas(l_int32 i,
PTA **pptas,
PTA **pptad)
{
*pptas = ptaCreate(3);
ptaAddPt(*pptas, x1[i], y1[i]);
ptaAddPt(*pptas, x2[i], y2[i]);
ptaAddPt(*pptas, x3[i], y3[i]);
*pptad = ptaCreate(3);
ptaAddPt(*pptad, xp1[i], yp1[i]);
ptaAddPt(*pptad, xp2[i], yp2[i]);
ptaAddPt(*pptad, xp3[i], yp3[i]);
return;
}
l_int32
RenderHashedBoxa(PIX *pixt,
BOXA *boxa,
l_int32 i)
{
l_int32 j, n, rval, gval, bval;
BOX *box;
n = boxaGetCount(boxa);
rval = (1413 * i) % 256;
gval = (4917 * i) % 256;
bval = (7341 * i) % 256;
for (j = 0; j < n; j++) {
box = boxaGetBox(boxa, j, L_CLONE);
pixRenderHashBoxArb(pixt, box, 10, 3, i % 4, 1, rval, gval, bval);
boxDestroy(&box);
}
return 0;
}

View File

@@ -0,0 +1,188 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* alltests_reg.c
*
* Tests all the reg tests:
*
* alltests_reg command
*
* where
* <command> == "generate" to make the golden files in /tmp/golden
* <command> == "compare" to make local files and compare with
* the golden files
* <command> == "display" to make local files and display
*
* You can also run each test individually with any one of these
* arguments. Warning: if you run this with "display", a very
* large number of images will be displayed on the screen.
*/
#include <string.h>
#include "allheaders.h"
static const char *tests[] = {
"alphaops_reg",
"alphaxform_reg",
"bilateral2_reg",
"binarize_reg",
"blackwhite_reg",
"blend3_reg",
"blend4_reg",
"colorcontent_reg",
"coloring_reg",
"colormask_reg",
"colorquant_reg",
"colorspace_reg",
"compare_reg",
"convolve_reg",
"dewarp_reg",
/* "distance_reg", */
"dna_reg",
"dwamorph1_reg",
"enhance_reg",
"files_reg",
"findcorners_reg",
"findpattern_reg",
"fpix1_reg",
"fpix2_reg",
/* "gifio_reg", */
"graymorph2_reg",
"hardlight_reg",
"insert_reg",
"ioformats_reg",
"jpegio_reg",
"kernel_reg",
"label_reg",
"maze_reg",
"multitype_reg",
"nearline_reg",
"newspaper_reg",
"overlap_reg",
"paint_reg",
"paintmask_reg",
"pdfseg_reg",
"pixa2_reg",
"pixserial_reg",
"pngio_reg",
"projection_reg",
"psio_reg",
"psioseg_reg",
"pta_reg",
"rankbin_reg",
"rankhisto_reg",
"rasteropip_reg",
"rotateorth_reg",
"rotate1_reg",
"rotate2_reg",
"scale_reg",
"seedspread_reg",
"selio_reg",
"shear1_reg",
"shear2_reg",
"skew_reg",
"splitcomp_reg",
"subpixel_reg",
"threshnorm_reg",
"translate_reg",
"warper_reg",
"writetext_reg",
"xformbox_reg",
};
static const char *header = {"\n=======================\n"
"Regression Test Results\n"
"======================="};
int main(int argc,
char **argv)
{
char *str, *results_file;
char command[256], buf[256];
l_int32 i, ntests, dotest, nfail, ret, start, stop;
SARRAY *sa;
static char mainName[] = "alltests_reg";
if (argc != 2)
return ERROR_INT(" Syntax alltests_reg [generate | compare | display]",
mainName, 1);
l_getCurrentTime(&start, NULL);
ntests = sizeof(tests) / sizeof(char *);
fprintf(stderr, "Running alltests_reg:\n"
"This currently tests %d of the 120 Regression Test\n"
"programs in the /prog directory.\n", ntests);
/* Clear the output file if we're doing the set of reg tests */
dotest = strcmp(argv[1], "compare") ? 0 : 1;
if (dotest) {
results_file = genPathname("/tmp", "reg_results.txt");
sa = sarrayCreate(3);
sarrayAddString(sa, (char *)header, L_COPY);
sarrayAddString(sa, getLeptonicaVersion(), L_INSERT);
sarrayAddString(sa, getImagelibVersions(), L_INSERT);
str = sarrayToString(sa, 1);
sarrayDestroy(&sa);
l_binaryWrite("/tmp/reg_results.txt", "w", str, strlen(str));
lept_free(str);
}
nfail = 0;
for (i = 0; i < ntests; i++) {
#ifndef _WIN32
snprintf(command, sizeof(command) - 2, "./%s %s", tests[i], argv[1]);
#else /* windows interprets '/' as a commandline flag */
snprintf(command, sizeof(command) - 2, "%s %s", tests[i], argv[1]);
#endif /* ! _WIN32 */
ret = system(command);
if (ret) {
snprintf(buf, sizeof(buf), "Failed to complete %s\n", tests[i]);
if (dotest) {
l_binaryWrite("/tmp/reg_results.txt", "a", buf, strlen(buf));
nfail++;
}
else
fprintf(stderr, "%s", buf);
}
}
if (dotest) {
#ifndef _WIN32
snprintf(command, sizeof(command) - 2, "cat %s", results_file);
#else
snprintf(command, sizeof(command) - 2, "type \"%s\"", results_file);
#endif /* !_WIN32 */
lept_free(results_file);
ret = system(command);
fprintf(stderr, "Success in %d of %d *_reg programs (output matches"
" the \"golden\" files)\n", ntests - nfail, ntests);
}
l_getCurrentTime(&stop, NULL);
fprintf(stderr, "Time for all regression tests: %d sec\n", stop - start);
return 0;
}

View File

@@ -0,0 +1,361 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* alphaops_reg.c
*
* Tests various functions that use the alpha layer:
*
* (1) Remove and add alpha layers.
* Removing is done by blending with a uniform image.
* Adding is done by setting all white pixels to transparent,
* and grading the alpha layer to opaque depending on
* the distance from the nearest transparent pixel.
*
* (2) Tests transparency and cleaning under alpha.
*
* (3) Blending with a uniform color. Also tests an alternative
* way to "blend" to a color: component-wise multiplication by
* the color.
*
* (4) Testing RGB and colormapped images with alpha, including
* binary and ascii colormap serialization.
*/
#include "allheaders.h"
static PIX *DoBlendTest(PIX *pix, BOX *box, l_uint32 val, l_float32 gamma,
l_int32 minval, l_int32 maxval, l_int32 which);
void CmapEqual(PIXCMAP *cmap1, PIXCMAP *cmap2, l_int32 *pequal);
int main(int argc,
char **argv)
{
l_uint8 *data;
l_int32 w, h, n1, n2, n, i, minval, maxval;
l_int32 ncolors, rval, gval, bval, equal;
l_int32 *rmap, *gmap, *bmap;
l_uint32 color;
l_float32 gamma;
BOX *box;
FILE *fp;
PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
PIX *pixs, *pixb, *pixg, *pixc, *pixd;
PIX *pixg2, *pixcs1, *pixcs2, *pixd1, *pixd2;
PIXA *pixa, *pixa2, *pixa3;
PIXCMAP *cmap, *cmap2;
RGBA_QUAD *cta;
L_REGPARAMS *rp;
if (regTestSetup(argc, argv, &rp))
return 1;
/* ------------------------ (1) ----------------------------*/
/* Blend with a white background */
pix1 = pixRead("books_logo.png");
pixDisplayWithTitle(pix1, 100, 0, NULL, rp->display);
pix2 = pixAlphaBlendUniform(pix1, 0xffffff00);
pixDisplayWithTitle(pix2, 100, 150, NULL, rp->display);
regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 0 */
regTestWritePixAndCheck(rp, pix2, IFF_PNG); /* 1 */
/* Generate an alpha layer based on the white background */
pix3 = pixSetAlphaOverWhite(pix2);
pixSetSpp(pix3, 3);
pixWrite("/tmp/regout/alphaops.2.png", pix3, IFF_PNG); /* without alpha */
regTestCheckFile(rp, "/tmp/regout/alphaops.2.png"); /* 2 */
pixSetSpp(pix3, 4);
regTestWritePixAndCheck(rp, pix3, IFF_PNG); /* 3, with alpha */
pixDisplayWithTitle(pix3, 100, 300, NULL, rp->display);
/* Render on a light yellow background */
pix4 = pixAlphaBlendUniform(pix3, 0xffffe000);
regTestWritePixAndCheck(rp, pix4, IFF_PNG); /* 4 */
pixDisplayWithTitle(pix4, 100, 450, NULL, rp->display);
pixDestroy(&pix1);
pixDestroy(&pix2);
pixDestroy(&pix3);
pixDestroy(&pix4);
/* ------------------------ (2) ----------------------------*/
lept_mkdir("lept");
/* Make the transparency (alpha) layer.
* pixs is the mask. We turn it into a transparency (alpha)
* layer by converting to 8 bpp. A small convolution fuzzes
* the mask edges so that you don't see the pixels. */
pixs = pixRead("feyn-fract.tif");
pixGetDimensions(pixs, &w, &h, NULL);
pixg = pixConvert1To8(NULL, pixs, 0, 255);
pixg2 = pixBlockconvGray(pixg, NULL, 1, 1);
regTestWritePixAndCheck(rp, pixg2, IFF_JFIF_JPEG); /* 5 */
pixDisplayWithTitle(pixg2, 0, 0, "alpha", rp->display);
/* Make the viewable image.
* pixc is the image that we see where the alpha layer is
* opaque -- i.e., greater than 0. Scale it to the same
* size as the mask. To visualize what this will look like
* when displayed over a black background, create the black
* background image, pixb, and do the blending with pixcs1
* explicitly using the alpha layer pixg2. */
pixc = pixRead("tetons.jpg");
pixcs1 = pixScaleToSize(pixc, w, h);
regTestWritePixAndCheck(rp, pixcs1, IFF_JFIF_JPEG); /* 6 */
pixDisplayWithTitle(pixcs1, 300, 0, "viewable", rp->display);
pixb = pixCreateTemplate(pixcs1); /* black */
pixd1 = pixBlendWithGrayMask(pixb, pixcs1, pixg2, 0, 0);
regTestWritePixAndCheck(rp, pixd1, IFF_JFIF_JPEG); /* 7 */
pixDisplayWithTitle(pixd1, 600, 0, "alpha-blended 1", rp->display);
/* Embed the alpha layer pixg2 into the color image pixc.
* Write it out as is. Then clean pixcs1 (to 0) under the fully
* transparent part of the alpha layer, and write that result
* out as well. */
pixSetRGBComponent(pixcs1, pixg2, L_ALPHA_CHANNEL);
pixWrite("/tmp/lept/alpha_cs1.png", pixcs1, IFF_PNG);
pixcs2 = pixSetUnderTransparency(pixcs1, 0, 0);
pixWrite("/tmp/lept/alpha_cs2.png", pixcs2, IFF_PNG);
/* What will this look like over a black background?
* Do the blending explicitly and display. It should
* look identical to the blended result pixd1 before cleaning. */
pixd2 = pixBlendWithGrayMask(pixb, pixcs2, pixg2, 0, 0);
regTestWritePixAndCheck(rp, pixd2, IFF_JFIF_JPEG); /* 8 */
pixDisplayWithTitle(pixd2, 0, 400, "alpha blended 2", rp->display);
/* Read the two images back, ignoring the transparency layer.
* The uncleaned image will come back identical to pixcs1.
* However, the cleaned image will be black wherever
* the alpha layer was fully transparent. It will
* look the same when viewed through the alpha layer,
* but have much better compression. */
pix1 = pixRead("/tmp/lept/alpha_cs1.png"); /* just pixcs1 */
pix2 = pixRead("/tmp/lept/alpha_cs2.png"); /* cleaned under transparent */
n1 = nbytesInFile("/tmp/lept/alpha_cs1.png");
n2 = nbytesInFile("/tmp/lept/alpha_cs2.png");
fprintf(stderr, " Original: %d bytes\n Cleaned: %d bytes\n", n1, n2);
regTestWritePixAndCheck(rp, pix1, IFF_JFIF_JPEG); /* 9 */
regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 10 */
pixDisplayWithTitle(pix1, 300, 400, "without alpha", rp->display);
pixDisplayWithTitle(pix2, 600, 400, "cleaned under transparent",
rp->display);
pixa = pixaCreate(0);
pixSaveTiled(pixg2, pixa, 1.0, 1, 20, 32);
pixSaveTiled(pixcs1, pixa, 1.0, 1, 20, 0);
pixSaveTiled(pix1, pixa, 1.0, 0, 20, 0);
pixSaveTiled(pixd1, pixa, 1.0, 1, 20, 0);
pixSaveTiled(pixd2, pixa, 1.0, 0, 20, 0);
pixSaveTiled(pix2, pixa, 1.0, 1, 20, 0);
pixd = pixaDisplay(pixa, 0, 0);
regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 11 */
pixDisplayWithTitle(pixd, 200, 200, "composite", rp->display);
pixWrite("/tmp/lept/alpha.png", pixd, IFF_JFIF_JPEG);
pixDestroy(&pixd);
pixaDestroy(&pixa);
pixDestroy(&pixs);
pixDestroy(&pixb);
pixDestroy(&pixg);
pixDestroy(&pixg2);
pixDestroy(&pixc);
pixDestroy(&pixcs1);
pixDestroy(&pixcs2);
pixDestroy(&pixd);
pixDestroy(&pixd1);
pixDestroy(&pixd2);
pixDestroy(&pix1);
pixDestroy(&pix2);
/* ------------------------ (3) ----------------------------*/
color = 0xffffa000;
gamma = 1.0;
minval = 0;
maxval = 200;
box = boxCreate(0, 85, 600, 100);
pixa = pixaCreate(6);
pix1 = pixRead("blend-green1.jpg");
pixaAddPix(pixa, pix1, L_INSERT);
pix1 = pixRead("blend-green2.png");
pixaAddPix(pixa, pix1, L_INSERT);
pix1 = pixRead("blend-green3.png");
pixaAddPix(pixa, pix1, L_INSERT);
pix1 = pixRead("blend-orange.jpg");
pixaAddPix(pixa, pix1, L_INSERT);
pix1 = pixRead("blend-yellow.jpg");
pixaAddPix(pixa, pix1, L_INSERT);
pix1 = pixRead("blend-red.png");
pixaAddPix(pixa, pix1, L_INSERT);
n = pixaGetCount(pixa);
pixa2 = pixaCreate(n);
pixa3 = pixaCreate(n);
for (i = 0; i < n; i++) {
pix1 = pixaGetPix(pixa, i, L_CLONE);
pix2 = DoBlendTest(pix1, box, color, gamma, minval, maxval, 1);
regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 12, 14, ... 22 */
pixDisplayWithTitle(pix2, 150 * i, 0, NULL, rp->display);
pixaAddPix(pixa2, pix2, L_INSERT);
pix2 = DoBlendTest(pix1, box, color, gamma, minval, maxval, 2);
regTestWritePixAndCheck(rp, pix2, IFF_JFIF_JPEG); /* 13, 15, ... 23 */
pixDisplayWithTitle(pix2, 150 * i, 200, NULL, rp->display);
pixaAddPix(pixa3, pix2, L_INSERT);
pixDestroy(&pix1);
}
if (rp->display) {
pixaConvertToPdf(pixa2, 0, 0.75, L_FLATE_ENCODE, 0, "blend 1 test",
"/tmp/lept/alpha_blend1.pdf");
pixaConvertToPdf(pixa3, 0, 0.75, L_FLATE_ENCODE, 0, "blend 2 test",
"/tmp/lept/alpha_blend2.pdf");
}
pixaDestroy(&pixa);
pixaDestroy(&pixa2);
pixaDestroy(&pixa3);
boxDestroy(&box);
/* ------------------------ (4) ----------------------------*/
/* Use one image as the alpha component for a second image */
pix1 = pixRead("test24.jpg");
pix2 = pixRead("marge.jpg");
pix3 = pixScale(pix2, 1.9, 2.2);
pix4 = pixConvertTo8(pix3, 0);
pixSetRGBComponent(pix1, pix4, L_ALPHA_CHANNEL);
regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 24 */
pixDisplayWithTitle(pix1, 600, 0, NULL, rp->display);
/* Set the alpha value in a colormap to bval */
pix5 = pixOctreeColorQuant(pix1, 128, 0);
cmap = pixGetColormap(pix5);
pixcmapToArrays(cmap, &rmap, &gmap, &bmap, NULL);
n = pixcmapGetCount(cmap);
for (i = 0; i < n; i++) {
pixcmapGetColor(cmap, i, &rval, &gval, &bval);
cta = (RGBA_QUAD *)cmap->array;
cta[i].alpha = bval;
}
/* Test binary serialization/deserialization of colormap with alpha */
pixcmapSerializeToMemory(cmap, 4, &ncolors, &data);
cmap2 = pixcmapDeserializeFromMemory(data, 4, ncolors);
CmapEqual(cmap, cmap2, &equal);
regTestCompareValues(rp, TRUE, equal, 0.0); /* 25 */
pixcmapDestroy(&cmap2);
lept_free(data);
/* Test ascii serialization/deserialization of colormap with alpha */
fp = fopenWriteStream("/tmp/lept/alpha_cmap.4", "w");
pixcmapWriteStream(fp, cmap);
fclose(fp);
fp = fopenReadStream("/tmp/lept/alpha_cmap.4");
cmap2 = pixcmapReadStream(fp);
fclose(fp);
CmapEqual(cmap, cmap2, &equal);
regTestCompareValues(rp, TRUE, equal, 0.0); /* 26 */
pixcmapDestroy(&cmap2);
/* Test r/w for cmapped pix with non-opaque alpha */
pixDisplayWithTitle(pix5, 900, 0, NULL, rp->display);
regTestWritePixAndCheck(rp, pix5, IFF_PNG); /* 27 */
pixWrite("/tmp/lept/alpha_fourcomp.png", pix5, IFF_PNG);
pix6 = pixRead("/tmp/lept/alpha_fourcomp.png");
regTestComparePix(rp, pix5, pix6); /* 28 */
pixDestroy(&pix1);
pixDestroy(&pix2);
pixDestroy(&pix3);
pixDestroy(&pix4);
pixDestroy(&pix5);
pixDestroy(&pix6);
lept_free(rmap);
lept_free(gmap);
lept_free(bmap);
return regTestCleanup(rp);
}
/* Use which == 1 to test alpha blending; which == 2 to test "blending"
* by pixel multiplication. This generates a composite of 5 images:
* the original, blending over a box at the bottom (2 ways), and
* multiplying over a box at the bottom (2 ways). */
static PIX *
DoBlendTest(PIX *pix, BOX *box, l_uint32 color, l_float32 gamma,
l_int32 minval, l_int32 maxval, l_int32 which)
{
PIX *pix1, *pix2, *pix3, *pixd;
PIXA *pixa;
pixa = pixaCreate(5);
pix1 = pixRemoveColormap(pix, REMOVE_CMAP_TO_FULL_COLOR);
pix2 = pixCopy(NULL, pix1);
pixaAddPix(pixa, pix2, L_COPY);
if (which == 1)
pix3 = pixBlendBackgroundToColor(NULL, pix2, box, color,
gamma, minval, maxval);
else
pix3 = pixMultiplyByColor(NULL, pix2, box, color);
pixaAddPix(pixa, pix3, L_INSERT);
if (which == 1)
pixBlendBackgroundToColor(pix2, pix2, box, color,
gamma, minval, maxval);
else
pixMultiplyByColor(pix2, pix2, box, color);
pixaAddPix(pixa, pix2, L_INSERT);
pix2 = pixCopy(NULL, pix1);
if (which == 1)
pix3 = pixBlendBackgroundToColor(NULL, pix2, NULL, color,
gamma, minval, maxval);
else
pix3 = pixMultiplyByColor(NULL, pix2, NULL, color);
pixaAddPix(pixa, pix3, L_INSERT);
if (which == 1)
pixBlendBackgroundToColor(pix2, pix2, NULL, color,
gamma, minval, maxval);
else
pixMultiplyByColor(pix2, pix2, NULL, color);
pixaAddPix(pixa, pix2, L_INSERT);
pixd = pixaDisplayTiledInRows(pixa, 32, 800, 1.0, 0, 30, 2);
pixDestroy(&pix1);
pixaDestroy(&pixa);
return pixd;
}
void
CmapEqual(PIXCMAP *cmap1, PIXCMAP *cmap2, l_int32 *pequal)
{
l_int32 n1, n2, i, rval1, gval1, bval1, aval1, rval2, gval2, bval2, aval2;
*pequal = FALSE;
n1 = pixcmapGetCount(cmap1);
n2 = pixcmapGetCount(cmap1);
if (n1 != n2) return;
for (i = 0; i < n1; i++) {
pixcmapGetRGBA(cmap1, i, &rval1, &gval1, &bval1, &aval1);
pixcmapGetRGBA(cmap2, i, &rval2, &gval2, &bval2, &aval2);
if ((rval1 != rval2) || (gval1 != gval2) ||
(bval1 != bval2) || (aval1 != aval2))
return;
}
*pequal = TRUE;
return;
}

View File

@@ -0,0 +1,226 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* alphaxform_reg.c
*
* This tests the alpha blending functions when used with various
* transforms (scaling, rotation, affine, projective, bilinear).
*
* It also tests the version that are wrapped in a gamma transform,
* which is a technique for getting a truer color on transforming,
* because it undoes the gamma that has been applied to an image
* before transforming and then re-applying the gamma transform.
*/
#include "allheaders.h"
static void MakePtas(l_int32 i, l_int32 npts, PTA **pptas, PTA **pptad);
static const l_int32 x1[] = { 300, 300, 300, 95, 32 };
static const l_int32 y1[] = { 1200, 1200, 1250, 2821, 934 };
static const l_int32 x2[] = { 1200, 1200, 1125, 1432, 487 };
static const l_int32 y2[] = { 1100, 1100, 1100, 2682, 934 };
static const l_int32 x3[] = { 200, 200, 200, 232, 32 };
static const l_int32 y3[] = { 200, 200, 200, 657, 67 };
static const l_int32 x4[] = { 1200, 1200, 1125, 1432, 487 };
static const l_int32 y4[] = { 200, 200, 200, 242, 84 };
static const l_int32 xp1[] = { 500, 300, 350, 117, 32 };
static const l_int32 yp1[] = { 1700, 1400, 1100, 2629, 934 };
static const l_int32 xp2[] = { 850, 400, 1100, 1664, 487 };
static const l_int32 yp2[] = { 850, 500, 1300, 2432, 804 };
static const l_int32 xp3[] = { 450, 200, 400, 183, 61 };
static const l_int32 yp3[] = { 300, 300, 400, 490, 83 };
static const l_int32 xp4[] = { 850, 1000, 1100, 1664, 487 };
static const l_int32 yp4[] = { 350, 350, 400, 532, 114 };
int main(int argc,
char **argv)
{
PIX *pixs2, *pixs3, *pixb1, *pixb2, *pixb3;
PIX *pixr2, *pixr3;
PIX *pixc1, *pixc2, *pixc3, *pixcs1, *pixcs2, *pixcs3;
PIX *pixd, *pixt1, *pixt2, *pixt3;
PTA *ptas1, *ptas2, *ptas3, *ptad1, *ptad2, *ptad3;
L_REGPARAMS *rp;
if (regTestSetup(argc, argv, &rp))
return 1;
pixc1 = pixRead("test24.jpg");
pixc2 = pixRead("wyom.jpg");
pixc3 = pixRead("marge.jpg");
/* Test alpha blend scaling */
pixd = pixCreate(900, 400, 32);
pixSetAll(pixd);
pixs2 = pixScaleWithAlpha(pixc2, 0.5, 0.5, NULL, 0.3);
pixs3 = pixScaleWithAlpha(pixc3, 0.4, 0.4, NULL, 0.7);
pixb1 = pixBlendWithGrayMask(pixd, pixs3, NULL, 100, 100);
pixb2 = pixBlendWithGrayMask(pixb1, pixs2, NULL, 300, 130);
pixb3 = pixBlendWithGrayMask(pixb2, pixs3, NULL, 600, 160);
regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 0 */
pixDisplayWithTitle(pixb3, 900, 100, NULL, rp->display);
pixDestroy(&pixd);
pixDestroy(&pixs2);
pixDestroy(&pixs3);
pixDestroy(&pixb1);
pixDestroy(&pixb2);
pixDestroy(&pixb3);
/* Test alpha blend rotation */
pixd = pixCreate(1200, 800, 32);
pixSetAll(pixd);
pixr3 = pixRotateWithAlpha(pixc3, -0.3, NULL, 1.0);
pixr2 = pixRotateWithAlpha(pixc2, +0.3, NULL, 1.0);
pixb3 = pixBlendWithGrayMask(pixd, pixr3, NULL, 100, 100);
pixb2 = pixBlendWithGrayMask(pixb3, pixr2, NULL, 400, 100);
regTestWritePixAndCheck(rp, pixb2, IFF_PNG); /* 1 */
pixDisplayWithTitle(pixb2, 500, 100, NULL, rp->display);
pixDestroy(&pixd);
pixDestroy(&pixr3);
pixDestroy(&pixr2);
pixDestroy(&pixb3);
pixDestroy(&pixb2);
pixcs1 = pixScale(pixc1, 0.35, 0.35);
pixcs2 = pixScale(pixc2, 0.55, 0.55);
pixcs3 = pixScale(pixc3, 0.65, 0.65);
/* Test alpha blend affine */
pixd = pixCreate(800, 900, 32);
pixSetAll(pixd);
MakePtas(2, 3, &ptas1, &ptad1);
MakePtas(4, 3, &ptas2, &ptad2);
MakePtas(3, 3, &ptas3, &ptad3);
pixt1 = pixAffinePtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300);
pixt2 = pixAffinePtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400);
pixt3 = pixAffinePtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 300);
pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -250, 20);
pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -150, -250);
pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220);
regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 2 */
pixDisplayWithTitle(pixb3, 100, 100, NULL, rp->display);
pixDestroy(&pixd);
pixDestroy(&pixb1);
pixDestroy(&pixb2);
pixDestroy(&pixb3);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
ptaDestroy(&ptas1);
ptaDestroy(&ptas2);
ptaDestroy(&ptas3);
ptaDestroy(&ptad1);
ptaDestroy(&ptad2);
ptaDestroy(&ptad3);
/* Test alpha blend projective */
pixd = pixCreate(900, 900, 32);
pixSetAll(pixd);
MakePtas(2, 4, &ptas1, &ptad1);
MakePtas(4, 4, &ptas2, &ptad2);
MakePtas(3, 4, &ptas3, &ptad3);
pixt1 = pixProjectivePtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300);
pixt2 = pixProjectivePtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400);
pixt3 = pixProjectivePtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 400);
pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -150, 20);
pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -50, -250);
pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220);
regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 3 */
pixDisplayWithTitle(pixb3, 300, 100, NULL, rp->display);
pixDestroy(&pixd);
pixDestroy(&pixb1);
pixDestroy(&pixb2);
pixDestroy(&pixb3);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
ptaDestroy(&ptas1);
ptaDestroy(&ptas2);
ptaDestroy(&ptas3);
ptaDestroy(&ptad1);
ptaDestroy(&ptad2);
ptaDestroy(&ptad3);
/* Test alpha blend bilinear */
pixd = pixCreate(900, 900, 32);
pixSetAll(pixd);
MakePtas(2, 4, &ptas1, &ptad1);
MakePtas(4, 4, &ptas2, &ptad2);
MakePtas(3, 4, &ptas3, &ptad3);
pixt1 = pixBilinearPtaWithAlpha(pixcs1, ptad1, ptas1, NULL, 1.0, 300);
pixt2 = pixBilinearPtaWithAlpha(pixcs2, ptad2, ptas2, NULL, 0.8, 400);
pixt3 = pixBilinearPtaWithAlpha(pixcs3, ptad3, ptas3, NULL, 0.7, 400);
pixb1 = pixBlendWithGrayMask(pixd, pixt1, NULL, -150, 20);
pixb2 = pixBlendWithGrayMask(pixb1, pixt2, NULL, -50, -250);
pixb3 = pixBlendWithGrayMask(pixb2, pixt3, NULL, -100, 220);
regTestWritePixAndCheck(rp, pixb3, IFF_PNG); /* 4 */
pixDisplayWithTitle(pixb3, 500, 100, NULL, rp->display);
pixDestroy(&pixd);
pixDestroy(&pixb1);
pixDestroy(&pixb2);
pixDestroy(&pixb3);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
ptaDestroy(&ptas1);
ptaDestroy(&ptas2);
ptaDestroy(&ptas3);
ptaDestroy(&ptad1);
ptaDestroy(&ptad2);
ptaDestroy(&ptad3);
pixDestroy(&pixc1);
pixDestroy(&pixc2);
pixDestroy(&pixc3);
pixDestroy(&pixcs1);
pixDestroy(&pixcs2);
pixDestroy(&pixcs3);
return regTestCleanup(rp);
}
static void
MakePtas(l_int32 i,
l_int32 npts, /* 3 or 4 */
PTA **pptas,
PTA **pptad)
{
*pptas = ptaCreate(npts);
ptaAddPt(*pptas, x1[i], y1[i]);
ptaAddPt(*pptas, x2[i], y2[i]);
ptaAddPt(*pptas, x3[i], y3[i]);
if (npts == 4) ptaAddPt(*pptas, x4[i], y4[i]);
*pptad = ptaCreate(npts);
ptaAddPt(*pptad, xp1[i], yp1[i]);
ptaAddPt(*pptad, xp2[i], yp2[i]);
ptaAddPt(*pptad, xp3[i], yp3[i]);
if (npts == 4) ptaAddPt(*pptad, xp4[i], yp4[i]);
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -0,0 +1,161 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* arabic_lines.c
*
* Demonstrates some segmentation techniques and display options
* To see the results in one image: /tmp/result.png.
*
* Requires gthumb to visualize the results.
*/
#include "allheaders.h"
/* Hit-miss transform that splits lightly touching lines */
static const char *seltext = "xxxxxxx"
" x "
" x "
" x "
" x "
" x "
" x "
" x "
"o X o"
" x "
" x "
" x "
" x "
" x "
" x "
" x "
"xxxxxxx";
int main(int argc,
char **argv)
{
l_int32 w, h, d, w2, h2, i, ncols, ignore;
l_float32 angle, conf;
BOX *box;
BOXA *boxa, *boxa2;
PIX *pix, *pixs, *pixb, *pixb2, *pixd;
PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6;
PIXA *pixam; /* mask with a single component over each column */
PIXA *pixac, *pixad, *pixat;
PIXAA *pixaa, *pixaa2;
SEL *selsplit;
static char mainName[] = "arabic_lines";
if (argc != 1)
return ERROR_INT(" Syntax: arabic_lines", mainName, 1);
pixDisplayWrite(NULL, -1); /* init debug output */
/* Binarize input */
pixs = pixRead("arabic.png");
pixGetDimensions(pixs, &w, &h, &d);
pix = pixConvertTo1(pixs, 128);
/* Deskew */
pixb = pixFindSkewAndDeskew(pix, 1, &angle, &conf);
pixDestroy(&pix);
fprintf(stderr, "Skew angle: %7.2f degrees; %6.2f conf\n", angle, conf);
pixDisplayWrite(pixb, 1);
/* Use full image morphology to find columns, at 2x reduction.
This only works for very simple layouts where each column
of text extends the full height of the input image. */
pixb2 = pixReduceRankBinary2(pixb, 2, NULL);
pix1 = pixMorphCompSequence(pixb2, "c5.500", 0);
boxa = pixConnComp(pix1, &pixam, 8);
ncols = boxaGetCount(boxa);
fprintf(stderr, "Num columns: %d\n", ncols);
pixDisplayWrite(pix1, 1);
/* Use selective region-based morphology to get the textline mask. */
pixad = pixaMorphSequenceByRegion(pixb2, pixam, "c100.3", 0, 0);
pixGetDimensions(pixb2, &w2, &h2, NULL);
pix2 = pixaDisplay(pixad, w2, h2);
pixDisplayWrite(pix2, 1);
pixDestroy(&pix2);
/* Some of the lines may be touching, so use a HMT to split the
lines in each column, and use a pixaa to save the results. */
selsplit = selCreateFromString(seltext, 17, 7, "selsplit");
pixaa = pixaaCreate(ncols);
for (i = 0; i < ncols; i++) {
pix3 = pixaGetPix(pixad, i, L_CLONE);
box = pixaGetBox(pixad, i, L_COPY);
pix4 = pixHMT(NULL, pix3, selsplit);
pixXor(pix4, pix4, pix3);
boxa2 = pixConnComp(pix4, &pixac, 8);
pixaaAddPixa(pixaa, pixac, L_INSERT);
pixaaAddBox(pixaa, box, L_INSERT);
pix5 = pixaDisplayRandomCmap(pixac, 0, 0);
pixDisplayWrite(pix5, 1);
fprintf(stderr, "Num textlines in col %d: %d\n", i,
boxaGetCount(boxa2));
pixDestroy(&pix5);
pixDestroy(&pix3);
pixDestroy(&pix4);
boxaDestroy(&boxa2);
}
/* Visual output */
ignore = system("gthumb /tmp/display/file* &");
pixat = pixaReadFiles("/tmp/display", "file");
pix5 = selDisplayInPix(selsplit, 31, 2);
pixaAddPix(pixat, pix5, L_INSERT);
pix6 = pixaDisplayTiledAndScaled(pixat, 32, 400, 3, 0, 35, 3);
pixWrite("/tmp/result.png", pix6, IFF_PNG);
pixaDestroy(&pixat);
pixDestroy(&pix6);
/* Test pixaa I/O */
pixaaWrite("/tmp/pixaa", pixaa);
pixaa2 = pixaaRead("/tmp/pixaa");
pixaaWrite("/tmp/pixaa2", pixaa2);
/* Test pixaa display */
pixd = pixaaDisplay(pixaa, w2, h2);
pixWrite("/tmp/textlines.png", pixd, IFF_PNG);
pixDestroy(&pixd);
/* Cleanup */
pixDestroy(&pixb2);
pixDestroy(&pix1);
pixaDestroy(&pixam);
pixaDestroy(&pixad);
pixaaDestroy(&pixaa);
pixaaDestroy(&pixaa2);
boxaDestroy(&boxa);
selDestroy(&selsplit);
pixDestroy(&pixs);
pixDestroy(&pixb);
return 0;
}

View File

@@ -0,0 +1,75 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* arithtest.c
*
*/
#include "allheaders.h"
int main(int argc,
char **argv)
{
char *filein;
l_int32 w, h;
PIX *pixs, *pix1, *pix2, *pix3, *pix4, *pix5;
static char mainName[] = "arithtest";
if (argc != 2)
return ERROR_INT(" Syntax: arithtest filein", mainName, 1);
filein = argv[1];
if ((pixs = pixRead(filein)) == NULL)
return ERROR_INT("pix not made", mainName, 1);
/* Input a grayscale image and convert it to 16 bpp */
pixGetDimensions(pixs, &w, &h, NULL);
pix1 = pixInitAccumulate(w, h, 0);
pixAccumulate(pix1, pixs, L_ARITH_ADD);
pixMultConstAccumulate(pix1, 255., 0);
pix2 = pixFinalAccumulate(pix1, 0, 16);
l_pngSetReadStrip16To8(0);
pixWrite("/tmp/pix1.png", pix2, IFF_PNG);
/* Convert it back to 8 bpp, linear mapped */
pix3 = pixMaxDynamicRange(pix2, L_LINEAR_SCALE);
pixWrite("/tmp/pix2.png", pix3, IFF_PNG);
/* Convert it back to 8 bpp using the MSB */
pix4 = pixRead("/tmp/pix1.png");
pix5 = pixConvert16To8(pix4, 1);
pixWrite("/tmp/pix3.png", pix5, IFF_PNG);
pixDestroy(&pixs);
pixDestroy(&pix1);
pixDestroy(&pix2);
pixDestroy(&pix3);
pixDestroy(&pix4);
pixDestroy(&pix5);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,78 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* barcodetest.c
*
* barcodetest filein
*
* For each barcode in the image, if the barcode format is supported,
* this deskews and crops it, and then decodes it twice:
* (1) as is (deskewed)
* (2) after 180 degree rotation
*/
#include "allheaders.h"
#include "readbarcode.h"
int main(int argc,
char **argv)
{
char *filein;
PIX *pixs;
SARRAY *saw1, *saw2, *saw3, *sad1, *sad2, *sad3;
static char mainName[] = "barcodetest";
if (argc != 2)
return ERROR_INT(" Syntax: barcodetest filein", mainName, 1);
filein = argv[1];
if ((pixs = pixRead(filein)) == NULL)
return ERROR_INT("pixs not made", mainName, 1);
sad1 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WIDTHS, &saw1, 0);
sarrayWrite("/tmp/junksaw1", saw1);
sarrayWrite("/tmp/junksad1", sad1);
sarrayDestroy(&saw1);
sarrayDestroy(&sad1);
pixRotate180(pixs, pixs);
sad2 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WIDTHS, &saw2, 0);
sarrayWrite("/tmp/junksaw2", saw2);
sarrayWrite("/tmp/junksad2", sad2);
sarrayDestroy(&saw2);
sarrayDestroy(&sad2);
/* sad3 = pixProcessBarcodes(pixs, L_BF_ANY, L_USE_WINDOW, &saw3, 1);
sarrayWrite("/tmp/junksaw3", saw3);
sarrayWrite("/tmp/junksad3", sad3);
sarrayDestroy(&saw3);
sarrayDestroy(&sad3); */
pixDestroy(&pixs);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -0,0 +1,78 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* baselinetest.c
*
* - e.g., use keystone.png as the input image
* - to get plots of baseline locations and other derived
* parameters, set DEBUG_PLOT to 1 in baseline.c
*/
#include "allheaders.h"
int main(int argc,
char **argv)
{
char *filein, *fileout;
NUMA *na;
PIX *pixs, *pixd;
PTA *pta;
static char mainName[] = "baselinetest";
if (argc != 3)
return ERROR_INT(" Syntax: baselinetest filein fileout", mainName, 1);
filein = argv[1];
fileout = argv[2];
pixs = pixRead(filein);
#if 1
/* Test function for deskewing using projective transform
* on linear approximation for local skew angle */
pixd = pixDeskewLocal(pixs, 10, 0, 0, 0.0, 0.0, 0.0);
pixWrite(fileout, pixd, IFF_TIFF_G4);
/* test baseline finder */
na = pixFindBaselines(pixd, &pta, 1);
/* ptaWriteStream(stderr, pta, 1); */
pixDestroy(&pixd);
numaDestroy(&na);
ptaDestroy(&pta);
#endif
#if 0
/* Test function for finding local skew angles */
na = pixGetLocalSkewAngles(pixs, 10, 0, 0, 0.0, 0.0, 0.0, NULL, NULL);
numaDestroy(&na);
#endif
pixDestroy(&pixs);
return 0;
}

View File

@@ -0,0 +1,132 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* bilateral1_reg.c
*
* Regression test for bilateral (nonlinear) filtering, with both:
* (1) Separable results with full res intermediate images
* (2) Exact results
* This test takes about 30 seconds, so it is not included
* in the alltests_reg set.
*/
#include "allheaders.h"
static void DoTestsOnImage(PIX *pixs, L_REGPARAMS *rp, l_int32 width);
static const l_int32 ncomps = 10;
int main(int argc,
char **argv)
{
PIX *pixs;
L_REGPARAMS *rp;
if (regTestSetup(argc, argv, &rp))
return 1;
pixs = pixRead("rock.png");
DoTestsOnImage(pixs, rp, 2000); /* 0 - 16 */
pixDestroy(&pixs);
pixs = pixRead("church.png");
DoTestsOnImage(pixs, rp, 1500); /* 17 - 33 */
pixDestroy(&pixs);
pixs = pixRead("color-wheel-hue.jpg");
DoTestsOnImage(pixs, rp, 1000); /* 34 - 50 */
pixDestroy(&pixs);
return regTestCleanup(rp);
}
static void
DoTestsOnImage(PIX *pixs,
L_REGPARAMS *rp,
l_int32 width)
{
PIX *pix, *pixd;
PIXA *pixa;
pixa = pixaCreate(0);
pix = pixBilateral(pixs, 5.0, 10.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 5.0, 20.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 5.0, 40.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 5.0, 60.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 10.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 20.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 40.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 60.0, ncomps, 1);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 10.0, ncomps, 2);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 20.0, ncomps, 2);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 40.0, ncomps, 2);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 60.0, ncomps, 2);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBlockBilateralExact(pixs, 10.0, 10.0);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBlockBilateralExact(pixs, 10.0, 20.0);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBlockBilateralExact(pixs, 10.0, 40.0);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBlockBilateralExact(pixs, 10.0, 60.0);
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pixd = pixaDisplayTiledInRows(pixa, 32, width, 1.0, 0, 30, 2);
regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG);
pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
pixDestroy(&pixd);
pixaDestroy(&pixa);
return;
}

View File

@@ -0,0 +1,101 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* bilateral2_reg.c
*
* Regression test for bilateral (nonlinear) filtering.
*
* Separable operation with intermediate images at 4x reduction.
* This speeds the filtering up by about 30x compared to
* separable operation with full resolution intermediate images.
* Using 4x reduction on intermediates, this runs at about
* 3 MPix/sec, with very good quality.
*/
#include "allheaders.h"
static void DoTestsOnImage(PIX *pixs, L_REGPARAMS *rp);
static const l_int32 ncomps = 10;
int main(int argc,
char **argv)
{
PIX *pixs;
L_REGPARAMS *rp;
if (regTestSetup(argc, argv, &rp))
return 1;
pixs = pixRead("test24.jpg");
DoTestsOnImage(pixs, rp); /* 0 - 7 */
pixDestroy(&pixs);
return regTestCleanup(rp);
}
static void
DoTestsOnImage(PIX *pixs,
L_REGPARAMS *rp)
{
PIX *pix, *pixd;
PIXA *pixa;
pixa = pixaCreate(0);
pix = pixBilateral(pixs, 5.0, 10.0, ncomps, 4); /* 0 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 5.0, 20.0, ncomps, 4); /* 1 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 5.0, 40.0, ncomps, 4); /* 2 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 5.0, 60.0, ncomps, 4); /* 3 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 10.0, ncomps, 4); /* 4 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 20.0, ncomps, 4); /* 5 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 40.0, ncomps, 4); /* 6 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pix = pixBilateral(pixs, 10.0, 60.0, ncomps, 4); /* 7 */
regTestWritePixAndCheck(rp, pix, IFF_JFIF_JPEG);
pixaAddPix(pixa, pix, L_INSERT);
pixd = pixaDisplayTiledInRows(pixa, 32, 2500, 1.0, 0, 30, 2);
pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display);
pixDestroy(&pixd);
pixaDestroy(&pixa);
return;
}

View File

@@ -0,0 +1,196 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* bilinear_reg.c
*/
#include "allheaders.h"
static void MakePtas(l_int32 i, PTA **pptas, PTA **pptad);
/* Sample values.
* 1: test with relatively large distortion
* 2-3: invertability tests
*/
static const l_int32 x1[] = { 32, 32, 32};
static const l_int32 y1[] = { 150, 150, 150};
static const l_int32 x2[] = { 520, 520, 520};
static const l_int32 y2[] = { 150, 150, 150};
static const l_int32 x3[] = { 32, 32, 32};
static const l_int32 y3[] = { 612, 612, 612};
static const l_int32 x4[] = { 520, 520, 520};
static const l_int32 y4[] = { 612, 612, 612};
static const l_int32 xp1[] = { 32, 32, 32};
static const l_int32 yp1[] = { 150, 150, 150};
static const l_int32 xp2[] = { 520, 520, 520};
static const l_int32 yp2[] = { 44, 124, 140};
static const l_int32 xp3[] = { 32, 32, 32};
static const l_int32 yp3[] = { 612, 612, 612};
static const l_int32 xp4[] = { 520, 520, 520};
static const l_int32 yp4[] = { 694, 624, 622};
#define ALL 1
#define ADDED_BORDER_PIXELS 500
int main(int argc,
char **argv)
{
l_int32 i;
PIX *pixs, *pixgb, *pixt1, *pixt2, *pixt3, *pixt4, *pixg, *pixd;
PIXA *pixa;
PTA *ptas, *ptad;
static char mainName[] = "bilinear_reg";
if (argc != 1)
return ERROR_INT(" Syntax: bilinear_reg", mainName, 1);
#if 1
pixs = pixRead("feyn.tif");
pixg = pixScaleToGray3(pixs);
#else
pixs = pixRead("marge.jpg");
pixg = pixConvertTo8(pixs, 0);
#endif
#if ALL
/* Test non-invertability of sampling */
pixa = pixaCreate(0);
for (i = 1; i < 3; i++) {
pixgb = pixAddBorder(pixg, ADDED_BORDER_PIXELS, 255);
MakePtas(i, &ptas, &ptad);
pixt1 = pixBilinearSampledPta(pixgb, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt1, pixa, 0.5, 1, 20, 8);
pixt2 = pixBilinearSampledPta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
pixSaveTiled(pixt2, pixa, 0.5, 0, 20, 0);
pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS);
pixInvert(pixd, pixd);
pixXor(pixd, pixd, pixg);
pixSaveTiled(pixd, pixa, 0.5, 0, 20, 0);
if (i == 0) pixWrite("/tmp/junksamp.png", pixt1, IFF_PNG);
pixDestroy(&pixgb);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
}
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/junkbilin1.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 300);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
#endif
#if ALL
/* Test non-invertability of interpolation */
pixa = pixaCreate(0);
for (i = 1; i < 3; i++) {
pixgb = pixAddBorder(pixg, ADDED_BORDER_PIXELS, 255);
MakePtas(i, &ptas, &ptad);
pixt1 = pixBilinearPta(pixgb, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt1, pixa, 0.5, 1, 20, 8);
pixt2 = pixBilinearPta(pixt1, ptas, ptad, L_BRING_IN_WHITE);
pixSaveTiled(pixt2, pixa, 0.5, 0, 20, 0);
pixd = pixRemoveBorder(pixt2, ADDED_BORDER_PIXELS);
pixInvert(pixd, pixd);
pixXor(pixd, pixd, pixg);
pixSaveTiled(pixd, pixa, 0.5, 0, 20, 0);
if (i == 0) pixWrite("/tmp/junkinterp.png", pixt1, IFF_PNG);
pixDestroy(&pixgb);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixd);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
}
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/junkbilin2.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 300);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
#endif
#if ALL /* test with large distortion and inversion */
MakePtas(0, &ptas, &ptad);
pixa = pixaCreate(0);
startTimer();
pixt1 = pixBilinearSampledPta(pixg, ptas, ptad, L_BRING_IN_WHITE);
fprintf(stderr, " Time for pixBilinearSampled(): %6.2f sec\n", stopTimer());
pixSaveTiled(pixt1, pixa, 0.5, 1, 20, 8);
startTimer();
pixt2 = pixBilinearPta(pixg, ptas, ptad, L_BRING_IN_WHITE);
fprintf(stderr, " Time for pixBilinearInterpolated(): %6.2f sec\n",
stopTimer());
pixSaveTiled(pixt2, pixa, 0.5, 0, 20, 8);
pixt3 = pixBilinearSampledPta(pixt1, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt3, pixa, 0.5, 0, 20, 8);
pixt4 = pixBilinearPta(pixt2, ptad, ptas, L_BRING_IN_WHITE);
pixSaveTiled(pixt4, pixa, 0.5, 0, 20, 8);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixt1 = pixaDisplay(pixa, 0, 0);
pixWrite("/tmp/junkbilin3.png", pixt1, IFF_PNG);
pixDisplay(pixt1, 100, 300);
pixDestroy(&pixt1);
pixaDestroy(&pixa);
pixDestroy(&pixs);
pixDestroy(&pixg);
ptaDestroy(&ptas);
ptaDestroy(&ptad);
#endif
return 0;
}
static void
MakePtas(l_int32 i,
PTA **pptas,
PTA **pptad)
{
*pptas = ptaCreate(4);
ptaAddPt(*pptas, x1[i], y1[i]);
ptaAddPt(*pptas, x2[i], y2[i]);
ptaAddPt(*pptas, x3[i], y3[i]);
ptaAddPt(*pptas, x4[i], y4[i]);
*pptad = ptaCreate(4);
ptaAddPt(*pptad, xp1[i], yp1[i]);
ptaAddPt(*pptad, xp2[i], yp2[i]);
ptaAddPt(*pptad, xp3[i], yp3[i]);
ptaAddPt(*pptad, xp4[i], yp4[i]);
return;
}

View File

@@ -0,0 +1,179 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binarize_reg.c
*
* Tests Sauvola local binarization and variants
*/
#include "allheaders.h"
PIX *PixTest1(PIX *pixs, l_int32 size, l_float32 factor, L_REGPARAMS *rp);
PIX *PixTest2(PIX *pixs, l_int32 size, l_float32 factor, l_int32 nx,
l_int32 ny, L_REGPARAMS *rp);
void PixTest3(PIX *pixs, l_int32 size, l_float32 factor,
l_int32 nx, l_int32 ny, l_int32 paircount, L_REGPARAMS *rp);
int main(int argc,
char **argv)
{
PIX *pixs, *pixt1, *pixt2;
L_REGPARAMS *rp;
if (regTestSetup(argc, argv, &rp))
return 1;
pixs = pixRead("w91frag.jpg");
PixTest3(pixs, 3, 0.20, 2, 3, 0, rp);
PixTest3(pixs, 6, 0.20, 100, 100, 1, rp);
PixTest3(pixs, 10, 0.40, 10, 10, 2, rp);
PixTest3(pixs, 10, 0.40, 20, 20, 3, rp);
PixTest3(pixs, 20, 0.34, 30, 30, 4, rp);
pixt1 = PixTest1(pixs, 7, 0.34, rp);
pixt2 = PixTest2(pixs, 7, 0.34, 4, 4, rp);
regTestComparePix(rp, pixt1, pixt2);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
/* Do combination of contrast norm and sauvola */
pixt1 = pixContrastNorm(NULL, pixs, 100, 100, 55, 1, 1);
pixSauvolaBinarizeTiled(pixt1, 8, 0.34, 1, 1, NULL, &pixt2);
regTestWritePixAndCheck(rp, pixt1, IFF_PNG);
regTestWritePixAndCheck(rp, pixt2, IFF_PNG);
pixDisplayWithTitle(pixt1, 100, 500, NULL, rp->display);
pixDisplayWithTitle(pixt2, 700, 500, NULL, rp->display);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixs);
return regTestCleanup(rp);
}
PIX *
PixTest1(PIX *pixs,
l_int32 size,
l_float32 factor,
L_REGPARAMS *rp)
{
l_int32 w, h;
PIX *pixm, *pixsd, *pixth, *pixd, *pixt;
PIXA *pixa;
pixm = pixsd = pixth = pixd = NULL;
pixGetDimensions(pixs, &w, &h, NULL);
/* Get speed */
startTimer();
pixSauvolaBinarize(pixs, size, factor, 1, NULL, NULL, NULL, &pixd);
fprintf(stderr, "\nSpeed: 1 tile, %7.3f Mpix/sec\n",
(w * h / 1000000.) / stopTimer());
pixDestroy(&pixd);
/* Get results */
pixSauvolaBinarize(pixs, size, factor, 1, &pixm, &pixsd, &pixth, &pixd);
pixa = pixaCreate(0);
pixSaveTiled(pixm, pixa, 1.0, 1, 30, 8);
pixSaveTiled(pixsd, pixa, 1.0, 0, 30, 8);
pixSaveTiled(pixth, pixa, 1.0, 1, 30, 8);
pixSaveTiled(pixd, pixa, 1.0, 0, 30, 8);
pixt = pixaDisplay(pixa, 0, 0);
regTestWritePixAndCheck(rp, pixt, IFF_JFIF_JPEG);
if (rp->index < 5)
pixDisplayWithTitle(pixt, 100, 100, NULL, rp->display);
regTestWritePixAndCheck(rp, pixd, IFF_PNG);
pixaDestroy(&pixa);
pixDestroy(&pixm);
pixDestroy(&pixsd);
pixDestroy(&pixth);
pixDestroy(&pixt);
return pixd;
}
PIX *
PixTest2(PIX *pixs,
l_int32 size,
l_float32 factor,
l_int32 nx,
l_int32 ny,
L_REGPARAMS *rp)
{
l_int32 w, h;
PIX *pixth, *pixd, *pixt;
PIXA *pixa;
pixth = pixd = NULL;
pixGetDimensions(pixs, &w, &h, NULL);
/* Get speed */
startTimer();
pixSauvolaBinarizeTiled(pixs, size, factor, nx, ny, NULL, &pixd);
fprintf(stderr, "Speed: %d x %d tiles, %7.3f Mpix/sec\n",
nx, ny, (w * h / 1000000.) / stopTimer());
pixDestroy(&pixd);
/* Get results */
pixSauvolaBinarizeTiled(pixs, size, factor, nx, ny, &pixth, &pixd);
regTestWritePixAndCheck(rp, pixth, IFF_JFIF_JPEG);
regTestWritePixAndCheck(rp, pixd, IFF_PNG);
if (rp->index < 5 && rp->display) {
pixa = pixaCreate(0);
pixSaveTiled(pixth, pixa, 1.0, 1, 30, 8);
pixSaveTiled(pixd, pixa, 1.0, 0, 30, 8);
pixt = pixaDisplay(pixa, 0, 0);
pixDisplayWithTitle(pixt, 100, 400, NULL, rp->display);
pixDestroy(&pixt);
pixaDestroy(&pixa);
}
pixDestroy(&pixth);
return pixd;
}
void
PixTest3(PIX *pixs,
l_int32 size,
l_float32 factor,
l_int32 nx,
l_int32 ny,
l_int32 paircount,
L_REGPARAMS *rp)
{
PIX *pixt1, *pixt2;
pixt1 = PixTest1(pixs, size, factor, rp);
pixt2 = PixTest2(pixs, size, factor, nx, ny, rp);
regTestComparePix(rp, pixt1, pixt2);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
return;
}

View File

@@ -0,0 +1,178 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binarize_set.c
*
* Does 5 different types of binarization for the contest.
*
* Method 1. Using local background normalization, followed by
* a global threshold.
* Method 2. Using local background normalization, followed by
* Otsu on the result to get a global threshold that
* can be applied to the normalized image.
* Method 3. Using local background normalization with two different
* thresholds. For the part of the image near the text,
* a high threshold can be chosen, to render the text
* fully in black. For the rest of the image,
* much of which is background, use a threshold based on
* the Otsu global value of the original image.
* Method 4. Background normalization followed by Sauvola binarization.
* Method 5. Contrast normalization followed by background normalization
* and thresholding.
*
* The first 3 were submitted to a binarization contest associated
* with ICDAR in 2009. The 4th and 5th work better for difficult
* images, such as w91frag.jpg.
*/
#include "allheaders.h"
#define ALL 1
int main(int argc,
char **argv)
{
char *infile;
l_int32 w, d, i, threshval, ival, newval;
l_uint32 val;
PIX *pixs, *pixg, *pixg2;
PIX *pix1, *pix2;
PIXA *pixa;
static char mainName[] = "binarize_set";
if (argc != 2)
return ERROR_INT(" Syntax: binarize_set infile", mainName, 1);
infile = argv[1];
pixa = pixaCreate(5);
pixs = pixRead(infile);
pixGetDimensions(pixs, &w, NULL, &d);
pixSaveTiled(pixs, pixa, 1.0, 1, 50, 32);
pixDisplay(pixs, 100, 0);
#if ALL
/* 1. Standard background normalization with a global threshold. */
pixg = pixConvertTo8(pixs, 0);
pix1 = pixBackgroundNorm(pixg, NULL, NULL, 10, 15, 100, 50, 255, 2, 2);
pix2 = pixThresholdToBinary(pix1, 160);
pixWrite("/tmp/binar1.png", pix2, IFF_PNG);
pixDisplay(pix2, 100, 0);
pixSaveTiled(pix2, pixa, 1.0, 1, 50, 32);
pixDestroy(&pixg);
pixDestroy(&pix1);
pixDestroy(&pix2);
#endif
#if ALL
/* 2. Background normalization followed by Otsu thresholding. Otsu
* binarization attempts to split the image into two roughly equal
* sets of pixels, and it does a very poor job when there are large
* amounts of dark background. By doing a background normalization
* first (to get the background near 255), we remove this problem.
* Then we use a modified Otsu to estimate the best global
* threshold on the normalized image. */
pixg = pixConvertTo8(pixs, 0);
pix1 = pixOtsuThreshOnBackgroundNorm(pixg, NULL, 10, 15, 100,
50, 255, 2, 2, 0.10, &threshval);
fprintf(stderr, "thresh val = %d\n", threshval);
pixSaveTiled(pix1, pixa, 1.0, 1, 50, 32);
pixWrite("/tmp/binar2.png", pix1, IFF_PNG);
pixDisplay(pix1, 100, 200);
pixDestroy(&pixg);
pixDestroy(&pix1);
#endif
#if ALL
/* 3. Background normalization with Otsu threshold estimation and
* masking for threshold selection. */
pixg = pixConvertTo8(pixs, 0);
pix1 = pixMaskedThreshOnBackgroundNorm(pixg, NULL, 10, 15, 100,
50, 2, 2, 0.10, &threshval);
fprintf(stderr, "thresh val = %d\n", threshval);
pixSaveTiled(pix1, pixa, 1.0, 1, 50, 32);
pixWrite("/tmp/binar3.png", pix1, IFF_PNG);
pixDisplay(pix1, 100, 400);
pixDestroy(&pixg);
pixDestroy(&pix1);
#endif
#if ALL
/* 4. Background normalization followed by Sauvola binarization */
if (d == 32)
pixg = pixConvertRGBToGray(pixs, 0.2, 0.7, 0.1);
else
pixg = pixConvertTo8(pixs, 0);
pixg2 = pixContrastNorm(NULL, pixg, 20, 20, 130, 2, 2);
pixSauvolaBinarizeTiled(pixg2, 25, 0.40, 1, 1, NULL, &pix1);
pixSaveTiled(pix1, pixa, 1.0, 1, 50, 32);
pixWrite("/tmp/binar4.png", pix1, IFF_PNG);
pixDisplay(pix1, 100, 600);
pixDestroy(&pixg);
pixDestroy(&pixg2);
pixDestroy(&pix1);
#endif
#if ALL
/* 5. Contrast normalization followed by background normalization, and
* thresholding. */
if (d == 32)
pixg = pixConvertRGBToGray(pixs, 0.2, 0.7, 0.1);
else
pixg = pixConvertTo8(pixs, 0);
pixOtsuAdaptiveThreshold(pixg, 5000, 5000, 0, 0, 0.1, &pix1, NULL);
pixGetPixel(pix1, 0, 0, &val);
ival = (l_int32)val;
newval = ival + (l_int32)(0.6 * (110 - ival));
fprintf(stderr, "th1 = %d, th2 = %d\n", ival, newval);
pixDestroy(&pix1);
pixContrastNorm(pixg, pixg, 50, 50, 130, 2, 2);
pixg2 = pixBackgroundNorm(pixg, NULL, NULL, 20, 20, 70, 40, 200, 2, 2);
ival = L_MIN(ival, 110);
pix1 = pixThresholdToBinary(pixg2, ival);
pixSaveTiled(pix1, pixa, 1.0, 1, 50, 32);
pixWrite("/tmp/binar5.png", pix1, IFF_PNG);
pixDisplay(pix1, 100, 800);
pixDestroy(&pixg);
pixDestroy(&pixg2);
pixDestroy(&pix1);
#endif
pix1 = pixaDisplayTiledInRows(pixa, 32, w + 100, 1.0, 0, 30, 2);
pixWrite("/tmp/binar6.png", pix1, IFF_PNG);
pixDisplay(pix1, 1000, 0);
pixDestroy(&pix1);
pixaDestroy(&pixa);
pixDestroy(&pixs);
return 0;
}

View File

@@ -0,0 +1,115 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binarizefiles.c
*
* Program that optionally scales and then binarizes a set of files,
* writing them to the specified directory in tiff-g4 format.
* The resolution is preserved.
*/
#include "string.h"
#include <sys/stat.h>
#include <sys/types.h>
#include "allheaders.h"
l_int32 main(int argc,
char **argv)
{
char buf[256], dirname[256];
char *dirin, *pattern, *subdirout, *fname, *tail, *basename;
l_int32 thresh, i, n;
l_float32 scalefactor;
PIX *pix1, *pix2, *pix3, *pix4;
SARRAY *sa;
static char mainName[] = "binarizefiles.c";
if (argc != 6) {
fprintf(stderr,
"Syntax: binarizefiles dirin pattern thresh scalefact dirout\n"
" dirin: input directory for image files\n"
" pattern: use 'allfiles' to convert all files\n"
" in the directory\n"
" thresh: 0 for adaptive; > 0 for global thresh (e.g., 128)\n"
" scalefactor: in (0.0 ... 4.0]; use 1.0 to prevent scaling\n"
" subdirout: subdirectory of /tmp for output files\n");
return 1;
}
dirin = argv[1];
pattern = argv[2];
thresh = atoi(argv[3]);
scalefactor = atof(argv[4]);
subdirout = argv[5];
if (!strcmp(pattern, "allfiles"))
pattern = NULL;
if (scalefactor <= 0.0 || scalefactor > 4.0) {
L_WARNING("invalid scalefactor: setting to 1.0\n", mainName);
scalefactor = 1.0;
}
/* Get the input filenames */
sa = getSortedPathnamesInDirectory(dirin, pattern, 0, 0);
sarrayWriteStream(stderr, sa);
n = sarrayGetCount(sa);
/* Write the output files */
makeTempDirname(dirname, 256, subdirout);
fprintf(stderr, "dirname: %s\n", dirname);
lept_mkdir(subdirout);
for (i = 0; i < n; i++) {
fname = sarrayGetString(sa, i, L_NOCOPY);
if ((pix1 = pixRead(fname)) == NULL) {
L_ERROR("file %s not read as image", mainName, fname);
continue;
}
splitPathAtDirectory(fname, NULL, &tail);
splitPathAtExtension(tail, &basename, NULL);
snprintf(buf, sizeof(buf), "%s/%s.tif", dirname, basename);
FREE(tail);
FREE(basename);
fprintf(stderr, "fileout: %s\n", buf);
if (scalefactor != 1.0)
pix2 = pixScale(pix1, scalefactor, scalefactor);
else
pix2 = pixClone(pix1);
if (thresh == 0) {
pix4 = pixConvertTo8(pix2, 0);
pix3 = pixAdaptThresholdToBinary(pix4, NULL, 1.0);
pixDestroy(&pix4);
} else {
pix3 = pixConvertTo1(pix2, thresh);
}
pixWrite(buf, pix3, IFF_TIFF_G4);
pixDestroy(&pix1);
pixDestroy(&pix2);
pixDestroy(&pix3);
}
sarrayDestroy(&sa);
return 0;
}

View File

@@ -0,0 +1,93 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* bincompare.c
*
* Bitwise comparison of two binary images
*/
#include "allheaders.h"
/* set one of these to 1 */
#define XOR 1
#define SUBTRACT_1_FROM_2 0
#define SUBTRACT_2_FROM_1 0
int main(int argc,
char **argv)
{
l_int32 w, h, d, n;
char *filein1, *filein2, *fileout;
PIX *pixs1, *pixs2;
static char mainName[] = "bincompare";
if (argc != 4)
return ERROR_INT(" Syntax: bincompare filein1 filein2 fileout",
mainName, 1);
filein1 = argv[1];
filein2 = argv[2];
fileout = argv[3];
if ((pixs1 = pixRead(filein1)) == NULL)
return ERROR_INT("pixs1 not made", mainName, 1);
if ((pixs2 = pixRead(filein2)) == NULL)
return ERROR_INT("pixs2 not made", mainName, 1);
pixGetDimensions(pixs1, &w, &h, &d);
if (d != 1)
return ERROR_INT("pixs1 not binary", mainName, 1);
pixCountPixels(pixs1, &n, NULL);
fprintf(stderr, "Number of fg pixels in file1 = %d\n", n);
pixCountPixels(pixs2, &n, NULL);
fprintf(stderr, "Number of fg pixels in file2 = %d\n", n);
#if XOR
fprintf(stderr, "xor: 1 ^ 2\n");
pixRasterop(pixs1, 0, 0, w, h, PIX_SRC ^ PIX_DST, pixs2, 0, 0);
pixCountPixels(pixs1, &n, NULL);
fprintf(stderr, "Number of fg pixels in XOR = %d\n", n);
pixWrite(fileout, pixs1, IFF_PNG);
#elif SUBTRACT_1_FROM_2
fprintf(stderr, "subtract: 2 - 1\n");
pixRasterop(pixs1, 0, 0, w, h, PIX_SRC & PIX_NOT(PIX_DST), pixs2, 0, 0);
pixCountPixels(pixs1, &n, NULL);
fprintf(stderr, "Number of fg pixels in 2 - 1 = %d\n", n);
pixWrite(fileout, pixs1, IFF_PNG);
#elif SUBTRACT_2_FROM_1
fprintf(stderr, "subtract: 1 - 2\n");
pixRasterop(pixs1, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC), pixs2, 0, 0);
pixCountPixels(pixs1, &n, NULL);
fprintf(stderr, "Number of fg pixels in 1 - 2 = %d\n", n);
pixWrite(fileout, pixs1, IFF_PNG);
#else
fprintf(stderr, "no comparison selected\n");
#endif
return 0;
}

View File

@@ -0,0 +1,570 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binmorph1_reg.c
*
* This is a thorough regression test of different methods for
* doing binary morphology. It should always be run if changes
* are made to the low-level morphology code.
*
* Some things to note:
*
* (1) We add a white border to guarantee safe closing; i.e., that
* closing is extensive for ASYMMETRIC_MORPH_BC. The separable
* sequence for closing is not safe, so if we didn't add the border
* ab initio, we would get different results for the atomic sequence
* closing (which is safe) and the separable one.
*
* (2) There are no differences in any of the operations:
* rasterop general
* rasterop brick
* morph sequence rasterop brick
* dwa brick
* morph sequence dwa brick
* morph sequence dwa composite brick
* when using ASYMMETRIC_MORPH_BC.
* However, when using SYMMETRIC_MORPH_BC, there are differences
* in two of the safe closing operations. These differences
* are in pix numbers 4 and 5. These differences are
* all due to the fact that for SYMMETRIC_MORPH_BC, we don't need
* to add any borders to get the correct answer. When we do
* add a border of 0 pixels, we naturally get a different result.
*
* (3) The 2-way Sel decomposition functions, implemented with the
* separable brick interface, are tested separately against
* the rasterop brick. See binmorph2_reg.c.
*/
#include "allheaders.h"
/* set these ad lib. */
#define WIDTH 21 /* brick sel width */
#define HEIGHT 15 /* brick sel height */
#define TEST_SYMMETRIC 0 /* set to 1 to set symmetric b.c.;
otherwise, it tests asymmetric b.c. */
int main(int argc,
char **argv)
{
l_int32 ok, same;
char sequence[512];
PIX *pixs, *pixref;
PIX *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
PIX *pixt7, *pixt8, *pixt9, *pixt10, *pixt11;
PIX *pixt12, *pixt13, *pixt14;
SEL *sel;
static char mainName[] = "binmorph1_reg";
if (argc != 1)
return ERROR_INT(" Syntax: binmorph1_reg", mainName, 1);
if ((pixs = pixRead("feyn.tif")) == NULL)
return ERROR_INT("pix not made", mainName, 1);
#if TEST_SYMMETRIC
/* This works properly if there is an added border */
resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC);
#if 1
pixt1 = pixAddBorder(pixs, 32, 0);
pixTransferAllData(pixs, &pixt1, 0, 0);
#endif
#endif /* TEST_SYMMETRIC */
/* This is our test sel */
sel = selCreateBrick(HEIGHT, WIDTH, HEIGHT / 2, WIDTH / 2, SEL_HIT);
/* Dilation */
fprintf(stderr, "Testing dilation\n");
ok = TRUE;
pixref = pixDilate(NULL, pixs, sel); /* new one */
pixt1 = pixCreateTemplate(pixs);
pixDilate(pixt1, pixs, sel); /* existing one */
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixt2 = pixCopy(NULL, pixs);
pixDilate(pixt2, pixt2, sel); /* in-place */
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
sprintf(sequence, "d%d.%d", WIDTH, HEIGHT);
pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */
pixEqual(pixref, pixt3, &same);
if (!same) {
fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE;
}
sprintf(sequence, "d%d.1 + d1.%d", WIDTH, HEIGHT);
pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixt5 = pixDilateBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt5, &same);
if (!same) {
fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE;
}
pixt6 = pixCreateTemplate(pixs);
pixDilateBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt6, &same);
if (!same) {
fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE;
}
pixt7 = pixCopy(NULL, pixs);
pixDilateBrick(pixt7, pixt7, WIDTH, HEIGHT); /* in-place */
pixEqual(pixref, pixt7, &same);
if (!same) {
fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE;
}
pixt8 = pixDilateBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt8, &same);
if (!same) {
fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE;
}
pixt9 = pixCreateTemplate(pixs);
pixDilateBrickDwa(pixt9, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt9, &same);
if (!same) {
fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE;
}
pixt10 = pixCopy(NULL, pixs);
pixDilateBrickDwa(pixt10, pixt10, WIDTH, HEIGHT); /* in-place */
pixEqual(pixref, pixt10, &same);
if (!same) {
fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE;
}
pixt11 = pixCreateTemplate(pixs);
pixDilateCompBrickDwa(pixt11, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt11, &same);
if (!same) {
fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE;
}
sprintf(sequence, "d%d.%d", WIDTH, HEIGHT);
pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */
pixEqual(pixref, pixt12, &same);
if (!same) {
fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE;
}
pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */
pixEqual(pixref, pixt13, &same);
if (!same) {
fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
pixDestroy(&pixt7);
pixDestroy(&pixt8);
pixDestroy(&pixt9);
pixDestroy(&pixt10);
pixDestroy(&pixt11);
pixDestroy(&pixt12);
pixDestroy(&pixt13);
/* Erosion */
fprintf(stderr, "Testing erosion\n");
pixref = pixErode(NULL, pixs, sel); /* new one */
pixt1 = pixCreateTemplate(pixs);
pixErode(pixt1, pixs, sel); /* existing one */
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixt2 = pixCopy(NULL, pixs);
pixErode(pixt2, pixt2, sel); /* in-place */
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
sprintf(sequence, "e%d.%d", WIDTH, HEIGHT);
pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */
pixEqual(pixref, pixt3, &same);
if (!same) {
fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE;
}
sprintf(sequence, "e%d.1 + e1.%d", WIDTH, HEIGHT);
pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixt5 = pixErodeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt5, &same);
if (!same) {
fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE;
}
pixt6 = pixCreateTemplate(pixs);
pixErodeBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt6, &same);
if (!same) {
fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE;
}
pixt7 = pixCopy(NULL, pixs);
pixErodeBrick(pixt7, pixt7, WIDTH, HEIGHT); /* in-place */
pixEqual(pixref, pixt7, &same);
if (!same) {
fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE;
}
pixt8 = pixErodeBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt8, &same);
if (!same) {
fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE;
}
pixt9 = pixCreateTemplate(pixs);
pixErodeBrickDwa(pixt9, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt9, &same);
if (!same) {
fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE;
}
pixt10 = pixCopy(NULL, pixs);
pixErodeBrickDwa(pixt10, pixt10, WIDTH, HEIGHT); /* in-place */
pixEqual(pixref, pixt10, &same);
if (!same) {
fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE;
}
pixt11 = pixCreateTemplate(pixs);
pixErodeCompBrickDwa(pixt11, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt11, &same);
if (!same) {
fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE;
}
sprintf(sequence, "e%d.%d", WIDTH, HEIGHT);
pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */
pixEqual(pixref, pixt12, &same);
if (!same) {
fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE;
}
pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */
pixEqual(pixref, pixt13, &same);
if (!same) {
fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
pixDestroy(&pixt7);
pixDestroy(&pixt8);
pixDestroy(&pixt9);
pixDestroy(&pixt10);
pixDestroy(&pixt11);
pixDestroy(&pixt12);
pixDestroy(&pixt13);
/* Opening */
fprintf(stderr, "Testing opening\n");
pixref = pixOpen(NULL, pixs, sel); /* new one */
pixt1 = pixCreateTemplate(pixs);
pixOpen(pixt1, pixs, sel); /* existing one */
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixt2 = pixCopy(NULL, pixs);
pixOpen(pixt2, pixt2, sel); /* in-place */
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
sprintf(sequence, "o%d.%d", WIDTH, HEIGHT);
pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */
pixEqual(pixref, pixt3, &same);
if (!same) {
fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE;
}
sprintf(sequence, "e%d.%d + d%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT);
pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
sprintf(sequence, "e%d.1 + e1.%d + d%d.1 + d1.%d", WIDTH, HEIGHT,
WIDTH, HEIGHT);
pixt5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */
pixEqual(pixref, pixt5, &same);
if (!same) {
fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE;
}
pixt6 = pixOpenBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt6, &same);
if (!same) {
fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE;
}
pixt7 = pixCreateTemplate(pixs);
pixOpenBrick(pixt7, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt7, &same);
if (!same) {
fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE;
}
pixt8 = pixCopy(NULL, pixs); /* in-place */
pixOpenBrick(pixt8, pixt8, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt8, &same);
if (!same) {
fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE;
}
pixt9 = pixOpenBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt9, &same);
if (!same) {
fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE;
}
pixt10 = pixCreateTemplate(pixs);
pixOpenBrickDwa(pixt10, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt10, &same);
if (!same) {
fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE;
}
pixt11 = pixCopy(NULL, pixs);
pixOpenBrickDwa(pixt11, pixt11, WIDTH, HEIGHT); /* in-place */
pixEqual(pixref, pixt11, &same);
if (!same) {
fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE;
}
sprintf(sequence, "o%d.%d", WIDTH, HEIGHT);
pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */
pixEqual(pixref, pixt12, &same);
if (!same) {
fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE;
}
#if 0
pixWrite("/tmp/junkref.png", pixref, IFF_PNG);
pixWrite("/tmp/junk12.png", pixt12, IFF_PNG);
pixt13 = pixXor(NULL, pixref, pixt12);
pixWrite("/tmp/junk12a.png", pixt13, IFF_PNG);
pixDestroy(&pixt13);
#endif
pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */
pixEqual(pixref, pixt13, &same);
if (!same) {
fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE;
}
pixt14 = pixCreateTemplate(pixs);
pixOpenCompBrickDwa(pixt14, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt14, &same);
if (!same) {
fprintf(stderr, "pixref != pixt14 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
pixDestroy(&pixt7);
pixDestroy(&pixt8);
pixDestroy(&pixt9);
pixDestroy(&pixt10);
pixDestroy(&pixt11);
pixDestroy(&pixt12);
pixDestroy(&pixt13);
pixDestroy(&pixt14);
/* Closing */
fprintf(stderr, "Testing closing\n");
pixref = pixClose(NULL, pixs, sel); /* new one */
pixt1 = pixCreateTemplate(pixs);
pixClose(pixt1, pixs, sel); /* existing one */
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixt2 = pixCopy(NULL, pixs);
pixClose(pixt2, pixt2, sel); /* in-place */
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
sprintf(sequence, "d%d.%d + e%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT);
pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */
pixEqual(pixref, pixt3, &same);
if (!same) {
fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE;
}
sprintf(sequence, "d%d.1 + d1.%d + e%d.1 + e1.%d", WIDTH, HEIGHT,
WIDTH, HEIGHT);
pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixt5 = pixCloseBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt5, &same);
if (!same) {
fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE;
}
pixt6 = pixCreateTemplate(pixs);
pixCloseBrick(pixt6, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt6, &same);
if (!same) {
fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE;
}
pixt7 = pixCopy(NULL, pixs); /* in-place */
pixCloseBrick(pixt7, pixt7, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt7, &same);
if (!same) {
fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
pixDestroy(&pixt7);
/* Safe closing (using pix, not pixs) */
fprintf(stderr, "Testing safe closing\n");
pixref = pixCloseSafe(NULL, pixs, sel); /* new one */
pixt1 = pixCreateTemplate(pixs);
pixCloseSafe(pixt1, pixs, sel); /* existing one */
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixt2 = pixCopy(NULL, pixs);
pixCloseSafe(pixt2, pixt2, sel); /* in-place */
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
sprintf(sequence, "c%d.%d", WIDTH, HEIGHT);
pixt3 = pixMorphSequence(pixs, sequence, 0); /* sequence, atomic */
pixEqual(pixref, pixt3, &same);
if (!same) {
fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE;
}
sprintf(sequence, "b32 + d%d.%d + e%d.%d", WIDTH, HEIGHT, WIDTH, HEIGHT);
pixt4 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable */
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
sprintf(sequence, "b32 + d%d.1 + d1.%d + e%d.1 + e1.%d", WIDTH, HEIGHT,
WIDTH, HEIGHT);
pixt5 = pixMorphSequence(pixs, sequence, 0); /* sequence, separable^2 */
pixEqual(pixref, pixt5, &same);
if (!same) {
fprintf(stderr, "pixref != pixt5 !\n"); ok = FALSE;
}
pixt6 = pixCloseSafeBrick(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt6, &same);
if (!same) {
fprintf(stderr, "pixref != pixt6 !\n"); ok = FALSE;
}
pixt7 = pixCreateTemplate(pixs);
pixCloseSafeBrick(pixt7, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt7, &same);
if (!same) {
fprintf(stderr, "pixref != pixt7 !\n"); ok = FALSE;
}
pixt8 = pixCopy(NULL, pixs); /* in-place */
pixCloseSafeBrick(pixt8, pixt8, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt8, &same);
if (!same) {
fprintf(stderr, "pixref != pixt8 !\n"); ok = FALSE;
}
pixt9 = pixCloseBrickDwa(NULL, pixs, WIDTH, HEIGHT); /* new one */
pixEqual(pixref, pixt9, &same);
if (!same) {
fprintf(stderr, "pixref != pixt9 !\n"); ok = FALSE;
}
pixt10 = pixCreateTemplate(pixs);
pixCloseBrickDwa(pixt10, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt10, &same);
if (!same) {
fprintf(stderr, "pixref != pixt10 !\n"); ok = FALSE;
}
pixt11 = pixCopy(NULL, pixs);
pixCloseBrickDwa(pixt11, pixt11, WIDTH, HEIGHT); /* in-place */
pixEqual(pixref, pixt11, &same);
if (!same) {
fprintf(stderr, "pixref != pixt11 !\n"); ok = FALSE;
}
sprintf(sequence, "c%d.%d", WIDTH, HEIGHT);
pixt12 = pixMorphCompSequence(pixs, sequence, 0); /* comp sequence */
pixEqual(pixref, pixt12, &same);
if (!same) {
fprintf(stderr, "pixref != pixt12!\n"); ok = FALSE;
}
pixt13 = pixMorphSequenceDwa(pixs, sequence, 0); /* dwa sequence */
pixEqual(pixref, pixt13, &same);
if (!same) {
fprintf(stderr, "pixref != pixt13!\n"); ok = FALSE;
}
pixt14 = pixCreateTemplate(pixs);
pixCloseCompBrickDwa(pixt14, pixs, WIDTH, HEIGHT); /* existing one */
pixEqual(pixref, pixt14, &same);
if (!same) {
fprintf(stderr, "pixref != pixt14 !\n"); ok = FALSE;
}
#if 0
pixWrite("/tmp/junkref.png", pixref, IFF_PNG);
pixWrite("/tmp/junk12.png", pixt12, IFF_PNG);
pixt13 = pixXor(NULL, pixref, pixt12);
pixWrite("/tmp/junk12a.png", pixt13, IFF_PNG);
pixDestroy(&pixt13);
#endif
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
pixDestroy(&pixt7);
pixDestroy(&pixt8);
pixDestroy(&pixt9);
pixDestroy(&pixt10);
pixDestroy(&pixt11);
pixDestroy(&pixt12);
pixDestroy(&pixt13);
pixDestroy(&pixt14);
if (ok)
fprintf(stderr, "All morph tests OK!\n");
pixDestroy(&pixs);
selDestroy(&sel);
return 0;
}

View File

@@ -0,0 +1,228 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binmorph2_reg.c
*
* Thorough regression test for binary separable rasterops,
* using the sequence interpreters. This compares the
* results for 2-way composite Sels with unitary Sels,
* all invoked on the separable block morph ops.
*/
#include "allheaders.h"
static const l_int32 MAX_SEL_SIZE = 120;
static void writeResult(char *sequence, l_int32 same);
int main(int argc,
char **argv)
{
char *str;
char buffer1[256];
char buffer2[256];
l_int32 i, same, same2, factor1, factor2, diff, success;
PIX *pixs, *pixsd, *pixt1, *pixt2, *pixt3;
SEL *sel1, *sel2;
static char mainName[] = "binmorph2_reg";
if (argc != 1)
return ERROR_INT(" Syntax: binmorph2_reg", mainName, 1);
#if 1
pixs = pixRead("rabi.png");
pixsd = pixMorphCompSequence(pixs, "d5.5", 0);
success = TRUE;
for (i = 1; i < MAX_SEL_SIZE; i++) {
/* Check if the size is exactly decomposable */
selectComposableSizes(i, &factor1, &factor2);
diff = factor1 * factor2 - i;
fprintf(stderr, "%d: (%d, %d): %d\n", i, factor1, factor2, diff);
/* Carry out operations on identical sized Sels: dilation */
sprintf(buffer1, "d%d.%d", i + diff, i + diff);
sprintf(buffer2, "d%d.%d", i, i);
pixt1 = pixMorphSequence(pixsd, buffer1, 0);
pixt2 = pixMorphCompSequence(pixsd, buffer2, 0);
pixEqual(pixt1, pixt2, &same);
if (i < 64) {
pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0);
pixEqual(pixt1, pixt3, &same2);
} else {
pixt3 = NULL;
same2 = TRUE;
}
if (same && same2)
writeResult(buffer1, 1);
else {
writeResult(buffer1, 0);
success = FALSE;
}
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
/* ... erosion */
sprintf(buffer1, "e%d.%d", i + diff, i + diff);
sprintf(buffer2, "e%d.%d", i, i);
pixt1 = pixMorphSequence(pixsd, buffer1, 0);
pixt2 = pixMorphCompSequence(pixsd, buffer2, 0);
pixEqual(pixt1, pixt2, &same);
if (i < 64) {
pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0);
pixEqual(pixt1, pixt3, &same2);
} else {
pixt3 = NULL;
same2 = TRUE;
}
if (same && same2)
writeResult(buffer1, 1);
else {
writeResult(buffer1, 0);
success = FALSE;
}
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
/* ... opening */
sprintf(buffer1, "o%d.%d", i + diff, i + diff);
sprintf(buffer2, "o%d.%d", i, i);
pixt1 = pixMorphSequence(pixsd, buffer1, 0);
pixt2 = pixMorphCompSequence(pixsd, buffer2, 0);
pixEqual(pixt1, pixt2, &same);
if (i < 64) {
pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0);
pixEqual(pixt1, pixt3, &same2);
} else {
pixt3 = NULL;
same2 = TRUE;
}
if (same && same2)
writeResult(buffer1, 1);
else {
writeResult(buffer1, 0);
success = FALSE;
}
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
/* ... closing */
sprintf(buffer1, "c%d.%d", i + diff, i + diff);
sprintf(buffer2, "c%d.%d", i, i);
pixt1 = pixMorphSequence(pixsd, buffer1, 0);
pixt2 = pixMorphCompSequence(pixsd, buffer2, 0);
pixEqual(pixt1, pixt2, &same);
if (i < 64) {
pixt3 = pixMorphCompSequenceDwa(pixsd, buffer2, 0);
pixEqual(pixt1, pixt3, &same2);
} else {
pixt3 = NULL;
same2 = TRUE;
}
if (same && same2)
writeResult(buffer1, 1);
else {
writeResult(buffer1, 0);
success = FALSE;
}
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
}
pixDestroy(&pixs);
pixDestroy(&pixsd);
if (success)
fprintf(stderr, "\n---------- Success: no errors ----------\n");
else
fprintf(stderr, "\n---------- Failure: error(s) found -----------\n");
#endif
#if 0
for (i = 1; i < 400; i++) {
selectComposableSizes(i, &factor1, &factor2);
diff = factor1 * factor2 - i;
fprintf(stderr, "%d: (%d, %d): %d\n",
i, factor1, factor2, diff);
selectComposableSels(i, L_HORIZ, &sel1, &sel2);
selDestroy(&sel1);
selDestroy(&sel2);
}
#endif
#if 0
selectComposableSels(68, L_HORIZ, &sel1, &sel2); /* 17, 4 */
str = selPrintToString(sel2);
fprintf(stderr, str);
selDestroy(&sel1);
selDestroy(&sel2);
lept_free(str);
selectComposableSels(70, L_HORIZ, &sel1, &sel2); /* 10, 7 */
str = selPrintToString(sel2);
selDestroy(&sel1);
selDestroy(&sel2);
fprintf(stderr, str);
lept_free(str);
selectComposableSels(85, L_HORIZ, &sel1, &sel2); /* 17, 5 */
str = selPrintToString(sel2);
selDestroy(&sel1);
selDestroy(&sel2);
fprintf(stderr, str);
lept_free(str);
selectComposableSels(96, L_HORIZ, &sel1, &sel2); /* 12, 8 */
str = selPrintToString(sel2);
selDestroy(&sel1);
selDestroy(&sel2);
fprintf(stderr, str);
lept_free(str);
{ SELA *sela;
sela = selaAddBasic(NULL);
selaWrite("/tmp/junksela.sela", sela);
selaDestroy(&sela);
}
#endif
return 0;
}
static void writeResult(char *sequence,
l_int32 same)
{
if (same)
fprintf(stderr, "Sequence %s: SUCCESS\n", sequence);
else
fprintf(stderr, "Sequence %s: FAILURE\n", sequence);
}

View File

@@ -0,0 +1,381 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binmorph3_reg.c
*
* This is a regression test of dwa functions. It should always
* be run if changes are made to the low-level morphology code.
*
* Some things to note:
*
* (1) This compares results for these operations:
* - rasterop brick (non-separable, separable)
* - dwa brick (separable), as implemented in morphdwa.c
* - dwa brick separable, but using lower-level non-separable
* autogen'd code.
*
* (2) See in-line comments for ordinary closing and safe closing.
* The complication is due to the fact that the results differ
* for symmetric and asymmetric b.c., so we must do some
* fine adjustments of the border when implementing using
* the lower-level code directly.
*/
#include "allheaders.h"
#define TEST_SYMMETRIC 0 /* set to 1 for symmetric b.c.;
otherwise, it tests asymmetric b.c. */
int main(int argc,
char **argv)
{
char *selnameh, *selnamev;
l_int32 ok, same, w, h, i, bordercolor, extraborder;
l_int32 width[3] = {21, 1, 21};
l_int32 height[3] = {1, 7, 7};
PIX *pixs, *pixref;
PIX *pixt0, *pixt1, *pixt2, *pixt3, *pixt4;
SEL *sel;
SELA *sela;
static char mainName[] = "binmorph3_reg";
if (argc != 1)
return ERROR_INT(" Syntax: binmorph3_reg", mainName, 1);
if ((pixs = pixRead("feyn.tif")) == NULL)
return ERROR_INT("pix not made", mainName, 1);
#if TEST_SYMMETRIC
resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC);
#endif /* TEST_SYMMETRIC */
for (i = 0; i < 3; i++) {
w = width[i];
h = height[i];
sel = selCreateBrick(h, w, h / 2, w / 2, SEL_HIT);
selnameh = NULL;
selnamev = NULL;
/* Get the selnames for horiz and vert */
sela = selaAddBasic(NULL);
if (w > 1) {
if ((selnameh = selaGetBrickName(sela, w, 1)) == NULL) {
selaDestroy(&sela);
return ERROR_INT("dwa hor sel not defined", mainName, 1);
}
}
if (h > 1) {
if ((selnamev = selaGetBrickName(sela, 1, h)) == NULL) {
selaDestroy(&sela);
return ERROR_INT("dwa vert sel not defined", mainName, 1);
}
}
fprintf(stderr, "w = %d, h = %d, selh = %s, selv = %s\n",
w, h, selnameh, selnamev);
ok = TRUE;
selaDestroy(&sela);
/* ----------------- Dilation ----------------- */
fprintf(stderr, "Testing dilation\n");
pixref = pixDilate(NULL, pixs, sel);
pixt1 = pixDilateBrickDwa(NULL, pixs, w, h);
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixDestroy(&pixt1);
if (w > 1)
pixt1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh);
else
pixt1 = pixClone(pixs);
if (h > 1)
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_DILATE, selnamev);
else
pixt2 = pixClone(pixt1);
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixt1 = pixAddBorder(pixs, 32, 0);
if (w > 1)
pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
else
pixt2 = pixClone(pixt1);
if (h > 1)
pixt3 = pixFMorphopGen_1(NULL, pixt2, L_MORPH_DILATE, selnamev);
else
pixt3 = pixClone(pixt2);
pixt4 = pixRemoveBorder(pixt3, 32);
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
/* ----------------- Erosion ----------------- */
fprintf(stderr, "Testing erosion\n");
pixref = pixErode(NULL, pixs, sel);
pixt1 = pixErodeBrickDwa(NULL, pixs, w, h);
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixDestroy(&pixt1);
if (w > 1)
pixt1 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnameh);
else
pixt1 = pixClone(pixs);
if (h > 1)
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_ERODE, selnamev);
else
pixt2 = pixClone(pixt1);
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixt1 = pixAddBorder(pixs, 32, 0);
if (w > 1)
pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
else
pixt2 = pixClone(pixt1);
if (h > 1)
pixt3 = pixFMorphopGen_1(NULL, pixt2, L_MORPH_ERODE, selnamev);
else
pixt3 = pixClone(pixt2);
pixt4 = pixRemoveBorder(pixt3, 32);
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
/* ----------------- Opening ----------------- */
fprintf(stderr, "Testing opening\n");
pixref = pixOpen(NULL, pixs, sel);
pixt1 = pixOpenBrickDwa(NULL, pixs, w, h);
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixDestroy(&pixt1);
if (h == 1)
pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_OPEN, selnameh);
else if (w == 1)
pixt2 = pixMorphDwa_1(NULL, pixs, L_MORPH_OPEN, selnamev);
else {
pixt1 = pixMorphDwa_1(NULL, pixs, L_MORPH_ERODE, selnameh);
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_ERODE, selnamev);
pixMorphDwa_1(pixt1, pixt2, L_MORPH_DILATE, selnameh);
pixMorphDwa_1(pixt2, pixt1, L_MORPH_DILATE, selnamev);
pixDestroy(&pixt1);
}
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
pixDestroy(&pixt2);
pixt1 = pixAddBorder(pixs, 32, 0);
if (h == 1)
pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_OPEN, selnameh);
else if (w == 1)
pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_OPEN, selnamev);
else {
pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
pixt3 = pixFMorphopGen_1(NULL, pixt2, L_MORPH_ERODE, selnamev);
pixFMorphopGen_1(pixt2, pixt3, L_MORPH_DILATE, selnameh);
pixFMorphopGen_1(pixt3, pixt2, L_MORPH_DILATE, selnamev);
pixDestroy(&pixt2);
}
pixt4 = pixRemoveBorder(pixt3, 32);
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
/* ----------------- Closing ----------------- */
fprintf(stderr, "Testing closing\n");
pixref = pixClose(NULL, pixs, sel);
/* Note: L_MORPH_CLOSE for h==1 or w==1 gives safe closing,
* so we can't use it here. */
if (h == 1) {
pixt1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh);
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_ERODE, selnameh);
}
else if (w == 1) {
pixt1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnamev);
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_ERODE, selnamev);
}
else {
pixt1 = pixMorphDwa_1(NULL, pixs, L_MORPH_DILATE, selnameh);
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_DILATE, selnamev);
pixMorphDwa_1(pixt1, pixt2, L_MORPH_ERODE, selnameh);
pixMorphDwa_1(pixt2, pixt1, L_MORPH_ERODE, selnamev);
}
pixDestroy(&pixt1);
pixEqual(pixref, pixt2, &same);
if (!same) {
fprintf(stderr, "pixref != pixt2 !\n"); ok = FALSE;
}
pixDestroy(&pixt2);
/* Note: by adding only 32 pixels of border, we get
* the normal closing operation, even when calling
* with L_MORPH_CLOSE, because it requires 32 pixels
* of border to be safe. */
pixt1 = pixAddBorder(pixs, 32, 0);
if (h == 1)
pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnameh);
else if (w == 1)
pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnamev);
else {
pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
pixt3 = pixFMorphopGen_1(NULL, pixt2, L_MORPH_DILATE, selnamev);
pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnameh);
pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev);
pixDestroy(&pixt2);
}
pixt4 = pixRemoveBorder(pixt3, 32);
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
/* ------------- Safe Closing ----------------- */
fprintf(stderr, "Testing safe closing\n");
pixref = pixCloseSafe(NULL, pixs, sel);
pixt0 = pixCloseSafeBrick(NULL, pixs, w, h);
pixEqual(pixref, pixt0, &same);
if (!same) {
fprintf(stderr, "pixref != pixt0 !\n"); ok = FALSE;
}
pixDestroy(&pixt0);
pixt1 = pixCloseBrickDwa(NULL, pixs, w, h);
pixEqual(pixref, pixt1, &same);
if (!same) {
fprintf(stderr, "pixref != pixt1 !\n"); ok = FALSE;
}
pixDestroy(&pixt1);
bordercolor = getMorphBorderPixelColor(L_MORPH_ERODE, 1);
if (bordercolor == 0) /* asymmetric b.c. */
extraborder = 32;
else /* symmetric b.c. */
extraborder = 0;
/* Note: for safe closing we need 64 border pixels.
* However, when we implement a separable Sel
* with pixMorphDwa_*(), we must do dilation and
* erosion explicitly, and these functions only
* add/remove a 32-pixel border. Thus, for that
* case we must add an additional 32-pixel border
* before doing the operations. That is the reason
* why the implementation in morphdwa.c adds the
* 64 bit border and then uses the lower-level
* pixFMorphopGen_*() functions. */
if (h == 1)
pixt3 = pixMorphDwa_1(NULL, pixs, L_MORPH_CLOSE, selnameh);
else if (w == 1)
pixt3 = pixMorphDwa_1(NULL, pixs, L_MORPH_CLOSE, selnamev);
else {
pixt0 = pixAddBorder(pixs, extraborder, 0);
pixt1 = pixMorphDwa_1(NULL, pixt0, L_MORPH_DILATE, selnameh);
pixt2 = pixMorphDwa_1(NULL, pixt1, L_MORPH_DILATE, selnamev);
pixMorphDwa_1(pixt1, pixt2, L_MORPH_ERODE, selnameh);
pixMorphDwa_1(pixt2, pixt1, L_MORPH_ERODE, selnamev);
pixt3 = pixRemoveBorder(pixt2, extraborder);
pixDestroy(&pixt0);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
}
pixEqual(pixref, pixt3, &same);
if (!same) {
fprintf(stderr, "pixref != pixt3 !\n"); ok = FALSE;
}
pixDestroy(&pixt3);
pixt1 = pixAddBorder(pixs, 32 + extraborder, 0);
if (h == 1)
pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnameh);
else if (w == 1)
pixt3 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_CLOSE, selnamev);
else {
pixt2 = pixFMorphopGen_1(NULL, pixt1, L_MORPH_DILATE, selnameh);
pixt3 = pixFMorphopGen_1(NULL, pixt2, L_MORPH_DILATE, selnamev);
pixFMorphopGen_1(pixt2, pixt3, L_MORPH_ERODE, selnameh);
pixFMorphopGen_1(pixt3, pixt2, L_MORPH_ERODE, selnamev);
pixDestroy(&pixt2);
}
pixt4 = pixRemoveBorder(pixt3, 32 + extraborder);
pixEqual(pixref, pixt4, &same);
if (!same) {
fprintf(stderr, "pixref != pixt4 !\n"); ok = FALSE;
}
pixDestroy(&pixref);
pixDestroy(&pixt1);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
if (ok)
fprintf(stderr, "All morph tests OK!\n");
selDestroy(&sel);
lept_free(selnameh);
lept_free(selnamev);
}
pixDestroy(&pixs);
return 0;
}

View File

@@ -0,0 +1,559 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binmorph4_reg.c
*
* Regression test for dwa brick morph operations
* We compare:
* (1) morph composite vs. morph non-composite
* (2) dwa non-composite vs. morph composite
* (3) dwa composite vs. dwa non-composite
* (4) dwa composite vs. morph composite
* (5) dwa composite vs. morph non-composite
* The brick functions all have a pre-allocated pix as the dest.
*/
#include "allheaders.h"
l_int32 DoComparisonDwa1(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 isize);
l_int32 DoComparisonDwa2(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 isize);
l_int32 DoComparisonDwa3(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 isize);
l_int32 DoComparisonDwa4(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 isize);
l_int32 DoComparisonDwa5(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 isize);
l_int32 PixCompareDwa(l_int32 size, const char *type, PIX *pixt1, PIX *pixt2,
PIX *pixt3, PIX *pixt4, PIX *pixt5, PIX *pixt6);
#define TIMING 0
/* This fails on the symmetric case, but the differences are
* relatively small. Most of the problems seems to be in the
* non-dwa code, because we are doing sequential erosions
* without an extra border, and things aren't being properly
* initialized. To avoid these errors, add a border in advance
* for symmetric b.c. Note that asymmetric b.c. are recommended
* for document image operations, and this test passes for
* asymmetric b.c. */
#define TEST_SYMMETRIC 0 /* set to 1 for symmetric b.c.;
otherwise, it tests asymmetric b.c. */
int main(int argc,
char **argv)
{
l_int32 i;
PIX *pixs, *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
pixs = pixRead("feyn.tif");
#if TEST_SYMMETRIC
/* This works properly if there is an added border */
resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC);
#if 1
pixt1 = pixAddBorder(pixs, 64, 0);
pixTransferAllData(pixs, &pixt1, 0, 0);
#endif
#endif /* TEST_SYMMETRIC */
pixt1 = pixCreateTemplateNoInit(pixs);
pixt2 = pixCreateTemplateNoInit(pixs);
pixt3 = pixCreateTemplateNoInit(pixs);
pixt4 = pixCreateTemplateNoInit(pixs);
pixt5 = pixCreateTemplateNoInit(pixs);
pixt6 = pixCreateTemplateNoInit(pixs);
for (i = 2; i < 64; i++) {
#if 1
/* Compare morph composite with morph non-composite */
DoComparisonDwa1(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, i);
#endif
#if 1
/* Compare DWA non-composite with morph composite */
if (i < 16)
DoComparisonDwa2(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, i);
/* Compare DWA composite with DWA non-composite */
if (i < 16)
DoComparisonDwa3(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, i);
/* Compare DWA composite with morph composite */
DoComparisonDwa4(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, i);
/* Compare DWA composite with morph non-composite */
DoComparisonDwa5(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, i);
#endif
}
pixDestroy(&pixs);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
return 0;
}
/* morph composite with morph non-composite */
l_int32
DoComparisonDwa1(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 isize)
{
l_int32 fact1, fact2, size;
selectComposableSizes(isize, &fact1, &fact2);
size = fact1 * fact2;
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateCompBrick(pixt1, pixs, size, 1);
pixDilateCompBrick(pixt3, pixs, 1, size);
pixDilateCompBrick(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateBrick(pixt2, pixs, size, 1);
pixDilateBrick(pixt4, pixs, 1, size);
pixDilateBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixErodeCompBrick(pixt1, pixs, size, 1);
pixErodeCompBrick(pixt3, pixs, 1, size);
pixErodeCompBrick(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeBrick(pixt2, pixs, size, 1);
pixErodeBrick(pixt4, pixs, 1, size);
pixErodeBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenCompBrick(pixt1, pixs, size, 1);
pixOpenCompBrick(pixt3, pixs, 1, size);
pixOpenCompBrick(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenBrick(pixt2, pixs, size, 1);
pixOpenBrick(pixt4, pixs, 1, size);
pixOpenBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
#if 1
pixWrite("/tmp/junko1.png", pixt1, IFF_PNG);
pixWrite("/tmp/junko2.png", pixt2, IFF_PNG);
pixXor(pixt1, pixt1, pixt2);
pixWrite("/tmp/junkoxor.png", pixt1, IFF_PNG);
#endif
#if 0
pixDisplay(pixt1, 100, 100);
pixDisplay(pixt2, 800, 100);
pixWrite("/tmp/junkpixt1.png", pixt1, IFF_PNG);
pixWrite("/tmp/junkpixt2.png", pixt2, IFF_PNG);
#endif
if (TIMING) startTimer();
pixCloseSafeCompBrick(pixt1, pixs, size, 1);
pixCloseSafeCompBrick(pixt3, pixs, 1, size);
pixCloseSafeCompBrick(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseSafeBrick(pixt2, pixs, size, 1);
pixCloseSafeBrick(pixt4, pixs, 1, size);
pixCloseSafeBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
#if 1
pixWrite("/tmp/junkc1.png", pixt1, IFF_PNG);
pixWrite("/tmp/junkc2.png", pixt2, IFF_PNG);
pixXor(pixt1, pixt1, pixt2);
pixWrite("/tmp/junkcxor.png", pixt1, IFF_PNG);
#endif
return 0;
}
/* dwa non-composite with morph composite */
l_int32
DoComparisonDwa2(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 isize)
{
l_int32 fact1, fact2, size;
selectComposableSizes(isize, &fact1, &fact2);
size = fact1 * fact2;
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateBrickDwa(pixt1, pixs, size, 1);
pixDilateBrickDwa(pixt3, pixs, 1, size);
pixDilateBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateCompBrick(pixt2, pixs, size, 1);
pixDilateCompBrick(pixt4, pixs, 1, size);
pixDilateCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
/* pixDisplay(pixt1, 100, 100); */
/* pixDisplay(pixt2, 800, 100); */
if (TIMING) startTimer();
pixErodeBrickDwa(pixt1, pixs, size, 1);
pixErodeBrickDwa(pixt3, pixs, 1, size);
pixErodeBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeCompBrick(pixt2, pixs, size, 1);
pixErodeCompBrick(pixt4, pixs, 1, size);
pixErodeCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenBrickDwa(pixt1, pixs, size, 1);
pixOpenBrickDwa(pixt3, pixs, 1, size);
pixOpenBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenCompBrick(pixt2, pixs, size, 1);
pixOpenCompBrick(pixt4, pixs, 1, size);
pixOpenCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixCloseBrickDwa(pixt1, pixs, size, 1);
pixCloseBrickDwa(pixt3, pixs, 1, size);
pixCloseBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseSafeCompBrick(pixt2, pixs, size, 1);
pixCloseSafeCompBrick(pixt4, pixs, 1, size);
pixCloseSafeCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
/* pixWrite("/tmp/junkpixt1.png", pixt1, IFF_PNG); */
/* pixWrite("/tmp/junkpixt2.png", pixt2, IFF_PNG); */
/* pixXor(pixt1, pixt1, pixt2); */
/* pixWrite("/tmp/junkxor.png", pixt1, IFF_PNG); */
return 0;
}
/* dwa composite with dwa non-composite */
l_int32
DoComparisonDwa3(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 isize)
{
l_int32 fact1, fact2, size;
selectComposableSizes(isize, &fact1, &fact2);
size = fact1 * fact2;
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateCompBrickDwa(pixt1, pixs, size, 1);
pixDilateCompBrickDwa(pixt3, pixs, 1, size);
pixDilateCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateBrickDwa(pixt2, pixs, size, 1);
pixDilateBrickDwa(pixt4, pixs, 1, size);
pixDilateBrickDwa(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
/* pixDisplay(pixt1, 100, 100); */
/* pixDisplay(pixt2, 800, 100); */
if (TIMING) startTimer();
pixErodeCompBrickDwa(pixt1, pixs, size, 1);
pixErodeCompBrickDwa(pixt3, pixs, 1, size);
pixErodeCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeBrickDwa(pixt2, pixs, size, 1);
pixErodeBrickDwa(pixt4, pixs, 1, size);
pixErodeBrickDwa(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenCompBrickDwa(pixt1, pixs, size, 1);
pixOpenCompBrickDwa(pixt3, pixs, 1, size);
pixOpenCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenBrickDwa(pixt2, pixs, size, 1);
pixOpenBrickDwa(pixt4, pixs, 1, size);
pixOpenBrickDwa(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixCloseCompBrickDwa(pixt1, pixs, size, 1);
pixCloseCompBrickDwa(pixt3, pixs, 1, size);
pixCloseCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseBrickDwa(pixt2, pixs, size, 1);
pixCloseBrickDwa(pixt4, pixs, 1, size);
pixCloseBrickDwa(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
#if 0
pixWrite("/tmp/junkpixt1.png", pixt1, IFF_PNG);
pixWrite("/tmp/junkpixt2.png", pixt2, IFF_PNG);
pixXor(pixt1, pixt1, pixt2);
pixWrite("/tmp/junkxor.png", pixt1, IFF_PNG);
#endif
return 0;
}
/* dwa composite with morph composite */
l_int32
DoComparisonDwa4(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 isize)
{
l_int32 fact1, fact2, size;
selectComposableSizes(isize, &fact1, &fact2);
size = fact1 * fact2;
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateCompBrickDwa(pixt1, pixs, size, 1);
pixDilateCompBrickDwa(pixt3, pixs, 1, size);
pixDilateCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateCompBrick(pixt2, pixs, size, 1);
pixDilateCompBrick(pixt4, pixs, 1, size);
pixDilateCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
/* pixDisplay(pixt1, 100, 100); */
/* pixDisplay(pixt2, 800, 100); */
if (TIMING) startTimer();
pixErodeCompBrickDwa(pixt1, pixs, size, 1);
pixErodeCompBrickDwa(pixt3, pixs, 1, size);
pixErodeCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeCompBrick(pixt2, pixs, size, 1);
pixErodeCompBrick(pixt4, pixs, 1, size);
pixErodeCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenCompBrickDwa(pixt1, pixs, size, 1);
pixOpenCompBrickDwa(pixt3, pixs, 1, size);
pixOpenCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenCompBrick(pixt2, pixs, size, 1);
pixOpenCompBrick(pixt4, pixs, 1, size);
pixOpenCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
/* pixDisplay(pixt1, 100, 100); */
/* pixDisplay(pixt2, 800, 100); */
/* pixWrite("/tmp/junkpixt1.png", pixt1, IFF_PNG); */
/* pixWrite("/tmp/junkpixt2.png", pixt2, IFF_PNG); */
if (TIMING) startTimer();
pixCloseCompBrickDwa(pixt1, pixs, size, 1);
pixCloseCompBrickDwa(pixt3, pixs, 1, size);
pixCloseCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseSafeCompBrick(pixt2, pixs, size, 1);
pixCloseSafeCompBrick(pixt4, pixs, 1, size);
pixCloseSafeCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
return 0;
}
/* dwa composite with morph non-composite */
l_int32
DoComparisonDwa5(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 isize)
{
l_int32 fact1, fact2, size;
selectComposableSizes(isize, &fact1, &fact2);
size = fact1 * fact2;
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateCompBrickDwa(pixt1, pixs, size, 1);
pixDilateCompBrickDwa(pixt3, pixs, 1, size);
pixDilateCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateBrick(pixt2, pixs, size, 1);
pixDilateBrick(pixt4, pixs, 1, size);
pixDilateBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
/* pixDisplay(pixt1, 100, 100); */
/* pixDisplay(pixt2, 800, 100); */
if (TIMING) startTimer();
pixErodeCompBrickDwa(pixt1, pixs, size, 1);
pixErodeCompBrickDwa(pixt3, pixs, 1, size);
pixErodeCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeBrick(pixt2, pixs, size, 1);
pixErodeBrick(pixt4, pixs, 1, size);
pixErodeBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenCompBrickDwa(pixt1, pixs, size, 1);
pixOpenCompBrickDwa(pixt3, pixs, 1, size);
pixOpenCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenBrick(pixt2, pixs, size, 1);
pixOpenBrick(pixt4, pixs, 1, size);
pixOpenBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixCloseCompBrickDwa(pixt1, pixs, size, 1);
pixCloseCompBrickDwa(pixt3, pixs, 1, size);
pixCloseCompBrickDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseSafeBrick(pixt2, pixs, size, 1);
pixCloseSafeBrick(pixt4, pixs, 1, size);
pixCloseSafeBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
return 0;
}
l_int32
PixCompareDwa(l_int32 size,
const char *type,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6)
{
l_int32 same, fail;
fail = FALSE;
pixEqual(pixt1, pixt2, &same);
if (!same) {
fail = TRUE;
fprintf(stderr, "%s (%d, 1) not same\n", type, size);
}
pixEqual(pixt3, pixt4, &same);
if (!same) {
fail = TRUE;
fprintf(stderr, "%s (1, %d) not same\n", type, size);
}
pixEqual(pixt5, pixt6, &same);
if (!same) {
fail = TRUE;
fprintf(stderr, "%s (%d, %d) not same\n", type, size, size);
}
return fail;
}

View File

@@ -0,0 +1,319 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* binmorph5_reg.c
*
* Regression test for expanded dwa morph operations.
* We compare:
* (1) dwa composite vs. morph composite
* (2) dwa composite vs. morph non-composite
*/
#include "allheaders.h"
l_int32 DoComparisonDwa1(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 isize);
l_int32 DoComparisonDwa2(PIX *pixs, PIX *pixt1, PIX *pixt2, PIX *pixt3,
PIX *pixt4, PIX *pixt5, PIX *pixt6, l_int32 size);
l_int32 PixCompareDwa(l_int32 size, const char *type, PIX *pixt1, PIX *pixt2,
PIX *pixt3, PIX *pixt4, PIX *pixt5, PIX *pixt6);
#define TIMING 0
#define FASTER_TEST 1
#define SLOWER_TEST 1
/* This fails on the symmetric case, but the differences are
* relatively small. Most of the problems seems to be in the
* non-dwa code, because we are doing sequential erosions
* without an extra border, and things aren't being properly
* initialized. To avoid these errors, add a border in advance
* for symmetric b.c. Note that asymmetric b.c. are recommended
* for document image operations, and this test passes for
* asymmetric b.c. */
#define TEST_SYMMETRIC 0 /* set to 1 for symmetric b.c.;
otherwise, it tests asymmetric b.c. */
int main(int argc,
char **argv)
{
l_int32 i, n, rsize, fact1, fact2, extra;
l_int32 size, lastsize;
l_int32 dwasize[256];
l_int32 ropsize[256];
PIX *pixs, *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixt6;
pixs = pixRead("feyn.tif");
#if TEST_SYMMETRIC
/* This works properly if there's an added border */
resetMorphBoundaryCondition(SYMMETRIC_MORPH_BC);
#if 1
pixt1 = pixAddBorder(pixs, 64, 0);
pixTransferAllData(pixs, &pixt1, 0, 0);
#endif
#endif /* TEST_SYMMETRIC */
pixt1 = pixCreateTemplateNoInit(pixs);
pixt2 = pixCreateTemplateNoInit(pixs);
pixt3 = pixCreateTemplateNoInit(pixs);
pixt4 = pixCreateTemplateNoInit(pixs);
pixt5 = pixCreateTemplateNoInit(pixs);
pixt6 = pixCreateTemplateNoInit(pixs);
/* ---------------------------------------------------------------- *
* Faster test; testing fewer sizes *
* ---------------------------------------------------------------- */
#if FASTER_TEST
/* Compute the actual sizes used for each input size 'i' */
for (i = 0; i < 256; i++) {
dwasize[i] = 0;
ropsize[i] = 0;
}
for (i = 65; i < 256; i++) {
selectComposableSizes(i, &fact1, &fact2);
rsize = fact1 * fact2;
ropsize[i] = rsize;
getExtendedCompositeParameters(i, &n, &extra, &dwasize[i]);
}
/* Use only values where the resulting sizes are equal */
for (i = 65; i < 240; i++) {
n = 1 + (l_int32)((i - 63) / 62);
extra = i - 63 - (n - 1) * 62 + 1;
if (extra == 2) continue; /* don't use this one (e.g., i == 126) */
if (ropsize[i] == dwasize[i])
DoComparisonDwa1(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, i);
}
#endif /* FASTER_TEST */
/* ---------------------------------------------------------------- *
* Slower test; testing maximum number of sizes *
* ---------------------------------------------------------------- */
#if SLOWER_TEST
lastsize = 0;
for (i = 65; i < 199; i++) {
getExtendedCompositeParameters(i, &n, &extra, &size);
if (size == lastsize) continue;
if (size == 126 || size == 188) continue; /* deliberately off by one */
lastsize = size;
DoComparisonDwa2(pixs, pixt1, pixt2, pixt3, pixt4,
pixt5, pixt6, size);
}
#endif /* SLOWER_TEST */
pixDestroy(&pixs);
pixDestroy(&pixt1);
pixDestroy(&pixt2);
pixDestroy(&pixt3);
pixDestroy(&pixt4);
pixDestroy(&pixt5);
pixDestroy(&pixt6);
return 0;
}
l_int32
DoComparisonDwa1(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 isize)
{
l_int32 fact1, fact2, size;
selectComposableSizes(isize, &fact1, &fact2);
size = fact1 * fact2;
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateCompBrickExtendDwa(pixt1, pixs, size, 1);
pixDilateCompBrickExtendDwa(pixt3, pixs, 1, size);
pixDilateCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateCompBrick(pixt2, pixs, size, 1);
pixDilateCompBrick(pixt4, pixs, 1, size);
pixDilateCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixErodeCompBrickExtendDwa(pixt1, pixs, size, 1);
pixErodeCompBrickExtendDwa(pixt3, pixs, 1, size);
pixErodeCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeCompBrick(pixt2, pixs, size, 1);
pixErodeCompBrick(pixt4, pixs, 1, size);
pixErodeCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenCompBrickExtendDwa(pixt1, pixs, size, 1);
pixOpenCompBrickExtendDwa(pixt3, pixs, 1, size);
pixOpenCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenCompBrick(pixt2, pixs, size, 1);
pixOpenCompBrick(pixt4, pixs, 1, size);
pixOpenCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixCloseCompBrickExtendDwa(pixt1, pixs, size, 1);
pixCloseCompBrickExtendDwa(pixt3, pixs, 1, size);
pixCloseCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseSafeCompBrick(pixt2, pixs, size, 1);
pixCloseSafeCompBrick(pixt4, pixs, 1, size);
pixCloseSafeCompBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
#if 0
pixWrite("/tmp/junkpixt3.png", pixt3, IFF_PNG);
pixWrite("/tmp/junkpixt4.png", pixt4, IFF_PNG);
pixXor(pixt3, pixt3, pixt4);
pixWrite("/tmp/junkxor.png", pixt3, IFF_PNG);
#endif
return 0;
}
l_int32
DoComparisonDwa2(PIX *pixs,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6,
l_int32 size) /* exactly decomposable */
{
fprintf(stderr, "..%d..", size);
if (TIMING) startTimer();
pixDilateCompBrickExtendDwa(pixt1, pixs, size, 1);
pixDilateCompBrickExtendDwa(pixt3, pixs, 1, size);
pixDilateCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixDilateBrick(pixt2, pixs, size, 1);
pixDilateBrick(pixt4, pixs, 1, size);
pixDilateBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "dilate", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixErodeCompBrickExtendDwa(pixt1, pixs, size, 1);
pixErodeCompBrickExtendDwa(pixt3, pixs, 1, size);
pixErodeCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixErodeBrick(pixt2, pixs, size, 1);
pixErodeBrick(pixt4, pixs, 1, size);
pixErodeBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "erode", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixOpenCompBrickExtendDwa(pixt1, pixs, size, 1);
pixOpenCompBrickExtendDwa(pixt3, pixs, 1, size);
pixOpenCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixOpenBrick(pixt2, pixs, size, 1);
pixOpenBrick(pixt4, pixs, 1, size);
pixOpenBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "open", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
if (TIMING) startTimer();
pixCloseCompBrickExtendDwa(pixt1, pixs, size, 1);
pixCloseCompBrickExtendDwa(pixt3, pixs, 1, size);
pixCloseCompBrickExtendDwa(pixt5, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Dwa: %7.3f sec\n", stopTimer());
if (TIMING) startTimer();
pixCloseSafeBrick(pixt2, pixs, size, 1);
pixCloseSafeBrick(pixt4, pixs, 1, size);
pixCloseSafeBrick(pixt6, pixs, size, size);
if (TIMING) fprintf(stderr, "Time Rop: %7.3f sec\n", stopTimer());
PixCompareDwa(size, "close", pixt1, pixt2, pixt3, pixt4, pixt5, pixt6);
#if 0
pixWrite("/tmp/junkpixt3.png", pixt3, IFF_PNG);
pixWrite("/tmp/junkpixt4.png", pixt4, IFF_PNG);
pixXor(pixt3, pixt3, pixt4);
pixWrite("/tmp/junkxor.png", pixt3, IFF_PNG);
#endif
return 0;
}
l_int32
PixCompareDwa(l_int32 size,
const char *type,
PIX *pixt1,
PIX *pixt2,
PIX *pixt3,
PIX *pixt4,
PIX *pixt5,
PIX *pixt6)
{
l_int32 same, fail;
fail = FALSE;
pixEqual(pixt1, pixt2, &same);
if (!same) {
fail = TRUE;
fprintf(stderr, "%s (%d, 1) not same\n", type, size);
}
pixEqual(pixt3, pixt4, &same);
if (!same) {
fail = TRUE;
fprintf(stderr, "%s (1, %d) not same\n", type, size);
}
pixEqual(pixt5, pixt6, &same);
if (!same) {
fail = TRUE;
fprintf(stderr, "%s (%d, %d) not same\n", type, size, size);
}
return fail;
}

View File

@@ -0,0 +1,110 @@
/*====================================================================*
- Copyright (C) 2001 Leptonica. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*====================================================================*/
/*
* blackwhite_reg.c
*
* Tests functions that handle black and white pixels in an image.
*/
#include "allheaders.h"
const char *fnames[11] = {"test1.png", "speckle2.png", "weasel2.4g.png",
"speckle4.png", "weasel4.11c.png",
"dreyfus8.png", "weasel8.240c.png",
"test16.tif", "marge.jpg",
"test-cmap-alpha.png", "test-gray-alpha.png"};
const l_int32 setsize = 11;
int main(int argc,
char **argv)
{
l_int32 i, spp;
l_uint32 bval, wval;
PIX *pixs, *pix1, *pix2, *pix3, *pixd;
PIXA *pixa;
L_REGPARAMS *rp;
if (regTestSetup(argc, argv, &rp))
return 1;
/* Scale each image and add a white boundary */
pixa = pixaCreate(setsize);
for (i = 0; i < setsize; i++) {
pixs = pixRead(fnames[i]);
spp = pixGetSpp(pixs);
pixGetBlackOrWhiteVal(pixs, L_GET_WHITE_VAL, &wval);
pixGetBlackOrWhiteVal(pixs, L_GET_BLACK_VAL, &bval);
fprintf(stderr, "d = %d, spp = %d, bval = %x, wval = %x\n",
pixGetDepth(pixs), spp, bval, wval);
if (spp == 4) /* remove alpha, using white background */
pix1 = pixAlphaBlendUniform(pixs, wval);
else
pix1 = pixClone(pixs);
pix2 = pixScaleToSize(pix1, 150, 150);
pixGetBlackOrWhiteVal(pix2, L_GET_WHITE_VAL, &wval);
pix3 = pixAddBorderGeneral(pix2, 30, 30, 20, 20, wval);
pixaAddPix(pixa, pix3, L_INSERT);
pixDestroy(&pixs);
pixDestroy(&pix1);
pixDestroy(&pix2);
}
pixd = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 1, 30, 0);
regTestWritePixAndCheck(rp, pixd, IFF_PNG);
pixDisplayWithTitle(pixd, 0, 100, NULL, rp->display);
pixDestroy(&pixd);
pixaDestroy(&pixa);
/* Scale each image and add a black boundary */
pixa = pixaCreate(setsize);
for (i = 0; i < setsize; i++) {
pixs = pixRead(fnames[i]);
spp = pixGetSpp(pixs);
pixGetBlackOrWhiteVal(pixs, L_GET_WHITE_VAL, &wval);
pixGetBlackOrWhiteVal(pixs, L_GET_BLACK_VAL, &bval);
fprintf(stderr, "d = %d, spp = %d, bval = %x, wval = %x\n",
pixGetDepth(pixs), spp, bval, wval);
if (spp == 4) /* remove alpha, using white background */
pix1 = pixAlphaBlendUniform(pixs, wval);
else
pix1 = pixClone(pixs);
pix2 = pixScaleToSize(pix1, 150, 150);
pixGetBlackOrWhiteVal(pixs, L_GET_BLACK_VAL, &bval);
pix3 = pixAddBorderGeneral(pix2, 30, 30, 20, 20, bval);
pixaAddPix(pixa, pix3, L_INSERT);
pixDestroy(&pixs);
pixDestroy(&pix1);
pixDestroy(&pix2);
}
pixd = pixaDisplayTiledInRows(pixa, 32, 1200, 1.0, 0, 30, 0);
regTestWritePixAndCheck(rp, pixd, IFF_PNG);
pixDisplayWithTitle(pixd, 1000, 100, NULL, rp->display);
pixDestroy(&pixd);
pixaDestroy(&pixa);
return regTestCleanup(rp);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Some files were not shown because too many files have changed in this diff Show More