xref: /linux/drivers/video/logo/pnmtologo.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
18f0e0560SNikita Romanyuk // SPDX-License-Identifier: GPL-2.0-only
278a20a01SMasahiro Yamada /*
378a20a01SMasahiro Yamada  *  Convert a logo in ASCII PNM format to C source suitable for inclusion in
478a20a01SMasahiro Yamada  *  the Linux kernel
578a20a01SMasahiro Yamada  *
678a20a01SMasahiro Yamada  *  (C) Copyright 2001-2003 by Geert Uytterhoeven <geert@linux-m68k.org>
778a20a01SMasahiro Yamada  */
878a20a01SMasahiro Yamada 
978a20a01SMasahiro Yamada #include <ctype.h>
1078a20a01SMasahiro Yamada #include <errno.h>
1178a20a01SMasahiro Yamada #include <stdarg.h>
1278a20a01SMasahiro Yamada #include <stdio.h>
1378a20a01SMasahiro Yamada #include <stdlib.h>
1478a20a01SMasahiro Yamada #include <string.h>
1578a20a01SMasahiro Yamada #include <unistd.h>
1678a20a01SMasahiro Yamada 
1778a20a01SMasahiro Yamada 
1878a20a01SMasahiro Yamada static const char *programname;
1978a20a01SMasahiro Yamada static const char *filename;
2078a20a01SMasahiro Yamada static const char *logoname = "linux_logo";
2178a20a01SMasahiro Yamada static const char *outputname;
2278a20a01SMasahiro Yamada static FILE *out;
2378a20a01SMasahiro Yamada 
2478a20a01SMasahiro Yamada 
2578a20a01SMasahiro Yamada #define LINUX_LOGO_MONO		1	/* monochrome black/white */
2678a20a01SMasahiro Yamada #define LINUX_LOGO_VGA16	2	/* 16 colors VGA text palette */
2778a20a01SMasahiro Yamada #define LINUX_LOGO_CLUT224	3	/* 224 colors */
2878a20a01SMasahiro Yamada #define LINUX_LOGO_GRAY256	4	/* 256 levels grayscale */
2978a20a01SMasahiro Yamada 
3078a20a01SMasahiro Yamada static const char *logo_types[LINUX_LOGO_GRAY256+1] = {
3178a20a01SMasahiro Yamada 	[LINUX_LOGO_MONO] = "LINUX_LOGO_MONO",
3278a20a01SMasahiro Yamada 	[LINUX_LOGO_VGA16] = "LINUX_LOGO_VGA16",
3378a20a01SMasahiro Yamada 	[LINUX_LOGO_CLUT224] = "LINUX_LOGO_CLUT224",
3478a20a01SMasahiro Yamada 	[LINUX_LOGO_GRAY256] = "LINUX_LOGO_GRAY256"
3578a20a01SMasahiro Yamada };
3678a20a01SMasahiro Yamada 
3778a20a01SMasahiro Yamada #define MAX_LINUX_LOGO_COLORS	224
3878a20a01SMasahiro Yamada 
3978a20a01SMasahiro Yamada struct color {
4078a20a01SMasahiro Yamada 	unsigned char red;
4178a20a01SMasahiro Yamada 	unsigned char green;
4278a20a01SMasahiro Yamada 	unsigned char blue;
4378a20a01SMasahiro Yamada };
4478a20a01SMasahiro Yamada 
4578a20a01SMasahiro Yamada static const struct color clut_vga16[16] = {
4678a20a01SMasahiro Yamada 	{ 0x00, 0x00, 0x00 },
4778a20a01SMasahiro Yamada 	{ 0x00, 0x00, 0xaa },
4878a20a01SMasahiro Yamada 	{ 0x00, 0xaa, 0x00 },
4978a20a01SMasahiro Yamada 	{ 0x00, 0xaa, 0xaa },
5078a20a01SMasahiro Yamada 	{ 0xaa, 0x00, 0x00 },
5178a20a01SMasahiro Yamada 	{ 0xaa, 0x00, 0xaa },
5278a20a01SMasahiro Yamada 	{ 0xaa, 0x55, 0x00 },
5378a20a01SMasahiro Yamada 	{ 0xaa, 0xaa, 0xaa },
5478a20a01SMasahiro Yamada 	{ 0x55, 0x55, 0x55 },
5578a20a01SMasahiro Yamada 	{ 0x55, 0x55, 0xff },
5678a20a01SMasahiro Yamada 	{ 0x55, 0xff, 0x55 },
5778a20a01SMasahiro Yamada 	{ 0x55, 0xff, 0xff },
5878a20a01SMasahiro Yamada 	{ 0xff, 0x55, 0x55 },
5978a20a01SMasahiro Yamada 	{ 0xff, 0x55, 0xff },
6078a20a01SMasahiro Yamada 	{ 0xff, 0xff, 0x55 },
6178a20a01SMasahiro Yamada 	{ 0xff, 0xff, 0xff },
6278a20a01SMasahiro Yamada };
6378a20a01SMasahiro Yamada 
6478a20a01SMasahiro Yamada 
6578a20a01SMasahiro Yamada static int logo_type = LINUX_LOGO_CLUT224;
6678a20a01SMasahiro Yamada static unsigned int logo_width;
6778a20a01SMasahiro Yamada static unsigned int logo_height;
6878a20a01SMasahiro Yamada static struct color **logo_data;
6978a20a01SMasahiro Yamada static struct color logo_clut[MAX_LINUX_LOGO_COLORS];
7078a20a01SMasahiro Yamada static unsigned int logo_clutsize;
7178a20a01SMasahiro Yamada static int is_plain_pbm = 0;
7278a20a01SMasahiro Yamada 
7378a20a01SMasahiro Yamada static void die(const char *fmt, ...)
7478a20a01SMasahiro Yamada __attribute__((noreturn)) __attribute((format (printf, 1, 2)));
7578a20a01SMasahiro Yamada static void usage(void) __attribute((noreturn));
7678a20a01SMasahiro Yamada 
7778a20a01SMasahiro Yamada 
get_number(FILE * fp)7878a20a01SMasahiro Yamada static unsigned int get_number(FILE *fp)
7978a20a01SMasahiro Yamada {
8078a20a01SMasahiro Yamada 	int c, val;
8178a20a01SMasahiro Yamada 
8278a20a01SMasahiro Yamada 	/* Skip leading whitespace */
8378a20a01SMasahiro Yamada 	do {
8478a20a01SMasahiro Yamada 		c = fgetc(fp);
8578a20a01SMasahiro Yamada 		if (c == EOF)
8678a20a01SMasahiro Yamada 			die("%s: end of file\n", filename);
8778a20a01SMasahiro Yamada 		if (c == '#') {
8878a20a01SMasahiro Yamada 			/* Ignore comments 'till end of line */
8978a20a01SMasahiro Yamada 			do {
9078a20a01SMasahiro Yamada 				c = fgetc(fp);
9178a20a01SMasahiro Yamada 				if (c == EOF)
9278a20a01SMasahiro Yamada 					die("%s: end of file\n", filename);
9378a20a01SMasahiro Yamada 			} while (c != '\n');
9478a20a01SMasahiro Yamada 		}
9578a20a01SMasahiro Yamada 	} while (isspace(c));
9678a20a01SMasahiro Yamada 
9778a20a01SMasahiro Yamada 	/* Parse decimal number */
9878a20a01SMasahiro Yamada 	val = 0;
9978a20a01SMasahiro Yamada 	while (isdigit(c)) {
10078a20a01SMasahiro Yamada 		val = 10*val+c-'0';
10178a20a01SMasahiro Yamada 		/* some PBM are 'broken'; GiMP for example exports a PBM without space
10278a20a01SMasahiro Yamada 		 * between the digits. This is Ok cause we know a PBM can only have a '1'
103044b14b5SNikita Romanyuk 		 * or a '0' for the digit.
104044b14b5SNikita Romanyuk 		 */
10578a20a01SMasahiro Yamada 		if (is_plain_pbm)
10678a20a01SMasahiro Yamada 			break;
10778a20a01SMasahiro Yamada 		c = fgetc(fp);
10878a20a01SMasahiro Yamada 		if (c == EOF)
10978a20a01SMasahiro Yamada 			die("%s: end of file\n", filename);
11078a20a01SMasahiro Yamada 	}
11178a20a01SMasahiro Yamada 	return val;
11278a20a01SMasahiro Yamada }
11378a20a01SMasahiro Yamada 
get_number255(FILE * fp,unsigned int maxval)11478a20a01SMasahiro Yamada static unsigned int get_number255(FILE *fp, unsigned int maxval)
11578a20a01SMasahiro Yamada {
11678a20a01SMasahiro Yamada 	unsigned int val = get_number(fp);
117044b14b5SNikita Romanyuk 
11878a20a01SMasahiro Yamada 	return (255*val+maxval/2)/maxval;
11978a20a01SMasahiro Yamada }
12078a20a01SMasahiro Yamada 
read_image(void)12178a20a01SMasahiro Yamada static void read_image(void)
12278a20a01SMasahiro Yamada {
12378a20a01SMasahiro Yamada 	FILE *fp;
12478a20a01SMasahiro Yamada 	unsigned int i, j;
12578a20a01SMasahiro Yamada 	int magic;
12678a20a01SMasahiro Yamada 	unsigned int maxval;
12778a20a01SMasahiro Yamada 
12878a20a01SMasahiro Yamada 	/* open image file */
12978a20a01SMasahiro Yamada 	fp = fopen(filename, "r");
13078a20a01SMasahiro Yamada 	if (!fp)
13178a20a01SMasahiro Yamada 		die("Cannot open file %s: %s\n", filename, strerror(errno));
13278a20a01SMasahiro Yamada 
13378a20a01SMasahiro Yamada 	/* check file type and read file header */
13478a20a01SMasahiro Yamada 	magic = fgetc(fp);
13578a20a01SMasahiro Yamada 	if (magic != 'P')
13678a20a01SMasahiro Yamada 		die("%s is not a PNM file\n", filename);
13778a20a01SMasahiro Yamada 	magic = fgetc(fp);
13878a20a01SMasahiro Yamada 	switch (magic) {
13978a20a01SMasahiro Yamada 	case '1':
14078a20a01SMasahiro Yamada 	case '2':
14178a20a01SMasahiro Yamada 	case '3':
14278a20a01SMasahiro Yamada 		/* Plain PBM/PGM/PPM */
14378a20a01SMasahiro Yamada 		break;
14478a20a01SMasahiro Yamada 
14578a20a01SMasahiro Yamada 	case '4':
14678a20a01SMasahiro Yamada 	case '5':
14778a20a01SMasahiro Yamada 	case '6':
14878a20a01SMasahiro Yamada 		/* Binary PBM/PGM/PPM */
14978a20a01SMasahiro Yamada 		die("%s: Binary PNM is not supported\n"
15078a20a01SMasahiro Yamada 		"Use pnmnoraw(1) to convert it to ASCII PNM\n", filename);
15178a20a01SMasahiro Yamada 
15278a20a01SMasahiro Yamada 	default:
15378a20a01SMasahiro Yamada 		die("%s is not a PNM file\n", filename);
15478a20a01SMasahiro Yamada 	}
15578a20a01SMasahiro Yamada 	logo_width = get_number(fp);
15678a20a01SMasahiro Yamada 	logo_height = get_number(fp);
15778a20a01SMasahiro Yamada 
15878a20a01SMasahiro Yamada 	/* allocate image data */
15978a20a01SMasahiro Yamada 	logo_data = (struct color **)malloc(logo_height*sizeof(struct color *));
16078a20a01SMasahiro Yamada 	if (!logo_data)
16178a20a01SMasahiro Yamada 		die("%s\n", strerror(errno));
16278a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++) {
16378a20a01SMasahiro Yamada 		logo_data[i] = malloc(logo_width*sizeof(struct color));
16478a20a01SMasahiro Yamada 	if (!logo_data[i])
16578a20a01SMasahiro Yamada 		die("%s\n", strerror(errno));
16678a20a01SMasahiro Yamada 	}
16778a20a01SMasahiro Yamada 
16878a20a01SMasahiro Yamada 	/* read image data */
16978a20a01SMasahiro Yamada 	switch (magic) {
17078a20a01SMasahiro Yamada 	case '1':
17178a20a01SMasahiro Yamada 		/* Plain PBM */
17278a20a01SMasahiro Yamada 		is_plain_pbm = 1;
17378a20a01SMasahiro Yamada 		for (i = 0; i < logo_height; i++)
17478a20a01SMasahiro Yamada 			for (j = 0; j < logo_width; j++)
17578a20a01SMasahiro Yamada 				logo_data[i][j].red = logo_data[i][j].green =
17678a20a01SMasahiro Yamada 					logo_data[i][j].blue = 255*(1-get_number(fp));
17778a20a01SMasahiro Yamada 		break;
17878a20a01SMasahiro Yamada 
17978a20a01SMasahiro Yamada 	case '2':
18078a20a01SMasahiro Yamada 		/* Plain PGM */
18178a20a01SMasahiro Yamada 		maxval = get_number(fp);
18278a20a01SMasahiro Yamada 		for (i = 0; i < logo_height; i++)
18378a20a01SMasahiro Yamada 			for (j = 0; j < logo_width; j++)
18478a20a01SMasahiro Yamada 				logo_data[i][j].red = logo_data[i][j].green =
18578a20a01SMasahiro Yamada 					logo_data[i][j].blue = get_number255(fp, maxval);
18678a20a01SMasahiro Yamada 		break;
18778a20a01SMasahiro Yamada 
18878a20a01SMasahiro Yamada 	case '3':
18978a20a01SMasahiro Yamada 		/* Plain PPM */
19078a20a01SMasahiro Yamada 		maxval = get_number(fp);
19178a20a01SMasahiro Yamada 		for (i = 0; i < logo_height; i++)
19278a20a01SMasahiro Yamada 			for (j = 0; j < logo_width; j++) {
19378a20a01SMasahiro Yamada 				logo_data[i][j].red = get_number255(fp, maxval);
19478a20a01SMasahiro Yamada 				logo_data[i][j].green = get_number255(fp, maxval);
19578a20a01SMasahiro Yamada 				logo_data[i][j].blue = get_number255(fp, maxval);
19678a20a01SMasahiro Yamada 			}
19778a20a01SMasahiro Yamada 		break;
19878a20a01SMasahiro Yamada 	}
19978a20a01SMasahiro Yamada 
20078a20a01SMasahiro Yamada 	/* close file */
20178a20a01SMasahiro Yamada 	fclose(fp);
20278a20a01SMasahiro Yamada }
20378a20a01SMasahiro Yamada 
is_black(struct color c)20478a20a01SMasahiro Yamada static inline int is_black(struct color c)
20578a20a01SMasahiro Yamada {
20678a20a01SMasahiro Yamada 	return c.red == 0 && c.green == 0 && c.blue == 0;
20778a20a01SMasahiro Yamada }
20878a20a01SMasahiro Yamada 
is_white(struct color c)20978a20a01SMasahiro Yamada static inline int is_white(struct color c)
21078a20a01SMasahiro Yamada {
21178a20a01SMasahiro Yamada 	return c.red == 255 && c.green == 255 && c.blue == 255;
21278a20a01SMasahiro Yamada }
21378a20a01SMasahiro Yamada 
is_gray(struct color c)21478a20a01SMasahiro Yamada static inline int is_gray(struct color c)
21578a20a01SMasahiro Yamada {
21678a20a01SMasahiro Yamada 	return c.red == c.green && c.red == c.blue;
21778a20a01SMasahiro Yamada }
21878a20a01SMasahiro Yamada 
is_equal(struct color c1,struct color c2)21978a20a01SMasahiro Yamada static inline int is_equal(struct color c1, struct color c2)
22078a20a01SMasahiro Yamada {
22178a20a01SMasahiro Yamada 	return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue;
22278a20a01SMasahiro Yamada }
22378a20a01SMasahiro Yamada 
write_header(void)22478a20a01SMasahiro Yamada static void write_header(void)
22578a20a01SMasahiro Yamada {
22678a20a01SMasahiro Yamada 	/* open logo file */
22778a20a01SMasahiro Yamada 	if (outputname) {
22878a20a01SMasahiro Yamada 		out = fopen(outputname, "w");
22978a20a01SMasahiro Yamada 		if (!out)
23078a20a01SMasahiro Yamada 			die("Cannot create file %s: %s\n", outputname, strerror(errno));
23178a20a01SMasahiro Yamada 	} else {
23278a20a01SMasahiro Yamada 		out = stdout;
23378a20a01SMasahiro Yamada 	}
23478a20a01SMasahiro Yamada 
23578a20a01SMasahiro Yamada 	fputs("/*\n", out);
23678a20a01SMasahiro Yamada 	fputs(" *  DO NOT EDIT THIS FILE!\n", out);
23778a20a01SMasahiro Yamada 	fputs(" *\n", out);
23878a20a01SMasahiro Yamada 	fprintf(out, " *  Linux logo %s\n", logoname);
23978a20a01SMasahiro Yamada 	fputs(" */\n\n", out);
24078a20a01SMasahiro Yamada 	fputs("#include <linux/linux_logo.h>\n\n", out);
241*3dc59489SGeert Uytterhoeven 	fprintf(out, "static const unsigned char %s_data[] __initconst = {\n",
24278a20a01SMasahiro Yamada 		logoname);
24378a20a01SMasahiro Yamada }
24478a20a01SMasahiro Yamada 
write_footer(void)24578a20a01SMasahiro Yamada static void write_footer(void)
24678a20a01SMasahiro Yamada {
24778a20a01SMasahiro Yamada 	fputs("\n};\n\n", out);
24878a20a01SMasahiro Yamada 	fprintf(out, "const struct linux_logo %s __initconst = {\n", logoname);
24978a20a01SMasahiro Yamada 	fprintf(out, "\t.type\t\t= %s,\n", logo_types[logo_type]);
25029328fb0SColin Ian King 	fprintf(out, "\t.width\t\t= %u,\n", logo_width);
25129328fb0SColin Ian King 	fprintf(out, "\t.height\t\t= %u,\n", logo_height);
25278a20a01SMasahiro Yamada 	if (logo_type == LINUX_LOGO_CLUT224) {
25329328fb0SColin Ian King 		fprintf(out, "\t.clutsize\t= %u,\n", logo_clutsize);
25478a20a01SMasahiro Yamada 		fprintf(out, "\t.clut\t\t= %s_clut,\n", logoname);
25578a20a01SMasahiro Yamada 	}
25678a20a01SMasahiro Yamada 	fprintf(out, "\t.data\t\t= %s_data\n", logoname);
25778a20a01SMasahiro Yamada 	fputs("};\n\n", out);
25878a20a01SMasahiro Yamada 
25978a20a01SMasahiro Yamada 	/* close logo file */
26078a20a01SMasahiro Yamada 	if (outputname)
26178a20a01SMasahiro Yamada 		fclose(out);
26278a20a01SMasahiro Yamada }
26378a20a01SMasahiro Yamada 
26478a20a01SMasahiro Yamada static int write_hex_cnt;
26578a20a01SMasahiro Yamada 
write_hex(unsigned char byte)26678a20a01SMasahiro Yamada static void write_hex(unsigned char byte)
26778a20a01SMasahiro Yamada {
26878a20a01SMasahiro Yamada 	if (write_hex_cnt % 12)
26978a20a01SMasahiro Yamada 		fprintf(out, ", 0x%02x", byte);
27078a20a01SMasahiro Yamada 	else if (write_hex_cnt)
27178a20a01SMasahiro Yamada 		fprintf(out, ",\n\t0x%02x", byte);
27278a20a01SMasahiro Yamada 	else
27378a20a01SMasahiro Yamada 		fprintf(out, "\t0x%02x", byte);
27478a20a01SMasahiro Yamada 	write_hex_cnt++;
27578a20a01SMasahiro Yamada }
27678a20a01SMasahiro Yamada 
write_logo_mono(void)27778a20a01SMasahiro Yamada static void write_logo_mono(void)
27878a20a01SMasahiro Yamada {
27978a20a01SMasahiro Yamada 	unsigned int i, j;
28078a20a01SMasahiro Yamada 	unsigned char val, bit;
28178a20a01SMasahiro Yamada 
28278a20a01SMasahiro Yamada 	/* validate image */
28378a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
28478a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++)
28578a20a01SMasahiro Yamada 			if (!is_black(logo_data[i][j]) && !is_white(logo_data[i][j]))
28678a20a01SMasahiro Yamada 				die("Image must be monochrome\n");
28778a20a01SMasahiro Yamada 
28878a20a01SMasahiro Yamada 	/* write file header */
28978a20a01SMasahiro Yamada 	write_header();
29078a20a01SMasahiro Yamada 
29178a20a01SMasahiro Yamada 	/* write logo data */
29278a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++) {
29378a20a01SMasahiro Yamada 		for (j = 0; j < logo_width;) {
29478a20a01SMasahiro Yamada 			for (val = 0, bit = 0x80; bit && j < logo_width; j++, bit >>= 1)
29578a20a01SMasahiro Yamada 				if (logo_data[i][j].red)
29678a20a01SMasahiro Yamada 					val |= bit;
29778a20a01SMasahiro Yamada 			write_hex(val);
29878a20a01SMasahiro Yamada 		}
29978a20a01SMasahiro Yamada 	}
30078a20a01SMasahiro Yamada 
30178a20a01SMasahiro Yamada 	/* write logo structure and file footer */
30278a20a01SMasahiro Yamada 	write_footer();
30378a20a01SMasahiro Yamada }
30478a20a01SMasahiro Yamada 
write_logo_vga16(void)30578a20a01SMasahiro Yamada static void write_logo_vga16(void)
30678a20a01SMasahiro Yamada {
30778a20a01SMasahiro Yamada 	unsigned int i, j, k;
30878a20a01SMasahiro Yamada 	unsigned char val;
30978a20a01SMasahiro Yamada 
31078a20a01SMasahiro Yamada 	/* validate image */
31178a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
31278a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++) {
31378a20a01SMasahiro Yamada 			for (k = 0; k < 16; k++)
31478a20a01SMasahiro Yamada 				if (is_equal(logo_data[i][j], clut_vga16[k]))
31578a20a01SMasahiro Yamada 					break;
31678a20a01SMasahiro Yamada 			if (k == 16)
31778a20a01SMasahiro Yamada 				die("Image must use the 16 console colors only\n"
31878a20a01SMasahiro Yamada 				    "Use ppmquant(1) -map clut_vga16.ppm to reduce the number "
31978a20a01SMasahiro Yamada 				    "of colors\n");
32078a20a01SMasahiro Yamada 		}
32178a20a01SMasahiro Yamada 
32278a20a01SMasahiro Yamada 	/* write file header */
32378a20a01SMasahiro Yamada 	write_header();
32478a20a01SMasahiro Yamada 
32578a20a01SMasahiro Yamada 	/* write logo data */
32678a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
32778a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++) {
32878a20a01SMasahiro Yamada 			for (k = 0; k < 16; k++)
32978a20a01SMasahiro Yamada 				if (is_equal(logo_data[i][j], clut_vga16[k]))
33078a20a01SMasahiro Yamada 					break;
33178a20a01SMasahiro Yamada 			val = k<<4;
33278a20a01SMasahiro Yamada 			if (++j < logo_width) {
33378a20a01SMasahiro Yamada 				for (k = 0; k < 16; k++)
33478a20a01SMasahiro Yamada 					if (is_equal(logo_data[i][j], clut_vga16[k]))
33578a20a01SMasahiro Yamada 						break;
33678a20a01SMasahiro Yamada 				val |= k;
33778a20a01SMasahiro Yamada 			}
33878a20a01SMasahiro Yamada 			write_hex(val);
33978a20a01SMasahiro Yamada 		}
34078a20a01SMasahiro Yamada 
34178a20a01SMasahiro Yamada 	/* write logo structure and file footer */
34278a20a01SMasahiro Yamada 	write_footer();
34378a20a01SMasahiro Yamada }
34478a20a01SMasahiro Yamada 
write_logo_clut224(void)34578a20a01SMasahiro Yamada static void write_logo_clut224(void)
34678a20a01SMasahiro Yamada {
34778a20a01SMasahiro Yamada 	unsigned int i, j, k;
34878a20a01SMasahiro Yamada 
34978a20a01SMasahiro Yamada 	/* validate image */
35078a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
35178a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++) {
35278a20a01SMasahiro Yamada 			for (k = 0; k < logo_clutsize; k++)
35378a20a01SMasahiro Yamada 				if (is_equal(logo_data[i][j], logo_clut[k]))
35478a20a01SMasahiro Yamada 					break;
35578a20a01SMasahiro Yamada 			if (k == logo_clutsize) {
35678a20a01SMasahiro Yamada 				if (logo_clutsize == MAX_LINUX_LOGO_COLORS)
35778a20a01SMasahiro Yamada 					die("Image has more than %d colors\n"
35878a20a01SMasahiro Yamada 					    "Use ppmquant(1) to reduce the number of colors\n",
35978a20a01SMasahiro Yamada 					    MAX_LINUX_LOGO_COLORS);
36078a20a01SMasahiro Yamada 				logo_clut[logo_clutsize++] = logo_data[i][j];
36178a20a01SMasahiro Yamada 			}
36278a20a01SMasahiro Yamada 		}
36378a20a01SMasahiro Yamada 
36478a20a01SMasahiro Yamada 	/* write file header */
36578a20a01SMasahiro Yamada 	write_header();
36678a20a01SMasahiro Yamada 
36778a20a01SMasahiro Yamada 	/* write logo data */
36878a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
36978a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++) {
37078a20a01SMasahiro Yamada 			for (k = 0; k < logo_clutsize; k++)
37178a20a01SMasahiro Yamada 				if (is_equal(logo_data[i][j], logo_clut[k]))
37278a20a01SMasahiro Yamada 					break;
37378a20a01SMasahiro Yamada 			write_hex(k+32);
37478a20a01SMasahiro Yamada 		}
37578a20a01SMasahiro Yamada 	fputs("\n};\n\n", out);
37678a20a01SMasahiro Yamada 
37778a20a01SMasahiro Yamada 	/* write logo clut */
378*3dc59489SGeert Uytterhoeven 	fprintf(out, "static const unsigned char %s_clut[] __initconst = {\n",
37978a20a01SMasahiro Yamada 		logoname);
38078a20a01SMasahiro Yamada 	write_hex_cnt = 0;
38178a20a01SMasahiro Yamada 	for (i = 0; i < logo_clutsize; i++) {
38278a20a01SMasahiro Yamada 		write_hex(logo_clut[i].red);
38378a20a01SMasahiro Yamada 		write_hex(logo_clut[i].green);
38478a20a01SMasahiro Yamada 		write_hex(logo_clut[i].blue);
38578a20a01SMasahiro Yamada 	}
38678a20a01SMasahiro Yamada 
38778a20a01SMasahiro Yamada 	/* write logo structure and file footer */
38878a20a01SMasahiro Yamada 	write_footer();
38978a20a01SMasahiro Yamada }
39078a20a01SMasahiro Yamada 
write_logo_gray256(void)39178a20a01SMasahiro Yamada static void write_logo_gray256(void)
39278a20a01SMasahiro Yamada {
39378a20a01SMasahiro Yamada 	unsigned int i, j;
39478a20a01SMasahiro Yamada 
39578a20a01SMasahiro Yamada 	/* validate image */
39678a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
39778a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++)
39878a20a01SMasahiro Yamada 			if (!is_gray(logo_data[i][j]))
39978a20a01SMasahiro Yamada 				die("Image must be grayscale\n");
40078a20a01SMasahiro Yamada 
40178a20a01SMasahiro Yamada 	/* write file header */
40278a20a01SMasahiro Yamada 	write_header();
40378a20a01SMasahiro Yamada 
40478a20a01SMasahiro Yamada 	/* write logo data */
40578a20a01SMasahiro Yamada 	for (i = 0; i < logo_height; i++)
40678a20a01SMasahiro Yamada 		for (j = 0; j < logo_width; j++)
40778a20a01SMasahiro Yamada 			write_hex(logo_data[i][j].red);
40878a20a01SMasahiro Yamada 
40978a20a01SMasahiro Yamada 	/* write logo structure and file footer */
41078a20a01SMasahiro Yamada 	write_footer();
41178a20a01SMasahiro Yamada }
41278a20a01SMasahiro Yamada 
die(const char * fmt,...)41378a20a01SMasahiro Yamada static void die(const char *fmt, ...)
41478a20a01SMasahiro Yamada {
41578a20a01SMasahiro Yamada 	va_list ap;
41678a20a01SMasahiro Yamada 
41778a20a01SMasahiro Yamada 	va_start(ap, fmt);
41878a20a01SMasahiro Yamada 	vfprintf(stderr, fmt, ap);
41978a20a01SMasahiro Yamada 	va_end(ap);
42078a20a01SMasahiro Yamada 
42178a20a01SMasahiro Yamada 	exit(1);
42278a20a01SMasahiro Yamada }
42378a20a01SMasahiro Yamada 
usage(void)42478a20a01SMasahiro Yamada static void usage(void)
42578a20a01SMasahiro Yamada {
42678a20a01SMasahiro Yamada 	die("\n"
42778a20a01SMasahiro Yamada 	"Usage: %s [options] <filename>\n"
42878a20a01SMasahiro Yamada 	"\n"
42978a20a01SMasahiro Yamada 	"Valid options:\n"
43078a20a01SMasahiro Yamada 	"	-h		  : display this usage information\n"
43178a20a01SMasahiro Yamada 	"	-n <name>   : specify logo name (default: linux_logo)\n"
43278a20a01SMasahiro Yamada 	"	-o <output> : output to file <output> instead of stdout\n"
43378a20a01SMasahiro Yamada 	"	-t <type>   : specify logo type, one of\n"
43478a20a01SMasahiro Yamada 	"					  mono	: monochrome black/white\n"
43578a20a01SMasahiro Yamada 	"					  vga16   : 16 colors VGA text palette\n"
43678a20a01SMasahiro Yamada 	"					  clut224 : 224 colors (default)\n"
43778a20a01SMasahiro Yamada 	"					  gray256 : 256 levels grayscale\n"
43878a20a01SMasahiro Yamada 	"\n", programname);
43978a20a01SMasahiro Yamada }
44078a20a01SMasahiro Yamada 
main(int argc,char * argv[])44178a20a01SMasahiro Yamada int main(int argc, char *argv[])
44278a20a01SMasahiro Yamada {
44378a20a01SMasahiro Yamada 	int opt;
44478a20a01SMasahiro Yamada 
44578a20a01SMasahiro Yamada 	programname = argv[0];
44678a20a01SMasahiro Yamada 
44778a20a01SMasahiro Yamada 	opterr = 0;
44878a20a01SMasahiro Yamada 	while (1) {
44978a20a01SMasahiro Yamada 		opt = getopt(argc, argv, "hn:o:t:");
45078a20a01SMasahiro Yamada 		if (opt == -1)
45178a20a01SMasahiro Yamada 			break;
45278a20a01SMasahiro Yamada 
45378a20a01SMasahiro Yamada 		switch (opt) {
45478a20a01SMasahiro Yamada 		case 'h':
45578a20a01SMasahiro Yamada 			usage();
45678a20a01SMasahiro Yamada 			break;
45778a20a01SMasahiro Yamada 
45878a20a01SMasahiro Yamada 		case 'n':
45978a20a01SMasahiro Yamada 			logoname = optarg;
46078a20a01SMasahiro Yamada 			break;
46178a20a01SMasahiro Yamada 
46278a20a01SMasahiro Yamada 		case 'o':
46378a20a01SMasahiro Yamada 			outputname = optarg;
46478a20a01SMasahiro Yamada 			break;
46578a20a01SMasahiro Yamada 
46678a20a01SMasahiro Yamada 		case 't':
46778a20a01SMasahiro Yamada 			if (!strcmp(optarg, "mono"))
46878a20a01SMasahiro Yamada 				logo_type = LINUX_LOGO_MONO;
46978a20a01SMasahiro Yamada 			else if (!strcmp(optarg, "vga16"))
47078a20a01SMasahiro Yamada 				logo_type = LINUX_LOGO_VGA16;
47178a20a01SMasahiro Yamada 			else if (!strcmp(optarg, "clut224"))
47278a20a01SMasahiro Yamada 				logo_type = LINUX_LOGO_CLUT224;
47378a20a01SMasahiro Yamada 			else if (!strcmp(optarg, "gray256"))
47478a20a01SMasahiro Yamada 				logo_type = LINUX_LOGO_GRAY256;
47578a20a01SMasahiro Yamada 			else
47678a20a01SMasahiro Yamada 				usage();
47778a20a01SMasahiro Yamada 			break;
47878a20a01SMasahiro Yamada 
47978a20a01SMasahiro Yamada 		default:
48078a20a01SMasahiro Yamada 			usage();
48178a20a01SMasahiro Yamada 			break;
48278a20a01SMasahiro Yamada 		}
48378a20a01SMasahiro Yamada 	}
48478a20a01SMasahiro Yamada 	if (optind != argc-1)
48578a20a01SMasahiro Yamada 		usage();
48678a20a01SMasahiro Yamada 
48778a20a01SMasahiro Yamada 	filename = argv[optind];
48878a20a01SMasahiro Yamada 
48978a20a01SMasahiro Yamada 	read_image();
49078a20a01SMasahiro Yamada 	switch (logo_type) {
49178a20a01SMasahiro Yamada 	case LINUX_LOGO_MONO:
49278a20a01SMasahiro Yamada 		write_logo_mono();
49378a20a01SMasahiro Yamada 		break;
49478a20a01SMasahiro Yamada 
49578a20a01SMasahiro Yamada 	case LINUX_LOGO_VGA16:
49678a20a01SMasahiro Yamada 		write_logo_vga16();
49778a20a01SMasahiro Yamada 		break;
49878a20a01SMasahiro Yamada 
49978a20a01SMasahiro Yamada 	case LINUX_LOGO_CLUT224:
50078a20a01SMasahiro Yamada 		write_logo_clut224();
50178a20a01SMasahiro Yamada 		break;
50278a20a01SMasahiro Yamada 
50378a20a01SMasahiro Yamada 	case LINUX_LOGO_GRAY256:
50478a20a01SMasahiro Yamada 		write_logo_gray256();
50578a20a01SMasahiro Yamada 		break;
50678a20a01SMasahiro Yamada 	}
50778a20a01SMasahiro Yamada 	exit(0);
50878a20a01SMasahiro Yamada }
509