OcrReader *rd;
OcrCellType ct;
int w;
- Pixcol *cols;
+ const Pixcol *cols;
int x;
unsigned ctxmap;
} FindCharArgs;
struct OcrReader {
int h;
DatabaseNode contexts[NCONTEXTS];
+ char *result;
+ int lresult, aresult;
OcrResultGlyph *results;
int aresults, nresults;
};
int h, endsword;
char lbuf[100];
- char *dbfname= masprintf("%s/#%s-char%d#.txt",
+ char *dbfname= masprintf("%s/_%s-char%d.txt",
get_vardir(), which, rd->h);
if (!dbfile_open(dbfname))
goto x;
+ if (local)
+ o_flags |= ff_charset_havelocal;
+
FGETSLINE;
- dbassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v1"));
+ dbassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v3 depth=" STRING(AADEPTH)));
dbassert( dbfile_scanf("%d", &h) == 1);
dbassert(h==rd->h);
for (;;) {
FGETSLINE;
if (!lbuf[0]) { dbassert(current != &rd->contexts[ctxi]); break; }
- char *ep;
- cv= strtoul(lbuf,&ep,16); dbassert(!*ep);
- dbassert(!(cv & ~((1UL << rd->h)-1)));
+ dbassert( strlen(lbuf) == rd->h );
+ FILLZERO(cv);
+ int y;
+ for (y=0; y<h; y++) {
+ char pb[2];
+ pb[0]= lbuf[y];
+ pb[1]= 0;
+ char *ep;
+ unsigned pv= strtoul(pb,&ep,16); dbassert(!*ep);
+ pixcol_p_add(&cv, y, pv);
+ }
for (j=0; j<current->nlinks; j++)
- if (current->links[j].col == cv) {
+ if (!pixcol_cmp(&cv, ¤t->links[j].col)) {
current= current->links[j].then;
goto found_link;
}
free(dbfname);
}
+typedef struct Rejection Rejection;
+struct Rejection {
+ struct Rejection *next;
+ const char *fname;
+ int lno;
+ pcre *re;
+};
+
+Rejection *rejections;
+
+static void load_rejections(const char *which) {
+ char lbuf[1000];
+ char *fname= masprintf("%s/_%s-reject.txt", get_vardir(), which);
+ int c, lno=0;
+ Rejection *rej;
+
+ if (!dbfile_open(fname)) { free(fname); return; }
+
+ while ((c= fgetc(dbfile))!=EOF) {
+ ungetc(c,dbfile);
+ lno++;
+ dbfile_getsline(lbuf,sizeof(lbuf),fname,lno);
+
+ if (!lbuf[0] || isspace(lbuf[0] || lbuf[0]=='#'))
+ continue;
+
+ rej= mmalloc(sizeof(*rej));
+ rej->next= rejections;
+ rej->fname= fname;
+ rej->lno= lno;
+
+ const char *err;
+ int erroffset;
+ rej->re= pcre_compile(lbuf, PCRE_NO_AUTO_CAPTURE|PCRE_UTF8,
+ &err, &erroffset, 0);
+ if (!rej->re) {
+ char *what= masprintf("invalid regexp at offset %d: %s\n",
+ erroffset, err);
+ dbfile_assertfail(fname, lno, what);
+ }
+ debugf("OCR LOADED REJECTION %s:%d `%s' %p\n", fname,lno, lbuf, rej->re);
+
+ rejections= rej;
+ }
+ sysassert(feof(dbfile));
+ dbfile_close();
+}
+
+static int should_reject(OcrReader *rd) {
+ static int rejections_loaded;
+ int ovector[30];
+
+ if (!rejections_loaded) {
+ fetch_with_rsync("reject");
+ load_rejections("master");
+ load_rejections("local");
+ rejections_loaded=1;
+ }
+
+ debugf("[OCR REJECTION `%s'%d", rd->result, rd->lresult);
+ Rejection *rej;
+ for (rej=rejections; rej; rej=rej->next) {
+ debugf(" (%p)", rej);
+
+ int res= pcre_exec(rej->re, 0, rd->result,rd->lresult, 0,
+ 0, ovector, ARRAYSIZE(ovector));
+ if (res==PCRE_ERROR_NOMATCH) continue;
+ sysassert(res>0);
+
+ debugf(" MATCH]\n");
+ fprintf(stderr,"Rejecting OCR result `%s' (due to %s:%d)\n",
+ rd->result, rej->fname,rej->lno);
+ return 1;
+ }
+ debugf(" OK]");
+ return 0;
+}
+
static void cu_pr_ctxmap(FILE *resolver, unsigned ctxmap) {
fprintf(resolver,"{");
const char *spc="";
fprintf(resolver,"}");
}
-static void callout_unknown(OcrReader *rd, int w, Pixcol cols[],
+static void callout_unknown(OcrReader *rd, int w, const Pixcol cols[],
int unk_l, int unk_r, unsigned unk_ctxmap) {
int c,i, x,y;
const OcrResultGlyph *s;
const char *p;
- Pixcol pv;
FILE *resolver= resolve_start();
- if (!resolver || !(o_flags & ff_editcharset))
+ if (!resolver ||
+ !((o_flags & ff_charset_edit) ||
+ ((o_flags & ff_charset_allowedit) &&
+ (o_flags & ff_charset_havelocal))))
fatal("OCR failed - unrecognised characters or ligatures.\n"
"Character set database needs to be updated or augmented.\n"
"See README.charset.\n");
fputc('\n',resolver);
fprintf(resolver,
- "/* XPM */\n"
- "static char *t[] = {\n"
- "/* columns rows colors chars-per-pixel */\n"
- "\"%d %d 2 1\",\n"
- "\" c black\",\n"
- "\"o c white\",\n",
- w,rd->h);
- for (y=0, pv=1; y<rd->h; y++, pv<<=1) {
- fputc('"',resolver);
+ "P2\n%d %d %d\n", w, rd->h, AAMAXVAL);
+ for (y=0; y<rd->h; y++) {
for (x=0; x<w; x++)
- fputc(cols[x] & pv ? 'o' : ' ', resolver);
- fputs("\",\n",resolver);
+ fprintf(resolver, " %d", pixcol_p_get(&cols[x], y));
+ fputc('\n',resolver);
}
- fputs("};\n",resolver);
resolve_finish();
readdb(rd);
rd->results[rd->nresults].match= match;
rd->results[rd->nresults].ctxmap= ctxmap;
rd->nresults++;
+
+ if (!s) return; /* just the sentinel for the caller */
+
+ int sl= strlen(s);
+ int newlresult= rd->lresult + sl;
+ if (newlresult >= rd->aresult) {
+ rd->aresult= (newlresult << 1) + 1;
+ rd->result= mrealloc(rd->result, rd->aresult);
+ }
+ memcpy(rd->result + rd->lresult, s, sl);
+ rd->lresult= newlresult;
+ rd->result[rd->lresult]= 0;
}
debugf(" | x=%d",x);
if (x > fca->w) break;
Pixcol cv= fca->cols[x];
- debugf(" cv=%"PSPIXCOL(PRIx),cv);
+ debugf(" cv="PIXCOL_PRFMT, PIXCOL_PRVAL(cv));
for (i=0; i<current->nlinks; i++)
- if (current->links[i].col == cv)
+ if (!pixcol_cmp(&cv, ¤t->links[i].col))
goto found;
/* not found */
debugf(" ?");
const char *ocr_celltype_name(OcrCellType ct) { return ct->name; }
-OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
+OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w,
+ const Pixcol cols[]) {
int nspaces;
int x;
nspaces=- w;
fca.ctxmap= ct->initial;
rd->nresults=0;
+ rd->lresult=0;
+ rd->result[0]=0;
debugf("OCR h=%d w=%d",rd->h,w);
- for (x=0; x<w; x++) debugf(" %"PSPIXCOL(PRIx),cols[x]);
+ for (x=0; x<w; x++) debugf(" "PIXCOL_PRFMT, PIXCOL_PRVAL(cols[x]));
debugf("\n");
debug_flush();
if (x>=w)
break;
- if (!cols[x]) {
+ if (!pixcol_nonzero(&cols[x])) {
nspaces++;
x++;
if (nspaces == ct->space_spaces) {
if (match) {
debugf(" || YES");
add_result(rd, match->str, x, match_rx, match_ctxi, fca.ctxmap);
+ if (should_reject(rd)) {
+ callout_unknown(rd, w,cols, match_rx+1,match_rx, 0);
+ goto restart;
+ }
x= match_rx+1;
if (match->match) fca.ctxmap= ct->midword;
else debugf(" (empty)");
} else {
int rx;
debugf(" || UNKNOWN");
- for (rx=x; rx<w && cols[rx]; rx++);
+ for (rx=x; rx<w && pixcol_nonzero(&cols[rx]); rx++);
debugf(" x=%d ctxmap=%x %d..%d\n",x, fca.ctxmap, x,rx);
debug_flush();
callout_unknown(rd, w,cols, x,rx-1, fca.ctxmap);
OcrReader *ocr_init(int h) {
OcrReader *rd;
+ assert(h <= OCR_MAX_H);
+
if (o_flags & ff_dict_fetch) {
char *fetchfile= masprintf("char%d",h);
progress("Updating %s...",fetchfile);
rd= mmalloc(sizeof(*rd));
memset(rd,0,sizeof(*rd));
+
rd->h= h;
+
+ rd->aresult= 10;
+ rd->result= mmalloc(rd->aresult);
+
readdb(rd);
return rd;
}
void ocr_showcharsets(void) {
DIR *d;
struct dirent *de;
- char found[32];
+ char found[OCR_MAX_H];
pcre *fnpat;
int matchvec[10];
char hbuf[10];
memset(found,0,sizeof(found));
- fnpat= pcre_compile("\\#(?:master|local)\\-char([1-9]\\d{0,2})\\#\\.txt$",
+ fnpat= pcre_compile("_(?:master|local)\\-char([1-9]\\d{0,2})\\.txt$",
PCRE_ANCHORED|PCRE_DOLLAR_ENDONLY,
&pcre_err,&pcre_erroffset, 0);
debugf("pcre_compile %p %s\n",fnpat,pcre_err);