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