/* This is a Optical-Character-Recognition program Copyright (C) 2000-2009 Joerg Schulenburg This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. see README for EMAIL address */ #include #include "unicode.h" #include "output.h" #include "pcx.h" #include "gocr.h" /* extern job_t JOB; */ /* function is only for debugging and for developing it prints out a part of pixmap b at point x0,y0 to stderr using dots .,; if no pixel, and @xoO for pixels modify n_run and print out what would happen on 2nd, 3th loop! new: output original and copied pixmap in the same figure */ void out_b(struct box *px, pix *b, int x0, int y0, int dx, int dy, int cs ){ int x,y,x2,y2,yy0,tx,ty,n1,i; char c1, c2; yy0=y0; if (px) { /* overwrite rest of arguments */ if (!b) { b=px->p; x0=px->x0; dx=px->x1-px->x0+1; y0=px->y0; dy=px->y1-px->y0+1; yy0=y0; } if(cs==0) cs=JOB->cfg.cs; fprintf(stderr,"\n# list box x= %4d %4d d= %3d %3d r= %3d %3d" " nrun=%d p=%p", /* ToDo: r,nrun is obsolete */ px->x0, px->y0, px->x1 - px->x0 + 1, px->y1 - px->y0 + 1, px->x - px->x0, px->y - px->y0, JOB->tmp.n_run, (void*)px); fprintf(stderr,"\n# dots=%d boxes=%d subboxes=%d c=%s mod=%s" " line=%d m= %d %d %d %d", px->dots, px->num_boxes, px->num_subboxes, decode(px->c,ASCII), decode(px->modifier,ASCII), px->line, px->m1 - px->y0, px->m2 - px->y0, px->m3 - px->y0, px->m4 - px->y0); if (px->num_frames) { int i,j,jo; fprintf(stderr,"\n# frames= %d (sumvects=%d)",px->num_frames, ((px->num_frames)?px->num_frame_vectors[px->num_frames-1]:-1)); for (jo=j=i=0; inum_frames; i++, jo=j) { fprintf(stderr,"\n# frame %d (%+4d,%3d,%2d) ", i, px->frame_vol[i], px->frame_per[i], px->num_frame_vectors[i]-jo); /* print only the first vectors of each frame */ for (;jnum_frame_vectors[i] && jframe_vector[j][0] - px->x0, px->frame_vector[j][1] - px->y0); } } if (px->num_ac){ /* output table of chars and its probabilities */ fprintf(stderr,"\n# list box char: "); for(i=0;inum_ac && itas[i]) fprintf(stderr," %s(%d)", px->tas[i] ,px->wac[i]); else fprintf(stderr," %s(%d)",decode(px->tac[i],ASCII),px->wac[i]); } fprintf(stderr,"\n"); if (px->m2 && px->m1dots || y0>px->m2)) { yy0=px->m1; dy=px->y1-yy0+1; } } tx=dx/80+1; ty=dy/40+1; /* step, usually 1, but greater on large maps */ fprintf(stderr,"# list pattern x= %4d %4d d= %3d %3d t= %d %d yy0= %d\n", x0,y0,dx,dy,tx,ty,yy0); if (dx>0) for(y=yy0;yp,x2-x0+px->x0, y2-y0+px->y0)num_frames) { /* mark vectors */ int i; if (c1!='$' && c1!='S') /* dont mark twice */ for (i=0;inum_frame_vectors[px->num_frames-1];i++) if ((px->frame_vector[i][0]-px->x0)/tx==(x-x0)/tx && (px->frame_vector[i][1]-px->y0)/ty==(y-y0)/ty) { c1=((c1=='@')?'$':'S'); break; } } fprintf(stderr,"%c", c1 ); } /* 2nd image is the boxframe in the original bitmap */ if (dx<40) fprintf(stderr," "); if (dx<40) /* do it only, if we have enough place */ for(x=x0;xy0==px->m1 || y-y0+px->y0==px->m2 || y-y0+px->y0==px->m3 || y-y0+px->y0==px->m4) c1='<'; if (y==y0 || y==yy0+dy-1) c2='-'; /* boxmarks */ fprintf(stderr,"%c%c\n",c1,c2); } } /* same as out_b, but for faster use, only a box as argument */ void out_x(struct box *px) { out_b(px,NULL,0, 0, 0, 0, JOB->cfg.cs); } /* print out two boxes side by side, for debugging comparision algos */ void out_x2(struct box *box1, struct box *box2){ int x,y,i,tx,ty,dy; /*FIXME jb static*/static char *c1="OXXXXxx@.,,,,,,,"; pix *b=&JOB->src.p; dy=(box1->y1-box1->y0+1); if(dyy1-box2->y0+1)dy=box2->y1-box2->y0+1; tx=(box1->x1-box1->x0)/40+1; ty=(box1->y1-box1->y0)/40+1; /* step, usually 1, but greater on large maps */ if(box2)fprintf(stderr,"\n# list 2 patterns"); for(i=0;iy0+i; for(x=box1->x0;x<=box1->x1;x+=tx) fprintf(stderr,"%c", c1[ ((getpixel(b,x,y)cfg.cs)?0:8)+marked(b,x,y) ] ); if(!box2) continue; fprintf(stderr," "); y=box2->y0+i; for(x=box2->x0;x<=box2->x1;x+=tx) fprintf(stderr,"%c", c1[ ((getpixel(b,x,y)cfg.cs)?0:8)+marked(b,x,y) ] ); } } /* ---- list output ---- for debugging --- * list all boxes where the results can be found within the c-option */ int output_list(job_t *job) { int i = 0, j; struct box *box2; pix *pp = &job->src.p; char *lc = job->cfg.lc; fprintf(stderr,"\n# list shape for charlist %s",lc); for_each_data(&(JOB->res.boxlist)) { box2 = (struct box *) list_get_current(&(JOB->res.boxlist)); for (j=0; jnum_ac; j++) if (!lc || (box2->tac[j] && strchr(lc, box2->tac[j])) || (box2->tas[j] && strstr(lc, box2->tas[j]))) break; if (jnum_ac) fprintf(stderr,"\n# box found in charlist"); if (!lc || (strchr(lc, box2->c) && box2->c < 256 && box2->c) || (strchr(lc, '_') && box2->c==UNKNOWN) /* for compability */ || jnum_ac ){ /* also list alternative chars */ if (!pp) pp=box2->p; fprintf(stderr, "\n# list shape %3d x=%4d %4d d= %3d %3d vf=%d ac=%d %04x %s", i, box2->x0, box2->y0, box2->x1 - box2->x0 + 1, box2->y1 - box2->y0 + 1, box2->num_frames, box2->num_ac, (int)box2->c, /* wchar_t -> char ???? */ decode(box2->c,ASCII) ); if (JOB->cfg.verbose & 4) out_x(box2); } i++; } end_for_each(&(JOB->res.boxlist)); fprintf(stderr,"\n"); return 0; } /* --- output of image incl. corored lines usefull for developers --- * debugging * bit 0+1 is used for color coding (optical marker) * color/gray: 0x01=red, 0x02=blue, 0x04=green??? * opt: 1 - mark unknown boxes red (first pass) * 2 - mark unknown boxes more red (final pass) * 4 - mark lines blue * 8 - reset coloring (remove old marker) */ int debug_img(char *fname, struct job_s *job, int opt) { struct box *box2; int x, y, ic, dx, i, j, col; unsigned char *np; pix *pp = &job->tmp.ppo; if ( opt & 8 ) { /* clear debug bits in image */ for(y=0;yy;y++) { np=&pp->p[(pp->x)*y]; for(x=0;xx;x++) { *np = *np & 0xF1; np++; } } } /* mark longest line which was used to estimate the rotation angle */ if ((job->cfg.verbose&32) && job->res.lines.dx) for(i=0;ix;i++) { y=pp->y/2; if (job->res.lines.dx) y+=job->res.lines.dy*i/job->res.lines.dx; x=i; if (x<0 || x>=pp->x || y<0 || y>=pp->y) continue; np=&pp->p[x + (pp->x)*y]; if (*np<160) continue; if((x&7)<5 && !(x&1)) /* dotted line */ put(pp,x,y,255,8); } ic = ((opt & 2) ? 1 : 2); /* obsolete */ for_each_data(&(job->res.boxlist)) { box2 = (struct box *) list_get_current(&(job->res.boxlist)); /* mark boxes in 32=0x40=blue */ if (box2->c == ' ' || box2->c == '\n') continue; /* mark chars with green left and under line */ col = 4; /* green */ if (box2->c == UNKNOWN && (opt & 3)) col=2; /* red */ if (box2->x0>1) for (y = box2->y0; y <= box2->y1; y++) { np=&pp->p[box2->x0-1 + y * pp->x]; if (*np<160) continue; *np|=col; } if (box2->y1+1y) for (x = box2->x0; x <= box2->x1; x++) { np=&pp->p[x + (box2->y1+1) * pp->x]; if (*np<160) continue; *np|=col; } /* mark pictures by green cross */ if (box2->c == PICTURE) for (x = 0; x < box2->x1-box2->x0+1; x++){ y=(box2->y1-box2->y0+1)*x/(box2->x1-box2->x0+1); pp->p[(box2->x0+x) + (box2->y0+y) * pp->x] |= 4; pp->p[(box2->x1-x) + (box2->y0+y) * pp->x] |= 4; } } end_for_each(&(job->res.boxlist)); if( opt & 4 ) { struct tlines *lines = &job->res.lines; int yr; if (job->cfg.verbose) fprintf(stderr, "# mark lines for %s.ppm\n", fname); /* or read from outside??? */ for (i = 0; i < lines->num; i++) { /* mark lines by 0x08 = blue */ dx = lines->x1[i] - lines->x0[i] + 1; for (j = -1; j < dx+1; j++) { x = lines->x0[i] + j; if (x<0 || x>=pp->x) continue; for (y=lines->m1[i];y<=lines->m4[i];y++) { /* box arround m2-m3 */ if (y>=lines->m2[i] && y<=lines->m3[i] && j>-1 && jdx) yr += lines->dy * x / (lines->dx); if (yr<0 || yr>=pp->y) continue; np = &(pp->p[x + (pp->x)*yr]); if (*np<160) continue; /* do not touch dark pixels */ if ((*np&6)!=0) continue; /* only change white pixels */ put(pp, x, yr, 255, 6); /* UPN: 255 and 6 or */ } } } } if (job->cfg.verbose&1) fprintf(stderr,"# writing %s.ppm\n", fname); writeppm(fname, pp); return 0; }