chiark / gitweb /
antialiasing text conversion: seems to handle it in the C code so far ....
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 4 Jul 2009 11:50:04 +0000 (12:50 +0100)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Sat, 4 Jul 2009 11:50:04 +0000 (12:50 +0100)
pctb/common.h
pctb/ocr.c
pctb/ocr.h
pctb/structure.c

index 23b8ca33972d29bf589cae1799896c70408392bf..d4464bdbefa4adf958d8619d5d2b63ef8c3ab88d 100644 (file)
@@ -163,6 +163,6 @@ char *masprintf(const char *fmt, ...) FMT(1,2);
 
 
 #define ARRAYSIZE(a) ((sizeof((a)) / sizeof((a)[0])))
-
+#define FILLZERO(obj) (memset(&(obj),0,sizeof((obj))))
 
 #endif /*COMMON_H*/
index 6482b81430292af3a7c4da942088ce0e0ce00ace..c747b205cfc8f7eaca3c31bd40a130181341e8de 100644 (file)
@@ -44,7 +44,7 @@ typedef struct {
   OcrReader *rd;
   OcrCellType ct;
   int w;
-  Pixcol *cols;
+  const Pixcol *cols;
   int x;
   unsigned ctxmap;
 } FindCharArgs;
@@ -127,7 +127,7 @@ static void readdb1(OcrReader *rd, const char *which, int local) {
     goto x;
 
   FGETSLINE;
-  dbassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v1"));
+  dbassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v2"));
 
   dbassert( dbfile_scanf("%d", &h) == 1);
   dbassert(h==rd->h);
@@ -161,12 +161,20 @@ static void readdb1(OcrReader *rd, const char *which, int local) {
     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, &current->links[j].col)) {
          current= current->links[j].then;
          goto found_link;
        }
@@ -225,12 +233,11 @@ static void cu_pr_ctxmap(FILE *resolver, unsigned ctxmap) {
   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))
@@ -258,20 +265,12 @@ static void callout_unknown(OcrReader *rd, int w, Pixcol cols[],
   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\n%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, " %x", pixcol_p_get(&cols[x], y));
+    fputc('\n',resolver);
   }
-  fputs("};\n",resolver);
 
   resolve_finish();
   readdb(rd);
@@ -304,9 +303,9 @@ static DatabaseNode *findchar_1ctx(const FindCharArgs *fca,
     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, &current->links[i].col))
        goto found;
     /* not found */
     debugf(" ?");
@@ -408,7 +407,8 @@ const struct OcrCellTypeInfo ocr_celltype_text= {
 
 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;
 
@@ -425,7 +425,7 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
   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]);
+  for (x=0; x<w; x++) debugf(" "PIXCOL_PRFMT, PIXCOL_PRVAL(cols[x]));
   debugf("\n");
   debug_flush();
 
@@ -436,7 +436,7 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
     if (x>=w)
       break;
 
-    if (!cols[x]) {
+    if (!pixcol_nonzero(&cols[x])) {
       nspaces++;
       x++;
       if (nspaces == ct->space_spaces) {
@@ -472,7 +472,7 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
     } 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);
@@ -489,6 +489,8 @@ OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
 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);
@@ -529,7 +531,7 @@ static int show_char_compar(const void *av, const void *bv) {
 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];
index 5269723b50262494cb951189441cc77a25ed4351..7848ae7d2601988043c61363106d8a21a341148f 100644 (file)
 #define AAMAXVAL ((1<<AADEPTH)-1)
 
 
-typedef uint32_t Pixcol;
-#define PSPIXCOL(priscan) priscan##32
+typedef uint32_t Pixcolv;
+#define PIXCOL_P_PER_WORD (32 / AADEPTH)
+
+#define OCR_MAX_H    30
+#define PIXCOL_WORDS ((OCR_MAX_H + PIXCOL_P_PER_WORD - 1) / PIXCOL_P_PER_WORD)
+
+typedef struct { Pixcolv w[PIXCOL_WORDS]; } Pixcol;
+
+static inline int pixcol_p_word(int y) {
+  return y / PIXCOL_P_PER_WORD;
+}
+static inline int pixcol_p_shift(int y) {
+  return (y % PIXCOL_P_PER_WORD)*AADEPTH;
+}
+static inline void pixcol_p_add(Pixcol *pixcol, int y, unsigned pixval) {
+  pixcol->w[pixcol_p_word(y)] |= pixval << pixcol_p_shift(y);
+}
+static inline unsigned int pixcol_p_get(const Pixcol *pixcol, int y) {
+  return (pixcol->w[pixcol_p_word(y)] >> pixcol_p_shift(y)) & AAMAXVAL;
+}
+static inline int pixcol_cmp(const Pixcol *pixcol1, const Pixcol *pixcol2) {
+  return memcmp(pixcol1, pixcol2, sizeof(*pixcol1));
+}
+static inline int pixcol_nonzero(const Pixcol *pixcol) {
+  static const Pixcol zero;
+  return pixcol_cmp(pixcol, &zero);
+}
+
+#if AADEPTH==3
+# define PRPIXCOL1 "%0*" PRIo32
+#else
+# error need to implement PRPIXCOL1 for this AADEPTH
+#endif
+
+#if PIXCOL_WORDS==3
+# define PIXCOL_PRFMT                          \
+                             PRPIXCOL1 "-"     \
+                             PRPIXCOL1 "-"     \
+                             PRPIXCOL1
+# define PIXCOL_PRVAL(pixcol)                                  \
+                             PIXCOL_P_PER_WORD, (pixcol).w[2], \
+                             PIXCOL_P_PER_WORD, (pixcol).w[1], \
+                             PIXCOL_P_PER_WORD, (pixcol).w[0]
+#else
+# error need to implement PIXCOL_PR{FMT,VAL} for this PIXCOL_WORDS
+#endif
 
 typedef struct {
   const char *s; /* valid until next call to ocr() */
@@ -57,7 +101,7 @@ typedef struct OcrReader OcrReader;
 OcrReader *ocr_init(int h);
 void ocr_showcharsets(void);
 
-OcrResultGlyph *ocr(OcrReader *rd, OcrCellType, int w, Pixcol cols[]);
+OcrResultGlyph *ocr(OcrReader *rd, OcrCellType, int w, const Pixcol cols[]);
   /* return value is array terminated by {0,-1,-1}
    * array is valid until next call to ocr()
    */
index 5a593887350025f8ce39c5e5d2a90e9c72df61e9..da80cb9fda86297b74e57f8e6a37ec7a887244bd 100644 (file)
@@ -320,6 +320,8 @@ void find_structure(CanonImage *im, int *max_relevant_y_r) {
   SET_ONCE(text_h, comminty - 1);
   if (max_relevant_y_r)
     SET_ONCE(*max_relevant_y_r, mainr.br.y + 10);
+
+  MUST( text_h <= OCR_MAX_H, MI(text_h) );
 }                  
 
 void check_correct_commodities(void) {
@@ -527,22 +529,17 @@ static void ocr_rectangle(Rect r, const OcrCellType ct, FILE *tsv_output) {
   Pixcol cols[w+1];
   int x,y;
   for (x=0; x<w; x++) {
-    Pixcol cx, rv;
-    for (y=0, cx=0, rv=1; y<text_h; y++, rv<<=1) {
+    FILLZERO(cols[x]);
+    for (y=0; y<text_h; y++) {
       Point here= { x+r.tl.x, y+r.tl.y };
       int pixel= get_p(here);
-      switch (pixel) {
-      case ' ':                      break;
-      case '0':                      break;
-      case '0'+AAMAXVAL:  cx |= rv;  break;
-      default:
-       MUST(!"wrong pixel",
-            MC(pixel);MP(here);MSB(ocr_celltype_name(ct));MR(r); );
-      }
+      if (pixel==' ') pixel= '0';
+      MUST( pixel >= '0' && pixel <= '0'+AAMAXVAL,
+           MC(pixel);MP(here);MSB(ocr_celltype_name(ct));MR(r); );
+      pixcol_p_add(&cols[x], y, pixel-'0');
     }
-    cols[x]= cx;
   }
-  cols[w]= 0;
+  FILLZERO(cols[w]);
 
   results= ocr(rd,ct,w,cols);
   for (res=results; res->s; res++)