summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2002-05-14 14:40:51 +0000
committerDaniel Stenberg <daniel@haxx.se>2002-05-14 14:40:51 +0000
commit766a0ae4be6d2f91c328f91843ca6dfee63487d4 (patch)
tree9eeaec21e55a4f4589967f0f913571f1896c019a
parent48b3f5157aa9648f6ef9f58803d2b5a37e11d5c3 (diff)
downloadrockbox-766a0ae4be6d2f91c328f91843ca6dfee63487d4.tar.gz
rockbox-766a0ae4be6d2f91c328f91843ca6dfee63487d4.zip
initial BMP image reader attempt, does not work yet
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@579 a1c6a512-1295-4272-9138-f99709370657
-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 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Linus Nielsen Feltzing
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+/*********************************************************************
+ *
+ * Converts BMP files to Rockbox bitmap format
+ *
+ * 1999-05-03 Linus Nielsen Feltzing
+ *
+ **********************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "file.h"
+
+#ifdef __GNUC__
+#define STRUCT_PACKED __attribute__((packed))
+#endif
+
+struct Fileheader
+{
+ unsigned short Type; /* signature - 'BM' */
+ unsigned long Size; /* file size in bytes */
+ unsigned short Reserved1; /* 0 */
+ unsigned short Reserved2; /* 0 */
+ unsigned long OffBits; /* offset to bitmap */
+ unsigned long StructSize; /* size of this struct (40) */
+ unsigned long Width; /* bmap width in pixels */
+ unsigned long Height; /* bmap height in pixels */
+ unsigned short Planes; /* num planes - always 1 */
+ unsigned short BitCount; /* bits per pixel */
+ unsigned long Compression; /* compression flag */
+ unsigned long SizeImage; /* image size in bytes */
+ long XPelsPerMeter; /* horz resolution */
+ long YPelsPerMeter; /* vert resolution */
+ unsigned long ClrUsed; /* 0 -> color table size */
+ unsigned long ClrImportant; /* important color count */
+} STRUCT_PACKED;
+
+struct RGBQUAD
+{
+ unsigned char rgbBlue;
+ unsigned char rgbGreen;
+ unsigned char rgbRed;
+ unsigned char rgbReserved;
+} STRUCT_PACKED;
+
+static struct Fileheader fh;
+static unsigned char* bmp;
+static struct RGBQUAD palette[2]; /* two colors only */
+
+static unsigned int bitmap_width, bitmap_height;
+static unsigned char *bitmap;
+
+#ifdef STANDALONE
+static id_str[256];
+static bool compress = false;
+static bool assembly = false;
+static unsigned char* converted_bmp;
+static unsigned char* compressed_bmp;
+static unsigned int width;
+static unsigned int converted_size;
+static unsigned int compressed_size;
+static unsigned int rounded_width;
+#endif
+
+#define readshort(x) (((x&0xff00)>>8)|((x&0x00ff)<<8))
+#define readlong(x) (((x&0xff000000)>>24)| \
+ ((x&0x00ff0000)>>8) | \
+ ((x&0x0000ff00)<<8) | \
+ ((x&0x000000ff)<<24))
+
+
+/*********************************************************************
+ * read_bmp_file()
+ *
+ * Reads a monochrome BMP file and puts the data in a 1-pixel-per-byte
+ * array. Returns 0 on success.
+ *
+ **********************************************/
+int read_bmp_file(char* filename,
+ int *get_width, /* in pixels */
+ int *get_height, /* in pixels */
+ char *bitmap)
+{
+ long PaddedWidth;
+ int background;
+ int fd = open(filename, O_RDONLY);
+ long size;
+ unsigned int row, col, byte, bit;
+ int l;
+ char *bmp;
+ int width;
+ int height;
+
+ if(fd == -1)
+ {
+ debugf("error - can't open '%s'\n", filename);
+ return 1;
+ }
+ else
+ {
+ if(read(fd, &fh, sizeof(struct Fileheader)) !=
+ sizeof(struct Fileheader))
+ {
+ debugf("error - can't Read Fileheader Stucture\n");
+ return 2;
+ }
+
+ /* Exit if not monochrome */
+ if(readshort(fh.BitCount) > 8)
+ {
+ debugf("error - Bitmap must be less than 8, got %d\n",
+ readshort(fh.BitCount));
+ return 2;
+ }
+
+ /* Exit if too wide */
+ if(readlong(fh.Width) > 112)
+ {
+ debugf("error - Bitmap is too wide (%d pixels, max is 112)\n",
+ readlong(fh.Width));
+ return 3;
+ }
+ debugf("Bitmap is %d pixels wide\n", readlong(fh.Width));
+
+ /* Exit if too high */
+ if(readlong(fh.Height) > 64)
+ {
+ debugf("error - Bitmap is too high (%d pixels, max is 64)\n",
+ readlong(fh.Height));
+ return 4;
+ }
+ debugf("Bitmap is %d pixels heigh\n", readlong(fh.Height));
+
+ for(l=0;l < 2;l++)
+ {
+ if(read(fd, &palette[l],sizeof(struct RGBQUAD)) !=
+ sizeof(struct RGBQUAD))
+ {
+ debugf("error - Can't read bitmap's color palette\n");
+ return 5;
+ }
+ }
+ /* pass the other palettes */
+ lseek(fd, 254*sizeof(struct RGBQUAD), SEEK_CUR);
+
+ /* Try to guess the foreground and background colors.
+ We assume that the foreground color is the darkest. */
+ if(((int)palette[0].rgbRed +
+ (int)palette[0].rgbGreen +
+ (int)palette[0].rgbBlue) >
+ ((int)palette[1].rgbRed +
+ (int)palette[1].rgbGreen +
+ (int)palette[1].rgbBlue))
+ {
+ background = 0;
+ }
+ else
+ {
+ background = 1;
+ }
+
+ width = readlong(fh.Width)*readshort(fh.BitCount);
+ PaddedWidth = ((width+31)&(~0x1f))/8;
+ size = PaddedWidth*readlong(fh.Height);
+
+ bmp = (unsigned char *)malloc(size);
+
+ if(bmp == NULL)
+ {
+ debugf("error - Out of memory\n");
+ return 6;
+ }
+ else
+ {
+ if(read(fd, (unsigned char*)bmp,(long)size) != size) {
+ debugf("error - Can't read image\n");
+ return 7;
+ }
+ }
+
+ bitmap_height = readlong(fh.Height);
+ bitmap_width = readlong(fh.Width);
+
+ *get_width = bitmap_width;
+ *get_height = bitmap_height;
+
+#if 0
+ /* Now convert the bitmap into an array with 1 byte per pixel,
+ exactly the size of the image */
+ for(row = 0;row < bitmap_height;row++) {
+ bit = 7;
+ byte = 0;
+ for(col = 0;col < bitmap_width;col++) {
+ if((bmp[(bitmap_height - row - 1) * PaddedWidth + byte] &
+ (1 << bit))) {
+
+ bitmap[ (row/8) * bitmap_width + col ] |= 1<<(row&7);
+ }
+ else {
+ bitmap[ (row/8) * bitmap_width + col ] &= ~ 1<<(row&7);
+ }
+ if(bit) {
+ bit--;
+ }
+ else {
+ bit = 7;
+ byte++;
+ }
+ }
+ }
+#else
+ /* Now convert the bitmap into an array with 1 byte per pixel,
+ exactly the size of the image */
+ for(row = 0;row < bitmap_height;row++) {
+ for(col = 0;col < bitmap_width;col++) {
+ if(bmp[(bitmap_height - row) * PaddedWidth]) {
+ bitmap[ (row/8) * bitmap_width + col ] |= 1<<(row&7);
+ }
+ else {
+ bitmap[ (row/8) * bitmap_width + col ] &= ~ 1<<(row&7);
+ }
+ }
+ }
+
+#endif
+ }
+ return 0; /* success */
+}
+
+#ifdef STANDALONE
+
+/*********************************************************************
+** read_next_converted_byte()
+**
+** Reads the next 6-pixel chunk from the 1-byte-per-pixel array,
+** padding the last byte with zeros if the size is not divisible by 6.
+**********************************************/
+unsigned char read_next_converted_byte(void)
+{
+ unsigned char dest;
+ unsigned int i;
+ static unsigned int row = 0, col = 0;
+
+ dest = 0;
+ for(i = 0;i < 6 && col < bitmap_width;i++,col++)
+ {
+ if(bitmap[row * bitmap_width + col])
+ {
+ dest |= (unsigned char)(1 << (5-i));
+ }
+ }
+
+ if(col >= bitmap_width)
+ {
+ col = 0;
+ row++;
+ }
+
+ return dest;
+}
+
+/*********************************************************************
+** convert_image()
+**
+** Converts the 1-byte-per-pixel array into a 6-pixel-per-byte array,
+** i.e the BMP_FORMAT_VANILLA format.
+**********************************************/
+void convert_image(void)
+{
+ int newsize;
+ unsigned int row, col;
+
+ rounded_width = fh.Width/6 + ((fh.Width%6)?1:0);
+ newsize = rounded_width * fh.Height;
+
+ converted_bmp = (unsigned char *)malloc(newsize);
+
+ for(row = 0;row < fh.Height;row++)
+ {
+ for(col = 0;col < rounded_width;col++)
+ {
+ converted_bmp[row * rounded_width + col] = read_next_converted_byte();
+ }
+ }
+ converted_size = rounded_width * fh.Height;
+}
+
+#define COMPRESSED_ZEROS_AHEAD 0x40
+#define COMPRESSED_ONES_AHEAD 0x80
+
+/*********************************************************************
+** compress_image()
+**
+** Compresses the BMP_FORMAT_VANILLA format with a simple RLE
+** algorithm. The output is in the BMP_FORMAT_RLE format.
+**********************************************/
+void compress_image(void)
+{
+ unsigned int i, j, count;
+ unsigned int index = 0;
+ unsigned char val;
+
+ compressed_bmp = (unsigned char *)malloc(converted_size);
+
+ for(i = 0;i < converted_size;i++)
+ {
+ val = converted_bmp[i];
+
+ if(val == 0|| val == 0x3f)
+ {
+ count = 0;
+ while(count < 0x4000 && (i + count) < converted_size &&
+ converted_bmp[i+count] == val)
+ {
+ count++;
+ }
+ if(count > 2)
+ {
+ compressed_bmp[index++] = (unsigned char)
+ (((val == 0)?COMPRESSED_ZEROS_AHEAD:COMPRESSED_ONES_AHEAD) |
+ (count >> 8));
+ compressed_bmp[index++] = (unsigned char)(count & 0xff);
+ }
+ else
+ {
+ for(j = 0;j < count;j++)
+ {
+ compressed_bmp[index++] = val;
+ }
+ }
+ i += count - 1;
+ }
+ else
+ {
+ compressed_bmp[index++] = val;
+ }
+ }
+
+ compressed_size = index;
+}
+
+/*********************************************************************
+** generate_c_source()
+**
+** Outputs a C source code with the converted/compressed bitmap in
+** an array, accompanied by some #define's
+**********************************************/
+void generate_c_source(char *id, BOOL compressed)
+{
+ FILE *f;
+ unsigned int i;
+ unsigned int size;
+ unsigned char *bmp;
+
+ size = compressed?compressed_size:converted_size;
+ bmp = compressed?compressed_bmp:converted_bmp;
+
+ f = stdout;
+
+ fprintf(f, "#define %s_WIDTH %d\n", id, rounded_width * 6);
+ fprintf(f, "#define %s_HEIGHT %d\n", id, fh.Height);
+ fprintf(f, "#define %s_SIZE %d\n", id, size + 6);
+ if(compressed)
+ {
+ fprintf(f, "#define %s_ORIGINAL_SIZE %d\n", id, converted_size);
+ }
+ fprintf(f, "#define %s_FORMAT %s\n", id,
+ compressed?"BMP_FORMAT_RLE":"BMP_FORMAT_VANILLA");
+ fprintf(f, "\nconst unsigned char bmpdata_%s[] = {", id);
+
+ /* Header */
+ fprintf(f, "\n %s, 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,",
+ compressed?"BMP_FORMAT_RLE":"BMP_FORMAT_VANILLA",
+ size >> 8, size & 0xff, 2, fh.Height, rounded_width * 6);
+
+ for(i = 0;i < size;i++)
+ {
+ if(i % 10 == 0)
+ {
+ fprintf(f, "\n ");
+ }
+ fprintf(f, "0x%02x,", bmp[i]);
+ }
+ fprintf(f, "\n};");
+}
+
+/*********************************************************************
+** generate_asm_source()
+**
+** Outputs an ASM source code with the converted/compressed bitmap in
+** an array, the first 2 bytes describing the X and Y size
+**********************************************/
+void generate_asm_source(char *id, BOOL compressed)
+{
+ FILE *f;
+ unsigned int i;
+ unsigned int size;
+ unsigned char *bmp;
+
+ size = compressed?compressed_size:converted_size;
+ bmp = compressed?compressed_bmp:converted_bmp;
+
+ f = stdout;
+
+ fprintf(f, "bmpdata_%s:\n", id);
+ /* Header */
+ fprintf(f, "\n db %s, %.2xh,%.2xh,%.2xh,%.2xh,%.2xh,",
+ compressed?"1":"0",
+ size >> 8, size & 0xff, 2, fh.Height, rounded_width * 6);
+
+ for(i = 0;i < size;i++)
+ {
+ if(i % 10 == 0)
+ {
+ fprintf(f, "\n db ");
+ }
+ fprintf(f, "%.2xh,", bmp[i]);
+ }
+ fprintf(f, "\n");
+}
+
+void print_usage(void)
+{
+ printf("bmp2mt - Converts BMP files to MT Pro source code format\n");
+ printf("build date: " __DATE__ "\n\n");
+ printf("Usage: %s [-i <id>] [-c] [-a] <bitmap file>\n"
+ "-i <id> Bitmap ID (default is filename without extension)\n"
+ "-c Compress (BMP_FORMAT_RLE)\n"
+ "-f Frexx Format!!!\n"
+ "-a Assembly format source code\n", APPLICATION_NAME);
+}
+
+#pragma argsused
+int main(int argc, char **argv)
+{
+ char *bmp_filename = NULL;
+ char *id = NULL;
+ char errstr[80];
+ int i;
+
+ for(i = 1;i < argc;i++)
+ {
+ if(argv[i][0] == '-')
+ {
+ switch(argv[i][1])
+ {
+ case 'i': /* ID */
+ if(argv[i][2])
+ {
+ id = &argv[i][2];
+ }
+ else if(argc > i+1)
+ {
+ id = argv[i+1];
+ i++;
+ }
+ else
+ {
+ print_usage();
+ exit(1);
+ }
+ break;
+
+ case 'c': /* Compressed */
+ compress = true;
+ break;
+
+ case 'a': /* Assembly */
+ assembly = true;
+ break;
+
+ default:
+ print_usage();
+ exit(1);
+ break;
+ }
+ }
+ else
+ {
+ if(!bmp_filename)
+ {
+ bmp_filename = argv[i];
+ }
+ else
+ {
+ print_usage();
+ exit(1);
+ }
+ }
+ }
+
+ if(!bmp_filename)
+ {
+ print_usage();
+ exit(1);
+ }
+
+ if(!id)
+ {
+ id = strdup(bmp_filename);
+
+ for(i = 0;id[i];i++)
+ {
+ if(id[i] == ' ')
+ {
+ id[i] = '_';
+ }
+ else if(id[i] == '.')
+ {
+ id[i] = '\0';
+ break;
+ }
+ else
+ {
+ id[i] = (char)toupper(id[i]);
+ }
+ }
+ }
+
+ read_bmp_file(bmp_filename);
+ convert_image();
+ if(fh.Width % 6)
+ {
+
+ sprintf(errstr, "warning - width is not divisible by 6 (%d), "
+ "padding with zeros to %d\n", fh.Width, rounded_width*6);
+ print_error(errstr, 0);
+ }
+
+ if(compress)
+ {
+ compress_image();
+ }
+
+ if(assembly)
+ {
+ generate_asm_source(id, compress);
+ }
+ else
+ {
+ generate_c_source(id, compress);
+ }
+ return 0;
+}
+
+#endif