chiark / gitweb /
Do not flush in ocr debug if debug not enabled
[ypp-sc-tools.web-live.git] / pctb / ocr.c
index c747b20..92b0903 100644 (file)
@@ -83,6 +83,8 @@ struct OcrCellTypeInfo {
 struct OcrReader {
   int h;
   DatabaseNode contexts[NCONTEXTS];
+  char *result;
+  int lresult, aresult;
   OcrResultGlyph *results;
   int aresults, nresults;
 };
@@ -120,14 +122,17 @@ static void readdb1(OcrReader *rd, const char *which, int local) {
   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 v2"));
+  dbassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v3 depth=" STRING(AADEPTH)));
 
   dbassert( dbfile_scanf("%d", &h) == 1);
   dbassert(h==rd->h);
@@ -221,6 +226,84 @@ static void readdb1(OcrReader *rd, const char *which, int local) {
   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="";
@@ -240,7 +323,10 @@ static void callout_unknown(OcrReader *rd, int w, const Pixcol cols[],
   const char *p;
 
   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");
@@ -265,10 +351,10 @@ static void callout_unknown(OcrReader *rd, int w, const Pixcol cols[],
   fputc('\n',resolver);
 
   fprintf(resolver,
-         "P2\n%d %d\n%d\n", w, rd->h, AAMAXVAL);
+         "P2\n%d %d %d\n", w, rd->h, AAMAXVAL);
   for (y=0; y<rd->h; y++) {
     for (x=0; x<w; x++)
-      fprintf(resolver, " %x", pixcol_p_get(&cols[x], y));
+      fprintf(resolver, " %d", pixcol_p_get(&cols[x], y));
     fputc('\n',resolver);
   }
 
@@ -288,6 +374,18 @@ static void add_result(OcrReader *rd, const char *s, int l, int r,
   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;
 }
 
 
@@ -299,7 +397,7 @@ static DatabaseNode *findchar_1ctx(const FindCharArgs *fca,
   int x= fca->x;
 
   for (;;) {
-    debug_flush();
+    if (DEBUGP(ocr)) debug_flush();
     debugf(" | x=%d",x);
     if (x > fca->w) break;
     Pixcol cv= fca->cols[x];
@@ -424,6 +522,8 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w,
   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(" "PIXCOL_PRFMT, PIXCOL_PRVAL(cols[x]));
   debugf("\n");
@@ -431,7 +531,7 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w,
 
   x=0;
   for (;;) {
-    debug_flush();
+    if (DEBUGP(ocr)) debug_flush();
     /* skip spaces */
     if (x>=w)
       break;
@@ -460,6 +560,10 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w,
     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)");
@@ -493,14 +597,18 @@ OcrReader *ocr_init(int h) {
 
   if (o_flags & ff_dict_fetch) {
     char *fetchfile= masprintf("char%d",h);
-    progress("Updating %s...",fetchfile);
     fetch_with_rsync(fetchfile);
     free(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;
 }
@@ -540,7 +648,7 @@ void ocr_showcharsets(void) {
 
   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);