Corrected copyright year
[kugel-rb.git] / tools / bmp2rb.c
blobf874fed677f117c32f533e6f8264789c802d2fbe
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 /*********************************************************************
21 * Converts BMP files to Rockbox bitmap format
23 * 1999-05-03 Linus Nielsen Feltzing
25 **********************************************/
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdbool.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
36 #define debugf printf
38 #ifdef __GNUC__
39 #define STRUCT_PACKED __attribute__((packed))
40 #else
41 #define STRUCT_PACKED
42 #pragma pack (push, 2)
43 #endif
45 struct Fileheader
47 unsigned short Type; /* signature - 'BM' */
48 unsigned long Size; /* file size in bytes */
49 unsigned short Reserved1; /* 0 */
50 unsigned short Reserved2; /* 0 */
51 unsigned long OffBits; /* offset to bitmap */
52 unsigned long StructSize; /* size of this struct (40) */
53 unsigned long Width; /* bmap width in pixels */
54 unsigned long Height; /* bmap height in pixels */
55 unsigned short Planes; /* num planes - always 1 */
56 unsigned short BitCount; /* bits per pixel */
57 unsigned long Compression; /* compression flag */
58 unsigned long SizeImage; /* image size in bytes */
59 long XPelsPerMeter; /* horz resolution */
60 long YPelsPerMeter; /* vert resolution */
61 unsigned long ClrUsed; /* 0 -> color table size */
62 unsigned long ClrImportant; /* important color count */
63 } STRUCT_PACKED;
65 struct RGBQUAD
67 unsigned char rgbBlue;
68 unsigned char rgbGreen;
69 unsigned char rgbRed;
70 unsigned char rgbReserved;
71 } STRUCT_PACKED;
74 short readshort(void* value)
76 unsigned char* bytes = (unsigned char*) value;
77 return bytes[0] | (bytes[1] << 8);
80 int readlong(void* value)
82 unsigned char* bytes = (unsigned char*) value;
83 return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
86 /*********************************************************************
87 * read_bmp_file()
89 * Reads a 8bit BMP file and puts the data in a 1-pixel-per-byte
90 * array. Returns 0 on success.
92 *********************************************************************/
93 int read_bmp_file(char* filename,
94 int *get_width, /* in pixels */
95 int *get_height, /* in pixels */
96 char **bitmap)
98 struct Fileheader fh;
99 struct RGBQUAD palette[2]; /* two colors only */
101 unsigned int bitmap_width, bitmap_height;
103 long PaddedWidth;
104 int background;
105 int fd = open(filename, O_RDONLY);
106 long size;
107 long allocsize;
108 unsigned int row, col;
109 int l;
110 unsigned char *bmp;
111 int width;
112 int height;
113 int depth;
115 if(fd == -1)
117 debugf("error - can't open '%s'\n", filename);
118 return 1;
120 else
122 if(read(fd, &fh, sizeof(struct Fileheader)) !=
123 sizeof(struct Fileheader))
125 debugf("error - can't Read Fileheader Stucture\n");
126 close(fd);
127 return 2;
130 /* Exit if more than 8 bits */
131 depth = readshort(&fh.BitCount);
132 if(depth > 8)
134 debugf("error - Bitmap uses more than 8 bit depth, got %d\n",
135 depth);
136 close(fd);
137 return 2;
140 /* Exit if too wide */
141 if(readlong(&fh.Width) > 160)
143 debugf("error - Bitmap is too wide for iRiver models (%d pixels, max is 160)\n",
144 readlong(&fh.Width));
145 return 3;
147 if(readlong(&fh.Width) > 112)
149 debugf("info - Bitmap is too wide for Archos models (%d pixels, max is 112)\n",
150 readlong(&fh.Width));
153 /* Exit if too high */
154 if(readlong(&fh.Height) > 128)
156 debugf("error - Bitmap is too high for iRiver models (%d pixels, max is 128)\n",
157 readlong(&fh.Height));
158 return 4;
160 if(readlong(&fh.Height) > 64)
162 debugf("info - Bitmap is too high for Archos models (%d pixels, max is 64)\n",
163 readlong(&fh.Height));
166 for(l=0;l < 2;l++)
168 if(read(fd, &palette[l],sizeof(struct RGBQUAD)) !=
169 sizeof(struct RGBQUAD))
171 debugf("error - Can't read bitmap's color palette\n");
172 close(fd);
173 return 5;
176 if(depth == 8 ) {
177 /* pass the other palettes */
178 lseek(fd, 254*sizeof(struct RGBQUAD), SEEK_CUR);
181 /* Try to guess the foreground and background colors.
182 We assume that the foreground color is the darkest. */
183 if(((int)palette[0].rgbRed +
184 (int)palette[0].rgbGreen +
185 (int)palette[0].rgbBlue) >
186 ((int)palette[1].rgbRed +
187 (int)palette[1].rgbGreen +
188 (int)palette[1].rgbBlue))
190 background = 0;
192 else
194 background = 1;
197 width = readlong(&fh.Width);
199 if(depth == 8)
200 PaddedWidth = ((width+3)&(~0x3)); /* aligned 4-bytes boundaries */
201 else
202 PaddedWidth = ((width+31)&(~0x1f))/8;
204 height = readlong(&fh.Height);
206 allocsize = size = PaddedWidth*height; /* read this many bytes */
207 bmp = (unsigned char *)malloc(size);
209 if(height%8) {
210 /* not even 8 bytes, add up to a full 8 pixels boundary */
211 height += 8-(height%8);
212 allocsize = PaddedWidth*height; /* bytes to alloc */
215 *bitmap = (unsigned char *)malloc(allocsize);
217 if(bmp == NULL)
219 debugf("error - Out of memory\n");
220 close(fd);
221 return 6;
223 else
225 if(read(fd, (unsigned char*)bmp,(long)size) != size) {
226 debugf("error - Can't read image\n");
227 close(fd);
228 return 7;
232 bitmap_height = readlong(&fh.Height);
233 bitmap_width = readlong(&fh.Width);
235 *get_width = bitmap_width;
236 *get_height = bitmap_height;
238 if(depth == 8)
240 /* Now convert the bitmap into an array with 1 byte per pixel,
241 exactly the size of the image */
242 for(row = 0;row < bitmap_height;row++) {
243 for(col = 0;col < bitmap_width;col++) {
244 if(bmp[(bitmap_height-1 -row) * PaddedWidth + col]) {
245 (*bitmap)[ (row/8) * bitmap_width + col ] &=
246 ~ (1<<(row&7));
248 else {
249 (*bitmap)[ (row/8) * bitmap_width + col ] |=
250 1<<(row&7);
255 else
257 int bit;
258 int byte;
259 /* monocrome BMP conversion uses 8 pixels per byte */
260 for(row = 0; row < bitmap_height; row++) {
261 bit = 7;
262 byte = 0;
263 for(col = 0;col < bitmap_width;col++) {
264 if((bmp[(bitmap_height - row - 1) * PaddedWidth + byte] &
265 (1 << bit))) {
266 (*bitmap)[(row/8) * bitmap_width + col ] &=
267 ~(1<<(row&7));
269 else {
270 (*bitmap)[(row/8) * bitmap_width + col ] |=
271 1<<(row&7);
273 if(bit) {
274 bit--;
276 else {
277 bit = 7;
278 byte++;
284 free(bmp);
287 close(fd);
288 return 0; /* success */
291 /*********************************************************************
292 ** generate_c_source()
294 ** Outputs a C source code with the bitmap in an array, accompanied by
295 ** some #define's
296 **********************************************************************/
297 void generate_c_source(char *id, int width, int height, unsigned char *bitmap)
299 FILE *f;
300 unsigned int i, a, eline;
302 f = stdout;
304 if(!id || !id[0])
305 id = "bitmap";
307 fprintf(f,
308 "#define BMPHEIGHT_%s %d"
309 "\n#define BMPWIDTH_%s %d"
310 "\nconst unsigned char %s[] = {\n",
311 id, height, id, width, id );
313 for(i=0, eline=0; i< height; i+=8, eline++) {
314 for (a=0; a<width; a++)
315 fprintf(f, "0x%02x,%c", bitmap[eline*width + a],
316 (a+1)%13?' ':'\n');
317 fprintf(f, "\n");
321 fprintf(f, "\n};\n");
325 /*********************************************************************
326 ** generate_ascii()
328 ** Outputs an ascii picture of the bitmap
329 **********************************************************************/
330 void generate_ascii(int width, int height, unsigned char *bitmap)
332 FILE *f;
333 unsigned int i, eline;
335 f = stdout;
337 /* for screen output debugging */
338 for(i=0, eline=0; i< height; i+=8, eline++) {
339 unsigned int x, y;
340 for(y=0; y<8 && (i+y < height); y++) {
341 for(x=0; x < width; x++) {
343 if(bitmap[eline*width + x] & (1<<y)) {
344 fprintf(f, "*");
346 else
347 fprintf(f, " ");
349 fprintf(f, "\n");
354 void print_usage(void)
356 printf("Usage: %s [-i <id>] [-a] <bitmap file>\n"
357 "\t-i <id> Bitmap name (default is filename without extension)\n"
358 "\t-a Show ascii picture of bitmap\n",
359 APPLICATION_NAME);
360 printf("build date: " __DATE__ "\n\n");
363 int main(int argc, char **argv)
365 char *bmp_filename = NULL;
366 char *id = NULL;
367 int i;
368 int height, width;
369 int ascii = false;
370 char* bitmap = NULL;
373 for(i = 1;i < argc;i++)
375 if(argv[i][0] == '-')
377 switch(argv[i][1])
379 case 'i': /* ID */
380 if(argv[i][2])
382 id = &argv[i][2];
384 else if(argc > i+1)
386 id = argv[i+1];
387 i++;
389 else
391 print_usage();
392 exit(1);
394 break;
396 case 'a': /* Assembly */
397 ascii = true;
398 break;
400 default:
401 print_usage();
402 exit(1);
403 break;
406 else
408 if(!bmp_filename)
410 bmp_filename = argv[i];
412 else
414 print_usage();
415 exit(1);
420 if (!bmp_filename)
422 print_usage();
423 exit(1);
426 if (!id)
428 char *ptr=strrchr(bmp_filename, '/');
429 if(ptr)
430 ptr++;
431 else
432 ptr = bmp_filename;
433 id = strdup(ptr);
434 for (i = 0; id[i]; i++)
435 if (id[i] == '.')
436 id[i] = '\0';
439 if (read_bmp_file(bmp_filename, &width, &height, &bitmap))
440 return 0;
442 if (ascii)
443 generate_ascii(width, height, bitmap);
444 else
445 generate_c_source(id, width, height, bitmap);
447 return 0;