/* bmp2c.c - Don Yang (uguu.org) Convert Windows BMP to C arrays. Assume Intel byte order. Assume sizeof(int) = 4. Assume no write error. LCLint 2.5m: 107 errors -boolops +charint -compdef +matchanyintegral -modobserver -predboolint -retvalint -shiftsigned -usedef 11/18/00 */ #include #include #include #include #define MAX_STRING_LEN 256 #define DEFAULT_C_SUFFIX "c" #define DEFAULT_H_SUFFIX "h" static int CheckName(char *n); static int CheckHeader(FILE *bmp, int *width, int *height, int *bpp); static int Grayscale(unsigned char *palette, int size); static int LoadPalette(FILE *bmp, unsigned char *palette, int *size); static int Translate1(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n); static int Translate4(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n); static int Translate8(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n); static int Translate8g(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n); static int Translate24(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n); static void WritePHeader(FILE *h, int sw, int sh, int size, char *n); static void WritePalette(FILE *c, unsigned char *palette, int size, char *n); static int ReadError(void); /******************************************************************** main */ int main(int argc, char **argv) { char bmpname[MAX_STRING_LEN], cname[MAX_STRING_LEN], hname[MAX_STRING_LEN]; char csuffix[MAX_STRING_LEN] = DEFAULT_C_SUFFIX; char hsuffix[MAX_STRING_LEN] = DEFAULT_H_SUFFIX; char prefix[MAX_STRING_LEN]; char name[MAX_STRING_LEN]; FILE *bmp, *c, *h, *p; int i, j, width, height, bpp; if( argc < 2 ) { puts( "bmp2c 1.0 (11/18/00) - Don Yang (uguu.org)\n\n" "bmp2c [options] \n\n" "Options:\n" " -c Set output source file suffix to xxx\n" " -h Set output header file suffix to yyy\n" " -p
Prepend contents of
to output source.\n"); return 0; } prefix[0] = 0; for(i = 1; i < argc; i++) { if( argv[i][0] == '-' ) { if( i + 1 >= argc ) { puts( "Invalid options.\n" "Run without arguments for list of options."); return 1; } switch( tolower(argv[i][1]) ) { case 'c': strcpy(csuffix, argv[++i]); break; case 'h': strcpy(hsuffix, argv[++i]); break; case 'p': strcpy(prefix, argv[++i]); break; default: printf( "Unrecognized option: %s\n" "Run without arguments for list of options.\n", argv[i]); return 1; } continue; } strncpy(bmpname, argv[i], MAX_STRING_LEN); if( (bmp = fopen(bmpname, "rb")) == NULL ) { strncat(bmpname, ".bmp", MAX_STRING_LEN); if( (bmp = fopen(bmpname, "rb")) == NULL ) { printf("Can not open %s or %s.\n", argv[i], bmpname); return 1; } } printf("%s: ", bmpname); if( CheckHeader(bmp, &width, &height, &bpp) ) { fclose(bmp); return 1; } strncpy(name, bmpname, MAX_STRING_LEN); for(j = strlen(name) - 1; j > 0 && name[j] != '.'; j--); if( j ) name[j] = 0; strcpy(cname, name); strcat(cname, "."); strcat(cname, csuffix); strcpy(hname, name); strcat(hname, "."); strcat(hname, hsuffix); if( (c = fopen(cname, "wt+")) == NULL ) { fclose(bmp); printf("Can not create %s.\n", cname); return 1; } if( (h = fopen(hname, "wt+")) == NULL ) { fclose(bmp); fclose(c); remove(cname); printf("Can not create %s.\n", hname); return 1; } if( prefix[0] ) { if( (p = fopen(prefix, "rt")) == NULL ) { fclose(bmp); fclose(c); remove(cname); fclose(h); remove(hname); printf("Can not open %s.\n", prefix); return 1; } fseek(p, 0, SEEK_SET); for(j = fgetc(p); !feof(p); j = fgetc(p)) fputc(j, c); fclose(p); } switch( bpp ) { case 1: j = Translate1(bmp, c, h, width, height, name); break; case 4: j = Translate4(bmp, c, h, width, height, name); break; case 8: j = Translate8(bmp, c, h, width, height, name); break; default: j = Translate24(bmp, c, h, width, height, name); break; } fclose(c); fclose(h); fclose(bmp); if( j ) return 1; if( CheckName(name) ) printf(" (warning: bad identifier name \"%s\")\n", name); else putchar('\n'); } return 0; } /* main() */ /*************************************************************** CheckName */ static int CheckName(char *n) { int i; for(i = 0; n[i]; i++) { if( !isalnum(n[i]) && n[i] != '_' ) return 1; } return 0; } /* CheckName() */ /************************************************************* CheckHeader */ static int CheckHeader(FILE *bmp, int *width, int *height, int *bpp) { static unsigned char hd[54]; fseek(bmp, 0, SEEK_SET); if( fread(hd, 54, 1, bmp) != 1 ) return ReadError(); if( hd[0] != 'B' || hd[1] != 'M' ) { puts("Invalid signature."); return 1; } *bpp = (int)(hd[28] | (hd[29]<<8)); *width = (int)(hd[18] | (hd[19]<<8) | (hd[20]<<16) | (hd[21]<<24)); *height = (int)(hd[22] | (hd[23]<<8) | (hd[24]<<16) | (hd[25]<<24)); if( (hd[26] != 1) || hd[27] || hd[30] || hd[31] || hd[32] || hd[33] || (*bpp != 1 && *bpp != 4 && *bpp != 8 && *bpp != 24) ) { puts("Unsupported format."); return 1; } return 0; } /* CheckHeader() */ /*************************************************************** Grayscale */ static int Grayscale(unsigned char *palette, int size) { int i; if( size < 256 ) return 0; for(i = 0; i < 256; i++) { if( (palette[i * 4] != palette[i * 4 + 1]) || (palette[i * 4] != palette[i * 4 + 2]) || (palette[i * 4] != (unsigned char)i) ) return 0; } return 1; } /* Grayscale() */ /************************************************************* LoadPalette */ static int LoadPalette(FILE *bmp, unsigned char *palette, int *size) { fseek(bmp, 46, SEEK_SET); if( fread(size, 4, 1, bmp) != 1 ) return ReadError(); fseek(bmp, 54, SEEK_SET); if( fread(palette, 4, *size, bmp) != (size_t)*size ) return ReadError(); return 0; } /* LoadPalette() */ /************************************************************** Translate1 */ static int Translate1(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n) { static unsigned char palette[1024]; static char string[32]; int start, colors, bps, pixel, x, y; if( LoadPalette(bmp, palette, &colors) ) return 1; fseek(bmp, 10, SEEK_SET); if( fread(&start, 4, 1, bmp) != 1 ) return ReadError(); WritePHeader(h, sw, sh, colors, n); WritePalette(c, palette, colors, n); fprintf(c, "unsigned char i_%s[%d] = {\n", n, sw * sh + 1); for(bps = sw / 8; bps & 3; bps++); for(y = 0; y < sh; y++) { fseek(bmp, start + (sh - y - 1) * bps, SEEK_SET); fputs(" ", c); for(x = 0; x < sw; x += 8) { if( (pixel = fgetc(bmp)) < 0 ) return ReadError(); sprintf(string, "%d,%d,%d,%d,%d,%d,%d,%d,", ((pixel >> 7) & 1), ((pixel >> 6) & 1), ((pixel >> 5) & 1), ((pixel >> 4) & 1), ((pixel >> 3) & 1), ((pixel >> 2) & 1), ((pixel >> 1) & 1), ( pixel & 1) ); if( sw - x < 8 ) string[(sw - x) * 2] = 0; fputs(string, c); } fputs((y + 1 == sh) ? " 0x0};\n" : "\n", c); } printf("%d x %d x 1", sw, sh); return 0; } /* Translate1() */ /************************************************************** Translate4 */ static int Translate4(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n) { static unsigned char palette[1024]; static char string[64]; unsigned int pixel; int start, colors, bps, x, y; if( LoadPalette(bmp, palette, &colors) ) return 1; fseek(bmp, 10, SEEK_SET); if( fread(&start, 4, 1, bmp) != 1 ) return ReadError(); WritePHeader(h, sw, sh, colors, n); WritePalette(c, palette, colors, n); fprintf(c, "unsigned char i_%s[%d] = {\n", n, sw * sh + 1); for(bps = sw / 2; bps & 3; bps++); for(y = 0; y < sh; y++) { fseek(bmp, start + (sh - y - 1) * bps, SEEK_SET); fputs(" ", c); for(x = 0; x < sw; x += 8) { if( fread(&pixel, 4, 1, bmp) != 1 ) return ReadError(); sprintf(string, "%2u,%2u,%2u,%2u,%2u,%2u,%2u,%2u,", ((pixel >> 4) & 15), ( pixel & 15), ((pixel >> 12) & 15), ((pixel >> 8) & 15), ((pixel >> 20) & 15), ((pixel >> 16) & 15), ((pixel >> 28) & 15), ((pixel >> 24) & 15) ); if( sw - x < 8 ) string[(sw - x) * 3] = 0; fputs(string, c); } fputs((y + 1 == sh) ? " 0x0};\n" : "\n", c); } printf("%d x %d x 4", sw, sh); return 0; } /* Translate4() */ /************************************************************** Translate8 */ static int Translate8(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n) { static unsigned char palette[1024]; static char string[32]; unsigned int pixel; int start, colors, bps, x, y; if( LoadPalette(bmp, palette, &colors) ) return 1; if( Grayscale(palette, colors) ) return Translate8g(bmp, c, h, sw, sh, n); fseek(bmp, 10, SEEK_SET); if( fread(&start, 4, 1, bmp) != 1 ) return ReadError(); WritePHeader(h, sw, sh, colors, n); WritePalette(c, palette, colors, n); fprintf(c, "unsigned char i_%s[%d] = {\n", n, sw * sh + 1); for(bps = sw; bps & 3; bps++); for(y = 0; y < sh; y++) { fseek(bmp, start + (sh - y - 1) * bps, SEEK_SET); fputs(" ", c); for(x = 0; x < sw; x += 4 ) { if( fread(&pixel, 4, 1, bmp) != 1 ) return ReadError(); sprintf(string, "%3u,%3u,%3u,%3u,", ( pixel & 255), ((pixel >> 8) & 255), ((pixel >> 16) & 255), ((pixel >> 24) & 255)); if( sw - x < 4 ) string[(sw - x) * 4] = 0; fputs(string, c); } fputs((y + 1 == sh) ? " 0x0};\n" : "\n", c); } printf("%d x %d x 8", sw, sh); return 0; } /* Translate8() */ /************************************************************* Translate8g */ static int Translate8g(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n) { static char string[32]; unsigned int pixel; int start, bps, x, y; fseek(bmp, 10, SEEK_SET); if( fread(&start, 4, 1, bmp) != 1 ) return ReadError(); fprintf(h, "/*\n" " r = i_%s[(y * %d + x)]\n" " g = i_%s[(y * %d + x)]\n" " b = i_%s[(y * %d + x)]\n" "*/\n" "#define w_%s %d\n" "#define h_%s %d\n" "#define s_%s %d\n" "extern unsigned char i_%s[%d];\n", n, sw, n, sw, n, sw, n, sw, n, sh, n, sw * sh, n, sw * sh + 1); fprintf(c, "unsigned char i_%s[%d] = {\n", n, sw * sh + 1); for(bps = sw; bps & 3; bps++); for(y = 0; y < sh; y++) { fseek(bmp, start + (sh - y - 1) * bps, SEEK_SET); fputs(" ", c); for(x = 0; x < sw; x += 4 ) { if( fread(&pixel, 4, 1, bmp) != 1 ) return ReadError(); sprintf(string, "%3u,%3u,%3u,%3u,", ( pixel & 255), ((pixel >> 8) & 255), ((pixel >> 16) & 255), ((pixel >> 24) & 255)); if( sw - x < 4 ) string[(sw - x) * 4] = 0; fputs(string, c); } fputs((y + 1 == sh) ? " 0x0};\n" : "\n", c); } printf("%d x %d grayscale", sw, sh); return 0; } /* Translate8g() */ /************************************************************* Translate24 */ static int Translate24(FILE *bmp, FILE *c, FILE *h, int sw, int sh, char *n) { int start, bps, x, y, r, g, b; fseek(bmp, 10, SEEK_SET); if( fread(&start, 4, 1, bmp) != 1 ) return ReadError(); fprintf(h, "/*\n" " r = i_%s[(y * %d + x) * 3]\n" " g = i_%s[(y * %d + x) * 3 + 1]\n" " b = i_%s[(y * %d + x) * 3 + 2]\n" "*/\n" "#define w_%s %d\n" "#define h_%s %d\n" "#define s_%s %d\n" "extern unsigned char i_%s[%d];\n", n, sw, n, sw, n, sw, n, sw, n, sh, n, sw * sh, n, sw * sh * 3 + 1); fprintf(c, "unsigned char i_%s[%d] = {\n", n, sw * sh * 3 + 1); for(bps = sw * 3; bps & 3; bps++); for(y = 0; y < sh; y++) { fseek(bmp, start + (sh - y - 1) * bps, SEEK_SET); fputs(" ", c); for(x = 0; x < sw; x++) { b = fgetc(bmp); g = fgetc(bmp); r = fgetc(bmp); if( b < 0 || g < 0 || r < 0 ) return ReadError(); fprintf(c, "%3d,%3d,%3d,", r, g, b); } fputs((y + 1 == sh) ? " 0x0};\n" : "\n", c); } printf("%d x %d x 24", sw, sh); return 0; } /* Translate24() */ /************************************************************ WritePHeader */ static void WritePHeader(FILE *h, int sw, int sh, int size, char *n) { fprintf(h, "/*\n" " r = p_%s[ i_%s[y * %d + x] ][0]\n" " g = p_%s[ i_%s[y * %d + x] ][1]\n" " b = p_%s[ i_%s[y * %d + x] ][2]\n" "*/\n" "#define w_%s %d\n" "#define h_%s %d\n" "#define s_%s %d\n" "#define c_%s %d\n" "extern unsigned char p_%s[%d][3];\n" "extern unsigned char i_%s[%d];\n", n, n, sw, n, n, sw, n, n, sw, n, sw, n, sh, n, sw * sh, n, size, n, size, n, sw * sh + 1); } /* WritePeader() */ /************************************************************ WritePalette */ static void WritePalette(FILE *c, unsigned char *palette, int size, char *n) { int i; fprintf(c, "unsigned char p_%s[%d][3] = {\n", n, size); for(i = 0; i < size; i++) { fprintf(c, " {%3d,%3d,%3d}%s\n", palette[i * 4 + 2], palette[i * 4 + 1], palette[i * 4], (i + 1 == size) ? " };\n" : ","); } } /* WritePalette() */ /*************************************************************** ReadError */ static int ReadError(void) { puts("Read error."); return 1; } /* ReadError() */