first working version from Android Studio
This commit is contained in:
44
tesseract/build.gradle
Normal file
44
tesseract/build.gradle
Normal file
@@ -0,0 +1,44 @@
|
||||
apply plugin: 'com.android.library'
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion '21.1.2'
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 19
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
//// This prevents the auto generation of Android.mk
|
||||
sourceSets.main.jni.srcDirs = []
|
||||
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
|
||||
def ndkDir = android.plugin.ndkFolder
|
||||
commandLine "$ndkDir/ndk-build",
|
||||
'-C', file('src/main/jni').absolutePath,
|
||||
'-j', Runtime.runtime.availableProcessors(),
|
||||
'all',
|
||||
'NDK_DEBUG=1'
|
||||
}
|
||||
task cleanNative(type: Exec, description: 'Clean JNI object files') {
|
||||
def ndkDir = android.plugin.ndkFolder
|
||||
commandLine "$ndkDir/ndk-build",
|
||||
'-C', file('src/main/jni').absolutePath,
|
||||
'clean'
|
||||
}
|
||||
clean.dependsOn 'cleanNative'
|
||||
tasks.withType(JavaCompile) {
|
||||
compileTask -> compileTask.dependsOn buildNative
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
productFlavors {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package com.googlecode.tesseract.android;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
||||
public static final String APPLICATION_ID = "com.googlecode.tesseract.android";
|
||||
public static final String BUILD_TYPE = "debug";
|
||||
public static final String FLAVOR = "";
|
||||
public static final int VERSION_CODE = 1;
|
||||
public static final String VERSION_NAME = "";
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package com.googlecode.tesseract.android;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = false;
|
||||
public static final String APPLICATION_ID = "com.googlecode.tesseract.android";
|
||||
public static final String BUILD_TYPE = "release";
|
||||
public static final String FLAVOR = "";
|
||||
public static final int VERSION_CODE = 1;
|
||||
public static final String VERSION_NAME = "";
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package com.googlecode.tesseract.android.test;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = Boolean.parseBoolean("true");
|
||||
public static final String APPLICATION_ID = "com.googlecode.tesseract.android.test";
|
||||
public static final String BUILD_TYPE = "debug";
|
||||
public static final String FLAVOR = "";
|
||||
public static final int VERSION_CODE = -1;
|
||||
public static final String VERSION_NAME = "";
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.googlecode.tesseract.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
</manifest>
|
BIN
tesseract/build/intermediates/bundles/debug/classes.jar
Normal file
BIN
tesseract/build/intermediates/bundles/debug/classes.jar
Normal file
Binary file not shown.
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.googlecode.tesseract.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
</manifest>
|
BIN
tesseract/build/intermediates/bundles/release/classes.jar
Normal file
BIN
tesseract/build/intermediates/bundles/release/classes.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="main"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/assets"/></dataSet><dataSet config="debug"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/debug/assets"/></dataSet></merger>
|
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="main"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/assets"/></dataSet><dataSet config="release"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/release/assets"/></dataSet></merger>
|
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="debug"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/intermediates/bundles/debug/assets"/></dataSet><dataSet config="main"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/androidTest/assets"/></dataSet></merger>
|
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="debug"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/intermediates/bundles/debug/res"/></dataSet><dataSet config="main"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/androidTest/res"/><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/generated/res/rs/test/debug"/><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/generated/res/generated/test/debug"/></dataSet><mergedItems/></merger>
|
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="main"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/res"/><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/generated/res/rs/debug"/><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/generated/res/generated/debug"/></dataSet><dataSet config="debug"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/debug/res"/></dataSet><mergedItems/></merger>
|
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="main"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/main/res"/><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/generated/res/rs/release"/><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/build/generated/res/generated/release"/></dataSet><dataSet config="release"><source path="/home/vins/AndroidStudioProjects/PointsPermis/tesseract/src/release/res"/></dataSet><mergedItems/></merger>
|
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.googlecode.tesseract.android.test" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="19" />
|
||||
|
||||
<instrumentation
|
||||
android:name="android.test.InstrumentationTestRunner"
|
||||
android:functionalTest="false"
|
||||
android:handleProfiling="false"
|
||||
android:label="Tests for com.googlecode.tesseract.android.test"
|
||||
android:targetPackage="com.googlecode.tesseract.android.test" />
|
||||
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.googlecode.tesseract.android.test">
|
||||
|
||||
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
|
||||
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner" />
|
||||
</application>
|
||||
|
||||
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
||||
android:targetPackage="com.googlecode.tesseract.android.test"
|
||||
android:handleProfiling="false"
|
||||
android:functionalTest="false"
|
||||
android:label="Tests for com.googlecode.tesseract.android.test"/>
|
||||
</manifest>
|
BIN
tesseract/build/intermediates/res/resources-debug-test.ap_
Normal file
BIN
tesseract/build/intermediates/res/resources-debug-test.ap_
Normal file
Binary file not shown.
BIN
tesseract/build/outputs/aar/tesseract-debug.aar
Normal file
BIN
tesseract/build/outputs/aar/tesseract-debug.aar
Normal file
Binary file not shown.
BIN
tesseract/build/outputs/aar/tesseract-release.aar
Normal file
BIN
tesseract/build/outputs/aar/tesseract-release.aar
Normal file
Binary file not shown.
2
tesseract/build/tmp/packageDebugJar/MANIFEST.MF
Normal file
2
tesseract/build/tmp/packageDebugJar/MANIFEST.MF
Normal file
@@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
2
tesseract/build/tmp/packageReleaseJar/MANIFEST.MF
Normal file
2
tesseract/build/tmp/packageReleaseJar/MANIFEST.MF
Normal file
@@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
26
tesseract/src/main/AndroidManifest.xml
Normal file
26
tesseract/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Copyright (C) 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.googlecode.tesseract.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="20" />
|
||||
|
||||
</manifest>
|
@@ -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);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user