8 struct OCRDatabaseNode *then;
11 #define MAXGLYPHCHRS 3
13 typedef struct OCRDatabaseNode {
14 char s[MAXGLYPHCHRS+1]; /* null-terminated; "" means no match here */
16 OCRDatabaseLink *links;
19 #define N_OCR_CONTEXTS 2
21 static OCRDatabaseNode ocr_contexts[N_OCR_CONTEXTS];
23 static OcrResultGlyph *results;
24 static int aresults, nresults;
26 static FILE *resolver;
27 static pid_t resolver_pid;
29 static void ocr_readdb(void) {
31 OCRDatabaseNode *current, *additional;
32 char chrs[MAXGLYPHCHRS+1];
37 db= fopen("database","r"); eassert(db);
40 r= fscanf(db, "%d %d", &ctx, &nchrs);
43 eassert(ctx>=0 && ctx<N_OCR_CONTEXTS);
44 eassert(nchrs>0 && nchrs<=MAXGLYPHCHRS);
46 for (i=0; i<nchrs; i++) {
48 r= fscanf(db, "%x", &c); eassert(r==1);
49 eassert(c>0 && c<=255);
55 r= fscanf(db, "%d", &twidth); eassert(r==1);
56 current= &ocr_contexts[ctx];
57 for (i=0; i<twidth; i++) {
58 r= fscanf(db, "%"PSPIXCOL(SCNx), &cv); eassert(r==1);
59 for (j=0; j<current->nlinks; j++)
60 if (current->links[j].col == cv) {
61 current= current->links[j].then;
65 additional= malloc(sizeof(*additional)); eassert(additional);
67 additional->nlinks= additional->alinks= 0;
69 if (current->nlinks==current->alinks) {
72 current->links= realloc(current->links,
73 sizeof(*current->links) * current->alinks);
74 eassert(current->links);
76 current->links[current->nlinks].col= cv;
77 current->links[current->nlinks].then= additional;
84 eassert(!current->s[0]);
85 strcpy(current->s, chrs);
91 static void callout_unknown(int w, int h, Pixcol cols[], int unk_l, int unk_r,
92 const OcrResultGlyph *sofar, int nsofar) {
93 int pfd[2], c, r,i, x,y;
94 const OcrResultGlyph *s;
99 r= pipe(pfd); eassert(!r);
100 resolver_pid= fork();
101 eassert(resolver_pid!=-1);
103 r= dup2(pfd[0],0); eassert(!r);
104 r= close(pfd[1]); eassert(!r);
105 execlp("./show-thing.tcl", "./show-thing.tcl",(char*)0);
106 eassert(!"execlp failed");
108 r= close(pfd[0]); eassert(!r);
109 resolver= fdopen(pfd[1],"w"); eassert(resolver);
111 fprintf(resolver,"%d %d",unk_l,unk_r);
112 for (i=0, s=sofar; i<nsofar; i++, s++) {
113 fprintf(resolver," %d %d %d ",s->l,s->r,s->ctx);
114 for (p=s->s; (c= *p); p++) {
115 if (c=='\\') fprintf(resolver,"\\%c",c);
116 else if (c>=33 && c<=126) fputc(c,resolver);
117 else fprintf(resolver,"\\x%02x",(unsigned char)c);
120 fputc('\n',resolver);
124 "static char *t[] = {\n"
125 "/* columns rows colors chars-per-pixel */\n"
130 for (y=0, pv=1; y<h; y++, pv<<=1) {
133 fputc(cols[x] & pv ? 'o' : ' ', resolver);
134 fputs("\",\n",resolver);
136 fputs("};\n",resolver);
137 eassert(!ferror(resolver));
138 eassert(!fflush(resolver));
142 pid_t pid= waitpid(resolver_pid, &r, WUNTRACED);
143 if (pid==-1) { eassert(errno==EINTR); continue; }
144 eassert(pid==resolver_pid);
146 eassert(!WEXITSTATUS(r));
149 } else if (WIFSTOPPED(r)) {
150 r= kill(resolver_pid,SIGCONT);
152 } else if (WIFSIGNALED(r)) {
153 eassert(!"resolver child died due to signal");
155 eassert(!"weird wait status");
157 struct stat stab, fstab;
158 r= stat("database",&stab); eassert(!r);
159 r= fstat(fileno(db),&fstab); eassert(!r);
160 if (stab.st_ino != fstab.st_ino ||
161 stab.st_dev != fstab.st_dev)
169 static void add_result(const char *s, int l, int r, int ctx) {
170 if (nresults >= aresults) {
171 aresults++; aresults<<=1;
172 results= realloc(results,sizeof(*results)*aresults);
175 results[nresults].s= s;
176 results[nresults].l= l;
177 results[nresults].r= r;
178 results[nresults].ctx= ctx;
182 OcrResultGlyph *ocr(int w, int h, Pixcol cols[]) {
198 if (nspaces>3) ctx=1;
203 OCRDatabaseNode *current=0, *bestmatch=0;
206 current= &ocr_contexts[ctx];
210 for (i=0; i<current->nlinks; i++)
211 if (current->links[i].col == cv)
216 current= current->links[i].then;
217 if (current->s[0]) { bestmatch=current; bestmatch_rx=x; }
222 add_result(bestmatch->s, lx, bestmatch_rx, ctx);
228 for (rx=lx+1; rx<w && cols[rx]; rx++);
229 printf("UNKNOWN x=%d ctx=%d %d..%d\n",x, ctx, lx,rx);
230 callout_unknown(w,h,cols, lx,rx, results,nresults);
234 add_result(0,-1,-1,0);
238 void ocr_init(void) {