chiark / gitweb /
95e75b3e613b55813df459168da9c55bd939a171
[ypp-sc-tools.web-live.git] / pctb / convert.c
1 #include <pam.h>
2 #include <stdint.h>
3 #include <inttypes.h>
4 #include <assert.h>
5 #include <string.h>
6
7 #define eassert assert
8 #define debug stdout
9
10 typedef struct {
11   unsigned long rgb; /* on screen */
12   char c; /* canonical */
13 } CanonColourInfo;
14
15 static int height, width;
16 static char *image;
17
18 static void debug_flush(void) {
19   eassert(!fflush(debug));
20   eassert(!ferror(debug));
21 }
22
23 typedef struct {
24   int x, y;
25 } Point;
26
27 typedef struct { /* both inclusive */
28   Point tl;
29   Point br;
30 } Rect;
31
32 static inline char get(int x, int y) { return image[y * width + x]; }
33 static inline char get_p(Point p) { return get(p.x,p.y); }
34
35
36 static const CanonColourInfo canoncolourinfos[]= {
37   { 0x475A5E, '*' }, /* edge */
38   { 0x2C5F7A, '*' }, /* edge just under box heading shadow */
39   { 0x7D9094, '+' }, /* interbox */
40   { 0xBDC5BF, ' ' }, /* background - pale */
41   { 0xADB5AF, ' ' }, /* background - dark */
42   { 0x000000, 'o' }, /* foreground */
43   { 0xD4B356, ' ' }, /* background (cursor) */
44   { 0xFFFFFF, 'o' }, /* foreground (cursor) */
45   { 0,0 }
46 };
47
48 #define START_MAIN {200,200}
49
50 static void require_rectangle(int tlx, int tly, int brx, int bry, char c) {
51   int x,y;
52   for (x=tlx; x<=brx; x++)
53     for (y=tly; y<=bry; y++)
54       eassert(get(x,y) == c);
55 }
56 static void require_rectangle_r(Rect rr, char c) {
57   require_rectangle(rr.tl.x,rr.tl.y, rr.br.x,rr.br.y, c);
58 }
59
60 static void debug_rect(const char *what, int whati, Rect rr) {
61   int y,r,w;
62   fprintf(debug, "%s %d: %d,%d..%d,%d:\n", what, whati,
63           rr.tl.x,rr.tl.y, rr.br.x,rr.br.y);
64   w= rr.br.x - rr.tl.x + 1;
65   for (y=rr.tl.y; y<=rr.br.y; y++) {
66     fprintf(debug, "%4d %4d ",y,y-rr.tl.y);
67     r= fwrite(image + y*width + rr.tl.x, 1, w, debug);
68     eassert(r==w);
69     fputc('|',debug);
70     fputc('\n',debug);
71   }
72   debug_flush();
73 }
74
75 static void find_main_rectangle(void) {
76   Rect whole = { {0,0}, {width-1,height-1} };
77   Rect mainr = { START_MAIN,START_MAIN };
78
79 #define WALK_UNTIL(point,coord,increm,stop,edge)                        \
80   for (;;) {                                                            \
81     if (get_p((point)) == (edge)) { (point).coord -= (increm); break; } \
82     eassert((point).coord != (stop));                           \
83     (point).coord += (increm);                                          \
84   }
85
86   WALK_UNTIL(mainr.tl, x,-1, whole.tl.x, '*');
87   WALK_UNTIL(mainr.tl, y,-1, whole.tl.y, '*');
88   WALK_UNTIL(mainr.br, x,+1, whole.br.x, '*');
89   WALK_UNTIL(mainr.br, y,+1, whole.br.y, '*');
90
91   require_rectangle(mainr.tl.x-1, mainr.tl.y, mainr.tl.x-1, mainr.br.y, '*');
92   require_rectangle(mainr.br.x+1, mainr.tl.y, mainr.br.x+1, mainr.br.y, '*');
93   require_rectangle(mainr.tl.x, mainr.tl.y-1, mainr.br.x, mainr.tl.y-1, '*');
94   require_rectangle(mainr.tl.x, mainr.br.y+1, mainr.br.x, mainr.br.y+1, '*');
95
96 #define CHECK_STRIP_BORDER(tlbr,xy,increm)      \
97   do {                                          \
98     Point csb_p;                                \
99     Rect csb_r;                                 \
100     csb_p= mainr.tl;                            \
101     csb_p.xy= mainr.tlbr.xy;                    \
102     if (get_p(csb_p)=='+') {                    \
103       csb_r= mainr;                             \
104       csb_r.tl.xy= csb_p.xy;                    \
105       csb_r.br.xy= csb_p.xy;                    \
106       require_rectangle_r(csb_r, '+');          \
107       mainr.tlbr.xy += increm;                  \
108     }                                           \
109   } while(0)
110
111   debug_rect("mainr",0, mainr);
112
113   CHECK_STRIP_BORDER(tl,x,+1);
114   CHECK_STRIP_BORDER(tl,y,+1);
115   CHECK_STRIP_BORDER(br,x,-1);
116   CHECK_STRIP_BORDER(br,y,-1);
117
118   debug_rect("mainr",1, mainr);
119 }                   
120
121 static void load_image_and_canonify(void) {
122   struct pam inpam;
123   unsigned char rgb[3];
124   int x,y,r;
125   const CanonColourInfo *cci;
126
127   pnm_readpaminit(stdin, &inpam, sizeof(inpam));
128   height= inpam.height;
129   width= inpam.width;
130   eassert(inpam.maxval == 255);
131   eassert(inpam.bytes_per_sample == 1);
132
133   image= malloc(width*height);
134   eassert(image);
135   memset(image,'?',width*height);
136
137   for (y=0; y<height; y++) {
138     for (x=0; x<width; x++) {
139       r= fread(&rgb,1,3,stdin);  eassert(r==3);
140       unsigned long rgb_l=
141         ((unsigned long)rgb[0]<<16) |
142         ((unsigned long)rgb[1]<<8) |
143                        (rgb[2]);
144       for (cci=canoncolourinfos; cci->c; cci++)
145         if (cci->rgb == rgb_l) {
146           image[y*width + x]= cci->c;
147           break;
148         }
149     }
150     fprintf(debug, "%4d ",y);
151     r= fwrite(image + y*width, 1,width, debug);  eassert(r==width);
152     fputc('\n',debug);
153   }
154   debug_flush();
155 }
156
157 int main(void) {
158   load_image_and_canonify();
159   find_main_rectangle();
160   /*
161   repeatedly_find_top_thing();
162   */
163   return 0;
164 }