DatabaseLink *links;
} DatabaseNode;
+typedef struct {
+ OcrReader *rd;
+ int w;
+ Pixcol *cols;
+ int x;
+ unsigned ctxmap;
+} FindCharArgs;
+typedef struct {
+ DatabaseNode *match;
+ int rx;
+} FindCharResults;
+
static const char *context_names[]= {
"Lower",
"Upper",
}
-const char *ocr_celltype_name(OcrCellType ct) { return ct->name; }
-
-static DatabaseNode *findchar(OcrReader *rd, int w, Pixcol cols[],
- int x, int ctxi, int *matchx_r) {
- DatabaseNode *current= &rd->contexts[ctxi];
+static DatabaseNode *findchar_1ctx(const FindCharArgs *fca,
+ DatabaseNode *start, int *matchx_r) {
+ DatabaseNode *current= start;
DatabaseNode *bestmatch= 0;
int i;
+ int x= fca->x;
for (;;) {
debug_flush();
debugf(" | x=%d",x);
- if (x>w) break;
- Pixcol cv= cols[x];
+ if (x > fca->w) break;
+ Pixcol cv= fca->cols[x];
debugf(" cv=%"PSPIXCOL(PRIx),cv);
for (i=0; i<current->nlinks; i++)
if (current->links[i].col == cv)
return bestmatch;
}
+static DatabaseNode *findchar(const FindCharArgs *fca, int *match_rx) {
+ FindCharResults results[NCONTEXTS];
+ int ctxi, match=-1, nmatches=0;
+
+ debugf("OCR lx=%d ct_state=%x ", fca->x, fca->ctxmap);
+ for (ctxi=0; ctxi<NCONTEXTS; ctxi++) {
+ results[ctxi].match= 0;
+ if (!(fca->ctxmap & (1u << ctxi))) continue;
+ debugf(" || %s",context_names[ctxi]);
+
+ results[ctxi].match= findchar_1ctx(fca, &fca->rd->contexts[ctxi],
+ &results[ctxi].rx);
+ if (!results[ctxi].match) continue;
+
+ match= ctxi;
+ nmatches++;
+ }
+ if (nmatches==1) {
+ debugf( " unambiguous");
+ } else {
+ match=-1;
+ }
+ if (match<0)
+ return 0;
+
+ *match_rx= results[ctxi].rx;
+ return results[ctxi].match;
+}
+
+const char *ocr_celltype_name(OcrCellType ct) { return ct->name; }
+
OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
int nspaces;
- unsigned ctxmap;
- int ctxi, x;
+ int x;
+
+ FindCharArgs fca;
+ fca.rd= rd;
+ fca.w= w;
+ fca.cols= cols;
+ fca.x= -1;
restart:
nspaces=- w;
- ctxmap= ct->initial;
+ fca.ctxmap= ct->initial;
rd->nresults=0;
debugf("OCR h=%d w=%d",rd->h,w);
for (x=0; x<w; x++) debugf(" %"PSPIXCOL(PRIx),cols[x]);
x++;
if (nspaces == ct->space_spaces) {
debugf("OCR x=%x nspaces=%d space\n",x,nspaces);
- ctxmap= ct->nextword;
+ fca.ctxmap= ct->nextword;
}
continue;
}
add_result(rd," ",x-nspaces,x+1,0);
nspaces=0;
- DatabaseNode *uniquematch= 0;
- int uniquematch_rx=-1;
-
- debugf("OCR lx=%d ctxmap=%x ",x,ctxmap);
+ fca.x= x;
- for (ctxi=0; ctxi<NCONTEXTS; ctxi++) {
- if (!(ctxmap & (1u << ctxi))) continue;
- debugf(" || %s",context_names[ctxi]);
-
- DatabaseNode *match=
- findchar(rd,w,cols, x,ctxi, &uniquematch_rx);
- if (!match) continue;
-
- if (uniquematch && strcmp(match->str, uniquematch->str)) {
- debugf( " ambiguous");
- uniquematch= 0;
- } else {
- uniquematch= match;
- }
- }
-
- if (uniquematch) {
+ int match_rx=-1;
+ DatabaseNode *match= findchar(&fca, &match_rx);
+
+ if (match) {
debugf(" || YES");
- add_result(rd, uniquematch->str, x, uniquematch_rx, ctxmap);
- x= uniquematch_rx+1;
- if (uniquematch->match) ctxmap= ct->midword;
+ add_result(rd, match->str, x, match_rx, fca.ctxmap);
+ x= match_rx+1;
+ if (match->match) fca.ctxmap= ct->midword;
else debugf(" (empty)");
- if (uniquematch->endsword) {
+ if (match->endsword) {
nspaces= ct->space_spaces;
debugf("_");
- ctxmap= ct->nextword;
+ fca.ctxmap= ct->nextword;
}
debugf("\n");
} else {
int rx;
debugf(" || UNKNOWN");
for (rx=x; rx<w && cols[rx]; rx++);
- debugf(" x=%d ctxmap=%x %d..%d\n",x, ctxmap, x,rx);
+ debugf(" x=%d ctxmap=%x %d..%d\n",x, fca.ctxmap, x,rx);
debug_flush();
- callout_unknown(rd, w,cols, x,rx-1, ctxmap);
+ callout_unknown(rd, w,cols, x,rx-1, fca.ctxmap);
goto restart;
}