From e9c7aaaaf3443b41b8d5473c939a8f7c0bab9ffb Mon Sep 17 00:00:00 2001 From: Robert Theis Date: Sun, 12 Aug 2018 12:56:54 -0700 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit f4653604ab0f83dcbb8ea99c8de5dadf20d98a7f Author: Robert Theis Date: Fri Apr 20 07:24:09 2018 -0700 Edit change log commit 6aa9dc7e741ddee4ae446337ded1e336afc4a7b4 Author: Robert Theis Date: Fri Apr 20 07:17:42 2018 -0700 Edit change log commit ce13d6f201962454c5506ae6acb894f4902a986d Author: Robert Theis Date: Thu Apr 19 20:56:55 2018 -0700 Update change log commit 35d3569d16904b7fd1af9388261a9709b3a097eb Author: Robert Theis Date: Thu Apr 19 20:13:58 2018 -0700 Set version to 9.0.0 commit 3b7e5442d1a33518584201fd51b9f861b11d0ad0 Author: Robert Theis Date: Thu Apr 19 20:00:01 2018 -0700 Fix 64-bit issues. Closes #197. commit 229906e637bbb7f74d0c60e805758bdefdc9ee98 Author: Robert Theis Date: Thu Apr 19 19:01:38 2018 -0700 Fix null check commit 6509ff4787e7aa2200f40b788d92e7957b63fa24 Author: Robert Theis Date: Thu Apr 19 18:38:45 2018 -0700 Add missing includes commit 4a4bc77eb56b32bf285f002ed940879c7b38afe7 Author: Robert Theis Date: Thu Apr 19 17:51:19 2018 -0700 Update dependency versions commit 0766501cbb5437012ceea7b504f41e2e4a3031fc Author: Robert Theis Date: Thu Apr 19 17:41:17 2018 -0700 Mute libjpeg build warning commit 5c0b8e3e32105326a285a7209eaf4c4bd7d96d24 Author: Robert Theis Date: Thu Apr 19 17:17:49 2018 -0700 Update documentation commit e2bea65b731468793a93920ef3c781c417526461 Author: Robert Theis Date: Thu Apr 19 16:44:51 2018 -0700 Catch Arabic/Hindi init misconfigurations. Closes #240. commit b0f3c2cb4bf8c883224aecc348fea26f83303aa2 Author: Robert Theis Date: Thu Apr 19 13:40:38 2018 -0700 Edit ABI targets commit 4661d8e0bc86183b39b07a34fe9267f897078050 Author: Robert Theis Date: Thu Apr 19 12:45:51 2018 -0700 Minor edit to Gradle config commit 3436f01b1d5fbd116d221f870d8396d9234cf79f Merge: 14fa90a a5fac7d Author: Robert Theis Date: Wed Jan 17 17:12:42 2018 -0800 Merge pull request #233 from mauriciotogneri/master Updated repositories. Changed compile to implementation. commit a5fac7d509b2bca09b935b651670aa2e7588f7c4 Author: mtogneri Date: Sat Jan 6 17:57:13 2018 +0100 Updated repositories. Changed compile to implementation. commit 14fa90a18f38ad669c3339bec61846720ecd0506 Merge: d85ef2d ce84fcd Author: Robert Theis Date: Thu Dec 28 20:28:25 2017 -0800 Merge pull request #231 from mauriciotogneri/master Updated version of SDK, build tools and support libraries commit ce84fcdd49bfd319b88004a491a1ea7ee8cc242c Author: Mauricio Togneri Date: Fri Dec 15 10:19:15 2017 +0100 Updated version of SDK, build tools and support libraries commit d85ef2db16c748db50b1ac04ba50c733a9d2a498 Author: Robert Theis Date: Thu Sep 7 21:46:50 2017 -0700 Add support annotations commit 52be81e0e1fce47259ab621c26c9a30e55307ad5 Author: Robert Theis Date: Sat Aug 12 20:10:17 2017 -0700 Update change log commit d5849bec6dec2a829e4796ef3e70b48185803034 Author: Robert Theis Date: Sat Aug 12 19:17:18 2017 -0700 Set version to 8.0.0 commit 688d487b11c2e8d17816fd91ba7de5a3c1cfd041 Author: Robert Theis Date: Sat Aug 12 19:17:04 2017 -0700 Don't build 64-bit ABIs by default commit ab9b9a31c76bd81dbdd18badd1d1f7aa6e56ae18 Author: Robert Theis Date: Sat Jul 22 14:32:20 2017 -0700 Update readme commit 5a1e4e2ae878513a2e6ea2a753c2fb95f35ac68f Author: Robert Theis Date: Wed Jun 28 07:22:16 2017 -0700 Update Github issue template commit b57e6afc6512a4ac584e9a08bb0805bb2c1f21b3 Merge: 1632130 2dc4ac4 Author: Robert Theis Date: Fri Jun 16 06:37:05 2017 -0700 Merge pull request #217 from ivankolev/master clone tag 3.04.00 from tessdata commit 2dc4ac4864002e944c6624cb30f8fbc73fca3603 Author: ivankolev Date: Thu Jun 15 21:06:06 2017 -0400 clone tag 3.04.00 from tessdata, as master now contains traineddata files for tesseract 4, notably it does not contain eng.cube.* files commit 16321305362b2f2c0650053d2d6ed427c8c8755e Merge: dafeb3c d727e0c Author: Robert Theis Date: Wed Jun 14 07:53:18 2017 -0700 Merge pull request #216 from ivankolev/master See issue #215 commit d727e0cae41894065203f8656bac1c0c78e79af7 Merge: b4066f1 dafeb3c Author: ivankolev Date: Tue Jun 13 18:19:09 2017 -0400 Merge remote-tracking branch 'original-origin/master' commit dafeb3ce0d0ef470b2dce8c55b255f552686cfb7 Author: Robert Theis Date: Mon Jun 12 21:25:03 2017 -0700 Update .gitignore commit 0bb3eb5f280320e9ce6034fe745b2bc8b39ba6c4 Author: Robert Theis Date: Mon Jun 12 21:23:54 2017 -0700 Update Gradle plugin commit a00479b02e972da14a922385d558112e40fb5553 Author: Robert Theis Date: Mon Jun 12 20:47:15 2017 -0700 Update change log commit 686a681674d7b2bc86db3cfe339a9d9057f4e240 Author: Robert Theis Date: Mon Jun 12 20:09:03 2017 -0700 Set version to 7.0.0 commit b4066f1295a86f99e1f9459d0250e16617331e8e Author: ivankolev Date: Mon Jun 12 18:20:48 2017 -0400 add header files explicitly so "gradlew assemble" could finish successfully commit fa9c178f092ac1f9082573e72e106cc0d7b9217d Author: Robert Theis Date: Wed May 17 19:59:07 2017 -0700 Improve data path used for testing. Closes #208. commit cc75026220fc4a969c168e63df031861ec3ca291 Merge: aa4933b 65a5987 Author: Robert Theis Date: Mon May 15 22:32:02 2017 -0400 Merge pull request #209 from Robyer/fixPageSegMode Add missing PageSegMode constant commit 65a598754a50a8f1e0e2eac5e76613e3a5d57b4c Author: Robert Pösel Date: Mon May 15 12:59:10 2017 +0200 Remove PSM_COUNT constant It is useless to have this in Java API. commit 4c75483865973604de771769402f3885280ff0a5 Author: Robert Pösel Date: Mon May 15 12:50:57 2017 +0200 Add missing PSM_RAW_LINE mode It was added in Tesseract v3.04 commit aa4933b5aa00d2359abc0cfbb7d32cc526fdeeee Author: Robert Theis Date: Sun May 14 13:19:33 2017 -0700 Minor update to Javadoc for ResultIterator commit ba06c7e148d1eeb8a907ae4d09faec164bd901b7 Merge: 43c52fe bfe2bcf Author: Robert Theis Date: Sun May 14 15:52:54 2017 -0400 Merge pull request #206 from Robyer/improveResultIterator Improve ResultIterator commit 43c52fe7eca0b7195c830442f21bff0431052493 Author: Robert Theis Date: Sun May 14 12:05:54 2017 -0700 Update test to check BeginDocument return value commit 615586c06798adece31eb72d17e2612750aad958 Merge: 98995d4 00d093d Author: Robert Theis Date: Sun May 14 15:04:33 2017 -0400 Merge pull request #207 from Robyer/fixBeginDocument Fix return value of BeginDocument (fixes #103) commit 98995d482e812b266121e881d878c3b2377acc19 Merge: 3bda8b1 939b96e Author: Robert Theis Date: Sun May 14 14:11:32 2017 -0400 Merge pull request #205 from Robyer/updateGradlePlugin Update gradle plugin commit 00d093d93fdfc517e28436ab12553827072690aa Author: Robert Pösel Date: Thu May 11 04:52:56 2017 +0200 Fix return value of BeginDocument (fixes #103) pdfRenderer->BeginDocument return true on success so the condition was wrongly inverted. This commit fixes that and uses a bit cleaner code. commit bfe2bcfcf1dfdea07b0672f35d6b9218f2ca060a Author: Robert Pösel Date: Thu May 11 03:59:49 2017 +0200 Fix typo in nativeDelete method commit 56203adc393e850558d337700caa7578b2440b9c Author: Robert Pösel Date: Thu May 11 04:39:52 2017 +0200 ResultIterator: Add IsAtBeginningOf and IsAtFinalElement methods commit 506d004e690a8aff886332245eb17073ff70c03c Author: Robert Pösel Date: Thu May 11 03:35:19 2017 +0200 Fix static native method parameter commit bdd2fe77dd8bf63afe74f55fe85c59da613b0589 Author: Robert Pösel Date: Thu May 11 03:06:03 2017 +0200 Fix size of string holding symbol and confidence We're printing "%s|%.2f" which could end up in "%s|100.00" so it's "strlen(utfText) + 7". commit af9fc834748fbe514e121afe3a15fac952a87d83 Author: Robert Pösel Date: Thu May 11 03:01:17 2017 +0200 ResultIterator can't return choices with custom level (closes #119) ChoicesIterator always return only list of alternatives of symbol, it doesn't let us specify different PageIteratorLevel here. So this commit removes the method parameter and renames the whole method to make more sense. commit 939b96eeab7922d65da33b3f6dc04b920b29f4f3 Author: Robert Pösel Date: Thu May 11 02:51:57 2017 +0200 Update gradle plugin commit 3bda8b15711a543bf75f243dc9578f07920d8bf3 Merge: 3debecf 7792a02 Author: Robert Theis Date: Thu Apr 27 07:12:34 2017 -0700 Merge pull request #202 from Robyer/fixJavadocs Fix javadocs errors and warnings commit 7792a02c2d6efe84c99e38a258eaeb82262e6af2 Author: Robert Pösel Date: Thu Apr 27 08:27:01 2017 +0200 Fix javadocs errors and warnings --- .gitignore | 1 + BUILDING.md | 41 +++++++++--- CHANGELOG.md | 63 ++++++++++++++++++- ISSUE_TEMPLATE.md | 9 +++ README.md | 9 ++- build.gradle | 6 +- eyes-two/build.gradle | 12 ++-- eyes-two/src/main/jni/Application.mk | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- preparetests.cmd | 31 ++++----- preparetests.sh | 17 ++--- tess-two-test/build.gradle | 13 ++-- .../android/test/TessBaseAPITest.java | 9 ++- .../android/test/TessPdfRendererTest.java | 2 +- tess-two/build.gradle | 9 +-- tess-two/jni/Application.mk | 2 +- .../utilities.cpp | 35 +++++------ .../resultiterator.cpp | 31 ++++++--- .../tessbaseapi.cpp | 8 +-- tess-two/jni/libjpeg/Android.mk | 1 + .../leptonica/android/Binarize.java | 19 +++--- .../com/googlecode/leptonica/android/Box.java | 3 +- .../googlecode/leptonica/android/Boxa.java | 3 +- .../googlecode/leptonica/android/Clip.java | 5 +- .../leptonica/android/Constants.java | 19 ++++++ .../googlecode/leptonica/android/Edge.java | 12 +++- .../googlecode/leptonica/android/JpegIO.java | 4 +- .../leptonica/android/MorphApp.java | 18 ++++-- .../com/googlecode/leptonica/android/Pix.java | 6 +- .../googlecode/leptonica/android/Pixa.java | 21 ++++--- .../googlecode/leptonica/android/Rotate.java | 8 ++- .../leptonica/android/WriteFile.java | 19 +++--- .../tesseract/android/PageIterator.java | 10 +-- .../tesseract/android/ResultIterator.java | 44 ++++++++++--- .../tesseract/android/TessBaseAPI.java | 53 +++++++++++++--- 35 files changed, 386 insertions(+), 163 deletions(-) diff --git a/.gitignore b/.gitignore index 27f526173..e551f3556 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ build/ .idea/ *.iml javadoc/ +tessdata/ diff --git a/BUILDING.md b/BUILDING.md index 109ea76b9..9f15eb017 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -5,18 +5,20 @@ AAR as an external dependency in your app project. To start the build, import the root directory of this project into Android Studio as an existing Android Studio project, or follow the instructions below to build on the command line. -Note: When building from Android Studio, you may need to set the path to your -NDK installation in the Project Structure dialog (File->Project Structure). - -## _Android Studio and Gradle_ +## _Building with Android Studio_ The Gradle build uses the gradle-stable plugin and the Android NDK to build the Tesseract and Leptonica native C/C++ code through a call to -`ndk-build` in `build.gradle`. After building, the AAR file that is generated -may be [imported][aar-import] into your app project as a dependency on a local -binary package. +`ndk-build` in `build.gradle`. In Android Studio, use + +Build -> Rebuild Project + +to build or rebuild the project. + +Note: When building from Android Studio, you may need to set the path to your +NDK installation in the Project Structure dialog (File->Project Structure). -To build the project from the command line: +## _Building on the Command Line_ _On Mac/Linux:_ @@ -44,7 +46,20 @@ Run the following commands: cd tess gradlew assemble -### Testing +# Importing + +After building, the code that is generated may be imported into your app +project in Android Studio as a module using + +File -> New -> Import Module -> `tess-two` folder + +and then adding the dependency to your app module build.gradle: + + dependencies { + implementation project(':tess-two') + } + +# Testing _On Mac/Linux:_ @@ -58,4 +73,10 @@ _On Windows:_ Note that some tests will fail due to existing issues. -[aar-import]:http://stackoverflow.com/a/28816265/667810 +# Removing + +If you want to remove your app's dependency on the tess-two module, reverse +the import process by removing the module using the Project Structure dialog +(File->Project Structure), manually deleting the tess-two subfolder from your +app project folder, and removing the tess-two reference from your app module +build.gradle. \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 946a3df65..a1b4edf89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,68 @@ # Change Log ## [Unreleased](https://github.com/rmtheis/tess-two/tree/HEAD) -[Full Changelog](https://github.com/rmtheis/tess-two/compare/6.3.0...HEAD) +[Full Changelog](https://github.com/rmtheis/tess-two/compare/9.0.0...HEAD) + +## [9.0.0](https://github.com/rmtheis/tess-two/tree/9.0.0) (2018-04-20) +[Full Changelog](https://github.com/rmtheis/tess-two/compare/8.0.0...9.0.0) + +**Change:** + +- This version fixes and adds back in the 64-bit ABIs, and removes the deprecated armv5 and mips/mips64 ABIs. + +**Implemented enhancements:** + +- Improve developer support for Hindi/Arabic [\#240](https://github.com/rmtheis/tess-two/issues/240) + +**Fixed bugs:** + +- Crashing reported on 64-bit devices [\#197](https://github.com/rmtheis/tess-two/issues/197) + +**Merged pull requests:** + +- Updated repositories. Changed compile to implementation. [\#233](https://github.com/rmtheis/tess-two/pull/233) ([mauriciotogneri](https://github.com/mauriciotogneri)) +- Updated version of SDK, build tools and support libraries [\#231](https://github.com/rmtheis/tess-two/pull/231) ([mauriciotogneri](https://github.com/mauriciotogneri)) + +## [8.0.0](https://github.com/rmtheis/tess-two/tree/8.0.0) (2017-08-13) +[Full Changelog](https://github.com/rmtheis/tess-two/compare/7.0.0...8.0.0) + +**Change:** + +- This version removes the 64-bit ABIs from the default build in order to avoid crashes due to [\#197](https://github.com/rmtheis/tess-two/issues/197) + +**Closed issues:** + +- Build failure with Android Studio 3 and NDK ver. 15.x [\#215](https://github.com/rmtheis/tess-two/issues/215) + +**Merged pull requests:** + +- clone tag 3.04.00 from tessdata [\#217](https://github.com/rmtheis/tess-two/pull/217) ([ivankolev](https://github.com/ivankolev)) +- See issue \#215 [\#216](https://github.com/rmtheis/tess-two/pull/216) ([ivankolev](https://github.com/ivankolev)) + +## [7.0.0](https://github.com/rmtheis/tess-two/tree/7.0.0) (2017-06-12) +[Full Changelog](https://github.com/rmtheis/tess-two/compare/6.3.0...7.0.0) + +**API-breaking change:** + +- ResultIterator getChoicesAndConfidence\(\) is now getSymbolChoicesAndConfidence\(\) + +**Fixed bugs:** + +- ResultIterator crashes with certain character combinations [\#126](https://github.com/rmtheis/tess-two/issues/126) +- ResultIterator returns single Character as Alternatives for Words [\#119](https://github.com/rmtheis/tess-two/issues/119) +- beginDocument\(\) returns false even when successful [\#103](https://github.com/rmtheis/tess-two/issues/103) + +**Closed issues:** + +- Hardcoded path in TessBaseAPITest.java [\#208](https://github.com/rmtheis/tess-two/issues/208) + +**Merged pull requests:** + +- Add missing PageSegMode constant [\#209](https://github.com/rmtheis/tess-two/pull/209) ([Robyer](https://github.com/Robyer)) +- Fix return value of BeginDocument \(fixes \#103\) [\#207](https://github.com/rmtheis/tess-two/pull/207) ([Robyer](https://github.com/Robyer)) +- Improve ResultIterator [\#206](https://github.com/rmtheis/tess-two/pull/206) ([Robyer](https://github.com/Robyer)) +- Update gradle plugin [\#205](https://github.com/rmtheis/tess-two/pull/205) ([Robyer](https://github.com/Robyer)) +- Fix javadocs errors and warnings [\#202](https://github.com/rmtheis/tess-two/pull/202) ([Robyer](https://github.com/Robyer)) ## [6.3.0](https://github.com/rmtheis/tess-two/tree/6.2.0) (2017-04-06) [Full Changelog](https://github.com/rmtheis/tess-two/compare/6.2.0...6.3.0) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 012cc1951..93b4f47fd 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -32,3 +32,12 @@ Phone/device architecture (armeabi, armeabi-v7a, x86, mips, arm64-v8a, x86_64, m +Link to training data used: + + + +Link to image used as input: + + + + diff --git a/README.md b/README.md index f7bc80fea..121f5b131 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ To use tess-two from your app, edit your app module's `build.gradle` file to add tess-two as an external dependency: dependencies { - compile 'com.rmtheis:tess-two:6.3.0' + implementation 'com.rmtheis:tess-two:9.0.0' } [Javadoc][javadoc] is available. @@ -84,6 +84,12 @@ submitting a pull request through GitHub. See the License for the specific language governing permissions and limitations under the License. +## See Also + +The Google Mobile Vision API team has made available an OCR capability that is +provided to developers through the Google Play Services library: The +[Mobile Vision API][mobile-vision-api] offers a simple API for OCR that +currently works for Latin-based characters. [tesseract-android-tools]: https://github.com/alanv/tesseract-android-tools [tesseract-ocr]: https://github.com/tesseract-ocr/tesseract @@ -93,3 +99,4 @@ submitting a pull request through GitHub. [javadoc]: https://rmtheis.github.io/tess-two/javadoc/index.html [semantic-versioning]: http://semver.org [stackoverflow]: https://stackoverflow.com/ +[mobile-vision-api]: https://developers.google.com/vision/ diff --git a/build.gradle b/build.gradle index 90daee674..d2a6ef4b2 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.0' + classpath 'com.android.tools.build:gradle:3.1.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' } @@ -14,9 +15,10 @@ buildscript { allprojects { group = 'com.rmtheis' - version = '6.3.0' + version = '9.0.0' repositories { + google() jcenter() } } diff --git a/eyes-two/build.gradle b/eyes-two/build.gradle index 2dc45ff77..9c77d1b7a 100644 --- a/eyes-two/build.gradle +++ b/eyes-two/build.gradle @@ -6,14 +6,14 @@ Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) android { - compileSdkVersion 23 - buildToolsVersion '25.0.0' + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { minSdkVersion 9 - targetSdkVersion 9 + targetSdkVersion 22 versionCode 1 - versionName "1.0" + versionName '1.0' } sourceSets { @@ -59,6 +59,6 @@ android { } dependencies { - compile project(':tess-two'); - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation project(':tess-two') + implementation fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/eyes-two/src/main/jni/Application.mk b/eyes-two/src/main/jni/Application.mk index 855cbbf61..af9bf9a7b 100644 --- a/eyes-two/src/main/jni/Application.mk +++ b/eyes-two/src/main/jni/Application.mk @@ -1,3 +1,3 @@ -APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64 mips64 +APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 APP_OPTIM := release NDK_TOOLCHAIN_VERSION := clang diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f85a41816..08e8ae50e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Apr 02 14:22:01 PDT 2017 +#Thu Apr 19 17:52:32 PDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/preparetests.cmd b/preparetests.cmd index f0305b0e5..2de2016d2 100644 --- a/preparetests.cmd +++ b/preparetests.cmd @@ -1,20 +1,21 @@ -git clone https://github.com/tesseract-ocr/tessdata.git +for /f %%i in ('adb shell echo $EXTERNAL_STORAGE') do set DIR=%%i -adb shell rm /sdcard/testAddPageToDocument.pdf -adb shell rm /sdcard/testCreate.pdf +git clone -b 3.04.00 https://github.com/tesseract-ocr/tessdata.git + +adb shell rm %DIR%/testAddPageToDocument.pdf +adb shell rm %DIR%/testCreate.pdf adb uninstall com.googlecode.tesseract.android.test -adb shell mkdir /sdcard/tesseract -adb shell mkdir /sdcard/tesseract/tessdata +adb shell mkdir %DIR%/tessdata -adb push -p tessdata/eng.cube.bigrams /sdcard/tesseract/tessdata -adb push -p tessdata/eng.cube.fold /sdcard/tesseract/tessdata -adb push -p tessdata/eng.cube.lm /sdcard/tesseract/tessdata -adb push -p tessdata/eng.cube.nn /sdcard/tesseract/tessdata -adb push -p tessdata/eng.cube.params /sdcard/tesseract/tessdata -adb push -p tessdata/eng.cube.size /sdcard/tesseract/tessdata -adb push -p tessdata/eng.cube.word-freq /sdcard/tesseract/tessdata -adb push -p tessdata/eng.tesseract_cube.nn /sdcard/tesseract/tessdata -adb push -p tessdata/eng.traineddata /sdcard/tesseract/tessdata -adb push -p tess-two/jni/com_googlecode_tesseract_android/src/tessdata/pdf.ttf /sdcard/tesseract/tessdata +adb push -p tessdata/eng.cube.bigrams %DIR%/tessdata +adb push -p tessdata/eng.cube.fold %DIR%/tessdata +adb push -p tessdata/eng.cube.lm %DIR%/tessdata +adb push -p tessdata/eng.cube.nn %DIR%/tessdata +adb push -p tessdata/eng.cube.params %DIR%/tessdata +adb push -p tessdata/eng.cube.size %DIR%/tessdata +adb push -p tessdata/eng.cube.word-freq %DIR%/tessdata +adb push -p tessdata/eng.tesseract_cube.nn %DIR%/tessdata +adb push -p tessdata/eng.traineddata %DIR%/tessdata +adb push -p tess-two/jni/com_googlecode_tesseract_android/src/tessdata/pdf.ttf %DIR%/tessdata diff --git a/preparetests.sh b/preparetests.sh index b8f3b4cf1..76ed94a8c 100755 --- a/preparetests.sh +++ b/preparetests.sh @@ -1,17 +1,18 @@ #!/bin/sh -git clone https://github.com/tesseract-ocr/tessdata.git +DIR="`adb shell echo \\$EXTERNAL_STORAGE`" -adb shell rm /sdcard/testAddPageToDocument.pdf -adb shell rm /sdcard/testCreate.pdf +git clone -b 3.04.00 https://github.com/tesseract-ocr/tessdata.git + +adb shell rm $DIR/testAddPageToDocument.pdf +adb shell rm $DIR/testCreate.pdf adb uninstall com.googlecode.tesseract.android.test -adb shell mkdir /sdcard/tesseract -adb shell mkdir /sdcard/tesseract/tessdata +adb shell mkdir $DIR/tessdata for f in tessdata/eng.*; do - TRAINEDDATA_FILENAME="/sdcard/tesseract/tessdata/`basename $f`" + TRAINEDDATA_FILENAME="$DIR/tessdata/`basename $f`" if [ `adb shell "if [ -f $TRAINEDDATA_FILENAME ]; then echo 1; fi"` ]; then echo "$TRAINEDDATA_FILENAME already present on device" @@ -19,9 +20,9 @@ for f in tessdata/eng.*; do fi echo "Copying $f to device..."; - adb push -p $f /sdcard/tesseract/tessdata + adb push -p $f $DIR/tessdata done -adb push -p tess-two/jni/com_googlecode_tesseract_android/src/tessdata/pdf.ttf /sdcard/tesseract/tessdata +adb push -p tess-two/jni/com_googlecode_tesseract_android/src/tessdata/pdf.ttf $DIR/tessdata # adb shell am instrument -w com.googlecode.tesseract.android.test/android.test.InstrumentationTestRunner diff --git a/tess-two-test/build.gradle b/tess-two-test/build.gradle index 49e45b13a..0394475b8 100644 --- a/tess-two-test/build.gradle +++ b/tess-two-test/build.gradle @@ -1,14 +1,14 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 23 - buildToolsVersion '25.0.0' + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { minSdkVersion 9 targetSdkVersion 22 versionCode 1 - versionName "1.0" + versionName '1.0' } sourceSets { @@ -28,7 +28,6 @@ android { } dependencies { - compile project(':tess-two'); - compile fileTree(dir: 'libs', include: ['*.jar']) - testCompile 'junit:junit:4.12' -} + implementation project(':tess-two') + testImplementation 'junit:junit:4.12' +} \ No newline at end of file diff --git a/tess-two-test/src/com/googlecode/tesseract/android/test/TessBaseAPITest.java b/tess-two-test/src/com/googlecode/tesseract/android/test/TessBaseAPITest.java index 24b42526f..1e5277a70 100644 --- a/tess-two-test/src/com/googlecode/tesseract/android/test/TessBaseAPITest.java +++ b/tess-two-test/src/com/googlecode/tesseract/android/test/TessBaseAPITest.java @@ -16,7 +16,6 @@ package com.googlecode.tesseract.android.test; -import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Canvas; @@ -26,6 +25,7 @@ import android.graphics.Paint.Style; import android.graphics.Rect; import android.os.AsyncTask; +import android.os.Environment; import android.test.suitebuilder.annotation.SmallTest; import android.text.Html; import android.util.Pair; @@ -47,10 +47,9 @@ import java.util.concurrent.Semaphore; public class TessBaseAPITest extends TestCase { - @SuppressLint("SdCardPath") - static final String TESSBASE_PATH = "/sdcard/tesseract/"; + static final String TESSBASE_PATH = Environment.getExternalStorageDirectory().toString(); static final String DEFAULT_LANGUAGE = "eng"; - private static final String TESSDATA_PATH = TESSBASE_PATH + "tessdata/"; + private static final String TESSDATA_PATH = TESSBASE_PATH + "/tessdata/"; private static final String[] EXPECTED_CUBE_DATA_FILES_ENG = { "eng.cube.bigrams", "eng.cube.fold", @@ -112,7 +111,7 @@ public void testChoiceIterator() { List> choicesAndConfidences; iterator.begin(); do { - choicesAndConfidences = iterator.getChoicesAndConfidence(PageIteratorLevel.RIL_SYMBOL); + choicesAndConfidences = iterator.getSymbolChoicesAndConfidence(); assertNotNull("Invalid result.", choicesAndConfidences); for (Pair choiceAndConfidence : choicesAndConfidences) { diff --git a/tess-two-test/src/com/googlecode/tesseract/android/test/TessPdfRendererTest.java b/tess-two-test/src/com/googlecode/tesseract/android/test/TessPdfRendererTest.java index 39fc0a61d..a5a4a25cf 100644 --- a/tess-two-test/src/com/googlecode/tesseract/android/test/TessPdfRendererTest.java +++ b/tess-two-test/src/com/googlecode/tesseract/android/test/TessPdfRendererTest.java @@ -75,7 +75,7 @@ public void testAddPageToDocument() throws IOException { // Start the PDF writing process. boolean beginSuccess = baseApi.beginDocument(pdfRenderer, "title"); - // assertTrue(beginSuccess); + assertTrue(beginSuccess); // Add a page to the PDF. final Pix pixOne = getTextImage("page one", 640, 480); diff --git a/tess-two/build.gradle b/tess-two/build.gradle index b471e07ba..9a236281c 100644 --- a/tess-two/build.gradle +++ b/tess-two/build.gradle @@ -8,14 +8,14 @@ Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) android { - compileSdkVersion 23 - buildToolsVersion '25.0.0' + compileSdkVersion 27 + buildToolsVersion '27.0.3' defaultConfig { minSdkVersion 9 targetSdkVersion 22 versionCode 1 - versionName "1.0" + versionName '1.0' consumerProguardFiles 'proguard-rules.pro' } @@ -60,7 +60,8 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "com.android.support:support-annotations:27.1.1" } diff --git a/tess-two/jni/Application.mk b/tess-two/jni/Application.mk index 4576c3284..f734e7c37 100644 --- a/tess-two/jni/Application.mk +++ b/tess-two/jni/Application.mk @@ -1,5 +1,5 @@ APP_STL := gnustl_static -APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a x86_64 mips64 +APP_ABI := armeabi-v7a x86 arm64-v8a x86_64 APP_OPTIM := release APP_PLATFORM := android-9 APP_CPPFLAGS += -fexceptions -frtti diff --git a/tess-two/jni/com_googlecode_leptonica_android/utilities.cpp b/tess-two/jni/com_googlecode_leptonica_android/utilities.cpp index 51d1ca1aa..1bc0dcf04 100644 --- a/tess-two/jni/com_googlecode_leptonica_android/utilities.cpp +++ b/tess-two/jni/com_googlecode_leptonica_android/utilities.cpp @@ -39,7 +39,7 @@ jlong Java_com_googlecode_leptonica_android_AdaptiveMap_nativeBackgroundNormMorp PIX *pixd = pixBackgroundNormMorph(pixs, NULL, (l_int32) reduction, (l_int32) size, (l_int32) bgval); - return (jlong) pixd; + return jlong(pixd); } jlong Java_com_googlecode_leptonica_android_AdaptiveMap_nativePixContrastNorm(JNIEnv *env, @@ -55,7 +55,7 @@ jlong Java_com_googlecode_leptonica_android_AdaptiveMap_nativePixContrastNorm(JN PIX *pixd = pixContrastNorm(NULL, pixs, (l_int32) sizeX, (l_int32) sizeY, (l_int32) minDiff, (l_int32) smoothX, (l_int32) smoothY); - return (jlong) pixd; + return jlong(pixd); } /************ @@ -79,7 +79,7 @@ jlong Java_com_googlecode_leptonica_android_Binarize_nativeOtsuAdaptiveThreshold return (jlong) 0; } - return (jlong) pixd; + return jlong(pixd); } jlong Java_com_googlecode_leptonica_android_Binarize_nativeSauvolaBinarizeTiled(JNIEnv *env, @@ -98,7 +98,7 @@ jlong Java_com_googlecode_leptonica_android_Binarize_nativeSauvolaBinarizeTiled( return (jlong) 0; } - return (jlong) pixd; + return jlong(pixd); } /******** @@ -112,7 +112,7 @@ jlong Java_com_googlecode_leptonica_android_Clip_nativeClipRectangle(JNIEnv *env BOX *box = (BOX *) nativeBox; PIX *pixd; pixd = pixClipRectangle(pixs,box,NULL); - return (jlong) pixd; + return jlong(pixd); } /*********** @@ -124,7 +124,7 @@ jlong Java_com_googlecode_leptonica_android_Convert_nativeConvertTo8(JNIEnv *env PIX *pixs = (PIX *) nativePix; PIX *pixd = pixConvertTo8(pixs, FALSE); - return (jlong) pixd; + return jlong(pixd); } /******** @@ -138,7 +138,7 @@ jlong Java_com_googlecode_leptonica_android_Edge_nativePixSobelEdgeFilter(JNIEnv PIX *pixs = (PIX *) nativePix; PIX *pixd = pixSobelEdgeFilter(pixs, (l_int32) orientFlag); - return (jlong) pixd; + return jlong(pixd); } /*********** @@ -152,7 +152,7 @@ jlong Java_com_googlecode_leptonica_android_Enhance_nativeUnsharpMasking(JNIEnv PIX *pixs = (PIX *) nativePix; PIX *pixd = pixUnsharpMasking(pixs, (l_int32) halfwidth, (l_float32) fract); - return (jlong) pixd; + return jlong(pixd); } /************* @@ -164,7 +164,7 @@ jlong Java_com_googlecode_leptonica_android_GrayQuant_nativePixThresholdToBinary PIX *pixs = (PIX *) nativePix; PIX *pixd = pixThresholdToBinary(pixs, (l_int32) thresh); - return (jlong) pixd; + return jlong(pixd); } /********** @@ -206,7 +206,7 @@ jlong Java_com_googlecode_leptonica_android_MorphApp_nativePixTophat(JNIEnv *env PIX *pixs = (PIX *) nativePix; PIX *pixd = pixTophat(pixs, (l_int32) hsize, (l_int32) vsize, (l_int32) type); - return (jlong) pixd; + return jlong(pixd); } jlong Java_com_googlecode_leptonica_android_MorphApp_nativePixFastTophat(JNIEnv *env, jclass clazz, @@ -215,7 +215,7 @@ jlong Java_com_googlecode_leptonica_android_MorphApp_nativePixFastTophat(JNIEnv PIX *pixs = (PIX *) nativePix; PIX *pixd = pixFastTophat(pixs, (l_int32) xsize, (l_int32) ysize, (l_int32) type); - return (jlong) pixd; + return jlong(pixd); } /********* @@ -225,18 +225,17 @@ jlong Java_com_googlecode_leptonica_android_MorphApp_nativePixFastTophat(JNIEnv jlong Java_com_googlecode_leptonica_android_Scale_nativeScaleGeneral(JNIEnv *env, jclass clazz, jlong nativePix, jfloat scaleX, jfloat scaleY, jfloat sharpfract, jint sharpwidth) { - PIX *pixs = (PIX *) nativePix; - PIX *pixd = pixScaleGeneral(pixs, (l_float32) scaleX, (l_float32) scaleY,(l_float32) sharpfract, (l_int32) sharpwidth); - return (jlong) pixd; + PIX *pixs = (Pix *) nativePix; + return (jlong) pixScaleGeneral(pixs, (l_float32) scaleX, (l_float32) scaleY,(l_float32) sharpfract, (l_int32) sharpwidth); } jlong Java_com_googlecode_leptonica_android_Scale_nativeScale(JNIEnv *env, jclass clazz, jlong nativePix, jfloat scaleX, jfloat scaleY) { - PIX *pixs = (PIX *) nativePix; + PIX *pixs = (Pix *) nativePix; PIX *pixd = pixScale(pixs, (l_float32) scaleX, (l_float32) scaleY); - return (jlong) pixd; + return jlong(pixd); } /******** @@ -291,7 +290,7 @@ jlong Java_com_googlecode_leptonica_android_Rotate_nativeRotate(JNIEnv *env, jcl pixd = pixRotate(pixs, radians, type, L_BRING_IN_WHITE, w, h); } - return (jlong) pixd; + return jlong(pixd); } jlong Java_com_googlecode_leptonica_android_Rotate_nativeRotateOrth(JNIEnv *env, jclass clazz, @@ -300,7 +299,7 @@ jlong Java_com_googlecode_leptonica_android_Rotate_nativeRotateOrth(JNIEnv *env, PIX *pixs = (PIX *) nativePix; PIX *pixd; pixd = pixRotateOrth(pixs,(int)quads); - return (jlong) pixd; + return jlong(pixd); } #ifdef __cplusplus diff --git a/tess-two/jni/com_googlecode_tesseract_android/resultiterator.cpp b/tess-two/jni/com_googlecode_tesseract_android/resultiterator.cpp index 7f2424e97..cac17f0b0 100644 --- a/tess-two/jni/com_googlecode_tesseract_android/resultiterator.cpp +++ b/tess-two/jni/com_googlecode_tesseract_android/resultiterator.cpp @@ -48,21 +48,20 @@ jfloat Java_com_googlecode_tesseract_android_ResultIterator_nativeConfidence(JNI return (jfloat) resultIterator->Confidence(enumLevel); } -jobjectArray Java_com_googlecode_tesseract_android_ResultIterator_nativeGetChoices(JNIEnv *env, - jobject thiz, jlong nativeResultIterator, jint level) { +jobjectArray Java_com_googlecode_tesseract_android_ResultIterator_nativeGetSymbolChoices(JNIEnv *env, + jclass clazz, jlong nativeResultIterator) { - // Get the actual result iterator and level (as C objects) - PageIteratorLevel enumLevel = (PageIteratorLevel) level; + // Get the actual result iterator (as C object) ResultIterator *resultIterator = (ResultIterator *) nativeResultIterator; - // Create a choice iterator to determine to the number of alternatives + // Create a choice iterator to determine the number of alternatives tesseract::ChoiceIterator ci(*resultIterator); int numberOfAlternatives = 0; do { numberOfAlternatives++; } while (ci.Next()); - // Create a string array to hold the results + // Create a string array to hold the choices jobjectArray ret = (jobjectArray) env->NewObjectArray(numberOfAlternatives, env->FindClass("java/lang/String"), env->NewStringUTF("")); // Save each result to the output array @@ -73,7 +72,7 @@ jobjectArray Java_com_googlecode_tesseract_android_ResultIterator_nativeGetChoic const char *utfText = cb.GetUTF8Text(); // Add each string to the object array elements - char newString[strlen(utfText) + 5]; + char newString[strlen(utfText) + 7]; sprintf(newString, "%s|%.2f", utfText, cb.Confidence()); env->SetObjectArrayElement(ret, i, env->NewStringUTF(newString)); @@ -85,13 +84,29 @@ jobjectArray Java_com_googlecode_tesseract_android_ResultIterator_nativeGetChoic return ret; } +jboolean Java_com_googlecode_tesseract_android_ResultIterator_nativeIsAtBeginningOf(JNIEnv *env, + jclass clazz, jlong nativeResultIterator, jint level) { + ResultIterator *resultIterator = (ResultIterator *) nativeResultIterator; + PageIteratorLevel enumLevel = (PageIteratorLevel) level; + + return (jboolean) (resultIterator->IsAtBeginningOf(enumLevel) ? JNI_TRUE : JNI_FALSE); +} + +jboolean Java_com_googlecode_tesseract_android_ResultIterator_nativeIsAtFinalElement(JNIEnv *env, + jclass clazz, jlong nativeResultIterator, jint level, jint element) { + ResultIterator *resultIterator = (ResultIterator *) nativeResultIterator; + PageIteratorLevel enumLevel = (PageIteratorLevel) level; + PageIteratorLevel enumElement = (PageIteratorLevel) element; + + return (jboolean) (resultIterator->IsAtFinalElement(enumLevel, enumElement) ? JNI_TRUE : JNI_FALSE); +} + void Java_com_googlecode_tesseract_android_ResultIterator_nativeDelete(JNIEnv *env, jclass clazz, jlong nativeResultIterator) { ResultIterator *resultIterator = (ResultIterator *) nativeResultIterator; if (resultIterator != 0) { delete resultIterator; } - return; } #ifdef __cplusplus diff --git a/tess-two/jni/com_googlecode_tesseract_android/tessbaseapi.cpp b/tess-two/jni/com_googlecode_tesseract_android/tessbaseapi.cpp index 272255d4c..09f2792f1 100644 --- a/tess-two/jni/com_googlecode_tesseract_android/tessbaseapi.cpp +++ b/tess-two/jni/com_googlecode_tesseract_android/tessbaseapi.cpp @@ -648,15 +648,11 @@ jboolean Java_com_googlecode_tesseract_android_TessBaseAPI_nativeBeginDocument(J const char *c_title = env->GetStringUTFChars(title, NULL); tesseract::TessPDFRenderer* pdfRenderer = (tesseract::TessPDFRenderer*) jRenderer; - jboolean res = JNI_TRUE; - - if (pdfRenderer->BeginDocument(c_title)) { - res = JNI_FALSE; - } + bool res = pdfRenderer->BeginDocument(c_title); env->ReleaseStringUTFChars(title, c_title); - return res; + return (jboolean) (res ? JNI_TRUE : JNI_FALSE); } jboolean Java_com_googlecode_tesseract_android_TessBaseAPI_nativeEndDocument(JNIEnv *env, diff --git a/tess-two/jni/libjpeg/Android.mk b/tess-two/jni/libjpeg/Android.mk index db4450959..297dbfd70 100644 --- a/tess-two/jni/libjpeg/Android.mk +++ b/tess-two/jni/libjpeg/Android.mk @@ -56,6 +56,7 @@ LOCAL_SRC_FILES := \ LOCAL_CFLAGS := \ -include stdlib.h \ + -Wno-deprecated-declarations \ -Wno-pointer-sign \ -Wno-implicit-function-declaration diff --git a/tess-two/src/com/googlecode/leptonica/android/Binarize.java b/tess-two/src/com/googlecode/leptonica/android/Binarize.java index 6641c76e0..07e807d4b 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Binarize.java +++ b/tess-two/src/com/googlecode/leptonica/android/Binarize.java @@ -16,6 +16,8 @@ package com.googlecode.leptonica.android; +import android.support.annotation.FloatRange; + /** * Image binarization methods. * @@ -118,8 +120,8 @@ public static Pix otsuAdaptiveThreshold(Pix pixs) { * 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) { + public static Pix otsuAdaptiveThreshold(Pix pixs, int sizeX, int sizeY, int smoothX, int smoothY, + @FloatRange(from=0.0, to=1.0) float scoreFraction) { if (pixs == null) throw new IllegalArgumentException("Source pix must be non-null"); if (pixs.getDepth() != 8) @@ -154,7 +156,7 @@ public static Pix sauvolaBinarizeTiled(Pix pixs) { * Notes: *
    *
  1. The window width and height are 2 * whsize + 1. The minimum - * value for whsize is 2; typically it is >= 7. + * value for whsize is 2; typically it is >= 7. *
  2. For nx == ny == 1, this defaults to pixSauvolaBinarize(). *
  3. Why a tiled version? * (a) Because the mean value accumulator is a uint32, overflow @@ -169,7 +171,7 @@ public static Pix sauvolaBinarizeTiled(Pix pixs) { * where: * t = local threshold * m = local mean - * k = @factor (>= 0) [ typ. 0.35 ] + * 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. *
  4. The basic idea of Niblack and Sauvola binarization is that @@ -180,12 +182,13 @@ public static Pix sauvolaBinarizeTiled(Pix pixs) { * * @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 + * @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) { + public static Pix sauvolaBinarizeTiled(Pix pixs, int whsize, @FloatRange(from=0.0) float factor, + int nx, int ny) { if (pixs == null) throw new IllegalArgumentException("Source pix must be non-null"); if (pixs.getDepth() != 8) diff --git a/tess-two/src/com/googlecode/leptonica/android/Box.java b/tess-two/src/com/googlecode/leptonica/android/Box.java index 823244106..4f2b44165 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Box.java +++ b/tess-two/src/com/googlecode/leptonica/android/Box.java @@ -17,6 +17,7 @@ package com.googlecode.leptonica.android; import android.graphics.Rect; +import android.support.annotation.Size; import android.util.Log; /** @@ -186,7 +187,7 @@ public int[] getGeometry() { * @param geometry A 4+ element integer array to fill with coordinates. * @return true on success */ - public boolean getGeometry(int[] geometry) { + public boolean getGeometry(@Size(min=4) int[] geometry) { if (mRecycled) throw new IllegalStateException(); diff --git a/tess-two/src/com/googlecode/leptonica/android/Boxa.java b/tess-two/src/com/googlecode/leptonica/android/Boxa.java index 052548e06..ec1a5903d 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Boxa.java +++ b/tess-two/src/com/googlecode/leptonica/android/Boxa.java @@ -17,6 +17,7 @@ package com.googlecode.leptonica.android; import android.graphics.Rect; +import android.support.annotation.Size; import android.util.Log; /** @@ -117,7 +118,7 @@ public int[] getGeometry(int index) { * @param geometry A 4+ element integer array to fill with coordinates. * @return true on success */ - public boolean getGeometry(int index, int[] geometry) { + public boolean getGeometry(int index, @Size(min=4) int[] geometry) { if (mRecycled) throw new IllegalStateException(); diff --git a/tess-two/src/com/googlecode/leptonica/android/Clip.java b/tess-two/src/com/googlecode/leptonica/android/Clip.java index b4fa0bbc7..d742b26ae 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Clip.java +++ b/tess-two/src/com/googlecode/leptonica/android/Clip.java @@ -33,7 +33,6 @@ public class Clip { * 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: - *

    *

    (1) clip the box to the pix *

    (2) make a new pix equal to the full box dimensions, * but let rasterop do the clipping and positioning @@ -56,7 +55,7 @@ public class Clip { * @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(), + long result = nativeClipRectangle(source.getNativePix(), box.getNativeBox()); if (result != 0) { return new Pix(result); @@ -68,5 +67,5 @@ public static Pix clipRectangle(Pix source, Box box) { // * NATIVE CODE * // *************** - private static native int nativeClipRectangle(long nativePix, long nativeBox); + private static native long nativeClipRectangle(long nativePix, long nativeBox); } \ No newline at end of file diff --git a/tess-two/src/com/googlecode/leptonica/android/Constants.java b/tess-two/src/com/googlecode/leptonica/android/Constants.java index 9dc5b8eec..fb94763e1 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Constants.java +++ b/tess-two/src/com/googlecode/leptonica/android/Constants.java @@ -16,6 +16,12 @@ package com.googlecode.leptonica.android; +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + /** * Leptonica constants. * @@ -46,6 +52,10 @@ public class Constants { * and L_INSERT and L_NOCOPY are always 0. */ + @Retention(SOURCE) + @IntDef({L_INSERT, L_COPY, L_CLONE}) + public @interface StorageFlag {} + /* Stuff it in; no copy, clone or copy-clone */ public static final int L_INSERT = 0; @@ -65,12 +75,21 @@ public class Constants { * Sort flags * *--------------------------------------------------------------------------*/ + @Retention(SOURCE) + @IntDef({L_SORT_INCREASING, L_SORT_DECREASING}) + public @interface SortOrder {} + /* Sort in increasing order */ public static final int L_SORT_INCREASING = 1; /* Sort in decreasing order */ public static final int L_SORT_DECREASING = 2; + @Retention(SOURCE) + @IntDef({L_SORT_BY_X, L_SORT_BY_Y, L_SORT_BY_WIDTH, L_SORT_BY_HEIGHT, L_SORT_BY_MIN_DIMENSION, + L_SORT_BY_MAX_DIMENSION, L_SORT_BY_PERIMETER, L_SORT_BY_ASPECT_RATIO}) + public @interface SortBy {} + /* Sort box or c.c. by horiz location */ public static final int L_SORT_BY_X = 3; diff --git a/tess-two/src/com/googlecode/leptonica/android/Edge.java b/tess-two/src/com/googlecode/leptonica/android/Edge.java index ccce11416..08e7a79e3 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Edge.java +++ b/tess-two/src/com/googlecode/leptonica/android/Edge.java @@ -16,6 +16,12 @@ package com.googlecode.leptonica.android; +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + /** * Edge detection. */ @@ -28,6 +34,9 @@ public class Edge { } // Edge orientation flags + @Retention(SOURCE) + @IntDef({L_HORIZONTAL_EDGES, L_VERTICAL_EDGES, L_ALL_EDGES}) + public @interface EdgeOrientationFlag {} /** Filters for horizontal edges */ public static final int L_HORIZONTAL_EDGES = 0; @@ -52,7 +61,6 @@ public class Edge { * using pixThresholdToBinary(). If the high edge values are to be fg (1), * invert after running pixThresholdToBinary(). *

  5. Label the pixels as follows: - *

    *

    1 4 7 *

    2 5 8 *

    3 6 9 @@ -66,7 +74,7 @@ public class Edge { * 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) { + public static Pix pixSobelEdgeFilter(Pix pixs, @EdgeOrientationFlag int orientFlag) { if (pixs == null) throw new IllegalArgumentException("Source pix must be non-null"); if (pixs.getDepth() != 8) diff --git a/tess-two/src/com/googlecode/leptonica/android/JpegIO.java b/tess-two/src/com/googlecode/leptonica/android/JpegIO.java index d6195bc9b..870aa6ad2 100644 --- a/tess-two/src/com/googlecode/leptonica/android/JpegIO.java +++ b/tess-two/src/com/googlecode/leptonica/android/JpegIO.java @@ -18,6 +18,7 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; +import android.support.annotation.IntRange; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -60,7 +61,8 @@ public static byte[] compressToJpeg(Pix pixs) { * @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) { + public static byte[] compressToJpeg(Pix pixs, @IntRange(from=0, to=100) int quality, + boolean progressive) { if (pixs == null) throw new IllegalArgumentException("Source pix must be non-null"); if (quality < 0 || quality > 100) diff --git a/tess-two/src/com/googlecode/leptonica/android/MorphApp.java b/tess-two/src/com/googlecode/leptonica/android/MorphApp.java index 474525a13..0c64292a4 100644 --- a/tess-two/src/com/googlecode/leptonica/android/MorphApp.java +++ b/tess-two/src/com/googlecode/leptonica/android/MorphApp.java @@ -16,6 +16,12 @@ package com.googlecode.leptonica.android; +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + /** * Composite image processing operations. */ @@ -28,7 +34,9 @@ public class MorphApp { } // Morphological tophat flags - + @Retention(SOURCE) + @IntDef({L_TOPHAT_BLACK, L_TOPHAT_WHITE}) + public @interface TophatType {} public static final int L_TOPHAT_WHITE = 0; public static final int L_TOPHAT_BLACK = 1; @@ -55,7 +63,7 @@ public class MorphApp { * @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) { + public static Pix pixTophat(Pix pixs, int hsize, int vsize, @TophatType int type) { if (pixs == null) throw new IllegalArgumentException("Source pix must be non-null"); if (pixs.getDepth() != 8) @@ -122,12 +130,12 @@ public static Pix pixFastTophatWhite(Pix pixs) { *

* * @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 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) { + public static Pix pixFastTophat(Pix pixs, int xsize, int ysize, @TophatType int type) { if (pixs == null) throw new IllegalArgumentException("Source pix must be non-null"); if (pixs.getDepth() != 8) diff --git a/tess-two/src/com/googlecode/leptonica/android/Pix.java b/tess-two/src/com/googlecode/leptonica/android/Pix.java index cef205e05..c1a215cb3 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Pix.java +++ b/tess-two/src/com/googlecode/leptonica/android/Pix.java @@ -17,6 +17,8 @@ package com.googlecode.leptonica.android; import android.graphics.Rect; +import android.support.annotation.ColorInt; +import android.support.annotation.Size; /** * Java representation of a native Leptonica PIX object. @@ -125,7 +127,7 @@ public int[] getDimensions() { * @param dimensions An integer array with at least three elements. * @return true on success */ - public boolean getDimensions(int[] dimensions) { + public boolean getDimensions(@Size(min=3) int[] dimensions) { if (mRecycled) throw new IllegalStateException(); @@ -297,7 +299,7 @@ public int getPixel(int x, int y) { * specified coordinate. * @throws IllegalArgumentException If x, y exceeds the image bounds. */ - public void setPixel(int x, int y, int color) { + public void setPixel(int x, int y, @ColorInt int color) { if (mRecycled) throw new IllegalStateException(); diff --git a/tess-two/src/com/googlecode/leptonica/android/Pixa.java b/tess-two/src/com/googlecode/leptonica/android/Pixa.java index e91fe6317..aba993857 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Pixa.java +++ b/tess-two/src/com/googlecode/leptonica/android/Pixa.java @@ -17,6 +17,7 @@ package com.googlecode.leptonica.android; import android.graphics.Rect; +import android.support.annotation.Size; import android.util.Log; import java.io.File; @@ -119,7 +120,7 @@ public Pixa copy() { if (mRecycled) throw new IllegalStateException(); - int nativePixa = nativeCopy(mNativePixa); + long nativePixa = nativeCopy(mNativePixa); if (nativePixa == 0) { throw new OutOfMemoryError(); @@ -138,11 +139,11 @@ public Pixa copy() { * Constants.L_SORT_INCREASING or Constants.L_SORT_DECREASING. * @return a sorted copy of this Pixa */ - public Pixa sort(int field, int order) { + public Pixa sort(@Constants.SortBy int field, @Constants.SortOrder int order) { if (mRecycled) throw new IllegalStateException(); - int nativePixa = nativeSort(mNativePixa, field, order); + long nativePixa = nativeSort(mNativePixa, field, order); if (nativePixa == 0) { throw new OutOfMemoryError(); @@ -211,7 +212,7 @@ public boolean join(Pixa otherPixa) { * @param mode The mode in which to add this Pix, typically * Constants.L_CLONE. */ - public void addPix(Pix pix, int mode) { + public void addPix(Pix pix, @Constants.StorageFlag int mode) { if (mRecycled) throw new IllegalStateException(); @@ -225,7 +226,7 @@ public void addPix(Pix pix, int mode) { * @param mode The mode in which to add this Box, typically * Constants.L_CLONE. */ - public void addBox(Box box, int mode) { + public void addBox(Box box, @Constants.StorageFlag int mode) { if (mRecycled) throw new IllegalStateException(); @@ -240,7 +241,7 @@ public void addBox(Box box, int mode) { * @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) { + public void add(Pix pix, Box box, @Constants.StorageFlag int mode) { if (mRecycled) throw new IllegalStateException(); @@ -355,7 +356,7 @@ public int[] getBoxGeometry(int index) { * elements. * @return true on success */ - public boolean getBoxGeometry(int index, int[] dimensions) { + public boolean getBoxGeometry(int index, @Size(min=4) int[] dimensions) { if (mRecycled) throw new IllegalStateException(); @@ -483,11 +484,11 @@ public void remove() { // * NATIVE CODE * // *************** - private static native int nativeCreate(int size); + private static native long nativeCreate(int size); - private static native int nativeCopy(long nativePixa); + private static native long nativeCopy(long nativePixa); - private static native int nativeSort(long nativePixa, int field, int order); + private static native long nativeSort(long nativePixa, int field, int order); private static native boolean nativeJoin(long nativePixa, long otherPixa); diff --git a/tess-two/src/com/googlecode/leptonica/android/Rotate.java b/tess-two/src/com/googlecode/leptonica/android/Rotate.java index 769bbf055..f04d88286 100644 --- a/tess-two/src/com/googlecode/leptonica/android/Rotate.java +++ b/tess-two/src/com/googlecode/leptonica/android/Rotate.java @@ -16,6 +16,8 @@ package com.googlecode.leptonica.android; +import android.support.annotation.IntRange; + /** * @author alanv@google.com (Alan Viverette) */ @@ -101,13 +103,13 @@ public static Pix rotate(Pix pixs, float degrees, boolean quality, boolean resiz * @param quads 0-3; number of 90 degree cw rotations * @return the rotated source image */ - public static Pix rotateOrth(Pix pixs, int quads) { + public static Pix rotateOrth(Pix pixs, @IntRange(from=0, to=3) 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.getNativePix(), quads); + long nativePix = nativeRotateOrth(pixs.getNativePix(), quads); if (nativePix == 0) return null; @@ -119,7 +121,7 @@ public static Pix rotateOrth(Pix pixs, int quads) { // * NATIVE CODE * // *************** - private static native int nativeRotateOrth(long nativePix, int quads); + private static native long nativeRotateOrth(long nativePix, int quads); private static native long nativeRotate(long nativePix, float degrees, boolean quality, boolean resize); diff --git a/tess-two/src/com/googlecode/leptonica/android/WriteFile.java b/tess-two/src/com/googlecode/leptonica/android/WriteFile.java index d77a307e1..03c0dee3d 100644 --- a/tess-two/src/com/googlecode/leptonica/android/WriteFile.java +++ b/tess-two/src/com/googlecode/leptonica/android/WriteFile.java @@ -112,18 +112,19 @@ public static Bitmap writeBitmap(Pix pixs) { throw new IllegalArgumentException("Source pix must be non-null"); final int[] dimensions = pixs.getDimensions(); - final int width = dimensions[Pix.INDEX_W]; - final int height = dimensions[Pix.INDEX_H]; + if (dimensions != null) { + final int width = dimensions[Pix.INDEX_W]; + final int height = dimensions[Pix.INDEX_H]; - final Bitmap.Config config = Bitmap.Config.ARGB_8888; - final Bitmap bitmap = Bitmap.createBitmap(width, height, config); + final Bitmap.Config config = Bitmap.Config.ARGB_8888; + final Bitmap bitmap = Bitmap.createBitmap(width, height, config); - if (nativeWriteBitmap(pixs.getNativePix(), bitmap)) { - return bitmap; - } - - bitmap.recycle(); + if (nativeWriteBitmap(pixs.getNativePix(), bitmap)) { + return bitmap; + } + bitmap.recycle(); + } return null; } diff --git a/tess-two/src/com/googlecode/tesseract/android/PageIterator.java b/tess-two/src/com/googlecode/tesseract/android/PageIterator.java index 6cd8a7c26..5330d7332 100644 --- a/tess-two/src/com/googlecode/tesseract/android/PageIterator.java +++ b/tess-two/src/com/googlecode/tesseract/android/PageIterator.java @@ -60,7 +60,7 @@ public void begin() { * @return {@code false} if the end of the page was reached, {@code true} * otherwise. */ - public boolean next(int level) { + public boolean next(@PageIteratorLevel.Level int level) { return nativeNext(mNativePageIterator, level); } @@ -70,7 +70,7 @@ public boolean next(int level) { * ============= Accessing data ==============. *

* Coordinate system: - *

    + *
      *
    • Integer coordinates are at the cracks between the pixels. *
    • The top-left corner of the top-left pixel in the image is at (0,0). *
    • The bottom-right corner of the bottom-right pixel in the image is at @@ -78,7 +78,7 @@ public boolean next(int level) { *
    • Every bounding box goes from the top-left of the top-left contained * pixel to the bottom-right of the bottom-right contained pixel, so * the bounding box of the single top-left pixel in the image is: - * (0,0)->(1,1). + * (0,0)->(1,1). *
    • If an image rectangle has been set in the API, then returned coordinates * relate to the original (full) image, rather than the rectangle. *

    @@ -90,7 +90,7 @@ public boolean next(int level) { * @param level the page iterator level. See {@link PageIteratorLevel}. * @return the bounding rectangle of the current object at the given level */ - public int[] getBoundingBox(int level) { + public int[] getBoundingBox(@PageIteratorLevel.Level int level) { return nativeBoundingBox(mNativePageIterator, level); } @@ -102,7 +102,7 @@ public int[] getBoundingBox(int level) { * @param level the page iterator level. See {@link PageIteratorLevel}. * @return the bounding rectangle of the current object at the given level */ - public Rect getBoundingRect(int level) { + public Rect getBoundingRect(@PageIteratorLevel.Level int level) { int[] box = getBoundingBox(level); return new Rect(box[0], box[1], box[2], box[3]); } diff --git a/tess-two/src/com/googlecode/tesseract/android/ResultIterator.java b/tess-two/src/com/googlecode/tesseract/android/ResultIterator.java index d970f01fa..dcdc5c53d 100644 --- a/tess-two/src/com/googlecode/tesseract/android/ResultIterator.java +++ b/tess-two/src/com/googlecode/tesseract/android/ResultIterator.java @@ -54,7 +54,7 @@ public class ResultIterator extends PageIterator { * @param level the page iterator level. See {@link PageIteratorLevel}. * @return the text string for the current object at the given level. */ - public String getUTF8Text(int level) { + public String getUTF8Text(@PageIteratorLevel.Level int level) { return nativeGetUTF8Text(mNativeResultIterator, level); } @@ -65,23 +65,47 @@ public String getUTF8Text(int level) { * @param level the page iterator level. See {@link PageIteratorLevel}. * @return the mean confidence of the current object at the given level. */ - public float confidence(int level) { + public float confidence(@PageIteratorLevel.Level int level) { return nativeConfidence(mNativeResultIterator, level); } + /** + * Returns true if the iterator is at the start of an object at the given + * level. Possible uses include determining if a call to Next(RIL_WORD) + * moved to the start of a RIL_PARA. + * + * @param level the page iterator level. See {@link PageIteratorLevel}. + * @return {@code true} if iterator points to the start of an object at the given level. + */ + public boolean isAtBeginningOf(@PageIteratorLevel.Level int level) { + return nativeIsAtBeginningOf(mNativeResultIterator, level); + } + + /** + * Returns whether the iterator is positioned at the last element in a + * given level. (e.g. the last word in a line, the last line in a block) + * + * @param level the page iterator level. See {@link PageIteratorLevel}. + * @param element the page iterator level. See {@link PageIteratorLevel}. + * @return {@code true} if iterator points to the last element in a given level. + */ + public boolean isAtFinalElement(@PageIteratorLevel.Level int level, + @PageIteratorLevel.Level int element) { + return nativeIsAtFinalElement(mNativeResultIterator, level, element); + } + /** * Returns all possible matching text strings and their confidence level - * for the current object at the given level. + * for the current object. *

    * The default matching text is blank (""). * The default confidence level is zero (0.0) * - * @param level the page iterator level. See {@link PageIteratorLevel}. - * @return A list of pairs with the UTF string and the confidence + * @return A list of pairs with the UTF symbol and the confidence */ - public List> getChoicesAndConfidence(int level) { + public List> getSymbolChoicesAndConfidence() { // Get the native choices - String[] nativeChoices = nativeGetChoices(mNativeResultIterator, level); + String[] nativeChoices = nativeGetSymbolChoices(mNativeResultIterator); // Create the output list ArrayList> pairedResults = new ArrayList>(); @@ -121,9 +145,11 @@ public void delete() { nativeDelete(mNativeResultIterator); } - private static native String[] nativeGetChoices(long nativeResultIterator, int level); + private static native String[] nativeGetSymbolChoices(long nativeResultIterator); private static native String nativeGetUTF8Text(long nativeResultIterator, int level); private static native float nativeConfidence(long nativeResultIterator, int level); - private static native void nativeDelete(long nativeIterator); + private static native boolean nativeIsAtBeginningOf(long nativeResultIterator, int level); + private static native boolean nativeIsAtFinalElement(long nativeResultIterator, int level, int element); + private static native void nativeDelete(long nativeResultIterator); } diff --git a/tess-two/src/com/googlecode/tesseract/android/TessBaseAPI.java b/tess-two/src/com/googlecode/tesseract/android/TessBaseAPI.java index b3cf14596..57b0718a2 100644 --- a/tess-two/src/com/googlecode/tesseract/android/TessBaseAPI.java +++ b/tess-two/src/com/googlecode/tesseract/android/TessBaseAPI.java @@ -17,15 +17,20 @@ package com.googlecode.tesseract.android; -import java.io.File; - import android.graphics.Bitmap; import android.graphics.Rect; +import android.support.annotation.IntDef; +import android.support.annotation.WorkerThread; import com.googlecode.leptonica.android.Pix; import com.googlecode.leptonica.android.Pixa; import com.googlecode.leptonica.android.ReadFile; +import java.io.File; +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + /** * Java interface for the Tesseract OCR engine. Does not implement all available * JNI methods, but does implement enough to be useful. Comments are adapted @@ -51,6 +56,12 @@ public class TessBaseAPI { /** Page segmentation mode. */ public static final class PageSegMode { + @Retention(SOURCE) + @IntDef({PSM_OSD_ONLY, PSM_AUTO_OSD, PSM_AUTO_ONLY, PSM_AUTO, PSM_SINGLE_COLUMN, + PSM_SINGLE_BLOCK_VERT_TEXT, PSM_SINGLE_BLOCK, PSM_SINGLE_LINE, PSM_SINGLE_WORD, + PSM_CIRCLE_WORD, PSM_SINGLE_CHAR, PSM_SPARSE_TEXT, PSM_SPARSE_TEXT_OSD, PSM_RAW_LINE}) + public @interface Mode {} + /** Orientation and script detection only. */ public static final int PSM_OSD_ONLY = 0; @@ -90,8 +101,8 @@ public static final class PageSegMode { /** Sparse text with orientation and script detection. */ public static final int PSM_SPARSE_TEXT_OSD = 12; - /** Number of enum entries. */ - public static final int PSM_COUNT = 13; + /** Treat the image as a single text line, bypassing hacks that are Tesseract-specific. */ + public static final int PSM_RAW_LINE = 13; } /** Whitelist of characters to recognize. */ @@ -109,6 +120,10 @@ public static final class PageSegMode { /** String value used to assign a boolean variable to false. */ public static final String VAR_FALSE = "F"; + @Retention(SOURCE) + @IntDef({OEM_TESSERACT_ONLY, OEM_CUBE_ONLY, OEM_TESSERACT_CUBE_COMBINED, OEM_DEFAULT}) + public @interface OcrEngineMode {} + /** Run Tesseract only - fastest */ public static final int OEM_TESSERACT_ONLY = 0; @@ -132,6 +147,10 @@ public static final class PageSegMode { * as there is no paragraph internally yet. */ public static final class PageIteratorLevel { + @Retention(SOURCE) + @IntDef({RIL_BLOCK, RIL_PARA, RIL_TEXTLINE, RIL_WORD, RIL_SYMBOL}) + public @interface Level {} + /** Block of text/image/separator line. */ public static final int RIL_BLOCK = 0; @@ -256,7 +275,7 @@ public TessBaseAPI(ProgressNotifier progressNotifier) { * multiple times on the same instance to change language, or just to reset * the classifier. *

    - * The language may be a string of the form [~][+[~]]* indicating + * The language may be a string of the form {@code [~][+[~]]*} indicating * that multiple languages are to be loaded. Eg hin+eng will load Hindi and * English. Languages may specify internally that they want to be loaded * with one or more other languages, so the ~ sign is available to override @@ -296,7 +315,7 @@ public boolean init(String datapath, String language) { * @param ocrEngineMode the OCR engine mode to be set * @return true on success */ - public boolean init(String datapath, String language, int ocrEngineMode) { + public boolean init(String datapath, String language, @OcrEngineMode int ocrEngineMode) { if (datapath == null) throw new IllegalArgumentException("Data path must not be null!"); if (!datapath.endsWith(File.separator)) @@ -318,6 +337,17 @@ public boolean init(String datapath, String language, int ocrEngineMode) { languageCode + ".traineddata"); if (!datafile.exists()) throw new IllegalArgumentException("Data file not found at " + datafile); + + // Catch some common problematic initialization cases. + if (languageCode.equals("ara") || (languageCode.equals("hin") && + ocrEngineMode == OEM_DEFAULT)) { + boolean sampleCubeFileExists = new File(tessdata + + File.separator + languageCode + ".cube.params").exists(); + if (!sampleCubeFileExists) { + throw new IllegalArgumentException("Cube data files not found." + + " See https://github.com/rmtheis/tess-two/issues/239"); + } + } } } } @@ -409,7 +439,7 @@ public boolean setVariable(String var, String value) { * * @return value of the current page segmentation mode */ - public int getPageSegMode() { + public @PageSegMode.Mode int getPageSegMode() { if (mRecycled) throw new IllegalStateException(); @@ -426,7 +456,7 @@ public int getPageSegMode() { * * @param mode the {@link PageSegMode} to set */ - public void setPageSegMode(int mode) { + public void setPageSegMode(@PageSegMode.Mode int mode) { if (mRecycled) throw new IllegalStateException(); @@ -486,6 +516,7 @@ public void setRectangle(int left, int top, int width, int height) { * * @param file absolute path to the image file */ + @WorkerThread public void setImage(File file) { if (mRecycled) throw new IllegalStateException(); @@ -510,6 +541,7 @@ public void setImage(File file) { * * @param bmp bitmap representation of the image */ + @WorkerThread public void setImage(Bitmap bmp) { if (mRecycled) throw new IllegalStateException(); @@ -532,6 +564,7 @@ public void setImage(Bitmap bmp) { * * @param image Leptonica pix representation of the image */ + @WorkerThread public void setImage(Pix image) { if (mRecycled) throw new IllegalStateException(); @@ -552,6 +585,7 @@ public void setImage(Pix image) { * @param bpp bytes per pixel * @param bpl bytes per line */ + @WorkerThread public void setImage(byte[] imagedata, int width, int height, int bpp, int bpl) { if (mRecycled) throw new IllegalStateException(); @@ -567,6 +601,7 @@ public void setImage(byte[] imagedata, int width, int height, int bpp, int bpl) * * @return the recognized text */ + @WorkerThread public String getUTF8Text() { if (mRecycled) throw new IllegalStateException(); @@ -726,6 +761,7 @@ public ResultIterator getResultIterator() { * @param page is 0-based but will appear in the output as 1-based. * @return HTML-formatted string with hOCR markup */ + @WorkerThread public String getHOCRText(int page){ if (mRecycled) throw new IllegalStateException(); @@ -934,6 +970,7 @@ private native void nativeSetImageBytes( private native void nativeSetDebug(long mNativeData, boolean debug); + @PageSegMode.Mode private native int nativeGetPageSegMode(long mNativeData); private native void nativeSetPageSegMode(long mNativeData, int mode);