1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <dirent.h>
8
9 #include <png.h>
10
11 static int verbose = 0;
12 static char *basename = "images";
13 static char *imagedir = ".";
14
15 /*****************************************************************************/
16
17 char *
concat(char * a,char * b)18 concat (char *a, char *b)
19 {
20 char *buf = 0;
21 int i = strlen(a) + strlen(b) + 2;
22 buf = (char *)malloc(i);
23 sprintf(buf, "%s/%s", a, b);
24 return buf;
25 }
26
27 /*****************************************************************************/
28
29 typedef struct subimage_struct {
30 struct subimage_struct *next;
31 char *filename;
32 int w, h, max;
33 int index;
34 } subimage_struct;
35
36 typedef struct image_struct {
37 struct image_struct *next;
38 char *name;
39 int a, d;
40 subimage_struct *sub[3];
41 int index;
42 } image_struct;
43
44 image_struct *image_list = 0;
45 int current_index = 0;
46
47 void
scan_image_directory()48 scan_image_directory ()
49 {
50 DIR *dir;
51 struct dirent *de;
52 image_struct *img;
53 subimage_struct *sub;
54
55 dir = opendir(imagedir);
56 if (!dir) {
57 fprintf(stderr, "Unable to scan directory %s for images.\n", imagedir);
58 perror("The error was");
59 exit(1);
60 }
61 while (de = readdir(dir)) {
62 FILE *f;
63 char *dot;
64 png_structp png_ptr;
65 png_infop info_ptr;
66 png_uint_32 width, height;
67 int bit_depth, color_type, interlace_type, type;
68
69 dot = strrchr(de->d_name, '.');
70 if (!dot)
71 continue;
72 if (strcmp(dot, ".png"))
73 continue;
74
75 dot = strchr(de->d_name, '.');
76 *dot = 0;
77 for (img=image_list; img; img=img->next)
78 if (strcmp(img->name, de->d_name) == 0)
79 break;
80 if (!img)
81 continue;
82 *dot = '.';
83
84 f = fopen(concat(imagedir, de->d_name), "rb");
85
86 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
87 info_ptr = png_create_info_struct (png_ptr);
88
89 if (setjmp (png_jmpbuf(png_ptr))) {
90 fclose (f);
91 continue;
92 }
93
94 png_init_io (png_ptr, f);
95
96 png_read_info (png_ptr, info_ptr);
97
98 png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth,
99 &color_type, &interlace_type, 0, 0);
100
101 if (bit_depth == 1)
102 type = 0;
103 else if (color_type & PNG_COLOR_MASK_COLOR)
104 type = 2;
105 else
106 type = 1;
107
108 sub = (subimage_struct *)malloc(sizeof(subimage_struct));
109 sub->next = img->sub[type];
110 img->sub[type] = sub;
111 sub->filename = strdup (concat (imagedir, de->d_name));
112 sub->w = width;
113 sub->h = height;
114 sub->index = current_index++;
115
116 fclose (f);
117 }
118
119 closedir(dir);
120 }
121
122 static int print_col = 0;
123 static int print_com = 1;
124 static void
print_int(FILE * f,int val)125 print_int(FILE *f, int val)
126 {
127 char buf[20];
128 sprintf(buf, "%d", val);
129 if (print_com) {
130 fputc(',', f);
131 print_col ++;
132 } else {
133 fprintf(f, " ");
134 print_col = 2;
135 }
136 if (print_col + strlen(buf) > 70) {
137 fprintf(f, "\n ");
138 print_col = 2;
139 }
140 fputs(buf, f);
141 print_col += strlen(buf);
142 print_com = 1;
143 }
144
145 void
dump_images(FILE * o)146 dump_images(FILE *o)
147 {
148 image_struct *img;
149 subimage_struct *sub;
150 int i;
151 static char *type_names[] = {"mono", "grey", "color"};
152
153 for (img=image_list; img; img=img->next)
154 for (i=0; i<3; i++)
155 for (sub=img->sub[i]; sub; sub=sub->next)
156 {
157 FILE *f = fopen(sub->filename, "rb");
158 int byte;
159 fprintf(o, "/* %s */\n", sub->filename);
160 fprintf(o, "static const unsigned char data_%d[] = {\n", sub->index);
161 print_com = 0;
162 while ((byte = fgetc (f)) != EOF)
163 print_int(o, byte);
164 fprintf(o, "};\n\n");
165 fclose (f);
166 }
167
168 for (img=image_list; img; img=img->next)
169 for (i=0; i<3; i++)
170 if (img->sub[i])
171 {
172 fprintf(o, "static image sub_%d_%s[] = {\n", img->index, type_names[i]);
173 for (sub=img->sub[i]; sub; sub=sub->next)
174 fprintf(o, " { %d, %d, data_%d },\n", sub->w, sub->h, sub->index);
175 fprintf(o, " { 0, 0, 0 }\n};\n\n");
176 }
177
178 fprintf(o, "image_list %s_imagelib[] = {\n", basename);
179 for (img=image_list; img; img=img->next)
180 {
181 char *c = "";
182 fprintf(o, " { \"%s\", %d, %d, { ", img->name, img->a, img->d);
183 for (i=0; i<3; i++)
184 {
185 if (img->sub[i])
186 fprintf(o, "%ssub_%d_%s", c, img->index, type_names[i]);
187 else
188 fprintf(o, "%s0", c);
189 c = ", ";
190 }
191 fprintf(o, " } },\n");
192 }
193 fprintf(o, " { 0, 0, 0, { 0, 0, 0 } }\n};\n\n");
194 }
195
196 /*****************************************************************************/
197
198 char *
tokenize(char * string)199 tokenize(char *string)
200 {
201 static char *next;
202 char *rv;
203 if (string) {
204 next = string;
205 return NULL;
206 }
207 while (*next && !isgraph(*next)) next++;
208 if (!*next) return 0;
209 rv = next;
210 while (*next && isgraph(*next)) next++;
211 if (*next)
212 *next++ = 0;
213 return rv;
214 }
215
216 void
give_help()217 give_help()
218 {
219 fprintf(stderr, "make-imgdir [options] infile outfile [pngs]\n");
220 fprintf(stderr, " -v verbose\n");
221 fprintf(stderr, " -h print this help message\n");
222 fprintf(stderr, " -n basename specify basename for symbols\n");
223 fprintf(stderr, " -i imagedir location of images\n");
224 fprintf(stderr, " -d dependencies write dependencies to this file\n");
225 fprintf(stderr, " infile format: <image> [across down]\n");
226 fprintf(stderr, " if infile is `-' image names are taken from the command line.\n");
227 exit(1);
228 }
229
230 /*****************************************************************************/
231
232 int
main(int argc,char ** argv)233 main(int argc, char **argv)
234 {
235 struct stat s;
236 int x, y, o;
237 FILE *inf, *outf, *depfile;
238 char *inbuf, *outfname, *tok;
239 char *imagename;
240 int across, down;
241 image_struct *img;
242
243 while (1)
244 switch (getopt(argc, argv, "vhn:i:d:m:")) {
245 case '?':
246 case 'h':
247 give_help();
248 case 'v':
249 verbose++;
250 break;
251 case 'n':
252 basename = optarg;
253 break;
254 case 'i':
255 imagedir = optarg;
256 break;
257 case 'd':
258 depfile = fopen(optarg, "w");
259 if (!depfile) {
260 fprintf(stderr, "Unable to open dependency file %s for writing\n", depfile);
261 perror("The error was");
262 exit(1);
263 }
264 break;
265 case -1:
266 goto done_args;
267 }
268 done_args:
269
270 if (optind > argc-1)
271 give_help();
272
273 if (strcmp (argv[optind], "-") == 0)
274 {
275 int i;
276 char *dot;
277 for (i=optind+2; i<argc; i++)
278 {
279 printf("image %s\n", argv[i]);
280 dot = strrchr(argv[i], '.');
281 if (dot) *dot = 0;
282
283 img = (image_struct *)malloc(sizeof(image_struct));
284 memset(img, 0, sizeof(*img));
285 img->name = strdup (argv[i]);
286 img->a = img->d = 1;
287 img->index = current_index++;
288
289 img->next = image_list;
290 image_list = img;
291 }
292 }
293 else
294 {
295 inf = fopen(argv[optind], "r");
296 if (!inf) {
297 fprintf(stderr, "Unable to open %s for reading\n", argv[optind]);
298 perror("The error was");
299 exit(1);
300 }
301 fstat(fileno(inf), &s);
302 inbuf = (char *)malloc(s.st_size+1);
303
304 while (fgets(inbuf, s.st_size, inf)) {
305
306 inbuf[strlen(inbuf)] = 0;
307 tokenize(inbuf);
308
309 imagename = tokenize(0);
310 if (!imagename) continue;
311
312 img = (image_struct *)malloc(sizeof(image_struct));
313 memset(img, 0, sizeof(*img));
314 img->name = strdup (imagename);
315 img->a = img->d = 1;
316 img->index = current_index++;
317
318 tok = tokenize(0);
319 if (tok)
320 img->a = atoi(tok);
321 tok = tokenize(0);
322 if (tok)
323 img->d = atoi(tok);
324
325 img->next = image_list;
326 image_list = img;
327 }
328 }
329
330 scan_image_directory();
331
332 if (optind > argc-2)
333 outfname = 0;
334 else
335 outfname = argv[optind+1];
336
337 if (outfname)
338 outf = fopen(outfname, "w");
339 else
340 outf = stdout;
341 if (!outf) {
342 fprintf(stderr, "Unable to open %s for writing\n", outfname);
343 perror("The error was");
344 exit(1);
345 }
346
347 fprintf(outf, "/* Automatically generated, do not edit */\n");
348 fprintf(outf, "#include \"imagelib.h\"\n\n");
349
350 dump_images(outf);
351
352 if (outfname) fclose(outf);
353
354 exit(0);
355 }
356