//============================================================================ // bin2bmp.cpp // Convert a binary data file into a BMP bitmap image file. // // History // 1.00 1997-03-29 dtribble. // First cut. // // Copyright (c)1997, David R. Tribble. // Identification static const char prog[] = "bin2bmp"; static const char vers[] = "1.00"; static const char date[] = "1997-03-29"; static const char auth[] = "David R. Tribble"; // System includes #include #include #include #include #include #ifdef __MSDOS__ #include #endif #include // Local includes #include "bmp.h" //---------------------------------------------------------------------------- // class Program class Program { public: /*void*/ Program(); /*void*/ ~Program(); int main(int argc, const char *const *argv); // Execute the program void usage(); // Print usage message and punt private: int binToBmp(const char *in, const char *out); // Convert binary file to BMP image private: int m_rcode; // Exit status code const char * m_out_fname; // Output file name const char * m_in_fname; // Input file name FILE * m_out; // Output file FILE * m_in; // Input file long m_width; // Image width in pixels long m_height; // Image heighth in pixels }; //---------------------------------------------------------------------------- // Program::Program() int Program::Program(): m_rcode(0) { // No other members to initialize } //---------------------------------------------------------------------------- // Program::~Program() int Program::~Program() { exit(m_rcode); } //---------------------------------------------------------------------------- // Program::usage() // Print a command usage message, then punt. // // Returns // Doesn't, calls exit(). void Program::usage() { fprintf(stderr, "usage: %s infile outfile\n", prog); fprintf(stderr, " %s infile - >outfile\n", prog); exit(127); } //---------------------------------------------------------------------------- // Program::main() // Execute the program. int Program::main(int argc, const char *const *argv) { if (argc < 3) usage(); // Process command args if (binToBmp(argv[1], argv[2]) < 0) fprintf(stderr, "You lose.\n"); return (m_rcode); } //---------------------------------------------------------------------------- // Program::binToBmp() // Convert binary data file `in' into BMP image file `out'. // // Returns // Zero on success, otherwise -1 on error. int Program::binToBmp(const char *in, const char *out) { // Set up m_out = NULL; m_out_fname = NULL; m_in_fname = NULL; m_in = NULL; // Open the output file m_out_fname = out; if (strcmp(m_out_fname, "-") == 0) { // Write to standard output m_out = stdout; #ifdef O_BINARY setmode(fileno(m_out), O_BINARY); #endif } else { // Write to a filename m_out = fopen(m_out_fname, "wb"); if (m_out == NULL) { fprintf(stderr, "Can't write to \"%s\", %s\n", m_out_fname, strerror(errno)); goto fail; } } // Open the input file m_in_fname = in; #if is_not_supported___ if (strcmp(m_in_fname, "-") == 0) { // Read from standard input m_out = stdin; #ifdef O_BINARY setmode(fileno(m_in), O_BINARY); #endif } else #endif { // Read from a filename m_in = fopen(m_in_fname, "rb"); if (m_in == NULL) { fprintf(stderr, "Can't read from \"%s\", %s\n", m_in_fname, strerror(errno)); goto fail; } } // Determine a good image size from the input file size if (m_in != stdin) { struct stat st; long slop, min_slop; long w; // Get file size (status) if (fstat(fileno(m_in), &st) < 0) { // Error fprintf(stderr, "Can't get status for \"%s\", %s\n", m_in_fname, strerror(errno)); goto fail; } fprintf(stderr, "Input file is %ld bytes\n", (long) st.st_size); // Determine best line width min_slop = 1000; m_width = 640; for (w = 200; w <= 640; w += 4) { slop = w - (st.st_size % (3*w)); if (min_slop > slop) { min_slop = slop; m_width = w; } } // Determine image heighth m_height = (st.st_size + 3*(m_width-1)) / (3*m_width); fprintf(stderr, "Image will be %ldv x %ldh pixels, " "with %ld bytes of slop\n", m_height, m_width, m_height * 3*m_width - st.st_size); } #if is_not_supported___ else { // Assume a reasonable line width ... } #endif // Fill in the BMP header struct bmp_header hdr; memset(&hdr, '\0', sizeof(hdr)); hdr.id = BMP_HDR_MAGIC; hdr.filesize = m_height * 3*m_width; hdr.headersize = sizeof(hdr); hdr.infoSize = 40; hdr.width = m_width; hdr.depth = m_height; hdr.biPlanes = 1; hdr.bits = 24; hdr.biCompression = BMP_CMP_NONE; hdr.biSizeImage = 0; hdr.biXPelsPerMeter = 3937; hdr.biYPelsPerMeter = 3937; hdr.biClrUsed = 0; hdr.biClrImportant = 0; // Write the BMP header if (fwrite(&hdr, sizeof(hdr), 1, m_out) != 1) { // Write error fprintf(stderr, "Can't write BMP header to \"%s\", %s\n", m_out_fname, strerror(errno)); goto fail; } // Write the image, copying bytes from the input file unsigned char bytes[3*800]; long h, w; long b_count; b_count = 0; for (h = 0; h < m_height; h++) { long len; // Read a line of binary data bytes from the input file len = fread(bytes, 1, 3*m_width, m_in); if (len <= 0) { fprintf(stderr, "Can't read data from \"%s\", %s\n", m_in_fname, strerror(errno)); goto fail; } // Pad slop pixels with zeros if (len < 3*m_width) { int slop, off; slop = 3*m_width - len; off = 3*m_width - slop; fprintf(stderr, "Slop is %d bytes\n", slop); memset(bytes+off, '\0', slop); } // Write a line of pixels to the output file if (fwrite(bytes, 1, 3*m_width, m_out) < 3*m_width) { fprintf(stderr, "Can't write pixels to \"%s\", %s\n", m_out_fname, strerror(errno)); goto fail; } b_count += 3*m_width; } fprintf(stderr, "%ld bytes written\n", b_count); // Close the input file fclose(m_in); m_in = NULL; m_in_fname = NULL; // Close the output file fclose(m_out); m_out = NULL; m_out_fname = NULL; // Done return (0); fail: // Failure, clean up if (m_out_fname != NULL) m_out_fname = NULL; if (m_out != NULL) { fclose(m_out); m_out = NULL; } if (m_in_fname != NULL) m_in_fname = NULL; if (m_in != NULL) { fclose(m_in); m_in = NULL; } return (-1); } //---------------------------------------------------------------------------- // ::main() int main(int argc, const char **argv) { Program prog; return (prog.main(argc, argv)); } // End bin2bmp.cpp