Skip to content

Commit 7f18bb4

Browse files
committed
add OCR in koptcontext
1 parent 8f26cc3 commit 7f18bb4

File tree

5 files changed

+146
-3
lines changed

5 files changed

+146
-3
lines changed

Makefile

+9-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ koreader-base: koreader-base.o einkfb.o pdf.o blitbuffer.o drawcontext.o koptcon
3030
$(LDFLAGS) \
3131
-Wl,-rpath=$(LIBDIR)/ \
3232
-o $@ \
33-
-lm -ldl -lpthread -lk2pdfopt -ldjvulibre -lluajit-5.1 -lcrengine \
33+
-lm -ldl -lpthread -lk2pdfopt -llept -ltesseract \
34+
-ldjvulibre -lluajit-5.1 -lcrengine \
3435
-L$(MUPDFLIBDIR) -L$(LIBDIR) \
3536
$(CRE_3RD_LIBS) \
3637
$(EMU_LDFLAGS) \
@@ -96,6 +97,11 @@ fetchthirdparty:
9697
test -f popen-noshell/popen_noshell.c || svn co http://popen-noshell.googlecode.com/svn/trunk/ popen-noshell
9798
# popen_noshell patch: Make it build on recent TCs, and implement a simple Makefile for building it as a static lib
9899
cd popen-noshell && test -f Makefile || patch -N -p0 < popen_noshell-buildfix.patch
100+
# download leptonica and tesseract-ocr src for libk2pdfopt
101+
cd $(K2PDFOPTLIBDIR) && wget http://leptonica.com/source/leptonica-1.69.tar.gz \
102+
&& tar zxf leptonica-1.69.tar.gz
103+
cd $(K2PDFOPTLIBDIR) && wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.02.tar.gz \
104+
&& tar zxf tesseract-ocr-3.02.02.tar.gz
99105

100106
clean:
101107
rm -f *.o koreader-base slider_watcher extr emu_event
@@ -159,5 +165,7 @@ $(K2PDFOPTLIB):
159165
$(MAKE) -j$(PROCESSORS) -C $(K2PDFOPTLIBDIR) BUILDMODE=shared CC="$(CC)" CFLAGS="$(CFLAGS) -O3" AR="$(AR)" all
160166
test -d $(LIBDIR) || mkdir $(LIBDIR)
161167
cp -a $(K2PDFOPTLIBDIR)/libk2pdfopt.so* $(LIBDIR)
168+
cp -a $(K2PDFOPTLIBDIR)/liblept.so* $(LIBDIR)
169+
cp -a $(K2PDFOPTLIBDIR)/libtesseract.so* $(LIBDIR)
162170

163171
thirdparty: $(MUPDFLIBS) $(THIRDPARTYLIBS) $(LUALIB) $(DJVULIBS) $(CRELIB) $(CRE_3RD_LIBS) $(POPENNSLIB) $(K2PDFOPTLIB)

Makefile.defs

+6-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ endif
9393

9494
# standard includes
9595
KOREADER_BASE_CFLAGS=$(CFLAGS) -I$(LUADIR)/src -I$(MUPDFDIR)/
96-
K2PDFOPT_CFLAGS=-I$(K2PDFOPTLIBDIR)/willuslib -I$(K2PDFOPTLIBDIR)/k2pdfoptlib -I$(K2PDFOPTLIBDIR)/
96+
K2PDFOPT_CFLAGS=-I$(K2PDFOPTLIBDIR)/willuslib -I$(K2PDFOPTLIBDIR)/k2pdfoptlib \
97+
-I$(K2PDFOPTLIBDIR)/ -I$(K2PDFOPTLIBDIR)/include_mod
9798

9899
# enable tracing output:
99100

@@ -124,4 +125,8 @@ LUALIB := $(LIBDIR)/libluajit-5.1.so.2
124125

125126
POPENNSLIB := $(POPENNSDIR)/libpopen_noshell.a
126127

128+
LEPTONICALIB := $(LIBDIR)/liblept.so.3
129+
130+
TESSERACTLIB := $(LIBDIR)/libtesseract.so.3
131+
127132
K2PDFOPTLIB := $(LIBDIR)/libk2pdfopt.so.1

koptcontext.c

+129
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19+
#include <assert.h>
1920
#include "koptcontext.h"
2021

2122
static int newKOPTContext(lua_State *L) {
@@ -47,6 +48,7 @@ static int newKOPTContext(lua_State *L) {
4748

4849
BBox bbox = {0, 0, 0, 0};
4950
int precache = 0;
51+
int debug = 0;
5052

5153
KOPTContext *kc = (KOPTContext*) lua_newuserdata(L, sizeof(KOPTContext));
5254

@@ -78,6 +80,10 @@ static int newKOPTContext(lua_State *L) {
7880

7981
kc->bbox = bbox;
8082
kc->precache = precache;
83+
kc->debug = debug;
84+
85+
kc->boxa = NULL;
86+
kc->nai = NULL;
8187

8288
bmp_init(&kc->src);
8389
bmp_init(&kc->dst);
@@ -95,6 +101,8 @@ static int freeContext(lua_State *L) {
95101
* bitmap since the usage of dst bitmap is delayed most of the times.
96102
*/
97103
bmp_free(&kc->dst);
104+
boxaDestroy(&kc->boxa);
105+
numaDestroy(&kc->nai);
98106
return 0;
99107
}
100108

@@ -249,6 +257,123 @@ static int kcIsPreCache(lua_State *L) {
249257
return 1;
250258
}
251259

260+
static int kcSetDebug(lua_State *L) {
261+
KOPTContext *kc = (KOPTContext*) luaL_checkudata(L, 1, "koptcontext");
262+
kc->debug = 1;
263+
return 0;
264+
}
265+
266+
static int kcGetWordBoxes(lua_State *L) {
267+
KOPTContext *kc = (KOPTContext*) luaL_checkudata(L, 1, "koptcontext");
268+
int x = luaL_checkint(L, 2);
269+
int y = luaL_checkint(L, 3);
270+
int w = luaL_checkint(L, 4);
271+
int h = luaL_checkint(L, 5);
272+
BOX *box;
273+
l_float32 max_val;
274+
int nr_line, last_index, nr_word, current_line;
275+
int counter_l, counter_w, counter_cw;
276+
int l_x0, l_y0, l_x1, l_y1;
277+
278+
k2pdfopt_get_word_boxes(kc, &kc->dst, x, y, w, h, 1, 10, 10, 300, 100);
279+
/* get number of lines in this area */
280+
numaGetMax(kc->nai, &max_val, &last_index);
281+
nr_line = (int) max_val;
282+
/* get number of lines in this area */
283+
nr_word = boxaGetCount(kc->boxa);
284+
assert(nr_word == numaGetCount(kc->nai));
285+
/* table that contains all the words */
286+
lua_newtable(L);
287+
lua_pushstring(L, "box_only");
288+
lua_pushnumber(L, 1);
289+
lua_settable(L, -3);
290+
for (counter_w = 0; counter_w < nr_word; counter_w++) {
291+
numaGetIValue(kc->nai, counter_w, &counter_l);
292+
current_line = counter_l;
293+
/* subtable that contains words in a line */
294+
lua_pushnumber(L, counter_l+1);
295+
lua_newtable(L);
296+
counter_cw = 0;
297+
l_y0 = l_x0 = 9999;
298+
l_x1 = l_y1 = 0;
299+
while (current_line == counter_l && counter_w < nr_word) {
300+
box = boxaGetBox(kc->boxa, counter_w, L_CLONE);
301+
/* create table that contains box for a word */
302+
lua_pushnumber(L, counter_cw+1);
303+
lua_newtable(L);
304+
counter_w++;
305+
counter_cw++;
306+
307+
/* update line box */
308+
l_x0 = box->x < l_x0 ? box->x : l_x0;
309+
l_y0 = box->y < l_y0 ? box->y : l_y0;
310+
l_x1 = box->x + box->w > l_x1 ? box->x + box->w : l_x1;
311+
l_y1 = box->y + box->h > l_y1 ? box->y + box->h : l_y1;
312+
313+
/* set word box */
314+
lua_pushstring(L, "x0");
315+
lua_pushnumber(L, box->x);
316+
lua_settable(L, -3);
317+
318+
lua_pushstring(L, "y0");
319+
lua_pushnumber(L, box->y);
320+
lua_settable(L, -3);
321+
322+
lua_pushstring(L, "x1");
323+
lua_pushnumber(L, box->x + box->w);
324+
lua_settable(L, -3);
325+
326+
lua_pushstring(L, "y1");
327+
lua_pushnumber(L, box->y + box->h);
328+
lua_settable(L, -3);
329+
330+
//printf("box %d:%d,%d,%d,%d\n",counter_w,box->x,box->y,box->w,box->h);
331+
/* set word entry to line subtable */
332+
lua_settable(L, -3);
333+
if (counter_w < nr_word)
334+
numaGetIValue(kc->nai, counter_w, &counter_l);
335+
} /* end of while */
336+
if (current_line != counter_l) counter_w--;
337+
/* box for a whole line */
338+
lua_pushstring(L, "x0");
339+
lua_pushnumber(L, l_x0);
340+
lua_settable(L, -3);
341+
lua_pushstring(L, "y0");
342+
lua_pushnumber(L, l_y0);
343+
lua_settable(L, -3);
344+
lua_pushstring(L, "x1");
345+
lua_pushnumber(L, l_x1);
346+
lua_settable(L, -3);
347+
lua_pushstring(L, "y1");
348+
lua_pushnumber(L, l_y1);
349+
lua_settable(L, -3);
350+
/* set line entry to box table */
351+
lua_settable(L, -3);
352+
} /* end of for */
353+
354+
return 1;
355+
}
356+
357+
static int kcGetOCRWord(lua_State *L) {
358+
KOPTContext *kc = (KOPTContext*) luaL_checkudata(L, 1, "koptcontext");
359+
const char *datadir = luaL_checkstring(L, 2);
360+
const char *lang = luaL_checkstring(L, 3);
361+
int x = luaL_checkint(L, 4);
362+
int y = luaL_checkint(L, 5);
363+
int w = luaL_checkint(L, 6);
364+
int h = luaL_checkint(L, 7);
365+
char word[256];
366+
367+
ocrtess_init(datadir, lang, 3, NULL);
368+
ocrtess_single_word_from_bmp8(
369+
word, 255, &kc->dst,
370+
x, y, x + w, y + h, 3, 0, 1, NULL);
371+
ocrtess_end();
372+
373+
lua_pushstring(L, word);
374+
return 1;
375+
}
376+
252377
static const struct luaL_Reg koptcontext_meth[] = {
253378
{"setBBox", kcSetBBox},
254379
{"setTrim", kcSetTrim},
@@ -276,6 +401,10 @@ static const struct luaL_Reg koptcontext_meth[] = {
276401

277402
{"setPreCache", kcSetPreCache},
278403
{"isPreCache", kcIsPreCache},
404+
{"setDebug", kcSetDebug},
405+
406+
{"getWordBoxes", kcGetWordBoxes},
407+
{"getOCRWord", kcGetOCRWord},
279408

280409
{"free", freeContext},
281410
{"__gc", freeContext},

koptcontext.h

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <lualib.h>
2323
#include <lauxlib.h>
2424
#include "context.h"
25+
#include "koptocr.h"
2526

2627
int luaopen_koptcontext(lua_State *L);
2728
#endif

0 commit comments

Comments
 (0)