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;
28 static int resolver_done;
30 static void ocr_readdb(void) {
32 OCRDatabaseNode *current, *additional;
33 char chrs[MAXGLYPHCHRS+1];
38 db= fopen("database","r"); eassert(db);
41 r= fscanf(db, "%d %d", &ctx, &nchrs);
44 eassert(ctx>=0 && ctx<N_OCR_CONTEXTS);
45 eassert(nchrs>0 && nchrs<=MAXGLYPHCHRS);
47 for (i=0; i<nchrs; i++) {
49 r= fscanf(db, "%x", &c); eassert(r==1);
50 eassert(c>0 && c<=255);
56 r= fscanf(db, "%d", &twidth); eassert(r==1);
57 current= &ocr_contexts[ctx];
58 for (i=0; i<twidth; i++) {
59 r= fscanf(db, "%"PSPIXCOL(SCNx), &cv); eassert(r==1);
60 for (j=0; j<current->nlinks; j++)
61 if (current->links[j].col == cv) {
62 current= current->links[j].then;
66 additional= malloc(sizeof(*additional)); eassert(additional);
68 additional->nlinks= additional->alinks= 0;
70 if (current->nlinks==current->alinks) {
73 current->links= realloc(current->links,
74 sizeof(*current->links) * current->alinks);
75 eassert(current->links);
77 current->links[current->nlinks].col= cv;
78 current->links[current->nlinks].then= additional;
85 eassert(!current->s[0]);
86 strcpy(current->s, chrs);
92 static void callout_unknown(int w, int h, Pixcol cols[],
93 int unk_l, int unk_r, int unk_ctx,
94 const OcrResultGlyph *sofar, int nsofar) {
95 int jobpipe[2],donepipe[2], c, r,i, x,y;
96 const OcrResultGlyph *s;
102 r= pipe(jobpipe); eassert(!r);
103 r= pipe(donepipe); eassert(!r);
104 resolver_pid= fork();
105 eassert(resolver_pid!=-1);
107 r= dup2(jobpipe[0],0); eassert(r==0);
108 r= close(jobpipe[1]); eassert(!r);
109 r= close(donepipe[0]); eassert(!r);
110 /* we know donepipe[1] is >= 4 and we have dealt with all the others
111 * so we aren't in any danger of overwriting some other fd 4: */
112 r= dup2(donepipe[1],4); eassert(r==4);
113 execlp("./show-thing.tcl", "./show-thing.tcl",
114 "--automatic","1",(char*)0);
115 eassert(!"execlp failed");
117 r= close(jobpipe[0]); eassert(!r);
118 r= close(donepipe[1]); eassert(!r);
119 resolver= fdopen(jobpipe[1],"w"); eassert(resolver);
120 resolver_done= donepipe[0];
122 fprintf(resolver,"%d %d %d",unk_l,unk_r,unk_ctx);
123 for (i=0, s=sofar; i<nsofar; i++, s++) {
124 if (!strcmp(s->s," ")) continue;
125 fprintf(resolver," %d %d %d ",s->l,s->r,s->ctx);
126 for (p=s->s; (c= *p); p++) {
127 if (c=='\\') fprintf(resolver,"\\%c",c);
128 else if (c>=33 && c<=126) fputc(c,resolver);
129 else fprintf(resolver,"\\x%02x",(unsigned char)c);
132 fputc('\n',resolver);
136 "static char *t[] = {\n"
137 "/* columns rows colors chars-per-pixel */\n"
142 for (y=0, pv=1; y<h; y++, pv<<=1) {
145 fputc(cols[x] & pv ? 'o' : ' ', resolver);
146 fputs("\",\n",resolver);
148 fputs("};\n",resolver);
149 eassert(!ferror(resolver));
150 eassert(!fflush(resolver));
155 r= read(resolver_done,&cb,1);
156 if (r==-1) { eassert(errno==EINTR); continue; }
163 pid= waitpid(resolver_pid, &r, 0);
164 if (pid==-1) { eassert(errno==EINTR); continue; }
167 eassert(pid==resolver_pid);
169 eassert(!WEXITSTATUS(r));
171 close(resolver_done);
173 } else if (WIFSIGNALED(r)) {
174 eassert(!"resolver child died due to signal");
176 eassert(!"weird wait status");
188 static void add_result(const char *s, int l, int r, int ctx) {
189 if (nresults >= aresults) {
190 aresults++; aresults<<=1;
191 results= realloc(results,sizeof(*results)*aresults);
194 results[nresults].s= s;
195 results[nresults].l= l;
196 results[nresults].r= r;
197 results[nresults].ctx= ctx;
201 OcrResultGlyph *ocr(int w, int h, Pixcol cols[]) {
208 fprintf(debug,"OCR h=%d w=%d",w,h);
209 for (x=0; x<w; x++) fprintf(debug," %"PSPIXCOL(PRIx),cols[x]);
225 fprintf(debug,"OCR x=%x nspaces=%d space\n",x,nspaces);
226 add_result(" ",x-nspaces,x+1,0);
234 OCRDatabaseNode *current=0, *bestmatch=0;
237 current= &ocr_contexts[ctx];
238 fprintf(debug,"OCR lx=%d ctx=%d ",lx,ctx);
242 fprintf(debug,"| x=%d",x);
245 fprintf(debug," cv=%"PSPIXCOL(PRIx),x);
246 for (i=0; i<current->nlinks; i++)
247 if (current->links[i].col == cv)
254 current= current->links[i].then;
256 fprintf(debug," \"%s\"",current->s);
257 bestmatch=current; bestmatch_rx=x;
259 fprintf(debug," ...");
265 fprintf(debug," YES\n");
266 add_result(bestmatch->s, lx, bestmatch_rx, ctx);
271 fprintf(debug," UNKNOWN");
272 for (rx=lx; rx<w && cols[rx]; rx++);
273 fprintf(debug," x=%d ctx=%d %d..%d\n",x, ctx, lx,rx);
275 callout_unknown(w,h,cols, lx,rx-1,ctx, results,nresults);
279 add_result(0,-1,-1,0);
280 fprintf(debug,"OCR finished %d glyphs\n",nresults);
285 void ocr_init(void) {