first working version from Android Studio
This commit is contained in:
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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
|
||||
* < <code>fract</code> < 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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
}
|
@@ -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();
|
||||
}
|
Reference in New Issue
Block a user