xref: /openbmc/u-boot/tools/easylogo/easylogo.c (revision 118978c8)
1 /*
2 ** Easylogo TGA->header converter
3 ** ==============================
4 ** (C) 2000 by Paolo Scaffardi (arsenio@tin.it)
5 ** AIRVENT SAM s.p.a - RIMINI(ITALY)
6 **
7 ** This is still under construction!
8 */
9 
10 #include <getopt.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #pragma pack(1)
17 
18 /*#define ENABLE_ASCII_BANNERS */
19 
20 typedef struct {
21 	unsigned char id;
22 	unsigned char ColorMapType;
23 	unsigned char ImageTypeCode;
24 	unsigned short ColorMapOrigin;
25 	unsigned short ColorMapLenght;
26 	unsigned char ColorMapEntrySize;
27 	unsigned short ImageXOrigin;
28 	unsigned short ImageYOrigin;
29 	unsigned short ImageWidth;
30 	unsigned short ImageHeight;
31 	unsigned char ImagePixelSize;
32 	unsigned char ImageDescriptorByte;
33 } tga_header_t;
34 
35 typedef struct {
36 	unsigned char r, g, b;
37 } rgb_t;
38 
39 typedef struct {
40 	unsigned char b, g, r;
41 } bgr_t;
42 
43 typedef struct {
44 	unsigned char Cb, y1, Cr, y2;
45 } yuyv_t;
46 
47 typedef struct {
48 	void *data, *palette;
49 	int width, height, pixels, bpp, pixel_size, size, palette_size, yuyv;
50 } image_t;
51 
52 void StringUpperCase (char *str)
53 {
54 	int count = strlen (str);
55 	char c;
56 
57 	while (count--) {
58 		c = *str;
59 		if ((c >= 'a') && (c <= 'z'))
60 			*str = 'A' + (c - 'a');
61 		str++;
62 	}
63 }
64 
65 void StringLowerCase (char *str)
66 {
67 	int count = strlen (str);
68 	char c;
69 
70 	while (count--) {
71 		c = *str;
72 		if ((c >= 'A') && (c <= 'Z'))
73 			*str = 'a' + (c - 'A');
74 		str++;
75 	}
76 }
77 void pixel_rgb_to_yuyv (rgb_t * rgb_pixel, yuyv_t * yuyv_pixel)
78 {
79 	unsigned int pR, pG, pB;
80 
81 	/* Transform (0-255) components to (0-100) */
82 	pR = rgb_pixel->r * 100 / 255;
83 	pG = rgb_pixel->g * 100 / 255;
84 	pB = rgb_pixel->b * 100 / 255;
85 
86 	/* Calculate YUV values (0-255) from RGB beetween 0-100 */
87 	yuyv_pixel->y1 = yuyv_pixel->y2 = 209 * (pR + pG + pB) / 300 + 16;
88 	yuyv_pixel->Cb = pB - (pR / 4) - (pG * 3 / 4) + 128;
89 	yuyv_pixel->Cr = pR - (pG * 3 / 4) - (pB / 4) + 128;
90 
91 	return;
92 }
93 
94 void printlogo_rgb (rgb_t * data, int w, int h)
95 {
96 	int x, y;
97 
98 	for (y = 0; y < h; y++) {
99 		for (x = 0; x < w; x++, data++)
100 			if ((data->r <
101 			     30) /*&&(data->g == 0)&&(data->b == 0) */ )
102 				printf (" ");
103 			else
104 				printf ("X");
105 		printf ("\n");
106 	}
107 }
108 
109 void printlogo_yuyv (unsigned short *data, int w, int h)
110 {
111 	int x, y;
112 
113 	for (y = 0; y < h; y++) {
114 		for (x = 0; x < w; x++, data++)
115 			if (*data == 0x1080)	/* Because of inverted on i386! */
116 				printf (" ");
117 			else
118 				printf ("X");
119 		printf ("\n");
120 	}
121 }
122 
123 static inline unsigned short le16_to_cpu (unsigned short val)
124 {
125 	union {
126 		unsigned char pval[2];
127 		unsigned short val;
128 	} swapped;
129 
130 	swapped.val = val;
131 	return (swapped.pval[1] << 8) + swapped.pval[0];
132 }
133 
134 int image_load_tga (image_t * image, char *filename)
135 {
136 	FILE *file;
137 	tga_header_t header;
138 	int i;
139 	unsigned char app;
140 	rgb_t *p;
141 
142 	if ((file = fopen (filename, "rb")) == NULL)
143 		return -1;
144 
145 	fread (&header, sizeof (header), 1, file);
146 
147 	/* byte swap: tga is little endian, host is ??? */
148 	header.ColorMapOrigin = le16_to_cpu (header.ColorMapOrigin);
149 	header.ColorMapLenght = le16_to_cpu (header.ColorMapLenght);
150 	header.ImageXOrigin = le16_to_cpu (header.ImageXOrigin);
151 	header.ImageYOrigin = le16_to_cpu (header.ImageYOrigin);
152 	header.ImageWidth = le16_to_cpu (header.ImageWidth);
153 	header.ImageHeight = le16_to_cpu (header.ImageHeight);
154 
155 	image->width = header.ImageWidth;
156 	image->height = header.ImageHeight;
157 
158 	switch (header.ImageTypeCode) {
159 	case 2:		/* Uncompressed RGB */
160 		image->yuyv = 0;
161 		image->palette_size = 0;
162 		image->palette = NULL;
163 		break;
164 
165 	default:
166 		printf ("Format not supported!\n");
167 		return -1;
168 	}
169 
170 	image->bpp = header.ImagePixelSize;
171 	image->pixel_size = ((image->bpp - 1) / 8) + 1;
172 	image->pixels = image->width * image->height;
173 	image->size = image->pixels * image->pixel_size;
174 	image->data = malloc (image->size);
175 
176 	if (image->bpp != 24) {
177 		printf ("Bpp not supported: %d!\n", image->bpp);
178 		return -1;
179 	}
180 
181 	fread (image->data, image->size, 1, file);
182 
183 /* Swapping R and B values */
184 
185 	p = image->data;
186 	for (i = 0; i < image->pixels; i++, p++) {
187 		app = p->r;
188 		p->r = p->b;
189 		p->b = app;
190 	}
191 
192 /* Swapping image */
193 
194 	if (!(header.ImageDescriptorByte & 0x20)) {
195 		unsigned char *temp = malloc (image->size);
196 		int linesize = image->pixel_size * image->width;
197 		void *dest = image->data,
198 			*source = temp + image->size - linesize;
199 
200 		printf ("S");
201 		if (temp == NULL) {
202 			printf ("Cannot alloc temp buffer!\n");
203 			return -1;
204 		}
205 
206 		memcpy (temp, image->data, image->size);
207 		for (i = 0; i < image->height;
208 		     i++, dest += linesize, source -= linesize)
209 			memcpy (dest, source, linesize);
210 
211 		free (temp);
212 	}
213 #ifdef ENABLE_ASCII_BANNERS
214 	printlogo_rgb (image->data, image->width, image->height);
215 #endif
216 
217 	fclose (file);
218 	return 0;
219 }
220 
221 void image_free (image_t * image)
222 {
223 	free (image->data);
224 	free (image->palette);
225 }
226 
227 int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image)
228 {
229 	rgb_t *rgb_ptr = (rgb_t *) rgb_image->data;
230 	yuyv_t yuyv;
231 	unsigned short *dest;
232 	int count = 0;
233 
234 	yuyv_image->pixel_size = 2;
235 	yuyv_image->bpp = 16;
236 	yuyv_image->yuyv = 1;
237 	yuyv_image->width = rgb_image->width;
238 	yuyv_image->height = rgb_image->height;
239 	yuyv_image->pixels = yuyv_image->width * yuyv_image->height;
240 	yuyv_image->size = yuyv_image->pixels * yuyv_image->pixel_size;
241 	dest = (unsigned short *) (yuyv_image->data =
242 				   malloc (yuyv_image->size));
243 	yuyv_image->palette = 0;
244 	yuyv_image->palette_size = 0;
245 
246 	while ((count++) < rgb_image->pixels) {
247 		pixel_rgb_to_yuyv (rgb_ptr++, &yuyv);
248 
249 		if ((count & 1) == 0)	/* Was == 0 */
250 			memcpy (dest, ((void *) &yuyv) + 2, sizeof (short));
251 		else
252 			memcpy (dest, (void *) &yuyv, sizeof (short));
253 
254 		dest++;
255 	}
256 
257 #ifdef ENABLE_ASCII_BANNERS
258 	printlogo_yuyv (yuyv_image->data, yuyv_image->width,
259 			yuyv_image->height);
260 #endif
261 	return 0;
262 }
263 
264 int image_save_header (image_t * image, char *filename, char *varname)
265 {
266 	FILE *file = fopen (filename, "w");
267 	char app[256], str[256] = "", def_name[64];
268 	int count = image->size, col = 0;
269 	unsigned char *dataptr = image->data;
270 
271 	if (file == NULL)
272 		return -1;
273 
274 	/*  Author information */
275 	fprintf (file,
276 		 "/*\n * Generated by EasyLogo, (C) 2000 by Paolo Scaffardi\n *\n");
277 	fprintf (file,
278 		 " * To use this, include it and call: easylogo_plot(screen,&%s, width,x,y)\n *\n",
279 		 varname);
280 	fprintf (file,
281 		 " * Where:\t'screen'\tis the pointer to the frame buffer\n");
282 	fprintf (file, " *\t\t'width'\tis the screen width\n");
283 	fprintf (file, " *\t\t'x'\t\tis the horizontal position\n");
284 	fprintf (file, " *\t\t'y'\t\tis the vertical position\n */\n\n");
285 
286 	/*	Headers */
287 	fprintf (file, "#include <video_easylogo.h>\n\n");
288 	/*	Macros */
289 	strcpy (def_name, varname);
290 	StringUpperCase (def_name);
291 	fprintf (file, "#define	DEF_%s_WIDTH\t\t%d\n", def_name,
292 		 image->width);
293 	fprintf (file, "#define	DEF_%s_HEIGHT\t\t%d\n", def_name,
294 		 image->height);
295 	fprintf (file, "#define	DEF_%s_PIXELS\t\t%d\n", def_name,
296 		 image->pixels);
297 	fprintf (file, "#define	DEF_%s_BPP\t\t%d\n", def_name, image->bpp);
298 	fprintf (file, "#define	DEF_%s_PIXEL_SIZE\t%d\n", def_name,
299 		 image->pixel_size);
300 	fprintf (file, "#define	DEF_%s_SIZE\t\t%d\n\n", def_name,
301 		 image->size);
302 	/*  Declaration */
303 	fprintf (file, "unsigned char DEF_%s_DATA[DEF_%s_SIZE] = {\n",
304 		 def_name, def_name);
305 
306 	/*	Data */
307 	while (count)
308 		switch (col) {
309 		case 0:
310 			sprintf (str, " 0x%02x", *dataptr++);
311 			col++;
312 			count--;
313 			break;
314 
315 		case 16:
316 			fprintf (file, "%s", str);
317 			if (count > 0)
318 				fprintf (file, ",");
319 			fprintf (file, "\n");
320 
321 			col = 0;
322 			break;
323 
324 		default:
325 			strcpy (app, str);
326 			sprintf (str, "%s, 0x%02x", app, *dataptr++);
327 			col++;
328 			count--;
329 			break;
330 		}
331 
332 	if (col)
333 		fprintf (file, "%s\n", str);
334 
335 	/* 	End of declaration */
336 	fprintf (file, "};\n\n");
337 	/*	Variable */
338 	fprintf (file, "fastimage_t %s = {\n", varname);
339 	fprintf (file, "		DEF_%s_DATA,\n", def_name);
340 	fprintf (file, "		DEF_%s_WIDTH,\n", def_name);
341 	fprintf (file, "		DEF_%s_HEIGHT,\n", def_name);
342 	fprintf (file, "		DEF_%s_BPP,\n", def_name);
343 	fprintf (file, "		DEF_%s_PIXEL_SIZE,\n", def_name);
344 	fprintf (file, "		DEF_%s_SIZE\n};\n", def_name);
345 
346 	fclose (file);
347 
348 	return 0;
349 }
350 
351 #define DEF_FILELEN	256
352 
353 static void usage (int exit_status)
354 {
355 	puts (
356 		"EasyLogo 1.0 (C) 2000 by Paolo Scaffardi\n"
357 		"\n"
358 		"Syntax:	easylogo [options] inputfile [outputvar [outputfile]]\n"
359 		"\n"
360 		"Options:\n"
361 		"  -r     Output RGB instead of YUYV\n"
362 		"  -h     Help output\n"
363 		"\n"
364 		"Where: 'inputfile'   is the TGA image to load\n"
365 		"       'outputvar'   is the variable name to create\n"
366 		"       'outputfile'  is the output header file (default is 'inputfile.h')"
367 	);
368 	exit (exit_status);
369 }
370 
371 int main (int argc, char *argv[])
372 {
373 	int c;
374 	bool use_rgb = false;
375 	char inputfile[DEF_FILELEN],
376 		outputfile[DEF_FILELEN], varname[DEF_FILELEN];
377 
378 	image_t rgb_logo, yuyv_logo;
379 
380 	while ((c = getopt(argc, argv, "hr")) > 0) {
381 		switch (c) {
382 		case 'h':
383 			usage (0);
384 			break;
385 		case 'r':
386 			use_rgb = true;
387 			puts ("Using 24-bit RGB Output Fromat");
388 			break;
389 		default:
390 			usage (1);
391 			break;
392 		}
393 	}
394 
395 	c = argc - optind;
396 	if (c > 4 || c < 1)
397 		usage (1);
398 
399 	strcpy (inputfile, argv[optind]);
400 
401 	if (c > 1)
402 		strcpy (varname, argv[optind + 1]);
403 	else {
404 		/* transform "input.tga" to just "input" */
405 		char *dot;
406 		strcpy (varname, inputfile);
407 		dot = strchr (varname, '.');
408 		if (dot)
409 			*dot = '\0';
410 	}
411 
412 	if (c > 2)
413 		strcpy (outputfile, argv[optind + 2]);
414 	else {
415 		/* just append ".h" to input file name */
416 		strcpy (outputfile, inputfile);
417 		strcat (outputfile, ".h");
418 	}
419 
420 	/* Make sure the output is sent as soon as we printf() */
421 	setbuf(stdout, NULL);
422 
423 	printf ("Doing '%s' (%s) from '%s'...",
424 		outputfile, varname, inputfile);
425 
426 	/* Import TGA logo */
427 
428 	printf ("L");
429 	if (image_load_tga (&rgb_logo, inputfile) < 0) {
430 		printf ("input file not found!\n");
431 		exit (1);
432 	}
433 
434 	/* Convert it to YUYV format if wanted */
435 
436 	if (!use_rgb) {
437 		printf ("C");
438 		image_rgb_to_yuyv (&rgb_logo, &yuyv_logo);
439 	}
440 
441 	/* Save it into a header format */
442 
443 	printf ("S");
444 	image_save_header (use_rgb ? &rgb_logo : &yuyv_logo, outputfile, varname);
445 
446 	/* Free original image and copy */
447 
448 	image_free (&rgb_logo);
449 	if (!use_rgb)
450 		image_free (&yuyv_logo);
451 
452 	printf ("\n");
453 
454 	return 0;
455 }
456