tool we use on the web site to produce an image of a font
[kugel-rb.git] / tools / bmp2rb.c
blob18b37f9cf65d00f4cdd219198242d93f89c7eb73
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 unsigned int row, col;
108 int l;
109 unsigned char *bmp;
110 int width;
111 int depth;
113 if(fd == -1)
115 debugf("error - can't open '%s'\n", filename);
116 return 1;
118 else
120 if(read(fd, &fh, sizeof(struct Fileheader)) !=
121 sizeof(struct Fileheader))
123 debugf("error - can't Read Fileheader Stucture\n");
124 close(fd);
125 return 2;
128 /* Exit if more than 8 bits */
129 depth = readshort(&fh.BitCount);
130 if(depth > 8)
132 debugf("error - Bitmap uses more than 8 bit depth, got %d\n",
133 depth);
134 close(fd);
135 return 2;
138 /* Exit if too wide */
139 if(readlong(&fh.Width) > 112)
141 debugf("error - Bitmap is too wide (%d pixels, max is 112)\n",
142 readlong(&fh.Width));
143 close(fd);
144 return 3;
147 /* Exit if too high */
148 if(readlong(&fh.Height) > 64)
150 debugf("error - Bitmap is too high (%d pixels, max is 64)\n",
151 readlong(&fh.Height));
152 close(fd);
153 return 4;
156 for(l=0;l < 2;l++)
158 if(read(fd, &palette[l],sizeof(struct RGBQUAD)) !=
159 sizeof(struct RGBQUAD))
161 debugf("error - Can't read bitmap's color palette\n");
162 close(fd);
163 return 5;
166 if(depth == 8 ) {
167 /* pass the other palettes */
168 lseek(fd, 254*sizeof(struct RGBQUAD), SEEK_CUR);
171 /* Try to guess the foreground and background colors.
172 We assume that the foreground color is the darkest. */
173 if(((int)palette[0].rgbRed +
174 (int)palette[0].rgbGreen +
175 (int)palette[0].rgbBlue) >
176 ((int)palette[1].rgbRed +
177 (int)palette[1].rgbGreen +
178 (int)palette[1].rgbBlue))
180 background = 0;
182 else
184 background = 1;
187 width = readlong(&fh.Width);
189 if(depth == 8)
190 PaddedWidth = ((width+3)&(~0x3)); /* aligned 4-bytes boundaries */
191 else
192 PaddedWidth = ((width+31)&(~0x1f))/8;
194 size = PaddedWidth*readlong(&fh.Height);
196 bmp = (unsigned char *)malloc(size);
197 *bitmap = (unsigned char *)malloc(size);
199 if(bmp == NULL)
201 debugf("error - Out of memory\n");
202 close(fd);
203 return 6;
205 else
207 if(read(fd, (unsigned char*)bmp,(long)size) != size) {
208 debugf("error - Can't read image\n");
209 close(fd);
210 return 7;
214 bitmap_height = readlong(&fh.Height);
215 bitmap_width = readlong(&fh.Width);
217 *get_width = bitmap_width;
218 *get_height = bitmap_height;
220 if(depth == 8)
222 /* Now convert the bitmap into an array with 1 byte per pixel,
223 exactly the size of the image */
224 for(row = 0;row < bitmap_height;row++) {
225 for(col = 0;col < bitmap_width;col++) {
226 if(bmp[(bitmap_height-1 -row) * PaddedWidth + col]) {
227 (*bitmap)[ (row/8) * bitmap_width + col ] &=
228 ~ (1<<(row&7));
230 else {
231 (*bitmap)[ (row/8) * bitmap_width + col ] |=
232 1<<(row&7);
237 else
239 int bit;
240 int byte;
241 /* monocrome BMP conversion uses 8 pixels per byte */
242 for(row = 0; row < bitmap_height; row++) {
243 bit = 7;
244 byte = 0;
245 for(col = 0;col < bitmap_width;col++) {
246 if((bmp[(bitmap_height - row - 1) * PaddedWidth + byte] &
247 (1 << bit))) {
248 (*bitmap)[(row/8) * bitmap_width + col ] &=
249 ~(1<<(row&7));
251 else {
252 (*bitmap)[(row/8) * bitmap_width + col ] |=
253 1<<(row&7);
255 if(bit) {
256 bit--;
258 else {
259 bit = 7;
260 byte++;
266 free(bmp);
269 close(fd);
270 return 0; /* success */
273 /*********************************************************************
274 ** generate_c_source()
276 ** Outputs a C source code with the bitmap in an array, accompanied by
277 ** some #define's
278 **********************************************************************/
279 void generate_c_source(char *id, int width, int height, unsigned char *bitmap)
281 FILE *f;
282 unsigned int i, a, eline;
284 f = stdout;
286 if(!id || !id[0])
287 id = "bitmap";
289 fprintf(f,
290 "#define BMPHEIGHT_%s %d"
291 "\n#define BMPWIDTH_%s %d"
292 "\nconst unsigned char %s[] = {\n",
293 id, height, id, width, id );
295 for(i=0, eline=0; i< height; i+=8, eline++) {
296 for (a=0; a<width; a++)
297 fprintf(f, "0x%02x,%c", bitmap[eline*width + a],
298 (a+1)%13?' ':'\n');
299 fprintf(f, "\n");
303 fprintf(f, "\n};\n");
307 /*********************************************************************
308 ** generate_ascii()
310 ** Outputs an ascii picture of the bitmap
311 **********************************************************************/
312 void generate_ascii(int width, int height, unsigned char *bitmap)
314 FILE *f;
315 unsigned int i, eline;
317 f = stdout;
319 /* for screen output debugging */
320 for(i=0, eline=0; i< height; i+=8, eline++) {
321 unsigned int x, y;
322 for(y=0; y<8 && (i+y < height); y++) {
323 for(x=0; x < width; x++) {
325 if(bitmap[eline*width + x] & (1<<y)) {
326 fprintf(f, "*");
328 else
329 fprintf(f, " ");
331 fprintf(f, "\n");
336 void print_usage(void)
338 printf("Usage: %s [-i <id>] [-a] <bitmap file>\n"
339 "\t-i <id> Bitmap name (default is filename without extension)\n"
340 "\t-a Show ascii picture of bitmap\n",
341 APPLICATION_NAME);
342 printf("build date: " __DATE__ "\n\n");
345 int main(int argc, char **argv)
347 char *bmp_filename = NULL;
348 char *id = NULL;
349 int i;
350 int height, width;
351 int ascii = false;
352 char* bitmap = NULL;
355 for(i = 1;i < argc;i++)
357 if(argv[i][0] == '-')
359 switch(argv[i][1])
361 case 'i': /* ID */
362 if(argv[i][2])
364 id = &argv[i][2];
366 else if(argc > i+1)
368 id = argv[i+1];
369 i++;
371 else
373 print_usage();
374 exit(1);
376 break;
378 case 'a': /* Assembly */
379 ascii = true;
380 break;
382 default:
383 print_usage();
384 exit(1);
385 break;
388 else
390 if(!bmp_filename)
392 bmp_filename = argv[i];
394 else
396 print_usage();
397 exit(1);
402 if (!bmp_filename)
404 print_usage();
405 exit(1);
408 if (!id)
410 char *ptr=strrchr(bmp_filename, '/');
411 if(ptr)
412 ptr++;
413 else
414 ptr = bmp_filename;
415 id = strdup(ptr);
416 for (i = 0; id[i]; i++)
417 if (id[i] == '.')
418 id[i] = '\0';
421 if (read_bmp_file(bmp_filename, &width, &height, &bitmap))
422 return 0;
424 if (ascii)
425 generate_ascii(width, height, bitmap);
426 else
427 generate_c_source(id, width, height, bitmap);
429 return 0;