rk: reset drivers/net/wireless drivers/video/display/display-sysfs.c sound/soc/codecs...
[firefly-linux-kernel-4.4.55.git] / scripts / pnmtologo.c
1
2 /*
3  *  Convert a logo in ASCII PNM format to C source suitable for inclusion in
4  *  the Linux kernel
5  *
6  *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
7  *
8  *  --------------------------------------------------------------------------
9  *
10  *  This file is subject to the terms and conditions of the GNU General Public
11  *  License. See the file COPYING in the main directory of the Linux
12  *  distribution for more details.
13  */
14
15 #include <ctype.h>
16 #include <errno.h>
17 #include <stdarg.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22
23
24 static const char *programname;
25 static const char *filename;
26 static const char *logoname = "linux_logo";
27 static const char *outputname;
28 static FILE *out;
29
30 #define LINUX_LOGO_MONO         1       /* monochrome black/white */
31 #define LINUX_LOGO_VGA16        2       /* 16 colors VGA text palette */
32 #define LINUX_LOGO_CLUT224      3       /* 224 colors */
33 #define LINUX_LOGO_GRAY256      4       /* 256 levels grayscale */
34
35 static const char *logo_types[LINUX_LOGO_GRAY256+1] = {
36     [LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
37     [LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
38     [LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
39     [LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
40 };
41
42 #define MAX_LINUX_LOGO_COLORS   224
43
44 struct color {
45     unsigned char red;
46     unsigned char green;
47     unsigned char blue;
48 };
49
50 static const struct color clut_vga16[16] = {
51     { 0x00, 0x00, 0x00 },
52     { 0x00, 0x00, 0xaa },
53     { 0x00, 0xaa, 0x00 },
54     { 0x00, 0xaa, 0xaa },
55     { 0xaa, 0x00, 0x00 },
56     { 0xaa, 0x00, 0xaa },
57     { 0xaa, 0x55, 0x00 },
58     { 0xaa, 0xaa, 0xaa },
59     { 0x55, 0x55, 0x55 },
60     { 0x55, 0x55, 0xff },
61     { 0x55, 0xff, 0x55 },
62     { 0x55, 0xff, 0xff },
63     { 0xff, 0x55, 0x55 },
64     { 0xff, 0x55, 0xff },
65     { 0xff, 0xff, 0x55 },
66     { 0xff, 0xff, 0xff },
67 };
68
69 unsigned char data_name[] = {
70         0x6C, 0x6F, 0x67,
71         0x6F, 0x5F, 0x52,
72         0x4B, 0x6C, 0x6F,
73         0x67, 0x6F, 0x5F,
74         0x64, 0x61, 0x74,
75         0x61
76 };
77
78 unsigned char clut_name[] = {
79         0x70, 0x70, 0x6c,
80         0x6C, 0x6F, 0x67,
81         0x6F, 0x5F, 0x52,
82         0x4B, 0x6C, 0x6F,
83         0x67, 0x6F, 0x5F,
84         0x63, 0x6C, 0x75,
85         0x74
86 };
87
88 static int logo_type = LINUX_LOGO_CLUT224;
89 static unsigned int logo_width;
90 static unsigned int logo_height;
91 static struct color **logo_data;
92 static struct color logo_clut[MAX_LINUX_LOGO_COLORS];
93 static unsigned int logo_clutsize;
94
95 static void die(const char *fmt, ...)
96     __attribute__ ((noreturn)) __attribute ((format (printf, 1, 2)));
97 static void usage(void) __attribute ((noreturn));
98
99 static unsigned int get_number(FILE *fp)
100 {
101     int c, val;
102
103     /* Skip leading whitespace */
104     do {
105         c = fgetc(fp);
106         if (c == EOF)
107             die("%s: end of file\n", filename);
108         if (c == '#') {
109             /* Ignore comments 'till end of line */
110             do {
111                 c = fgetc(fp);
112                 if (c == EOF)
113                     die("%s: end of file\n", filename);
114             } while (c != '\n');
115         }
116     } while (isspace(c));
117
118     /* Parse decimal number */
119     val = 0;
120     while (isdigit(c)) {
121         val = 10*val+c-'0';
122         c = fgetc(fp);
123         if (c == EOF)
124             die("%s: end of file\n", filename);
125     }
126     return val;
127 }
128
129 static unsigned int get_number255(FILE *fp, unsigned int maxval)
130 {
131     unsigned int val = get_number(fp);
132     return (255*val+maxval/2)/maxval;
133 }
134
135 static void read_image(void)
136 {
137         FILE *fp;
138         unsigned int i, j;
139         int magic;
140         unsigned int maxval;
141
142         /* open image file */
143         fp = fopen(filename, "r");
144         if (!fp)
145                 die("Cannot open file %s: %s\n", filename, strerror(errno));
146
147     /* check file type and read file header */
148     magic = fgetc(fp);
149     if (magic != 'P')
150         die("%s is not a PNM file\n", filename);
151     magic = fgetc(fp);
152     switch (magic) {
153         case '1':
154         case '2':
155         case '3':
156             /* Plain PBM/PGM/PPM */
157             break;
158
159         case '4':
160         case '5':
161         case '6':
162             /* Binary PBM/PGM/PPM */
163             die("%s: Binary PNM is not supported\n"
164                 "Use pnmnoraw(1) to convert it to ASCII PNM\n", filename);
165
166         default:
167             die("%s is not a PNM file\n", filename);
168     }
169         logo_width = get_number(fp);
170         logo_height = get_number(fp);
171
172
173         /* allocate image data */
174         logo_data = (struct color **)malloc(logo_height * sizeof(struct color *));
175         if (!logo_data)
176                 die("%s\n", strerror(errno));
177         for (i = 0; i < logo_height; i++) {
178                 logo_data[i] = (struct color *)malloc(logo_width * sizeof(struct color));
179                 if (!logo_data[i])
180                 die("%s\n", strerror(errno));
181         }
182
183     /* read image data */
184     switch (magic) {
185         case '1':
186             /* Plain PBM */
187             for (i = 0; i < logo_height; i++)
188                 for (j = 0; j < logo_width; j++)
189                     logo_data[i][j].red = logo_data[i][j].green =
190                         logo_data[i][j].blue = 255*(1-get_number(fp));
191             break;
192
193         case '2':
194             /* Plain PGM */
195             maxval = get_number(fp);
196             for (i = 0; i < logo_height; i++)
197                 for (j = 0; j < logo_width; j++)
198                     logo_data[i][j].red = logo_data[i][j].green =
199                         logo_data[i][j].blue = get_number255(fp, maxval);
200             break;
201
202         case '3':
203             /* Plain PPM */
204             maxval = get_number(fp);
205             for (i = 0; i < logo_height; i++)
206                 for (j = 0; j < logo_width; j++) {
207                     logo_data[i][j].red = get_number255(fp, maxval);
208                     logo_data[i][j].green = get_number255(fp, maxval);
209                     logo_data[i][j].blue = get_number255(fp, maxval);
210                 }
211             break;
212     }
213
214     /* close file */
215     fclose(fp);
216 }
217
218 static inline int is_black(struct color c)
219 {
220     return c.red == 0 && c.green == 0 && c.blue == 0;
221 }
222
223 static inline int is_white(struct color c)
224 {
225     return c.red == 255 && c.green == 255 && c.blue == 255;
226 }
227
228 static inline int is_gray(struct color c)
229 {
230     return c.red == c.green && c.red == c.blue;
231 }
232
233 static inline int is_equal(struct color c1, struct color c2)
234 {
235     return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
236 }
237
238 static int write_hex_cnt;
239
240 static void write_hex(unsigned char byte)
241 {
242     if (write_hex_cnt % 12)
243         fprintf(out, ", 0x%02x", byte);
244     else if (write_hex_cnt)
245         fprintf(out, ",\n\t0x%02x", byte);
246     else
247         fprintf(out, "\t0x%02x", byte);
248     write_hex_cnt++;
249 }
250
251 static void write_header(void)
252 {
253         /* open logo file */
254         if (outputname) {
255                 out = fopen(outputname, "w");
256                 if (!out)
257                         die("Cannot create file %s: %s\n", outputname, strerror(errno));
258         } else {
259                 out = stdout;
260         }
261
262         fputs("/*\n", out);
263         fputs(" *  DO NOT EDIT THIS FILE!\n", out);
264         fputs(" *\n", out);
265         fprintf(out, " *  It was automatically generated from %s\n", filename);
266         fputs(" *\n", out);
267         fprintf(out, " *  Linux logo %s\n", logoname);
268         fputs(" */\n\n", out);
269         fputs("#include <linux/linux_logo.h>\n\n", out);
270         fprintf(out, "static unsigned char %s_data[] __initdata = {\n",
271                 logoname);
272 }
273
274 static void write_footer(void)
275 {
276         fputs("\n};\n\n", out);
277         fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
278         fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
279
280         if (logo_type == LINUX_LOGO_CLUT224) {
281                 fprintf(out, "\t.clut\t\t= &(%s_clut[%ld]),\n", logoname, sizeof(clut_name));
282                 fprintf(out, "\t.data\t\t= &(%s_data[%ld])\n", logoname, sizeof(data_name) + 4);
283         } else {
284                 fprintf(out, "\t.width\t\t= %d,\n", logo_width);
285                 fprintf(out, "\t.height\t\t= %d,\n", logo_height);
286                 if (logo_type == LINUX_LOGO_CLUT224) {
287                         fprintf(out, "\t.clutsize\t= %d,\n", logo_clutsize);
288                         fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
289                 }
290                 fprintf(out, "\t.data\t\t= %s_data\n", logoname);
291         }
292
293         fputs("};\n\n", out);
294
295         /* close logo file */
296         if (outputname)
297                 fclose(out);
298 }
299
300 static void write_logo_mono(void)
301 {
302     unsigned int i, j;
303     unsigned char val, bit;
304
305     /* validate image */
306     for (i = 0; i < logo_height; i++)
307         for (j = 0; j < logo_width; j++)
308             if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
309                 die("Image must be monochrome\n");
310
311     /* write file header */
312     write_header();
313
314     /* write logo data */
315     for (i = 0; i < logo_height; i++) {
316         for (j = 0; j < logo_width;) {
317             for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
318                 if (logo_data[i][j].red)
319                     val |= bit;
320             write_hex(val);
321         }
322     }
323
324
325     /* write logo structure and file footer */
326     write_footer();
327 }
328
329 static void write_logo_vga16(void)
330 {
331     unsigned int i, j, k;
332     unsigned char val;
333
334     /* validate image */
335     for (i = 0; i < logo_height; i++)
336         for (j = 0; j < logo_width; j++) {
337             for (k = 0; k < 16; k++)
338                 if (is_equal(logo_data[i][j], clut_vga16[k]))
339                     break;
340             if (k == 16)
341                 die("Image must use the 16 console colors only\n"
342                     "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
343                     "of colors\n");
344         }
345
346     /* write file header */
347     write_header();
348
349     /* write logo data */
350     for (i = 0; i < logo_height; i++)
351         for (j = 0; j < logo_width; j++) {
352             for (k = 0; k < 16; k++)
353                 if (is_equal(logo_data[i][j], clut_vga16[k]))
354                     break;
355             val = k<<4;
356             if (++j < logo_width) {
357                 for (k = 0; k < 16; k++)
358                     if (is_equal(logo_data[i][j], clut_vga16[k]))
359                         break;
360                 val |= k;
361             }
362             write_hex(val);
363         }
364
365     /* write logo structure and file footer */
366     write_footer();
367 }
368
369 static void write_logo_clut224(void)
370 {
371         unsigned int i, j, k;
372
373         logo_clutsize = 0;
374
375         /* validate image */
376         for (i = 0; i < logo_height; i++)
377                 for (j = 0; j < logo_width; j++) {
378                         for (k = 0; k < logo_clutsize; k++)
379                                 if (is_equal(logo_data[i][j], logo_clut[k]))
380                                         break;
381                         if (k == logo_clutsize) {
382                                 if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
383                                         die("Image has more than %d colors\n"
384                                                 "Use ppmquant(1) to reduce the number of colors\n",
385                                                 MAX_LINUX_LOGO_COLORS);
386                                         logo_clut[logo_clutsize++] = logo_data[i][j];
387                         }
388                 }
389
390         write_hex_cnt = 0;
391
392         /* write file header */
393         write_header();
394
395         write_hex((unsigned char)(logo_width >> 8));
396         write_hex((unsigned char)logo_width);
397         write_hex((unsigned char)(logo_height >> 8));
398         write_hex((unsigned char)logo_height);
399
400         for (i = 0; i < sizeof(data_name); i++){
401                 write_hex(data_name[i]);
402         }
403         write_hex((unsigned char)(logo_width >> 8));
404         write_hex((unsigned char)logo_width);
405         write_hex((unsigned char)(logo_height >> 8));
406         write_hex((unsigned char)logo_height);
407
408         /* write logo data */
409         for (i = 0; i < logo_height; i++)
410                 for (j = 0; j < logo_width; j++) {
411                         for (k = 0; k < logo_clutsize; k++)
412                                 if (is_equal(logo_data[i][j], logo_clut[k]))
413                                         break;
414                         write_hex(k+32);
415                 }
416
417         fputs("\n};\n\n", out);
418
419         /* write logo clut */
420         fprintf(out, "static unsigned char %s_clut[] __initdata = {\n",
421                 logoname);
422
423         write_hex_cnt = 0;
424
425         for (i = 0; i < sizeof(clut_name); i++){
426                 write_hex(clut_name[i]);
427         }
428         write_hex(logo_clutsize);
429
430         for (i = 0; i < logo_clutsize; i++) {
431                 write_hex(logo_clut[i].red);
432                 write_hex(logo_clut[i].green);
433                 write_hex(logo_clut[i].blue);
434         }
435
436         for (i = logo_clutsize; i < (MAX_LINUX_LOGO_COLORS * 3); i++)
437         {
438                 write_hex(32);
439         }
440
441         /* write logo structure and file footer */
442         write_footer();
443 }
444
445 static void write_logo_gray256(void)
446 {
447     unsigned int i, j;
448
449     /* validate image */
450     for (i = 0; i < logo_height; i++)
451         for (j = 0; j < logo_width; j++)
452             if (!is_gray(logo_data[i][j]))
453                 die("Image must be grayscale\n");
454
455     /* write file header */
456     write_header();
457
458     /* write logo data */
459     for (i = 0; i < logo_height; i++)
460         for (j = 0; j < logo_width; j++)
461             write_hex(logo_data[i][j].red);
462
463     /* write logo structure and file footer */
464     write_footer();
465 }
466
467 static void die(const char *fmt, ...)
468 {
469     va_list ap;
470
471     va_start(ap, fmt);
472     vfprintf(stderr, fmt, ap);
473     va_end(ap);
474
475     exit(1);
476 }
477
478 static void usage(void)
479 {
480     die("\n"
481         "Usage: %s [options] <filename>\n"
482         "\n"
483         "Valid options:\n"
484         "    -h          : display this usage information\n"
485         "    -n <name>   : specify logo name (default: linux_logo)\n"
486         "    -o <output> : output to file <output> instead of stdout\n"
487         "    -t <type>   : specify logo type, one of\n"
488         "                      mono    : monochrome black/white\n"
489         "                      vga16   : 16 colors VGA text palette\n"
490         "                      clut224 : 224 colors (default)\n"
491         "                      gray256 : 256 levels grayscale\n"
492         "\n", programname);
493 }
494
495 int main(int argc, char *argv[])
496 {
497     int opt;
498
499     programname = argv[0];
500
501     opterr = 0;
502     while (1) {
503         opt = getopt(argc, argv, "hn:o:t:");
504         if (opt == -1)
505             break;
506
507         switch (opt) {
508             case 'h':
509                 usage();
510                 break;
511
512             case 'n':
513                 logoname = optarg;
514                 break;
515
516             case 'o':
517                 outputname = optarg;
518                 break;
519
520             case 't':
521                 if (!strcmp(optarg, "mono"))
522                     logo_type = LINUX_LOGO_MONO;
523                 else if (!strcmp(optarg, "vga16"))
524                     logo_type = LINUX_LOGO_VGA16;
525                 else if (!strcmp(optarg, "clut224"))
526                     logo_type = LINUX_LOGO_CLUT224;
527                 else if (!strcmp(optarg, "gray256"))
528                     logo_type = LINUX_LOGO_GRAY256;
529                 else
530                     usage();
531                 break;
532
533             default:
534                 usage();
535                 break;
536         }
537     }
538     if (optind != argc-1)
539         usage();
540
541     filename = argv[optind];
542
543     read_image();
544     switch (logo_type) {
545         case LINUX_LOGO_MONO:
546             write_logo_mono();
547             break;
548
549         case LINUX_LOGO_VGA16:
550             write_logo_vga16();
551             break;
552
553         case LINUX_LOGO_CLUT224:
554             write_logo_clut224();
555             break;
556
557         case LINUX_LOGO_GRAY256:
558             write_logo_gray256();
559             break;
560     }
561     exit(0);
562 }
563