add test code and more assertions, as well as simplify the JNI
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/ccmain/jni.cpp b/ccmain/jni.cpp
index 59b2304..5427128 100644
--- a/ccmain/jni.cpp
+++ b/ccmain/jni.cpp
@@ -30,12 +30,14 @@
"Capture the image from the IPE");
#endif
+#define LOG_NDEBUG 0
#define LOG_TAG "OcrLib(native)"
#include <utils/Log.h>
static jfieldID field_mNativeData;
struct native_data_t {
+ native_data_t() : image_obj(NULL), image_buffer(NULL) {}
tesseract::TessBaseAPI api;
jbyteArray image_obj;
jbyte* image_buffer;
@@ -45,6 +47,98 @@
return (native_data_t *)(env->GetIntField(object, field_mNativeData));
}
+#if DEBUG
+
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define FAILIF(cond, msg...) do { \
+ if (cond) { \
+ LOGE("%s(%d): ", __FILE__, __LINE__); \
+ LOGE(msg); \
+ return; \
+ } \
+} while(0)
+
+void test_ocr(const char *infile, int x, int y, int bpp,
+ const char *outfile, const char *lang,
+ const char *ratings, const char *tessdata)
+{
+ void *buffer;
+ struct stat s;
+ int ifd, ofd;
+
+ LOGI("input file %s\n", infile);
+ ifd = open(infile, O_RDONLY);
+ FAILIF(ifd < 0, "open(%s): %s\n", infile, strerror(errno));
+ FAILIF(fstat(ifd, &s) < 0, "fstat(%d): %s\n", ifd, strerror(errno));
+ LOGI("file size %lld\n", s.st_size);
+ buffer = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, ifd, 0);
+ FAILIF(buffer == MAP_FAILED, "mmap(): %s\n", strerror(errno));
+ LOGI("infile mmapped at %p\n", buffer);
+ FAILIF(!tessdata, "You must specify a path for tessdata.\n");
+
+ tesseract::TessBaseAPI api;
+
+ LOGI("tessdata %s\n", tessdata);
+ LOGI("lang %s\n", lang);
+ FAILIF(api.Init(tessdata, lang), "could not initialize tesseract\n");
+ if (ratings) {
+ LOGI("ratings %s\n", ratings);
+ FAILIF(false == api.ReadConfigFile(ratings),
+ "could not read config file\n");
+ }
+
+ LOGI("set image x=%d, y=%d bpp=%d\n", x, y, bpp);
+ FAILIF(!bpp || bpp == 2 || bpp > 4,
+ "Invalid value %d of bpp\n", bpp);
+ api.SetImage((const unsigned char *)buffer, x, y, bpp, bpp*x);
+
+ LOGI("set rectangle to cover entire image\n");
+ api.SetRectangle(0, 0, x, y);
+
+ LOGI("set page seg mode to single character\n");
+ api.SetPageSegMode(tesseract::PSM_SINGLE_CHAR);
+ LOGI("recognize\n");
+ char * text = api.GetUTF8Text();
+ if (tessedit_write_images) {
+ page_image.write("tessinput.tif");
+ }
+ FAILIF(text == NULL, "didn't recognize\n");
+
+ FILE* fp = fopen(outfile, "w");
+ if (fp != NULL) {
+ LOGI("write to output %s\n", outfile);
+ fwrite(text, strlen(text), 1, fp);
+ fclose(fp);
+ }
+ else LOGI("could not write to output %s\n", outfile);
+
+ int mean_confidence = api.MeanTextConf();
+ LOGI("mean confidence: %d\n", mean_confidence);
+
+ int* confs = api.AllWordConfidences();
+ int len, *trav;
+ for (len = 0, trav = confs; *trav != -1; trav++, len++)
+ LOGI("confidence %d: %d\n", len, *trav);
+ free(confs);
+
+ LOGI("clearing api\n");
+ api.Clear();
+ LOGI("clearing adaptive classifier\n");
+ api.ClearAdaptiveClassifier();
+
+ LOGI("clearing text\n");
+ delete [] text;
+}
+#endif
+
jboolean
ocr_open(JNIEnv *env, jobject thiz, jstring lang)
{
@@ -84,9 +178,9 @@
return res;
}
-#if DEBUG
static void dump_debug_data(char *text)
{
+#if DEBUG
if (tessedit_write_images) {
page_image.write("/data/tessinput.tif");
}
@@ -100,23 +194,18 @@
fclose(fp);
}
}
-}
-#else
-static void dump_debug_data(char *text __attribute__((unused)))
-{
-}
#endif
+}
jstring
ocr_recognize_image(JNIEnv *env, jobject thiz,
jbyteArray image,
jint width, jint height,
- jint bpp,
- jint rowWidth)
+ jint bpp)
{
LOGV(__FUNCTION__);
- LOGI("recognize image x=%d, y=%d, rw=%d\n", width, height, rowWidth);
+ LOGI("recognize image x=%d, y=%d bpp=%d\n", width, height, bpp);
native_data_t *nat = get_native_data(env, thiz);
@@ -128,7 +217,7 @@
jbyte* buffer = env->GetByteArrayElements(image, NULL);
nat->api.SetImage((const unsigned char *)buffer,
- width, height, bpp, rowWidth);
+ width, height, bpp, bpp*width);
char * text = nat->api.GetUTF8Text();
env->ReleaseByteArrayElements(image, buffer, JNI_ABORT);
@@ -142,19 +231,24 @@
ocr_set_image(JNIEnv *env, jobject thiz,
jbyteArray image,
jint width, jint height,
- jint bpp,
- jint rowWidth)
+ jint bpp)
{
LOGV(__FUNCTION__);
- LOG_ASSERT(nat->image_obj == NULL && nat->image_buffer == NULL,
- "image and/or image_buffer are not NULL!");
+
+ LOGI("set image x=%d, y=%d, bpp=%d\n", width, height, bpp);
native_data_t *nat = get_native_data(env, thiz);
+ LOG_ASSERT(nat->image_obj == NULL && nat->image_buffer == NULL,
+ "image %p and/or image_buffer %p are not NULL!",
+ nat->image_obj,
+ nat->image_buffer);
+
nat->image_obj = (jbyteArray)env->NewGlobalRef(image);
nat->image_buffer = env->GetByteArrayElements(nat->image_obj, NULL);
+ LOG_ASSERT(nat->image_buffer != NULL, "image buffer is NULL!");
nat->api.SetImage((const unsigned char *)nat->image_buffer,
- width, height, bpp, rowWidth);
+ width, height, bpp, bpp*width);
}
void
@@ -168,16 +262,16 @@
// can be recognized with the same image.
native_data_t *nat = get_native_data(env, thiz);
+ LOGI("set rectangle left=%d, top=%d, width=%d, height=%d\n",
+ left, top, width, height);
+
LOG_ASSERT(nat->image_obj != NULL && nat->image_buffer != NULL,
"image and/or image_buffer are NULL!");
nat->api.SetRectangle(left, top, width, height);
}
jstring
-ocr_recognize(JNIEnv *env, jobject thiz,
- jint width, jint height,
- jint bpp,
- jint rowWidth)
+ocr_recognize(JNIEnv *env, jobject thiz)
{
LOGV(__FUNCTION__);
@@ -186,7 +280,9 @@
LOG_ASSERT(nat->image_obj != NULL && nat->image_buffer != NULL,
"image and/or image_buffer are NULL!");
+ LOGI("BEFORE RECOGNIZE");
char * text = nat->api.GetUTF8Text();
+ LOGI("AFTER RECOGNIZE");
dump_debug_data(text);
@@ -305,6 +401,11 @@
static void class_init(JNIEnv* env, jclass clazz) {
LOGV(__FUNCTION__);
field_mNativeData = env->GetFieldID(clazz, "mNativeData", "I");
+#if DEBUG && 0
+ test_ocr("/sdcard/chi.yuv", 106, 106, 1,
+ "/sdcard/out.txt", "chi_sim0",
+ "/sdcard/tessdata/ratings", "/sdcard/");
+#endif
}
static void initialize_native_data(JNIEnv* env, jobject object) {
@@ -332,10 +433,10 @@
{"cleanupNativeDataNative", "()V", (void *)cleanup_native_data},
{"openNative", "(Ljava/lang/String;)Z", (void*)ocr_open},
- {"setImageNative", "([BIIII)V", (void*)ocr_set_image},
+ {"setImageNative", "([BIII)V", (void*)ocr_set_image},
{"setRectangleNative", "(IIII)V", (void*)ocr_set_rectangle},
{"recognizeNative", "()Ljava/lang/String;", (void*)ocr_recognize},
- {"recognizeNative", "([BIIII)Ljava/lang/String;", (void*)ocr_recognize_image},
+ {"recognizeNative", "([BIII)Ljava/lang/String;", (void*)ocr_recognize_image},
{"clearResultsNative", "()V", (void*)ocr_clear_results},
{"closeNative", "()V", (void*)ocr_close},
{"meanConfidenceNative", "()I", (void*)ocr_mean_confidence},