From 0051984495aa2a5ed61224a7618f5bbd04311f7a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 31 May 2009 23:24:50 +0100 Subject: [PATCH 01/16] WIP ocr --- .gitignore | 4 +++ pctb/Makefile | 5 ++++ pctb/convert.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ pctb/wrap-wip | 8 ++++++ 4 files changed, 92 insertions(+) create mode 100644 pctb/Makefile create mode 100644 pctb/convert.c create mode 100755 pctb/wrap-wip diff --git a/.gitignore b/.gitignore index 2ad500a..cfb08ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ *~ t + +pctb/t.* +pctb/u.* +pctb/convert diff --git a/pctb/Makefile b/pctb/Makefile new file mode 100644 index 0000000..bff47f5 --- /dev/null +++ b/pctb/Makefile @@ -0,0 +1,5 @@ +LDLIBS += -lnetpbm +CFLAGS += -Wall -Wwrite-strings -Wpointer-arith -Wmissing-prototypes \ + -Wstrict-prototypes + +all: convert diff --git a/pctb/convert.c b/pctb/convert.c new file mode 100644 index 0000000..80bc894 --- /dev/null +++ b/pctb/convert.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +#define eassert assert + +typedef struct { + unsigned long rgb; /* on screen */ + char c; /* canonical */ +} CanonColourInfo; + +static const CanonColourInfo canoncolourinfos[]= { + { 0x475A5E, '*' }, /* edge */ + { 0x7D9094, '+' }, /* interbox */ + { 0xBDC5BF, ' ' }, /* background - pale */ + { 0xADB5AF, ' ' }, /* background - dark */ + { 0x000000, 'o' }, /* foreground */ + { 0xD4B356, ' ' }, /* background (cursor) */ + { 0xFFFFFF, 'o' }, /* foreground (cursor) */ + { 0,0 } +}; + +static int height, width; +static char *image; + +static void load_image_and_canonify(void) { + struct pam inpam; + unsigned char rgb[3]; + int x,y,r; + const CanonColourInfo *cci; + + pnm_readpaminit(stdin, &inpam, sizeof(inpam)); + height= inpam.height; + width= inpam.width; + eassert(inpam.maxval == 255); + eassert(inpam.bytes_per_sample == 1); + + image= malloc(width*height); + eassert(image); + memset(image,'?',width*height); + + for (y=0; yc; cci++) + if (cci->rgb == rgb_l) { + image[y*width + x]= cci->c; + break; + } + if (y==234 && x==82) { + printf("y=%d/%d x=%d/%d rgb=%d,%d,%d rgb_l=%lx c=%c\n", + y,height,x,width, rgb[0],rgb[1],rgb[2], rgb_l, image[y*width+x]); + } + } + r= fwrite(image + y*width, 1,width, stdout); eassert(r==width); + putchar('\n'); + } + eassert(!fflush(stdout)); + eassert(!ferror(stdout)); +} + +int main(void) { + load_image_and_canonify(); + /* + find_main_rectangle(); + repeatedly_find_top_thing(); + */ + return 0; +} diff --git a/pctb/wrap-wip b/pctb/wrap-wip new file mode 100755 index 0000000..5c5bc1e --- /dev/null +++ b/pctb/wrap-wip @@ -0,0 +1,8 @@ +#!/bin/bash +set -ex + +xwd -name 'Puzzle Pirates - Aristarchus on the Midnight ocean' >t.xwd +# 60-odd commodity pages! Will take ~2 mins to run through them all + +convert t.xwd t.pnm +pnmdepth u.pnm -- 2.30.2 From f9c00eb882d1758e95422d8f40ef5606422cffa3 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 1 Jun 2009 00:23:46 +0100 Subject: [PATCH 02/16] Can find main rectangle --- pctb/convert.c | 113 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 12 deletions(-) diff --git a/pctb/convert.c b/pctb/convert.c index 80bc894..95e75b3 100644 --- a/pctb/convert.c +++ b/pctb/convert.c @@ -5,14 +5,37 @@ #include #define eassert assert +#define debug stdout typedef struct { unsigned long rgb; /* on screen */ char c; /* canonical */ } CanonColourInfo; +static int height, width; +static char *image; + +static void debug_flush(void) { + eassert(!fflush(debug)); + eassert(!ferror(debug)); +} + +typedef struct { + int x, y; +} Point; + +typedef struct { /* both inclusive */ + Point tl; + Point br; +} Rect; + +static inline char get(int x, int y) { return image[y * width + x]; } +static inline char get_p(Point p) { return get(p.x,p.y); } + + static const CanonColourInfo canoncolourinfos[]= { { 0x475A5E, '*' }, /* edge */ + { 0x2C5F7A, '*' }, /* edge just under box heading shadow */ { 0x7D9094, '+' }, /* interbox */ { 0xBDC5BF, ' ' }, /* background - pale */ { 0xADB5AF, ' ' }, /* background - dark */ @@ -22,8 +45,78 @@ static const CanonColourInfo canoncolourinfos[]= { { 0,0 } }; -static int height, width; -static char *image; +#define START_MAIN {200,200} + +static void require_rectangle(int tlx, int tly, int brx, int bry, char c) { + int x,y; + for (x=tlx; x<=brx; x++) + for (y=tly; y<=bry; y++) + eassert(get(x,y) == c); +} +static void require_rectangle_r(Rect rr, char c) { + require_rectangle(rr.tl.x,rr.tl.y, rr.br.x,rr.br.y, c); +} + +static void debug_rect(const char *what, int whati, Rect rr) { + int y,r,w; + fprintf(debug, "%s %d: %d,%d..%d,%d:\n", what, whati, + rr.tl.x,rr.tl.y, rr.br.x,rr.br.y); + w= rr.br.x - rr.tl.x + 1; + for (y=rr.tl.y; y<=rr.br.y; y++) { + fprintf(debug, "%4d %4d ",y,y-rr.tl.y); + r= fwrite(image + y*width + rr.tl.x, 1, w, debug); + eassert(r==w); + fputc('|',debug); + fputc('\n',debug); + } + debug_flush(); +} + +static void find_main_rectangle(void) { + Rect whole = { {0,0}, {width-1,height-1} }; + Rect mainr = { START_MAIN,START_MAIN }; + +#define WALK_UNTIL(point,coord,increm,stop,edge) \ + for (;;) { \ + if (get_p((point)) == (edge)) { (point).coord -= (increm); break; } \ + eassert((point).coord != (stop)); \ + (point).coord += (increm); \ + } + + WALK_UNTIL(mainr.tl, x,-1, whole.tl.x, '*'); + WALK_UNTIL(mainr.tl, y,-1, whole.tl.y, '*'); + WALK_UNTIL(mainr.br, x,+1, whole.br.x, '*'); + WALK_UNTIL(mainr.br, y,+1, whole.br.y, '*'); + + require_rectangle(mainr.tl.x-1, mainr.tl.y, mainr.tl.x-1, mainr.br.y, '*'); + require_rectangle(mainr.br.x+1, mainr.tl.y, mainr.br.x+1, mainr.br.y, '*'); + require_rectangle(mainr.tl.x, mainr.tl.y-1, mainr.br.x, mainr.tl.y-1, '*'); + require_rectangle(mainr.tl.x, mainr.br.y+1, mainr.br.x, mainr.br.y+1, '*'); + +#define CHECK_STRIP_BORDER(tlbr,xy,increm) \ + do { \ + Point csb_p; \ + Rect csb_r; \ + csb_p= mainr.tl; \ + csb_p.xy= mainr.tlbr.xy; \ + if (get_p(csb_p)=='+') { \ + csb_r= mainr; \ + csb_r.tl.xy= csb_p.xy; \ + csb_r.br.xy= csb_p.xy; \ + require_rectangle_r(csb_r, '+'); \ + mainr.tlbr.xy += increm; \ + } \ + } while(0) + + debug_rect("mainr",0, mainr); + + CHECK_STRIP_BORDER(tl,x,+1); + CHECK_STRIP_BORDER(tl,y,+1); + CHECK_STRIP_BORDER(br,x,-1); + CHECK_STRIP_BORDER(br,y,-1); + + debug_rect("mainr",1, mainr); +} static void load_image_and_canonify(void) { struct pam inpam; @@ -53,22 +146,18 @@ static void load_image_and_canonify(void) { image[y*width + x]= cci->c; break; } - if (y==234 && x==82) { - printf("y=%d/%d x=%d/%d rgb=%d,%d,%d rgb_l=%lx c=%c\n", - y,height,x,width, rgb[0],rgb[1],rgb[2], rgb_l, image[y*width+x]); - } } - r= fwrite(image + y*width, 1,width, stdout); eassert(r==width); - putchar('\n'); + fprintf(debug, "%4d ",y); + r= fwrite(image + y*width, 1,width, debug); eassert(r==width); + fputc('\n',debug); } - eassert(!fflush(stdout)); - eassert(!ferror(stdout)); + debug_flush(); } - + int main(void) { load_image_and_canonify(); - /* find_main_rectangle(); + /* repeatedly_find_top_thing(); */ return 0; -- 2.30.2 From 2f9b824c735e9174d7cc7d8aea829a85d2276d21 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 1 Jun 2009 01:14:18 +0100 Subject: [PATCH 03/16] Can find each commodity --- pctb/convert.c | 136 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 27 deletions(-) diff --git a/pctb/convert.c b/pctb/convert.c index 95e75b3..b518dba 100644 --- a/pctb/convert.c +++ b/pctb/convert.c @@ -33,6 +33,15 @@ static inline char get(int x, int y) { return image[y * width + x]; } static inline char get_p(Point p) { return get(p.x,p.y); } +#define START_MAIN {200,200} +#define INTERESTING_COLUMNS 6 +#define MAX_COLUMNS 7 + +static Rect mainr = { START_MAIN,START_MAIN }; +static int commbasey, comminty; +static int colrightx[INTERESTING_COLUMNS]; + + static const CanonColourInfo canoncolourinfos[]= { { 0x475A5E, '*' }, /* edge */ { 0x2C5F7A, '*' }, /* edge just under box heading shadow */ @@ -45,16 +54,17 @@ static const CanonColourInfo canoncolourinfos[]= { { 0,0 } }; -#define START_MAIN {200,200} - -static void require_rectangle(int tlx, int tly, int brx, int bry, char c) { +static void require_rectangle(int tlx, int tly, int brx, int bry, + const char *ok) { int x,y; for (x=tlx; x<=brx; x++) - for (y=tly; y<=bry; y++) - eassert(get(x,y) == c); + for (y=tly; y<=bry; y++) { + int c= get(x,y); + assert(strchr(ok,c)); + } } -static void require_rectangle_r(Rect rr, char c) { - require_rectangle(rr.tl.x,rr.tl.y, rr.br.x,rr.br.y, c); +static void require_rectangle_r(Rect rr, const char *ok) { + require_rectangle(rr.tl.x,rr.tl.y, rr.br.x,rr.br.y, ok); } static void debug_rect(const char *what, int whati, Rect rr) { @@ -63,7 +73,7 @@ static void debug_rect(const char *what, int whati, Rect rr) { rr.tl.x,rr.tl.y, rr.br.x,rr.br.y); w= rr.br.x - rr.tl.x + 1; for (y=rr.tl.y; y<=rr.br.y; y++) { - fprintf(debug, "%4d %4d ",y,y-rr.tl.y); + fprintf(debug, "%4d%*s|", y, rr.tl.x,""); r= fwrite(image + y*width + rr.tl.x, 1, w, debug); eassert(r==w); fputc('|',debug); @@ -72,26 +82,31 @@ static void debug_rect(const char *what, int whati, Rect rr) { debug_flush(); } -static void find_main_rectangle(void) { - Rect whole = { {0,0}, {width-1,height-1} }; - Rect mainr = { START_MAIN,START_MAIN }; - -#define WALK_UNTIL(point,coord,increm,stop,edge) \ +#define WALK_UNTIL(point,coord,increm,last,edge) \ for (;;) { \ + if ((point).coord == (last)+(increm)) break; \ if (get_p((point)) == (edge)) { (point).coord -= (increm); break; } \ - eassert((point).coord != (stop)); \ (point).coord += (increm); \ } - WALK_UNTIL(mainr.tl, x,-1, whole.tl.x, '*'); - WALK_UNTIL(mainr.tl, y,-1, whole.tl.y, '*'); - WALK_UNTIL(mainr.br, x,+1, whole.br.x, '*'); - WALK_UNTIL(mainr.br, y,+1, whole.br.y, '*'); +#define WALK_UNTIL_MUST(point,coord,increm,last,edge) \ + do { \ + WALK_UNTIL(point,coord,increm,last,edge); \ + eassert((point).coord != (last)+(increm)); \ + } while(0) + +static void find_structure(void) { + Rect whole = { {0,0}, {width-1,height-1} }; + + WALK_UNTIL_MUST(mainr.tl, x,-1, whole.tl.x, '*'); + WALK_UNTIL_MUST(mainr.tl, y,-1, whole.tl.y, '*'); + WALK_UNTIL_MUST(mainr.br, x,+1, whole.br.x, '*'); + WALK_UNTIL_MUST(mainr.br, y,+1, whole.br.y, '*'); - require_rectangle(mainr.tl.x-1, mainr.tl.y, mainr.tl.x-1, mainr.br.y, '*'); - require_rectangle(mainr.br.x+1, mainr.tl.y, mainr.br.x+1, mainr.br.y, '*'); - require_rectangle(mainr.tl.x, mainr.tl.y-1, mainr.br.x, mainr.tl.y-1, '*'); - require_rectangle(mainr.tl.x, mainr.br.y+1, mainr.br.x, mainr.br.y+1, '*'); + require_rectangle(mainr.tl.x-1, mainr.tl.y, mainr.tl.x-1, mainr.br.y, "*"); + require_rectangle(mainr.br.x+1, mainr.tl.y, mainr.br.x+1, mainr.br.y, "*"); + require_rectangle(mainr.tl.x, mainr.tl.y-1, mainr.br.x, mainr.tl.y-1, "*"); + require_rectangle(mainr.tl.x, mainr.br.y+1, mainr.br.x, mainr.br.y+1, "*"); #define CHECK_STRIP_BORDER(tlbr,xy,increm) \ do { \ @@ -103,7 +118,7 @@ static void find_main_rectangle(void) { csb_r= mainr; \ csb_r.tl.xy= csb_p.xy; \ csb_r.br.xy= csb_p.xy; \ - require_rectangle_r(csb_r, '+'); \ + require_rectangle_r(csb_r, "+"); \ mainr.tlbr.xy += increm; \ } \ } while(0) @@ -116,8 +131,70 @@ static void find_main_rectangle(void) { CHECK_STRIP_BORDER(br,y,-1); debug_rect("mainr",1, mainr); + + Point up = START_MAIN; + WALK_UNTIL_MUST(up, y,-1, mainr.tl.y, '+'); + + Point down = START_MAIN; + down.y++; + WALK_UNTIL_MUST(down, y,+1, mainr.br.y, '+'); + + int xscaleunit, y,x; + for (y=0, xscaleunit=1; y<4; y++, xscaleunit*=10) { + fprintf(debug," "); + for (x=0; x<=width; x++) { + if (x % xscaleunit) fputc(' ',debug); + else fprintf(debug,"%d",(x / xscaleunit)%10); + } + fputc('\n',debug); + } + + commbasey= up.y; + comminty= down.y - up.y + 2; + fprintf(debug, "up.y=%d down.y=%d commbasey=%d comminty=%d\n", + up.y,down.y, commbasey,comminty); + + Point across= { mainr.tl.x, commbasey }; + int colno=0; + for (;;) { + eassert(get_p(across) != '+'); + WALK_UNTIL(across, x,+1, mainr.br.x, '+'); + eassert(colno < MAX_COLUMNS); + int colrx= across.x; + if (colrx > mainr.br.x) colrx= mainr.br.x; + if (colno < INTERESTING_COLUMNS) { + colrightx[colno]= colrx; + fprintf(debug,"colrightx[%d]= %d\n",colno,colrx); + } else { + fprintf(debug,"extra colr %d %d\n",colno,colrx); + } + + colno++; + + if (across.x >= mainr.br.x-1) + break; + + across.x++; + require_rectangle(across.x,mainr.tl.y, across.x,mainr.br.y, "+"); + across.x++; + } + } +static void find_commodity(int offset, Rect *rr) { + /* rr->tl.x==-1 if offset out of range */ + rr->tl.y= commbasey - offset*comminty; + rr->br.y= rr->tl.y + comminty-2; + if (rr->tl.y < mainr.tl.y || rr->br.y > mainr.br.y) { rr->tl.x=-1; return; } + if (rr->tl.y > mainr.tl.y) + require_rectangle(rr->tl.x,rr->tl.y-1, rr->br.x,rr->tl.y-1, "+"); + if (rr->br.y < mainr.tl.y) + require_rectangle(rr->tl.x,rr->br.y+1, rr->br.x,rr->br.y+1, "+"); + + rr->tl.x= mainr.tl.x; + rr->br.x= mainr.br.x; +} + static void load_image_and_canonify(void) { struct pam inpam; unsigned char rgb[3]; @@ -156,9 +233,14 @@ static void load_image_and_canonify(void) { int main(void) { load_image_and_canonify(); - find_main_rectangle(); - /* - repeatedly_find_top_thing(); - */ + find_structure(); + + Rect thisr; + int tryrect; + for (tryrect= +height; tryrect >= -height; tryrect--) { + find_commodity(tryrect, &thisr); + if (thisr.tl.x >= 0) + debug_rect("commod",tryrect, thisr); + } return 0; } -- 2.30.2 From 815893191637908a5563fb422f5264d42a1fd4bf Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 1 Jun 2009 01:33:00 +0100 Subject: [PATCH 04/16] Font data, initial set --- pctb/charset.charsource | 113 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 pctb/charset.charsource diff --git a/pctb/charset.charsource b/pctb/charset.charsource new file mode 100644 index 0000000..59bddfc --- /dev/null +++ b/pctb/charset.charsource @@ -0,0 +1,113 @@ +a +++++++ + + + + + + ooo +o o + o + oooo +o o +o o + ooooo + + + +++++++ + +b +++++++ + + + +o +o +o ooo +oo o +o o +o o +o o +oo o +o ooo + + + +++++++ + +e ++++++ + + + + + + ooo +o o +o o +ooooo +o +o + oooo + + + ++++++ + +m ++++++++++ + + + + + +o oo oo +oo oo o +o o o +o o o +o o o +o o o +o o o + + + ++++++++++ + +n +++++++ + + + + + +o oo +oo o +o o +o o +o o +o o +o o + + + +++++++ + +o ++++++ + + + + + + ooo +o o +o o +o o +o o +o o + ooo + + + ++++++ -- 2.30.2 From a8e8a4a724140d6a91ff36a7bf603831583e5533 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 1 Jun 2009 01:44:54 +0100 Subject: [PATCH 05/16] finds cells; now start work on real ocr --- pctb/convert.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/pctb/convert.c b/pctb/convert.c index b518dba..598d446 100644 --- a/pctb/convert.c +++ b/pctb/convert.c @@ -34,8 +34,9 @@ static inline char get_p(Point p) { return get(p.x,p.y); } #define START_MAIN {200,200} +#define MIN_COLUMNS 6 #define INTERESTING_COLUMNS 6 -#define MAX_COLUMNS 7 +#define MAX_COLUMNS 7 static Rect mainr = { START_MAIN,START_MAIN }; static int commbasey, comminty; @@ -178,7 +179,7 @@ static void find_structure(void) { require_rectangle(across.x,mainr.tl.y, across.x,mainr.br.y, "+"); across.x++; } - + eassert(colno >= MIN_COLUMNS); } static void find_commodity(int offset, Rect *rr) { @@ -195,6 +196,15 @@ static void find_commodity(int offset, Rect *rr) { rr->br.x= mainr.br.x; } +static void find_table_entry(Rect commod, int colno, Rect *cellr) { + cellr->tl.y= commod.tl.y; + cellr->br.y= commod.br.y; + cellr->tl.x= !colno ? commod.tl.x : colrightx[colno-1]+2; + cellr->br.x= colrightx[colno]; + debug_rect("cell", colno, *cellr); + require_rectangle_r(*cellr, " o"); +} + static void load_image_and_canonify(void) { struct pam inpam; unsigned char rgb[3]; @@ -232,15 +242,22 @@ static void load_image_and_canonify(void) { } int main(void) { + Rect thisr, entryr; + int tryrect, colno; + load_image_and_canonify(); find_structure(); - Rect thisr; - int tryrect; for (tryrect= +height; tryrect >= -height; tryrect--) { find_commodity(tryrect, &thisr); - if (thisr.tl.x >= 0) - debug_rect("commod",tryrect, thisr); + if (thisr.tl.x < 0) + continue; + debug_rect("commod",tryrect, thisr); + + for (colno=0; colno Date: Tue, 2 Jun 2009 02:47:02 +0100 Subject: [PATCH 06/16] wip ocr --- pctb/Makefile | 2 +- pctb/convert.c | 150 +++++++++++++++- pctb/database | 7 + pctb/stuff/show-thing.tcl | 358 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 514 insertions(+), 3 deletions(-) create mode 100644 pctb/database create mode 100644 pctb/stuff/show-thing.tcl diff --git a/pctb/Makefile b/pctb/Makefile index bff47f5..10c0be9 100644 --- a/pctb/Makefile +++ b/pctb/Makefile @@ -1,5 +1,5 @@ LDLIBS += -lnetpbm CFLAGS += -Wall -Wwrite-strings -Wpointer-arith -Wmissing-prototypes \ - -Wstrict-prototypes + -Wstrict-prototypes -g all: convert diff --git a/pctb/convert.c b/pctb/convert.c index 598d446..a0ecca1 100644 --- a/pctb/convert.c +++ b/pctb/convert.c @@ -3,6 +3,7 @@ #include #include #include +#include #define eassert assert #define debug stdout @@ -241,10 +242,155 @@ static void load_image_and_canonify(void) { debug_flush(); } +typedef uint32_t Pixcol; +#define PSPIXCOL(priscan) priscan##32 + +typedef struct { + Pixcol col; + struct OCRDatabaseNode *then; +} OCRDatabaseLink; + +#define MAXGLYPHCHRS 3 + +typedef struct OCRDatabaseNode { + char s[MAXGLYPHCHRS+1]; /* null-terminated; "" means no match here */ + int nlinks, alinks; + OCRDatabaseLink *links; +} OCRDatabaseNode; + +#define N_OCR_CONTEXTS 2 +static OCRDatabaseNode ocr_contexts[N_OCR_CONTEXTS]; + +static void load_ocr_database(void) { + int ctx,nchrs; + OCRDatabaseNode *current, *additional; + char chrs[MAXGLYPHCHRS+1]; + Pixcol cv; + int r,i,j; + + FILE *db= fopen("database","r"); eassert(db); + + for (;;) { + r= fscanf(db, "%d %d", &ctx, &nchrs); + if (r==EOF) break; + eassert(r==2); + eassert(ctx>=0 && ctx0 && nchrs<=MAXGLYPHCHRS); + + for (i=0; i0 && c<=255); + chrs[i]= c; + } + chrs[nchrs]= 0; + + int twidth; + r= fscanf(db, "%d", &twidth); eassert(r==1); + current= &ocr_contexts[ctx]; + for (i=0; inlinks; j++) + if (current->links[j].col == cv) { + current= current->links[j].then; + goto found_link; + } + + additional= malloc(sizeof(*additional)); eassert(additional); + additional->s[0]= 0; + additional->nlinks= additional->alinks= 0; + additional->links= 0; + if (current->nlinks==current->alinks) { + current->alinks++; + current->alinks<<=1; + current->links= realloc(current->links, + sizeof(*current->links) * current->alinks); + eassert(current->links); + } + current->links[current->nlinks].col= cv; + current->links[current->nlinks].then= additional; + current->nlinks++; + current= additional; + + found_link:; + } + + eassert(!current->s[0]); + strcpy(current->s, chrs); + } + eassert(!ferror(db)); + eassert(feof(db)); + fclose(db); +} + +static void ocr_rectangle(Rect r) { + int w= r.br.x - r.tl.x + 1; + int h= r.br.y - r.tl.y + 1; + Pixcol cols[w+1]; + int x,y; + for (x=0; xw) break; + + if (!cols[x]) { + nspaces++; + x++; + if (nspaces>3) ctx=1; + continue; + } + + OCRDatabaseNode *current=0, *lastmatch=0; + int startx=x; + int afterlastmatchx=-1; + current= &ocr_contexts[ctx]; + for (;;) { + if (x>w) break; + Pixcol cv= cols[x]; + for (i=0; inlinks; i++) + if (current->links[i].col == cv) + goto found; + /* not found */ + break; + found: + x++; + current= current->links[i].then; + if (current->s[0]) { lastmatch=current; afterlastmatchx=x; } + } + + if (!lastmatch) { + int x2; + for (x2=x+1; x2s); + x= afterlastmatchx; + ctx= 0; + } + } +} + int main(void) { Rect thisr, entryr; int tryrect, colno; - + + load_ocr_database(); load_image_and_canonify(); find_structure(); @@ -256,7 +402,7 @@ int main(void) { for (colno=0; colno= 0} { + if {![regexp {^"(.*)",$} $l dummy l]} { + append o "$l\n" + continue + } + if {$y==-3} { + manyset $l cols rows colours cpp + #assert {$colours==2} + #assert {$cpp==1} + set mulcols [expr {$cols*$mul+$inter}] + set mulrows [expr {$rows*$mul+$inter}] + append o "\"$mulcols $mulrows 9 1\",\n" + for {set x 0} {$x<$cols} {incr x} { set wordmap($x) 0 } + } elseif {$y==-2} { # first pixel + append o \ +"\"+ c #111\", +\"a c #800\", +\"A c #fcc\", +\"b c #00c\", +\"B c #fff\", +\"u c #000\", +\"U c #ff0\", +\"q c #000\", +\"Q c #ff0\",\n" + } elseif {$y==-1} { # 2nd pixel but we've already printed ours + } else { + set ybit [expr {1<<$y}] + set x 0 + set ol "\"+" + set olh $ol + foreach c [split $l ""] { + set how "u" + if {$x >= $unk_l && $x <= $unk_r} { + set how q + } else { + set ab 0 + foreach {min max context got} $foolist { + set rhsmost_max $max + if {$x >= $min && $x <= $max} { + set how [lindex {a b} $ab] + break + } + set ab [expr {!$ab}] + } + } + switch -exact $c { + " " { set p $how } + "o" { + set p [string toupper $how] + incr wordmap($x) $ybit + } + default { error "$c ?" } + } + append ol "[string repeat $p [expr {$mul-$inter}]][ + string repeat + $inter]" + append olh [string repeat + $mul] + incr x + } + set ole "\",\n" + append ol $ole + append olh $ole + set olhn [string repeat $olh $inter] + if {!$y} { append o $olhn } + append o [string repeat $ol [expr {$mul-1}]] + append o $olhn + } + incr y +} + +#puts $o + +set xpm [exec xpmtoppm << $o] + +set gotsh 20 +set csrh 20 + +frame .d -width $mulcols -height [expr {$csrh+$mulrows+$gotsh}] + +set mi [image create photo -data $xpm] +label .d.mi -image $mi -borderwidth 0 + +frame .d.csr -bg black -width $mulcols -height $csrh +frame .d.got -bg black -width $mulcols -height $gotsh + +foreach {min max context got} $foolist { + frame .d.got.m$min -bd 0 -background \#888 + label .d.got.m$min.l -text "$got" -fg white -bg black -bd 0 + pack .d.got.m$min.l -padx 1 -pady 1 + place .d.got.m$min -x [expr {$min*$mul+$inter}] -y 0 +} + +set imcsr [image create bitmap -data \ +{#define csr_width 11 +#define csr_height 11 +static unsigned char csr_bits[] = { + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x21, 0x04, 0x22, 0x02, 0x25, 0x05, + 0xaa, 0x02, 0x74, 0x01, 0xa8, 0x00, 0x70, 0x00, 0x20, 0x00}; +}] + +frame .d.csr.csr +label .d.csr.csr.l -image $imcsr -compound left +entry .d.csr.csr.e -bd 0 +pack .d.csr.csr.l -side left + +frame .d.csr_0 -bg white -height $mulrows -width 1 +frame .d.csr_1 -bg white -height $mulrows -width 1 + +place .d.csr -x 0 -y 0 +place .d.mi -x 0 -y $csrh +place .d.got -x 0 -y [expr {$csrh+$mulrows}] +pack .d + +frame .help +pack .help + +set cur_already [expr {[llength $foolist]/4-1}] +set cur_mode 1 ;# one of: 0 1 already text + +set cur_0 $unk_l +set cur_1 [expr {$unk_r+1}] +set last_ht {} + +proc helptext {t} { + global last_ht + if {![string compare $t $last_ht]} return + eval destroy [grid slaves .help] + set y 0; foreach l $t { + set x 0; foreach c $l { + set w .help.at${x}x${y} + label $w -text $c + grid $w -row $y -column $x -padx 5 + incr x + } + incr y + } + set last_ht $t +} + +proc recursor/0 {} { recursor//01 0 } +proc recursor/1 {} { recursor//01 1 } +proc recursor//01 {z1} { + global mul rhsmost_max cols foolist + upvar #0 cur_$z1 cur + .d.csr.csr.l configure -text {adjust} + place .d.csr.csr -x [expr {$cur*$mul - 7}] + bind_key space { othercursor } + bind_leftright cur_$z1 0 [expr {$cols-1}] + if {[llength $foolist]} { + bind_key Tab { set cur_mode already; recursor } + } else { + bind_key Tab {} + } + bind_key Return { + if {$cur_0 != $cur_1} { + set cur_mode text + recursor + } + } + helptext { + {{<- ->} {move cursor, adjusting area to define}} + {Space {switch to moving other cursor}} + {Return {confirm location, enter letter(s)}} + {Tab {switch to correcting earlier ocr}} + } +} +proc othercursor {} { + global cur_mode + set cur_mode [expr {!$cur_mode}] + recursor +} + +proc recursor/text {} { + helptext { + {Return {confirm entry of new glyph}} + {Escape {abandon entry}} + } + unbind_all_keys + .d.csr.csr.l configure -text {define:} + pack .d.csr.csr.e -side left + focus .d.csr.csr.e + bind_key Return { + binary scan [.d.csr.csr.e get] h* hex + if {[string length $hex]} { + RETURN_RESULT DEFINE "$cur_0 $cur_1 $hex" + } + } + bind_key Escape { + bind_key Escape {} + pack forget .d.csr.csr.e + set cur_mode 1 + recursor + } +} + +proc recursor/already {} { + global mul + global foolist + global cur_already mul + global foolist cur_already mul + .d.csr.csr.l configure -text {correct} + set rmax [lindex $foolist [expr {$cur_already*4}]] + place .d.csr.csr -x [expr {$rmax*$mul-3}] + bind_key Return {} + bind_key space {} + bind_leftright cur_already 0 [expr {[llength $foolist]/4-1}] + bind_key Tab { bind_key Delete {}; set cur_mode 1; recursor } + bind_key Delete { + RETURN_RESULT DELETE [lrange $foolist \ + [expr $cur_already*4] \ + [expr $cur_already*4+1]] + } + helptext { + {{<- ->} {move cursor, selecting glyph to correct}} + {Del {clear this glyph from the recognition database}} + {Tab {switch to selecting area to define as new glyph}} + } +} + +proc bind_key {k proc} { + global keybindings + bind . $proc + set keybindings($k) [expr {!![string length $proc]}] +} +proc unbind_all_keys {} { + global keybindings + foreach k [array names keybindings] { bind_key $k {} } +} + +proc bind_leftright {var min max} { + bind_key Left [list leftright $var $min $max -1] + bind_key Right [list leftright $var $min $max +1] +} +proc leftright {var min max inc} { + upvar #0 $var v + set vnew $v + incr vnew $inc + if {$vnew < $min || $vnew > $max} return + set v $vnew + recursor +} + +proc recursor {} { + global csrh cur_mode cur_0 cur_1 mul + foreach z1 {0 1} { + place .d.csr_$z1 -y $csrh -x [expr {[set cur_$z1] * $mul}] + } + recursor/$cur_mode +} + + +# database format: +# series of glyphs: +# ... +# width +# + +# $database($context 0x 0x...) = $hex + +proc read_database {} { + global database + set f [open database r] + while {[gets $f l] >= 0} { + if {![regexp {^(\w+) (\d+) ([0-9a-f]{2}+)$} $l \ + dummy context strl strh]} { + error "bad syntax" + } + binary scan $strw h* strh + if {[string length $strh] != $strl*2} { error "$strh $strl" } + gets $f l; set width [format %d $l] + set bm $context + for {set x 0} {$x < $width} {incr x} { + gets $f l; lappend bm [format %x 0x$l] + } + set database($bm) $strh + } +} + +proc write_database {} { + global database + set ol {} + foreach bm [array names database] { + set strh $database($bm) + set strs [binary format h* $strh] + set strdo [format "%d %s" [expr {[string length $strh]/2}] $strh] + set o "[lindex $bm 0] $strdo\n" + append o [format "%d\n" [expr {[llength $bm]-1}]] + foreach x [lrange $bm 1 end] { append o "$x\n" } + lappend ol $o + } + foreach o [lsort $ol] { + puts -nonewline $o + } +} + +proc update_database/DEFINE {c0 c1 strh} { + global foolist unk_l unk_context wordmap database + if {$c0 > $c1} { manyset [list $c0 $c1] c1 c0 } + if {$c0 == $unk_l} { + set ncontext $unk_context + } else { + foreach {l r context got} $foolist { + if {$l==$c0} { set ncontext $context; break } + } + if {![exists ncontext]} { + puts stderr "must start at letter LHS!" + return + } + } + set bm $ncontext + for {set x $c0} {$x < $c1} {incr x} { + lappend bm [format %x $wordmap($x)] + } + set database($bm) $strh + write_database +} + + +proc RETURN_RESULT {how what} { + place forget .d.csr.csr + pack forget .d.csr.csr.e + helptext {{{ Processing }}} + unbind_all_keys + update idletasks + puts "$how $what" + eval update_database/$how $what +} + +# bind . {} + +read_database +recursor -- 2.30.2 From 68fa2edfa229682ec3023cc8b25738afed68532d Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 2 Jun 2009 02:50:32 +0100 Subject: [PATCH 07/16] wip ocr found files --- pctb/stuff/csr.xbm | 5 +++ pctb/stuff/show-thing.tcl | 0 pctb/stuff/t.xpm | 83 +++++++++++++++++++++++++++++++++++++++ pctb/stuff/text.xpm | 19 +++++++++ 4 files changed, 107 insertions(+) create mode 100644 pctb/stuff/csr.xbm mode change 100644 => 100755 pctb/stuff/show-thing.tcl create mode 100644 pctb/stuff/t.xpm create mode 100644 pctb/stuff/text.xpm diff --git a/pctb/stuff/csr.xbm b/pctb/stuff/csr.xbm new file mode 100644 index 0000000..c581f92 --- /dev/null +++ b/pctb/stuff/csr.xbm @@ -0,0 +1,5 @@ +#define csr_width 11 +#define csr_height 11 +static unsigned char csr_bits[] = { + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x21, 0x04, 0x22, 0x02, 0x25, 0x05, + 0xaa, 0x02, 0x74, 0x01, 0xa8, 0x00, 0x70, 0x00, 0x20, 0x00}; diff --git a/pctb/stuff/show-thing.tcl b/pctb/stuff/show-thing.tcl old mode 100644 new mode 100755 diff --git a/pctb/stuff/t.xpm b/pctb/stuff/t.xpm new file mode 100644 index 0000000..e2d7c7a --- /dev/null +++ b/pctb/stuff/t.xpm @@ -0,0 +1,83 @@ +/* XPM */ +static char *t[] = { +/* columns rows colors chars-per-pixel */ +"379 67 9 1", +"+ c #111", +"a c #600", +"A c #fcc", +"b c #008", +"B c #ccf", +"u c #000", +"U c #ff0", +"q c #000", +"Q c #ff0", +/* pixels */ +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+AAAAA+aaaaa+AAAAA+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+AAAAA+aaaaa+AAAAA+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+AAAAA+aaaaa+AAAAA+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+AAAAA+aaaaa+AAAAA+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+AAAAA+aaaaa+AAAAA+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+bbbbb+uuuuu+AAAAA+aaaaa+AAAAA+AAAAA+aaaaa+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+bbbbb+uuuuu+AAAAA+aaaaa+AAAAA+AAAAA+aaaaa+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+bbbbb+uuuuu+AAAAA+aaaaa+AAAAA+AAAAA+aaaaa+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+bbbbb+uuuuu+AAAAA+aaaaa+AAAAA+AAAAA+aaaaa+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+bbbbb+uuuuu+AAAAA+aaaaa+AAAAA+AAAAA+aaaaa+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+AAAAA+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+AAAAA+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+AAAAA+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+AAAAA+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+AAAAA+aaaaa+AAAAA+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+AAAAA+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+UUUUU+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+qqqqq+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+UUUUU+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+QQQQQ+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+QQQQQ+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+QQQQQ+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+QQQQQ+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+BBBBB+bbbbb+bbbbb+bbbbb+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+QQQQQ+qqqqq+qqqqq+QQQQQ+QQQQQ+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+UUUUU+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+qqqqq+QQQQQ+QQQQQ+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+qqqqq+QQQQQ+QQQQQ+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+qqqqq+QQQQQ+QQQQQ+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+qqqqq+QQQQQ+QQQQQ+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+bbbbb+BBBBB+BBBBB+BBBBB+BBBBB+uuuuu+AAAAA+aaaaa+aaaaa+aaaaa+AAAAA+uuuuu+qqqqq+QQQQQ+QQQQQ+qqqqq+QQQQQ+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+UUUUU+UUUUU+UUUUU+uuuuu+uuuuu+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+", +"+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+bbbbb+bbbbb+bbbbb+bbbbb+bbbbb+uuuuu+aaaaa+aaaaa+aaaaa+aaaaa+aaaaa+uuuuu+qqqqq+qqqqq+qqqqq+qqqqq+qqqqq+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+uuuuu+UUUUU+uuuuu+", +"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", +}; + diff --git a/pctb/stuff/text.xpm b/pctb/stuff/text.xpm new file mode 100644 index 0000000..d5c14ed --- /dev/null +++ b/pctb/stuff/text.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static char *t[] = { +/* columns rows colors chars-per-pixel */ +"63 11 2 1", +" c black", +"o c white", +/* pixels */ +" ", +" o o oo ", +" o o o ", +" oo oo o ", +" o o o ooo o oo o o ooo o oooo ooo o", +" o o o o oo o o o o o o o o o ", +" o o oooo o o o o oooo o o o oooo o ", +" o o o o o o o o o o o o o o o o ", +" o o o o o o o oo o o o oooo o o o", +" o o oooo o o oo o oooo ooo o oooo ", +" o o ", +}; -- 2.30.2 From 7891085124c955ab6b5dbd1106f991f846425f52 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 3 Jun 2009 17:50:49 +0100 Subject: [PATCH 08/16] found --- .gitignore | 8 ++++++++ pctb/stuff/old | 9 +++++++++ 2 files changed, 17 insertions(+) create mode 100644 pctb/stuff/old diff --git a/.gitignore b/.gitignore index cfb08ee..93f5ba1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,11 @@ t pctb/t.* pctb/u.* pctb/convert + +pctb/stuff/text.ppm +pctb/stuff/text.png +pctb/stuff/text.pbm +pctb/stuff/text.xbm + +pctb/stuff/database +pctb/stuff/t.* diff --git a/pctb/stuff/old b/pctb/stuff/old new file mode 100644 index 0000000..557b690 --- /dev/null +++ b/pctb/stuff/old @@ -0,0 +1,9 @@ +"\"+ c #111\", +\"a c #600\", +\"A c #fcc\", +\"b c #006\", +\"B c #ccf\", +\"u c #000\", +\"U c #888\", +\"q c #440\", +\"Q c #ff0\",\n" -- 2.30.2 From 54f10d7fe3898d21ea03d544c9c3d3f1c0561969 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 3 Jun 2009 17:51:31 +0100 Subject: [PATCH 09/16] show-thing is interesting --- pctb/{stuff => }/show-thing.tcl | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pctb/{stuff => }/show-thing.tcl (100%) diff --git a/pctb/stuff/show-thing.tcl b/pctb/show-thing.tcl similarity index 100% rename from pctb/stuff/show-thing.tcl rename to pctb/show-thing.tcl -- 2.30.2 From 7715bdc10f8ea8a0b26715bddb3fb5b973f0d404 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 3 Jun 2009 17:59:24 +0100 Subject: [PATCH 10/16] show-thing database interaction improved --- pctb/show-thing.tcl | 17 +++++++++++++---- pctb/{stuff => }/text.xpm | 0 2 files changed, 13 insertions(+), 4 deletions(-) rename pctb/{stuff => }/text.xpm (100%) diff --git a/pctb/show-thing.tcl b/pctb/show-thing.tcl index 4537e6a..1c55fcd 100755 --- a/pctb/show-thing.tcl +++ b/pctb/show-thing.tcl @@ -1,4 +1,10 @@ -#!/usr/bin/tk +#!/usr/bin/wish + +# usage: +# run show-thing without args +# then on stdin write +# one line which is a Tcl list for foolist +# the xpm in the format expected proc manyset {list args} { foreach val $list var $args { @@ -287,11 +293,10 @@ proc read_database {} { global database set f [open database r] while {[gets $f l] >= 0} { - if {![regexp {^(\w+) (\d+) ([0-9a-f]{2}+)$} $l \ + if {![regexp {^(\w+) (\d+) ((?:[0-9a-f]{2})+)$} $l \ dummy context strl strh]} { error "bad syntax" } - binary scan $strw h* strh if {[string length $strh] != $strl*2} { error "$strh $strl" } gets $f l; set width [format %d $l] set bm $context @@ -300,6 +305,7 @@ proc read_database {} { } set database($bm) $strh } + close $f } proc write_database {} { @@ -314,9 +320,12 @@ proc write_database {} { foreach x [lrange $bm 1 end] { append o "$x\n" } lappend ol $o } + set f [open database.new w] foreach o [lsort $ol] { - puts -nonewline $o + puts -nonewline $f $o } + close $f + file rename -force database.new database } proc update_database/DEFINE {c0 c1 strh} { diff --git a/pctb/stuff/text.xpm b/pctb/text.xpm similarity index 100% rename from pctb/stuff/text.xpm rename to pctb/text.xpm -- 2.30.2 From ad09cd7cce6584c63c275d7ed1106e66959b3f9d Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 3 Jun 2009 22:35:12 +0100 Subject: [PATCH 11/16] WIP now has most of the ocr parts but does not work yet --- .gitignore | 1 + pctb/Makefile | 4 + pctb/convert.c | 144 ++------------------------ pctb/ocr.c | 240 ++++++++++++++++++++++++++++++++++++++++++++ pctb/ocr.h | 32 ++++++ pctb/show-thing.tcl | 6 +- pctb/x.gdb | 4 + 7 files changed, 297 insertions(+), 134 deletions(-) create mode 100644 pctb/ocr.c create mode 100644 pctb/ocr.h create mode 100644 pctb/x.gdb diff --git a/.gitignore b/.gitignore index 93f5ba1..8875777 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ *~ t +pctb/*.o pctb/t.* pctb/u.* pctb/convert diff --git a/pctb/Makefile b/pctb/Makefile index 10c0be9..2cb3fad 100644 --- a/pctb/Makefile +++ b/pctb/Makefile @@ -3,3 +3,7 @@ CFLAGS += -Wall -Wwrite-strings -Wpointer-arith -Wmissing-prototypes \ -Wstrict-prototypes -g all: convert + +convert: convert.o ocr.o + +convert.o ocr.o: ocr.h diff --git a/pctb/convert.c b/pctb/convert.c index a0ecca1..f3de359 100644 --- a/pctb/convert.c +++ b/pctb/convert.c @@ -1,12 +1,5 @@ -#include -#include -#include -#include -#include -#include -#define eassert assert -#define debug stdout +#include "ocr.h" typedef struct { unsigned long rgb; /* on screen */ @@ -242,88 +235,9 @@ static void load_image_and_canonify(void) { debug_flush(); } -typedef uint32_t Pixcol; -#define PSPIXCOL(priscan) priscan##32 - -typedef struct { - Pixcol col; - struct OCRDatabaseNode *then; -} OCRDatabaseLink; - -#define MAXGLYPHCHRS 3 - -typedef struct OCRDatabaseNode { - char s[MAXGLYPHCHRS+1]; /* null-terminated; "" means no match here */ - int nlinks, alinks; - OCRDatabaseLink *links; -} OCRDatabaseNode; - -#define N_OCR_CONTEXTS 2 -static OCRDatabaseNode ocr_contexts[N_OCR_CONTEXTS]; - -static void load_ocr_database(void) { - int ctx,nchrs; - OCRDatabaseNode *current, *additional; - char chrs[MAXGLYPHCHRS+1]; - Pixcol cv; - int r,i,j; - - FILE *db= fopen("database","r"); eassert(db); - - for (;;) { - r= fscanf(db, "%d %d", &ctx, &nchrs); - if (r==EOF) break; - eassert(r==2); - eassert(ctx>=0 && ctx0 && nchrs<=MAXGLYPHCHRS); - - for (i=0; i0 && c<=255); - chrs[i]= c; - } - chrs[nchrs]= 0; - - int twidth; - r= fscanf(db, "%d", &twidth); eassert(r==1); - current= &ocr_contexts[ctx]; - for (i=0; inlinks; j++) - if (current->links[j].col == cv) { - current= current->links[j].then; - goto found_link; - } - - additional= malloc(sizeof(*additional)); eassert(additional); - additional->s[0]= 0; - additional->nlinks= additional->alinks= 0; - additional->links= 0; - if (current->nlinks==current->alinks) { - current->alinks++; - current->alinks<<=1; - current->links= realloc(current->links, - sizeof(*current->links) * current->alinks); - eassert(current->links); - } - current->links[current->nlinks].col= cv; - current->links[current->nlinks].then= additional; - current->nlinks++; - current= additional; - - found_link:; - } - - eassert(!current->s[0]); - strcpy(current->s, chrs); - } - eassert(!ferror(db)); - eassert(feof(db)); - fclose(db); -} - static void ocr_rectangle(Rect r) { + OcrResultGlyph *results, *res; + int w= r.br.x - r.tl.x + 1; int h= r.br.y - r.tl.y + 1; Pixcol cols[w+1]; @@ -341,56 +255,20 @@ static void ocr_rectangle(Rect r) { } cols[w]= 0; - int nspaces=0; - int ctx=1,i; - x=0; - - for (;;) { - if (x>w) break; - - if (!cols[x]) { - nspaces++; - x++; - if (nspaces>3) ctx=1; - continue; - } - - OCRDatabaseNode *current=0, *lastmatch=0; - int startx=x; - int afterlastmatchx=-1; - current= &ocr_contexts[ctx]; - for (;;) { - if (x>w) break; - Pixcol cv= cols[x]; - for (i=0; inlinks; i++) - if (current->links[i].col == cv) - goto found; - /* not found */ - break; - found: - x++; - current= current->links[i].then; - if (current->s[0]) { lastmatch=current; afterlastmatchx=x; } - } - - if (!lastmatch) { - int x2; - for (x2=x+1; x2s); - x= afterlastmatchx; - ctx= 0; - } - } + results= ocr(w,h,cols); + printf("YES! \""); + for (res=0; res->s; res++) + printf("%s",res->s); + printf("\"\n"); + eassert(!ferror(stdout)); + eassert(!fflush(stdout)); } int main(void) { Rect thisr, entryr; int tryrect, colno; - load_ocr_database(); + ocr_init(); load_image_and_canonify(); find_structure(); diff --git a/pctb/ocr.c b/pctb/ocr.c new file mode 100644 index 0000000..a90ecea --- /dev/null +++ b/pctb/ocr.c @@ -0,0 +1,240 @@ +/* + */ + +#include "ocr.h" + +typedef struct { + Pixcol col; + struct OCRDatabaseNode *then; +} OCRDatabaseLink; + +#define MAXGLYPHCHRS 3 + +typedef struct OCRDatabaseNode { + char s[MAXGLYPHCHRS+1]; /* null-terminated; "" means no match here */ + int nlinks, alinks; + OCRDatabaseLink *links; +} OCRDatabaseNode; + +#define N_OCR_CONTEXTS 2 + +static OCRDatabaseNode ocr_contexts[N_OCR_CONTEXTS]; +static FILE *db; +static OcrResultGlyph *results; +static int aresults, nresults; + +static FILE *resolver; +static pid_t resolver_pid; + +static void ocr_readdb(void) { + int ctx,nchrs; + OCRDatabaseNode *current, *additional; + char chrs[MAXGLYPHCHRS+1]; + Pixcol cv; + int r,i,j; + + assert(!db); + db= fopen("database","r"); eassert(db); + + for (;;) { + r= fscanf(db, "%d %d", &ctx, &nchrs); + if (r==EOF) break; + eassert(r==2); + eassert(ctx>=0 && ctx0 && nchrs<=MAXGLYPHCHRS); + + for (i=0; i0 && c<=255); + chrs[i]= c; + } + chrs[nchrs]= 0; + + int twidth; + r= fscanf(db, "%d", &twidth); eassert(r==1); + current= &ocr_contexts[ctx]; + for (i=0; inlinks; j++) + if (current->links[j].col == cv) { + current= current->links[j].then; + goto found_link; + } + + additional= malloc(sizeof(*additional)); eassert(additional); + additional->s[0]= 0; + additional->nlinks= additional->alinks= 0; + additional->links= 0; + if (current->nlinks==current->alinks) { + current->alinks++; + current->alinks<<=1; + current->links= realloc(current->links, + sizeof(*current->links) * current->alinks); + eassert(current->links); + } + current->links[current->nlinks].col= cv; + current->links[current->nlinks].then= additional; + current->nlinks++; + current= additional; + + found_link:; + } + + eassert(!current->s[0]); + strcpy(current->s, chrs); + } + eassert(!ferror(db)); + eassert(feof(db)); +} + +static void callout_unknown(int w, int h, Pixcol cols[], int unk_l, int unk_r, + const OcrResultGlyph *sofar, int nsofar) { + int pfd[2], c, r,i, x,y; + const OcrResultGlyph *s; + const char *p; + Pixcol pv; + + if (!resolver) { + r= pipe(pfd); eassert(!r); + resolver_pid= fork(); + eassert(resolver_pid!=-1); + if (!resolver_pid) { + r= dup2(pfd[0],0); eassert(!r); + r= close(pfd[1]); eassert(!r); + execlp("./show-thing.tcl", "./show-thing.tcl",(char*)0); + eassert(!"execlp failed"); + } + r= close(pfd[0]); eassert(!r); + resolver= fdopen(pfd[1],"w"); eassert(resolver); + } + fprintf(resolver,"%d %d",unk_l,unk_r); + for (i=0, s=sofar; il,s->r,s->ctx); + for (p=s->s; (c= *p); p++) { + if (c=='\\') fprintf(resolver,"\\%c",c); + else if (c>=33 && c<=126) fputc(c,resolver); + else fprintf(resolver,"\\x%02x",(unsigned char)c); + } + } + 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,h); + for (y=0, pv=1; y= aresults) { + aresults++; aresults<<=1; + results= realloc(results,sizeof(*results)*aresults); + eassert(results); + } + results[nresults].s= s; + results[nresults].l= l; + results[nresults].r= r; + results[nresults].ctx= ctx; + nresults++; +} + +OcrResultGlyph *ocr(int w, int h, Pixcol cols[]) { + int nspaces=0; + int ctx=1,i, x; + + nresults=0; + assert(db); + + restart: + x=0; + for (;;) { + /* skip spaces */ + if (x>=w) break; + + if (!cols[x]) { + nspaces++; + x++; + if (nspaces>3) ctx=1; + continue; + } + + /* find character */ + OCRDatabaseNode *current=0, *bestmatch=0; + int lx=x; + int bestmatch_rx=-1; + current= &ocr_contexts[ctx]; + for (;;) { + if (x>w) break; + Pixcol cv= cols[x]; + for (i=0; inlinks; i++) + if (current->links[i].col == cv) + goto found; + /* not found */ + break; + found: + current= current->links[i].then; + if (current->s[0]) { bestmatch=current; bestmatch_rx=x; } + x++; + } + + if (!bestmatch) { + add_result(bestmatch->s, lx, bestmatch_rx, ctx); + x= bestmatch_rx+1; + ctx= 0; + } else { + + int rx; + for (rx=lx+1; rx +#include +#include +#include +#include +#include +#include +#include + +typedef uint32_t Pixcol; +#define PSPIXCOL(priscan) priscan##32 + +typedef struct { + const char *s; /* valid until next call to ocr() */ + int l,r; /* column numbers */ + int ctx; /* match context index */ +} OcrResultGlyph; + +OcrResultGlyph *ocr(int w, int h, Pixcol cols[]); + /* return value is array terminated by {0,-1,-1} + * array is valid until next call to ocr() + */ + +void ocr_init(void); + +#define eassert assert +#define debug stdout + +#endif /*OCR_H*/ diff --git a/pctb/show-thing.tcl b/pctb/show-thing.tcl index 1c55fcd..9a5b1d2 100755 --- a/pctb/show-thing.tcl +++ b/pctb/show-thing.tcl @@ -5,6 +5,8 @@ # then on stdin write # one line which is a Tcl list for foolist # the xpm in the format expected +# then expect child to raise SIGSTOP or exit 0 or exit nonzero +# if child raised SIGSTOP, check database was updated proc manyset {list args} { foreach val $list var $args { @@ -31,9 +33,11 @@ set rhsmost_max -1 set f [open text.xpm] set o {} set y -3 -while {[gets $f l] >= 0} { +while 1 { + if {[gets $f l] < 0} { error "huh? "} if {![regexp {^"(.*)",$} $l dummy l]} { append o "$l\n" + if {[regexp {^\}\;$} $l]} break continue } if {$y==-3} { diff --git a/pctb/x.gdb b/pctb/x.gdb new file mode 100644 index 0000000..922bd4c --- /dev/null +++ b/pctb/x.gdb @@ -0,0 +1,4 @@ +file convert +set confirm off +set args Date: Wed, 3 Jun 2009 23:28:00 +0100 Subject: [PATCH 12/16] wip can invoke show-things.tcl --- pctb/Makefile | 2 +- pctb/convert.c | 2 +- pctb/ocr.c | 33 ++++++++++++++++++++++++++++----- pctb/ocr.h | 2 ++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/pctb/Makefile b/pctb/Makefile index 2cb3fad..3707d81 100644 --- a/pctb/Makefile +++ b/pctb/Makefile @@ -1,6 +1,6 @@ LDLIBS += -lnetpbm CFLAGS += -Wall -Wwrite-strings -Wpointer-arith -Wmissing-prototypes \ - -Wstrict-prototypes -g + -Wstrict-prototypes -Werror -g all: convert diff --git a/pctb/convert.c b/pctb/convert.c index f3de359..c8082e6 100644 --- a/pctb/convert.c +++ b/pctb/convert.c @@ -9,7 +9,7 @@ typedef struct { static int height, width; static char *image; -static void debug_flush(void) { +void debug_flush(void) { eassert(!fflush(debug)); eassert(!ferror(debug)); } diff --git a/pctb/ocr.c b/pctb/ocr.c index a90ecea..87bf808 100644 --- a/pctb/ocr.c +++ b/pctb/ocr.c @@ -186,11 +186,18 @@ OcrResultGlyph *ocr(int w, int h, Pixcol cols[]) { nresults=0; assert(db); + fprintf(debug,"OCR h=%d w=%d",w,h); + for (x=0; x=w) break; + if (x>=w) + break; if (!cols[x]) { nspaces++; @@ -204,34 +211,50 @@ OcrResultGlyph *ocr(int w, int h, Pixcol cols[]) { int lx=x; int bestmatch_rx=-1; current= &ocr_contexts[ctx]; + fprintf(debug,"OCR lx=%d ctx=%d ",lx,ctx); + for (;;) { + debug_flush(); + fprintf(debug,"| x=%d",x); if (x>w) break; Pixcol cv= cols[x]; + fprintf(debug," cv=%"PSPIXCOL(PRIx),x); for (i=0; inlinks; i++) if (current->links[i].col == cv) goto found; /* not found */ + fprintf(debug," ?"); break; + found: current= current->links[i].then; - if (current->s[0]) { bestmatch=current; bestmatch_rx=x; } + if (current->s[0]) { + fprintf(debug," \"%s\"",current->s); + bestmatch=current; bestmatch_rx=x; + } else { + fprintf(debug," ..."); + } x++; } - if (!bestmatch) { + if (bestmatch) { + fprintf(debug," YES\n"); add_result(bestmatch->s, lx, bestmatch_rx, ctx); x= bestmatch_rx+1; ctx= 0; } else { - int rx; + fprintf(debug," UNKNOWN"); for (rx=lx+1; rx Date: Wed, 3 Jun 2009 23:39:55 +0100 Subject: [PATCH 13/16] wip show-thing rework --- pctb/stuff/show-thing.tcl | 150 ++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 71 deletions(-) diff --git a/pctb/stuff/show-thing.tcl b/pctb/stuff/show-thing.tcl index 4537e6a..c1e8cb9 100755 --- a/pctb/stuff/show-thing.tcl +++ b/pctb/stuff/show-thing.tcl @@ -7,39 +7,28 @@ proc manyset {list args} { } } -set foolist { - 7 11 1 M - 13 17 0 a - 19 23 0 n -} -set unk_l 25 -set unk_r 29 -set unk_context 0 - - - set mul 6 set inter 1 set rhsmost_max -1 -set f [open text.xpm] -set o {} -set y -3 -while {[gets $f l] >= 0} { - if {![regexp {^"(.*)",$} $l dummy l]} { - append o "$l\n" - continue - } - if {$y==-3} { - manyset $l cols rows colours cpp - #assert {$colours==2} - #assert {$cpp==1} - set mulcols [expr {$cols*$mul+$inter}] - set mulrows [expr {$rows*$mul+$inter}] - append o "\"$mulcols $mulrows 9 1\",\n" - for {set x 0} {$x<$cols} {incr x} { set wordmap($x) 0 } - } elseif {$y==-2} { # first pixel - append o \ +proc read_xpm {f} { + set o {} + set y -3 + while {[gets $f l] >= 0} { + if {![regexp {^"(.*)",$} $l dummy l]} { + append o "$l\n" + continue + } + if {$y==-3} { + manyset $l cols rows colours cpp + #assert {$colours==2} + #assert {$cpp==1} + set mulcols [expr {$cols*$mul+$inter}] + set mulrows [expr {$rows*$mul+$inter}] + append o "\"$mulcols $mulrows 9 1\",\n" + for {set x 0} {$x<$cols} {incr x} { set wordmap($x) 0 } + } elseif {$y==-2} { # first pixel + append o \ "\"+ c #111\", \"a c #800\", \"A c #fcc\", @@ -49,61 +38,63 @@ while {[gets $f l] >= 0} { \"U c #ff0\", \"q c #000\", \"Q c #ff0\",\n" - } elseif {$y==-1} { # 2nd pixel but we've already printed ours - } else { - set ybit [expr {1<<$y}] - set x 0 - set ol "\"+" - set olh $ol - foreach c [split $l ""] { - set how "u" - if {$x >= $unk_l && $x <= $unk_r} { - set how q - } else { - set ab 0 - foreach {min max context got} $foolist { - set rhsmost_max $max - if {$x >= $min && $x <= $max} { - set how [lindex {a b} $ab] - break + } elseif {$y==-1} { # 2nd pixel but we've already printed ours + } else { + set ybit [expr {1<<$y}] + set x 0 + set ol "\"+" + set olh $ol + foreach c [split $l ""] { + set how "u" + if {$x >= $unk_l && $x <= $unk_r} { + set how q + } else { + set ab 0 + foreach {min max context got} $foolist { + set rhsmost_max $max + if {$x >= $min && $x <= $max} { + set how [lindex {a b} $ab] + break + } + set ab [expr {!$ab}] } - set ab [expr {!$ab}] } - } - switch -exact $c { - " " { set p $how } - "o" { - set p [string toupper $how] - incr wordmap($x) $ybit + switch -exact $c { + " " { set p $how } + "o" { + set p [string toupper $how] + incr wordmap($x) $ybit + } + default { error "$c ?" } } - default { error "$c ?" } - } - append ol "[string repeat $p [expr {$mul-$inter}]][ + append ol "[string repeat $p [expr {$mul-$inter}]][ string repeat + $inter]" - append olh [string repeat + $mul] - incr x + append olh [string repeat + $mul] + incr x + } + set ole "\",\n" + append ol $ole + append olh $ole + set olhn [string repeat $olh $inter] + if {!$y} { append o $olhn } + append o [string repeat $ol [expr {$mul-1}]] + append o $olhn } - set ole "\",\n" - append ol $ole - append olh $ole - set olhn [string repeat $olh $inter] - if {!$y} { append o $olhn } - append o [string repeat $ol [expr {$mul-1}]] - append o $olhn + incr y } - incr y + set data [exec xpmtoppm << $o] + image create photo main_image -data $xpm } #puts $o -set xpm [exec xpmtoppm << $o] - set gotsh 20 set csrh 20 frame .d -width $mulcols -height [expr {$csrh+$mulrows+$gotsh}] -set mi [image create photo -data $xpm] +set mi main_image +image create bitmap main_image label .d.mi -image $mi -borderwidth 0 frame .d.csr -bg black -width $mulcols -height $csrh @@ -354,5 +345,22 @@ proc RETURN_RESULT {how what} { # bind . {} -read_database -recursor +proc test_main {} { + global foolist + + set foolist { + 7 11 1 M + 13 17 0 a + 19 23 0 n + } + set unk_l 25 + set unk_r 29 + set unk_context 0 + + set f [open text.xpm] + read_xpm $f + close $f + + read_database + recursor +} -- 2.30.2 From 8ca929d6e99e7c48659061a7215a55cd533a4c42 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 4 Jun 2009 00:04:51 +0100 Subject: [PATCH 14/16] wip fixes to show-thing for reorg --- pctb/show-thing.tcl | 70 ++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/pctb/show-thing.tcl b/pctb/show-thing.tcl index f2055f4..19912cb 100755 --- a/pctb/show-thing.tcl +++ b/pctb/show-thing.tcl @@ -17,9 +17,14 @@ proc manyset {list args} { set mul 6 set inter 1 -set rhsmost_max -1 + +set gotsh 20 +set csrh 20 proc read_xpm {f} { + global foolist mul inter rhsmost_max unk_l unk_r gotsh csrh + global cols rows wordmap + set o {} set y -3 while 1 { @@ -93,28 +98,38 @@ proc read_xpm {f} { incr y } set data [exec xpmtoppm << $o] - image create photo main_image -data $xpm + image create photo main_image -data $data + + foreach w {.d .d.csr .d.got} { + $w configure -width $mulcols + } + .d configure -height [expr {$csrh+$mulrows+$gotsh}] + foreach w {0 1} { + .d.csr_$w configure -height $mulrows + } + place .d.got -x 0 -y [expr {$csrh+$mulrows}] } #puts $o -set gotsh 20 -set csrh 20 - -frame .d -width $mulcols -height [expr {$csrh+$mulrows+$gotsh}] +frame .d set mi main_image image create bitmap main_image label .d.mi -image $mi -borderwidth 0 -frame .d.csr -bg black -width $mulcols -height $csrh -frame .d.got -bg black -width $mulcols -height $gotsh - -foreach {min max context got} $foolist { - frame .d.got.m$min -bd 0 -background \#888 - label .d.got.m$min.l -text "$got" -fg white -bg black -bd 0 - pack .d.got.m$min.l -padx 1 -pady 1 - place .d.got.m$min -x [expr {$min*$mul+$inter}] -y 0 +frame .d.csr -bg black -height $csrh +frame .d.got -bg black -height $gotsh + +proc draw_foolist {} { + global foolist mul inter + eval destroy [winfo children .d.got] + foreach {min max context got} $foolist { + frame .d.got.m$min -bd 0 -background \#888 + label .d.got.m$min.l -text "$got" -fg white -bg black -bd 0 + pack .d.got.m$min.l -padx 1 -pady 1 + place .d.got.m$min -x [expr {$min*$mul+$inter}] -y 0 + } } set imcsr [image create bitmap -data \ @@ -130,23 +145,27 @@ label .d.csr.csr.l -image $imcsr -compound left entry .d.csr.csr.e -bd 0 pack .d.csr.csr.l -side left -frame .d.csr_0 -bg white -height $mulrows -width 1 -frame .d.csr_1 -bg white -height $mulrows -width 1 +frame .d.csr_0 -bg white -width 1 +frame .d.csr_1 -bg white -width 1 place .d.csr -x 0 -y 0 place .d.mi -x 0 -y $csrh -place .d.got -x 0 -y [expr {$csrh+$mulrows}] pack .d frame .help pack .help -set cur_already [expr {[llength $foolist]/4-1}] -set cur_mode 1 ;# one of: 0 1 already text +proc startup_cursor {} { + global cur_already cur_mode cur_0 cur_1 last_ht + global foolist unk_l unk_r + + set cur_already [expr {[llength $foolist]/4-1}] + set cur_mode 1 ;# one of: 0 1 already text -set cur_0 $unk_l -set cur_1 [expr {$unk_r+1}] -set last_ht {} + set cur_0 $unk_l + set cur_1 [expr {$unk_r+1}] + set last_ht {} +} proc helptext {t} { global last_ht @@ -359,7 +378,7 @@ proc RETURN_RESULT {how what} { # bind . {} proc test_main {} { - global foolist + global foolist unk_l unk_r unk_context set foolist { 7 11 1 M @@ -374,6 +393,11 @@ proc test_main {} { read_xpm $f close $f + draw_foolist + startup_cursor + read_database recursor } + +test_main -- 2.30.2 From 19d9fa719b3d1658a96b422161f0879d6b696664 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 4 Jun 2009 00:31:33 +0100 Subject: [PATCH 15/16] database updates seem to work --- pctb/database | 7 -- pctb/show-thing.tcl | 156 ++++++++++++++++++++++++++------------------ 2 files changed, 93 insertions(+), 70 deletions(-) diff --git a/pctb/database b/pctb/database index 7ccee42..e69de29 100644 --- a/pctb/database +++ b/pctb/database @@ -1,7 +0,0 @@ -0 1 57 -5 -1f0 -200 -200 -100 -3f0 diff --git a/pctb/show-thing.tcl b/pctb/show-thing.tcl index 19912cb..0b0b8f5 100755 --- a/pctb/show-thing.tcl +++ b/pctb/show-thing.tcl @@ -3,11 +3,12 @@ # usage: # run show-thing without args # then on stdin write -# one line which is a Tcl list for foolist +# one line which is a Tcl list for glyphsdone # the xpm in the format expected # then expect child to raise SIGSTOP or exit 0 or exit nonzero # if child raised SIGSTOP, check database was updated + proc manyset {list args} { foreach val $list var $args { upvar 1 $var my @@ -15,14 +16,55 @@ proc manyset {list args} { } } + +#---------- display core ---------- + set mul 6 set inter 1 set gotsh 20 set csrh 20 +proc init_widgets {} { + global csrh gotsh + + frame .d + + image create bitmap image/main + label .d.mi -image image/main -borderwidth 0 + + frame .d.csr -bg black -height $csrh + frame .d.got -bg black -height $gotsh + + image create bitmap image/cursor -data \ +{#define csr_width 11 +#define csr_height 11 +static unsigned char csr_bits[] = { + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x21, 0x04, 0x22, 0x02, 0x25, 0x05, + 0xaa, 0x02, 0x74, 0x01, 0xa8, 0x00, 0x70, 0x00, 0x20, 0x00}; +} + + frame .d.csr.csr + label .d.csr.csr.l -image image/cursor -compound left + entry .d.csr.csr.e -bd 0 + pack .d.csr.csr.l -side left + + frame .d.csr_0 -bg white -width 1 + frame .d.csr_1 -bg white -width 1 + + place .d.csr -x 0 -y 0 + place .d.mi -x 0 -y $csrh + pack .d + + frame .help + pack .help +} + + +#---------- xpm input processor ---------- + proc read_xpm {f} { - global foolist mul inter rhsmost_max unk_l unk_r gotsh csrh + global glyphsdone mul inter rhsmost_max unk_l unk_r gotsh csrh global cols rows wordmap set o {} @@ -65,7 +107,7 @@ proc read_xpm {f} { set how q } else { set ab 0 - foreach {min max context got} $foolist { + foreach {min max context got} $glyphsdone { set rhsmost_max $max if {$x >= $min && $x <= $max} { set how [lindex {a b} $ab] @@ -98,7 +140,7 @@ proc read_xpm {f} { incr y } set data [exec xpmtoppm << $o] - image create photo main_image -data $data + image create photo image/main -data $data foreach w {.d .d.csr .d.got} { $w configure -width $mulcols @@ -110,21 +152,13 @@ proc read_xpm {f} { place .d.got -x 0 -y [expr {$csrh+$mulrows}] } -#puts $o - -frame .d -set mi main_image -image create bitmap main_image -label .d.mi -image $mi -borderwidth 0 +#---------- per-invocation display ---------- -frame .d.csr -bg black -height $csrh -frame .d.got -bg black -height $gotsh - -proc draw_foolist {} { - global foolist mul inter +proc draw_glyphsdone {} { + global glyphsdone mul inter eval destroy [winfo children .d.got] - foreach {min max context got} $foolist { + foreach {min max context got} $glyphsdone { frame .d.got.m$min -bd 0 -background \#888 label .d.got.m$min.l -text "$got" -fg white -bg black -bd 0 pack .d.got.m$min.l -padx 1 -pady 1 @@ -132,34 +166,11 @@ proc draw_foolist {} { } } -set imcsr [image create bitmap -data \ -{#define csr_width 11 -#define csr_height 11 -static unsigned char csr_bits[] = { - 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x21, 0x04, 0x22, 0x02, 0x25, 0x05, - 0xaa, 0x02, 0x74, 0x01, 0xa8, 0x00, 0x70, 0x00, 0x20, 0x00}; -}] - -frame .d.csr.csr -label .d.csr.csr.l -image $imcsr -compound left -entry .d.csr.csr.e -bd 0 -pack .d.csr.csr.l -side left - -frame .d.csr_0 -bg white -width 1 -frame .d.csr_1 -bg white -width 1 - -place .d.csr -x 0 -y 0 -place .d.mi -x 0 -y $csrh -pack .d - -frame .help -pack .help - proc startup_cursor {} { global cur_already cur_mode cur_0 cur_1 last_ht - global foolist unk_l unk_r + global glyphsdone unk_l unk_r - set cur_already [expr {[llength $foolist]/4-1}] + set cur_already [expr {[llength $glyphsdone]/4-1}] set cur_mode 1 ;# one of: 0 1 already text set cur_0 $unk_l @@ -167,6 +178,9 @@ proc startup_cursor {} { set last_ht {} } + +#---------- runtime display and keystroke handling ---------- + proc helptext {t} { global last_ht if {![string compare $t $last_ht]} return @@ -186,13 +200,13 @@ proc helptext {t} { proc recursor/0 {} { recursor//01 0 } proc recursor/1 {} { recursor//01 1 } proc recursor//01 {z1} { - global mul rhsmost_max cols foolist + global mul rhsmost_max cols glyphsdone upvar #0 cur_$z1 cur .d.csr.csr.l configure -text {adjust} place .d.csr.csr -x [expr {$cur*$mul - 7}] bind_key space { othercursor } bind_leftright cur_$z1 0 [expr {$cols-1}] - if {[llength $foolist]} { + if {[llength $glyphsdone]} { bind_key Tab { set cur_mode already; recursor } } else { bind_key Tab {} @@ -241,20 +255,20 @@ proc recursor/text {} { proc recursor/already {} { global mul - global foolist + global glyphsdone global cur_already mul - global foolist cur_already mul + global glyphsdone cur_already mul .d.csr.csr.l configure -text {correct} - set rmax [lindex $foolist [expr {$cur_already*4}]] + set rmax [lindex $glyphsdone [expr {$cur_already*4}]] place .d.csr.csr -x [expr {$rmax*$mul-3}] bind_key Return {} bind_key space {} - bind_leftright cur_already 0 [expr {[llength $foolist]/4-1}] + bind_leftright cur_already 0 [expr {[llength $glyphsdone]/4-1}] bind_key Tab { bind_key Delete {}; set cur_mode 1; recursor } bind_key Delete { - RETURN_RESULT DELETE [lrange $foolist \ + RETURN_RESULT DELETE [lrange $glyphsdone \ [expr $cur_already*4] \ - [expr $cur_already*4+1]] + [expr $cur_already*4+2]] } helptext { {{<- ->} {move cursor, selecting glyph to correct}} @@ -295,6 +309,8 @@ proc recursor {} { } +#---------- database read and write ---------- + # database format: # series of glyphs: # ... @@ -342,27 +358,41 @@ proc write_database {} { file rename -force database.new database } +proc dbkey {ctx l r} { + global wordmap + set bm $ctx + for {set x $l} {$x <= $r} {incr x} { + lappend bm [format %x $wordmap($x)] + } + return $bm +} + proc update_database/DEFINE {c0 c1 strh} { - global foolist unk_l unk_context wordmap database + global glyphsdone unk_l unk_context wordmap database if {$c0 > $c1} { manyset [list $c0 $c1] c1 c0 } if {$c0 == $unk_l} { set ncontext $unk_context } else { - foreach {l r context got} $foolist { + foreach {l r context got} $glyphsdone { if {$l==$c0} { set ncontext $context; break } } - if {![exists ncontext]} { + if {![info exists ncontext]} { puts stderr "must start at letter LHS!" return } } - set bm $ncontext - for {set x $c0} {$x < $c1} {incr x} { - lappend bm [format %x $wordmap($x)] - } + incr c1 -1 + set bm [dbkey $ncontext $c0 $c1] set database($bm) $strh write_database } + +proc update_database/DELETE {l r ctx} { + global database + set bm [dbkey $ctx $l $r] + unset database($bm) + write_database +} proc RETURN_RESULT {how what} { @@ -378,9 +408,9 @@ proc RETURN_RESULT {how what} { # bind . {} proc test_main {} { - global foolist unk_l unk_r unk_context - - set foolist { + global glyphsdone unk_l unk_r unk_context + + set glyphsdone { 7 11 1 M 13 17 0 a 19 23 0 n @@ -393,11 +423,11 @@ proc test_main {} { read_xpm $f close $f - draw_foolist + draw_glyphsdone startup_cursor - - read_database - recursor } +read_database +init_widgets test_main +recursor -- 2.30.2 From 7198105eceff39cb71cd432312e0e9c82139d7b1 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 4 Jun 2009 00:52:29 +0100 Subject: [PATCH 16/16] wip. before remove sigstop based thing which is mad --- pctb/database | 30 ++++++++++++++++++++++++++++++ pctb/ocr.c | 9 +++++---- pctb/show-thing.tcl | 33 +++++++++++++++++++++++++++++---- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/pctb/database b/pctb/database index e69de29..d5e7803 100644 --- a/pctb/database +++ b/pctb/database @@ -0,0 +1,30 @@ +0 1 57 +5 +7e0 +800 +800 +400 +fe0 +0 1 76 +5 +27c0 +2820 +2820 +2420 +1fe0 +1 1 16 +6 +640 +920 +920 +920 +fc0 +800 +1 1 35 +6 +830 +848 +888 +888 +708 +8 diff --git a/pctb/ocr.c b/pctb/ocr.c index 87bf808..43636f2 100644 --- a/pctb/ocr.c +++ b/pctb/ocr.c @@ -88,7 +88,8 @@ static void ocr_readdb(void) { eassert(feof(db)); } -static void callout_unknown(int w, int h, Pixcol cols[], int unk_l, int unk_r, +static void callout_unknown(int w, int h, Pixcol cols[], + int unk_l, int unk_r, int unk_ctx, const OcrResultGlyph *sofar, int nsofar) { int pfd[2], c, r,i, x,y; const OcrResultGlyph *s; @@ -108,7 +109,7 @@ static void callout_unknown(int w, int h, Pixcol cols[], int unk_l, int unk_r, r= close(pfd[0]); eassert(!r); resolver= fdopen(pfd[1],"w"); eassert(resolver); } - fprintf(resolver,"%d %d",unk_l,unk_r); + fprintf(resolver,"%d %d %d",unk_l,unk_r,unk_ctx); for (i=0, s=sofar; il,s->r,s->ctx); for (p=s->s; (c= *p); p++) { @@ -245,10 +246,10 @@ OcrResultGlyph *ocr(int w, int h, Pixcol cols[]) { } else { int rx; fprintf(debug," UNKNOWN"); - for (rx=lx+1; rx {} +#---------- main progrm ---------- proc test_main {} { global glyphsdone unk_l unk_r unk_context @@ -427,7 +434,25 @@ proc test_main {} { startup_cursor } +proc required {} { + global glyphsdone unk_l unk_r unk_context + + if {[gets stdin l]<0} { + if {[eof stdin]} { fconfigure stdin -blocking yes; exit 0 } + return + } + init_widgets + manyset [lrange $l 0 3] unk_l unk_r unk_context + set glyphsdone [lrange $l 3 end] + puts "SHOW-THING GOT $l" + + fileevent stdin readable {} + + read_xpm stdin + draw_glyphsdone + startup_cursor +} + read_database -init_widgets -test_main -recursor +fconfigure stdin -blocking no +fileevent stdin readable required -- 2.30.2