summaryrefslogtreecommitdiff
path: root/uisimulator/bmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'uisimulator/bmp.c')
-rw-r--r--uisimulator/bmp.c566
1 files changed, 566 insertions, 0 deletions
diff --git a/uisimulator/bmp.c b/uisimulator/bmp.c
new file mode 100644
index 0000000000..5df003a537
--- /dev/null
+++ b/uisimulator/bmp.c
@@ -0,0 +1,566 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19/*********************************************************************
20 *
21 * Converts BMP files to Rockbox bitmap format
22 *
23 * 1999-05-03 Linus Nielsen Feltzing
24 *
25 **********************************************/
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <stdbool.h>
31
32#include "file.h"
33
34#ifdef __GNUC__
35#define STRUCT_PACKED __attribute__((packed))
36#endif
37
38struct Fileheader
39{
40 unsigned short Type; /* signature - 'BM' */
41 unsigned long Size; /* file size in bytes */
42 unsigned short Reserved1; /* 0 */
43 unsigned short Reserved2; /* 0 */
44 unsigned long OffBits; /* offset to bitmap */
45 unsigned long StructSize; /* size of this struct (40) */
46 unsigned long Width; /* bmap width in pixels */
47 unsigned long Height; /* bmap height in pixels */
48 unsigned short Planes; /* num planes - always 1 */
49 unsigned short BitCount; /* bits per pixel */
50 unsigned long Compression; /* compression flag */
51 unsigned long SizeImage; /* image size in bytes */
52 long XPelsPerMeter; /* horz resolution */
53 long YPelsPerMeter; /* vert resolution */
54 unsigned long ClrUsed; /* 0 -> color table size */
55 unsigned long ClrImportant; /* important color count */
56} STRUCT_PACKED;
57
58struct RGBQUAD
59{
60 unsigned char rgbBlue;
61 unsigned char rgbGreen;
62 unsigned char rgbRed;
63 unsigned char rgbReserved;
64} STRUCT_PACKED;
65
66static struct Fileheader fh;
67static unsigned char* bmp;
68static struct RGBQUAD palette[2]; /* two colors only */
69
70static unsigned int bitmap_width, bitmap_height;
71static unsigned char *bitmap;
72
73#ifdef STANDALONE
74static id_str[256];
75static bool compress = false;
76static bool assembly = false;
77static unsigned char* converted_bmp;
78static unsigned char* compressed_bmp;
79static unsigned int width;
80static unsigned int converted_size;
81static unsigned int compressed_size;
82static unsigned int rounded_width;
83#endif
84
85#define readshort(x) (((x&0xff00)>>8)|((x&0x00ff)<<8))
86#define readlong(x) (((x&0xff000000)>>24)| \
87 ((x&0x00ff0000)>>8) | \
88 ((x&0x0000ff00)<<8) | \
89 ((x&0x000000ff)<<24))
90
91
92/*********************************************************************
93 * read_bmp_file()
94 *
95 * Reads a monochrome BMP file and puts the data in a 1-pixel-per-byte
96 * array. Returns 0 on success.
97 *
98 **********************************************/
99int read_bmp_file(char* filename,
100 int *get_width, /* in pixels */
101 int *get_height, /* in pixels */
102 char *bitmap)
103{
104 long PaddedWidth;
105 int background;
106 int fd = open(filename, O_RDONLY);
107 long size;
108 unsigned int row, col, byte, bit;
109 int l;
110 char *bmp;
111 int width;
112 int height;
113
114 if(fd == -1)
115 {
116 debugf("error - can't open '%s'\n", filename);
117 return 1;
118 }
119 else
120 {
121 if(read(fd, &fh, sizeof(struct Fileheader)) !=
122 sizeof(struct Fileheader))
123 {
124 debugf("error - can't Read Fileheader Stucture\n");
125 return 2;
126 }
127
128 /* Exit if not monochrome */
129 if(readshort(fh.BitCount) > 8)
130 {
131 debugf("error - Bitmap must be less than 8, got %d\n",
132 readshort(fh.BitCount));
133 return 2;
134 }
135
136 /* Exit if too wide */
137 if(readlong(fh.Width) > 112)
138 {
139 debugf("error - Bitmap is too wide (%d pixels, max is 112)\n",
140 readlong(fh.Width));
141 return 3;
142 }
143 debugf("Bitmap is %d pixels wide\n", readlong(fh.Width));
144
145 /* Exit if too high */
146 if(readlong(fh.Height) > 64)
147 {
148 debugf("error - Bitmap is too high (%d pixels, max is 64)\n",
149 readlong(fh.Height));
150 return 4;
151 }
152 debugf("Bitmap is %d pixels heigh\n", readlong(fh.Height));
153
154 for(l=0;l < 2;l++)
155 {
156 if(read(fd, &palette[l],sizeof(struct RGBQUAD)) !=
157 sizeof(struct RGBQUAD))
158 {
159 debugf("error - Can't read bitmap's color palette\n");
160 return 5;
161 }
162 }
163 /* pass the other palettes */
164 lseek(fd, 254*sizeof(struct RGBQUAD), SEEK_CUR);
165
166 /* Try to guess the foreground and background colors.
167 We assume that the foreground color is the darkest. */
168 if(((int)palette[0].rgbRed +
169 (int)palette[0].rgbGreen +
170 (int)palette[0].rgbBlue) >
171 ((int)palette[1].rgbRed +
172 (int)palette[1].rgbGreen +
173 (int)palette[1].rgbBlue))
174 {
175 background = 0;
176 }
177 else
178 {
179 background = 1;
180 }
181
182 width = readlong(fh.Width)*readshort(fh.BitCount);
183 PaddedWidth = ((width+31)&(~0x1f))/8;
184 size = PaddedWidth*readlong(fh.Height);
185
186 bmp = (unsigned char *)malloc(size);
187
188 if(bmp == NULL)
189 {
190 debugf("error - Out of memory\n");
191 return 6;
192 }
193 else
194 {
195 if(read(fd, (unsigned char*)bmp,(long)size) != size) {
196 debugf("error - Can't read image\n");
197 return 7;
198 }
199 }
200
201 bitmap_height = readlong(fh.Height);
202 bitmap_width = readlong(fh.Width);
203
204 *get_width = bitmap_width;
205 *get_height = bitmap_height;
206
207#if 0
208 /* Now convert the bitmap into an array with 1 byte per pixel,
209 exactly the size of the image */
210 for(row = 0;row < bitmap_height;row++) {
211 bit = 7;
212 byte = 0;
213 for(col = 0;col < bitmap_width;col++) {
214 if((bmp[(bitmap_height - row - 1) * PaddedWidth + byte] &
215 (1 << bit))) {
216
217 bitmap[ (row/8) * bitmap_width + col ] |= 1<<(row&7);
218 }
219 else {
220 bitmap[ (row/8) * bitmap_width + col ] &= ~ 1<<(row&7);
221 }
222 if(bit) {
223 bit--;
224 }
225 else {
226 bit = 7;
227 byte++;
228 }
229 }
230 }
231#else
232 /* Now convert the bitmap into an array with 1 byte per pixel,
233 exactly the size of the image */
234 for(row = 0;row < bitmap_height;row++) {
235 for(col = 0;col < bitmap_width;col++) {
236 if(bmp[(bitmap_height - row) * PaddedWidth]) {
237 bitmap[ (row/8) * bitmap_width + col ] |= 1<<(row&7);
238 }
239 else {
240 bitmap[ (row/8) * bitmap_width + col ] &= ~ 1<<(row&7);
241 }
242 }
243 }
244
245#endif
246 }
247 return 0; /* success */
248}
249
250#ifdef STANDALONE
251
252/*********************************************************************
253** read_next_converted_byte()
254**
255** Reads the next 6-pixel chunk from the 1-byte-per-pixel array,
256** padding the last byte with zeros if the size is not divisible by 6.
257**********************************************/
258unsigned char read_next_converted_byte(void)
259{
260 unsigned char dest;
261 unsigned int i;
262 static unsigned int row = 0, col = 0;
263
264 dest = 0;
265 for(i = 0;i < 6 && col < bitmap_width;i++,col++)
266 {
267 if(bitmap[row * bitmap_width + col])
268 {
269 dest |= (unsigned char)(1 << (5-i));
270 }
271 }
272
273 if(col >= bitmap_width)
274 {
275 col = 0;
276 row++;
277 }
278
279 return dest;
280}
281
282/*********************************************************************
283** convert_image()
284**
285** Converts the 1-byte-per-pixel array into a 6-pixel-per-byte array,
286** i.e the BMP_FORMAT_VANILLA format.
287**********************************************/
288void convert_image(void)
289{
290 int newsize;
291 unsigned int row, col;
292
293 rounded_width = fh.Width/6 + ((fh.Width%6)?1:0);
294 newsize = rounded_width * fh.Height;
295
296 converted_bmp = (unsigned char *)malloc(newsize);
297
298 for(row = 0;row < fh.Height;row++)
299 {
300 for(col = 0;col < rounded_width;col++)
301 {
302 converted_bmp[row * rounded_width + col] = read_next_converted_byte();
303 }
304 }
305 converted_size = rounded_width * fh.Height;
306}
307
308#define COMPRESSED_ZEROS_AHEAD 0x40
309#define COMPRESSED_ONES_AHEAD 0x80
310
311/*********************************************************************
312** compress_image()
313**
314** Compresses the BMP_FORMAT_VANILLA format with a simple RLE
315** algorithm. The output is in the BMP_FORMAT_RLE format.
316**********************************************/
317void compress_image(void)
318{
319 unsigned int i, j, count;
320 unsigned int index = 0;
321 unsigned char val;
322
323 compressed_bmp = (unsigned char *)malloc(converted_size);
324
325 for(i = 0;i < converted_size;i++)
326 {
327 val = converted_bmp[i];
328
329 if(val == 0|| val == 0x3f)
330 {
331 count = 0;
332 while(count < 0x4000 && (i + count) < converted_size &&
333 converted_bmp[i+count] == val)
334 {
335 count++;
336 }
337 if(count > 2)
338 {
339 compressed_bmp[index++] = (unsigned char)
340 (((val == 0)?COMPRESSED_ZEROS_AHEAD:COMPRESSED_ONES_AHEAD) |
341 (count >> 8));
342 compressed_bmp[index++] = (unsigned char)(count & 0xff);
343 }
344 else
345 {
346 for(j = 0;j < count;j++)
347 {
348 compressed_bmp[index++] = val;
349 }
350 }
351 i += count - 1;
352 }
353 else
354 {
355 compressed_bmp[index++] = val;
356 }
357 }
358
359 compressed_size = index;
360}
361
362/*********************************************************************
363** generate_c_source()
364**
365** Outputs a C source code with the converted/compressed bitmap in
366** an array, accompanied by some #define's
367**********************************************/
368void generate_c_source(char *id, BOOL compressed)
369{
370 FILE *f;
371 unsigned int i;
372 unsigned int size;
373 unsigned char *bmp;
374
375 size = compressed?compressed_size:converted_size;
376 bmp = compressed?compressed_bmp:converted_bmp;
377
378 f = stdout;
379
380 fprintf(f, "#define %s_WIDTH %d\n", id, rounded_width * 6);
381 fprintf(f, "#define %s_HEIGHT %d\n", id, fh.Height);
382 fprintf(f, "#define %s_SIZE %d\n", id, size + 6);
383 if(compressed)
384 {
385 fprintf(f, "#define %s_ORIGINAL_SIZE %d\n", id, converted_size);
386 }
387 fprintf(f, "#define %s_FORMAT %s\n", id,
388 compressed?"BMP_FORMAT_RLE":"BMP_FORMAT_VANILLA");
389 fprintf(f, "\nconst unsigned char bmpdata_%s[] = {", id);
390
391 /* Header */
392 fprintf(f, "\n %s, 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,",
393 compressed?"BMP_FORMAT_RLE":"BMP_FORMAT_VANILLA",
394 size >> 8, size & 0xff, 2, fh.Height, rounded_width * 6);
395
396 for(i = 0;i < size;i++)
397 {
398 if(i % 10 == 0)
399 {
400 fprintf(f, "\n ");
401 }
402 fprintf(f, "0x%02x,", bmp[i]);
403 }
404 fprintf(f, "\n};");
405}
406
407/*********************************************************************
408** generate_asm_source()
409**
410** Outputs an ASM source code with the converted/compressed bitmap in
411** an array, the first 2 bytes describing the X and Y size
412**********************************************/
413void generate_asm_source(char *id, BOOL compressed)
414{
415 FILE *f;
416 unsigned int i;
417 unsigned int size;
418 unsigned char *bmp;
419
420 size = compressed?compressed_size:converted_size;
421 bmp = compressed?compressed_bmp:converted_bmp;
422
423 f = stdout;
424
425 fprintf(f, "bmpdata_%s:\n", id);
426 /* Header */
427 fprintf(f, "\n db %s, %.2xh,%.2xh,%.2xh,%.2xh,%.2xh,",
428 compressed?"1":"0",
429 size >> 8, size & 0xff, 2, fh.Height, rounded_width * 6);
430
431 for(i = 0;i < size;i++)
432 {
433 if(i % 10 == 0)
434 {
435 fprintf(f, "\n db ");
436 }
437 fprintf(f, "%.2xh,", bmp[i]);
438 }
439 fprintf(f, "\n");
440}
441
442void print_usage(void)
443{
444 printf("bmp2mt - Converts BMP files to MT Pro source code format\n");
445 printf("build date: " __DATE__ "\n\n");
446 printf("Usage: %s [-i <id>] [-c] [-a] <bitmap file>\n"
447 "-i <id> Bitmap ID (default is filename without extension)\n"
448 "-c Compress (BMP_FORMAT_RLE)\n"
449 "-f Frexx Format!!!\n"
450 "-a Assembly format source code\n", APPLICATION_NAME);
451}
452
453#pragma argsused
454int main(int argc, char **argv)
455{
456 char *bmp_filename = NULL;
457 char *id = NULL;
458 char errstr[80];
459 int i;
460
461 for(i = 1;i < argc;i++)
462 {
463 if(argv[i][0] == '-')
464 {
465 switch(argv[i][1])
466 {
467 case 'i': /* ID */
468 if(argv[i][2])
469 {
470 id = &argv[i][2];
471 }
472 else if(argc > i+1)
473 {
474 id = argv[i+1];
475 i++;
476 }
477 else
478 {
479 print_usage();
480 exit(1);
481 }
482 break;
483
484 case 'c': /* Compressed */
485 compress = true;
486 break;
487
488 case 'a': /* Assembly */
489 assembly = true;
490 break;
491
492 default:
493 print_usage();
494 exit(1);
495 break;
496 }
497 }
498 else
499 {
500 if(!bmp_filename)
501 {
502 bmp_filename = argv[i];
503 }
504 else
505 {
506 print_usage();
507 exit(1);
508 }
509 }
510 }
511
512 if(!bmp_filename)
513 {
514 print_usage();
515 exit(1);
516 }
517
518 if(!id)
519 {
520 id = strdup(bmp_filename);
521
522 for(i = 0;id[i];i++)
523 {
524 if(id[i] == ' ')
525 {
526 id[i] = '_';
527 }
528 else if(id[i] == '.')
529 {
530 id[i] = '\0';
531 break;
532 }
533 else
534 {
535 id[i] = (char)toupper(id[i]);
536 }
537 }
538 }
539
540 read_bmp_file(bmp_filename);
541 convert_image();
542 if(fh.Width % 6)
543 {
544
545 sprintf(errstr, "warning - width is not divisible by 6 (%d), "
546 "padding with zeros to %d\n", fh.Width, rounded_width*6);
547 print_error(errstr, 0);
548 }
549
550 if(compress)
551 {
552 compress_image();
553 }
554
555 if(assembly)
556 {
557 generate_asm_source(id, compress);
558 }
559 else
560 {
561 generate_c_source(id, compress);
562 }
563 return 0;
564}
565
566#endif