#include #include #include #include #include "rtv.h" #define expect(x) do { \ if (!(x)) { \ fprintf(stderr, "Unexpected %d\033 ", __LINE__); \ exit(1); \ } \ } while(0) u16 le_to_u16(unsigned char ** pp) { unsigned char * p; u16 r; p = *pp; r = *p++; r |= *p++ << 8; *pp = p; return r; } u32 le_to_u32(unsigned char ** pp) { unsigned char * p; u32 r; p = *pp; r = le_to_u16(&p); r |= le_to_u16(&p) << 16; *pp = p; return r; } static void bmx_read_header(FILE * in, u16 * out_width, u16 * out_height) { unsigned char buffer[16], * p; int c; u16 version, width, height, colors; u32 datasize; fread(buffer, 1, 16, in); expect(buffer[0] == 'B'); expect(buffer[1] == 'M'); expect(buffer[2] == 'X'); expect(buffer[3] == ' '); p = buffer + 4; version = le_to_u16(&p); width = le_to_u16(&p); height = le_to_u16(&p); colors = le_to_u16(&p); datasize = le_to_u32(&p); expect(version == 1); expect(colors == 256); *out_width = width; *out_height = height; } static void bmx_set_pixel(pixel ** p, int row, int col, unsigned char * c) { PPM_ASSIGN(p[row][col], c[3], c[2], c[1]); } static pixel ** bmx_build_memory_pixmap(FILE * in, u16 width, u16 height) { int bytes; int done = 0; int i, c; int row, col; pixel ** pixels; unsigned char colors[256][4]; pixels = ppm_allocarray(width, height); if (!pixels) { fprintf(stderr, "Couldn't allocate memory\n"); return; } fread(colors, 1, sizeof colors, in); row = height - 1; col = 0; while (!done && (c = fgetc(in)) != EOF) { switch(c) { case 0: c = fgetc(in); switch(c) { case 0: row--; col = 0; break; case 1: done = 1; break; case 2: /* XXX doesn't handle delta */ fprintf(stderr, "Delta! %d", fgetc(in)); fprintf(stderr, ",%d\n", fgetc(in)); break; default: bytes = c; for (i = 0; i < bytes; i++) bmx_set_pixel(pixels, row, col++, colors[fgetc(in)]); if (bytes % 2) fgetc(in); break; } break; default: bytes = c; c = fgetc(in); for (i = 0; i < bytes; i++) bmx_set_pixel(pixels, row, col++, colors[c]); break; } } return pixels; } static void bmx2ppm(FILE * in, FILE * out) { u16 width, height; pixel ** pixels; bmx_read_header(in, &width, &height); pixels = bmx_build_memory_pixmap(in, width, height); ppm_writeppm(stdout, pixels, width, height, 255, 0); } int main(int argc, char ** argv) { ppm_init(&argc, argv); bmx2ppm(stdin, stdout); return 0; }