chiark / gitweb /
Ignore size of connected component when assigning labels (some arches have no purchas...
[ypp-sc-tools.db-live.git] / yarrg / rgbimage.c
1 /*
2  * Handling of colour (RGB) images
3  */
4 /*
5  *  This is part of ypp-sc-tools, a set of third-party tools for assisting
6  *  players of Yohoho Puzzle Pirates.
7  * 
8  *  Copyright (C) 2009 Ian Jackson <ijackson@chiark.greenend.org.uk>
9  * 
10  *  This program is free software: you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation, either version 3 of the License, or
13  *  (at your option) any later version.
14  * 
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  * 
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  * 
23  *  Yohoho and Puzzle Pirates are probably trademarks of Three Rings and
24  *  are used without permission.  This program is not endorsed or
25  *  sponsored by Three Rings.
26  */
27
28 #include "convert.h"
29
30 /*
31  *
32  *
33  * widgets.txt
34  * format
35  *
36  *  <magic>
37  *
38  *  <context>
39  *  <string>
40  *  ppmnoraw depth 8
41  *
42  *  <context>
43  *  <string>
44  *  ppmnoraw depth 8
45  *  .
46  *
47  */
48
49 #include "convert.h"
50
51 static int identify1(const RgbImage *base, Rect portion,
52                     char result[MAXIMGIDENT], const char *what,
53                     const char *which, int (*opener)(const char *fn)) {
54   char *dbfile_name= masprintf("_%s-pixmap.txt",which);
55   if (!opener(dbfile_name))
56     goto not_found;
57
58 #define FGETSLINE (dbfile_getsline(result,MAXIMGIDENT,__FILE__,__LINE__))
59
60   FGETSLINE;
61   dbassert(!strcmp(result,"# ypp-sc-tools pctb pixmaps v1"));
62   
63   void *row= 0;
64   size_t rowa= 0;
65   
66   for (;;) {
67     FGETSLINE;
68     if (!result[0] || result[0]=='#') continue;
69     if (!strcmp(result,".")) break;
70
71     char magic[10];
72     dbfile_getsline(magic,sizeof(magic),__FILE__,__LINE__);
73
74     dbassert(!strcmp(magic,"P3"));
75     int w,h,maxval;
76     dbassert( dbfile_scanf("%d %d %d",&w,&h,&maxval) == 3);
77     dbassert(w>0); dbassert(h>0); dbassert(maxval==255);
78
79     if (rowa < w) {
80       rowa= w;
81       row= mrealloc(row, rowa*3);
82     }
83     int diff= w != RECT_W(portion) || h != RECT_H(portion);
84
85     int x,y,i;
86     for (y=0; y<h; y++) {
87       for (x=0; x<w; x++) {
88         uint32_t rgb=0;
89         for (i=0; i<3; i++) {
90           int c;
91           dbassert( dbfile_scanf("%d",&c) == 1);
92           dbassert(c>=0 && c<=255);
93           rgb |= (Rgb)c << (i*8);
94         }
95         int px= portion.tl.x + x, py= portion.tl.y + y;
96         diff |= px > portion.br.x || py > portion.br.y ||
97                 rgb != ri_rgb(base,px,py);
98       }
99     }
100     if (!diff) {
101       progress_log("Identified %s image: %s.",what,result);
102       goto found;
103     }
104   }
105  not_found:
106   result[0]= 0;
107
108  found:
109   dbfile_close();
110   free(dbfile_name);
111   return !!result[0];
112 }
113
114 static int identify(const RgbImage *base, Rect portion,
115                     char result[MAXIMGIDENT], const char *what) {
116   return identify1(base,portion,result,what, "master", dbfile_gzopen) ||
117          identify1(base,portion,result,what, "local",  dbfile_open);
118 }
119
120 void fwrite_ppmraw(FILE *f, const RgbImage *ri) {
121   int i;
122   fprintf(f,
123           "P6\n"
124           "%d %d\n"
125           "255\n", ri->w, ri->h);
126   for (i=0; i < ri->w * ri->h; i++) {
127     Rgb rgb= ri->data[i];
128     fputc_unlocked(rgb >> 0,  f);
129     fputc_unlocked(rgb >> 8,  f);
130     fputc_unlocked(rgb >> 16, f);
131   }
132   sysassert(!ferror(f));
133   sysassert(!fflush(f));
134 }
135
136 static void fwrite_ppm(FILE *f, const RgbImage *base, Rect portion) {
137   int x,y,i;
138   fprintf(f,"P3\n%d %d\n255\n", RECT_W(portion), RECT_H(portion));
139   for (y=portion.tl.y; y<=portion.br.y; y++) {
140     for (x=portion.tl.x; x<=portion.br.x; x++) {
141       putc(' ',f);
142       Rgb rgb= ri_rgb(base,x,y);
143       for (i=0; i<3; i++)
144         fprintf(f," %3d", (rgb>>(i*8)) & 0xff);
145     }
146     putc('\n',f);
147   }
148   sysassert(!ferror(f));
149   sysassert(!fflush(f));
150 }
151
152 void identify_rgbimage(const RgbImage *base, Rect portion,
153                        char result[MAXIMGIDENT], const char *what) {
154   static int synced;
155
156   if (!synced) {
157     if (o_flags & ff_dict_fetch)
158       fetch_with_rsync_gz("pixmap");
159     synced++;
160   }
161   
162   for (;;) {
163     int ok= identify(base, portion, result, what);
164     if (ok) return;
165     
166     if (DEBUGP(pixmap))
167       fwrite_ppm(stderr,base,portion);
168
169     FILE *resolver= resolve_start();
170     if (!resolver)
171         fatal("Image recognition failed - unrecognised island.\n"
172               "See FIXME.FIXME\n");
173
174     fprintf(resolver, "pixmap\n" "%s\n", what);
175     fwrite_ppm(resolver, base, portion);
176     putc('\n',resolver);
177
178     resolve_finish();
179   }
180 }
181
182 RgbImage *alloc_rgb_image(int w, int h) {
183   RgbImage *ri;
184   ri= mmalloc(sizeof(*ri) + w*h*sizeof(ri->data[0]));
185   ri->w= w;
186   ri->h= h;
187   return ri;
188 }