//============================================================================== // bxopen.cpp // Classes and functions to read and write Microsoft Windows bitmap (BMP) // graphic image files. // // Acknowledgements // Derived from source code written by David R. Tribble, Jan 1992. // // Copyright ©2008 by David R. Tribble, all rights reserved. // Permission is granted to any person or entity except those designated // by the United States Department of State as a terrorist, or terrorist // government or agency, to use and distribute this source code provided // that the original copyright notice remains present and unaltered. //============================================================================== // Identification static char REV[] = "@(#)drt/bmp/bxopen.cpp $Revision: 1.4 $$Date: 2008/06/28 16:25:08 $"; // System includes #include #define sys_errno_h 1 #include #define sys_iso646_h 1 #include #define sys_stddef_h 1 #include #define sys_stdint_h 1 #include #define sys_stdio_h 1 #include #define sys_string_h 1 // Local includes #include "bmpdefs.h" #include "bmpfile.hpp" //------------------------------------------------------------------------------ // Class constants //------------------------------------------------------------------------------ /*static*/ const struct bmp_rgb DrtBmpFile::palette16[0x10] = { // Blue Green Red X N Name { 0x00, 0x00, 0x00, 0 }, // 0x00, black { 0x80, 0x00, 0x00, 0 }, // 0x01, dark red { 0x00, 0x80, 0x00, 0 }, // 0x02, dark green { 0x80, 0x80, 0x00, 0 }, // 0x03, dark yellow (brown) { 0x00, 0x00, 0x80, 0 }, // 0x04, dark blue { 0x80, 0x00, 0x80, 0 }, // 0x05, dark magenta { 0x00, 0x80, 0x80, 0 }, // 0x06, dark cyan { 0x80, 0x80, 0x80, 0 }, // 0x07, dark gray { 0xC0, 0xC0, 0xC0, 0 }, // 0x08, light gray { 0xFF, 0x00, 0x00, 0 }, // 0x09, light red (pink) { 0x00, 0xFF, 0x00, 0 }, // 0x0a, light green { 0xFF, 0xFF, 0x00, 0 }, // 0x0B, light yellow { 0x00, 0x00, 0xFF, 0 }, // 0x0C, light blue { 0xFF, 0x00, 0xFF, 0 }, // 0x0D, light magenta { 0x00, 0xFF, 0xFF, 0 }, // 0x0E, light cyan { 0xFF, 0xFF, 0xFF, 0 }, // 0x0F, white }; //------------------------------------------------------------------------------ // DrtBmpFile::~DrtBmpFile() // Destructor. // // @since // 1.1, 2008-04-27 //------------------------------------------------------------------------------ /*void*/ DrtBmpFile::~DrtBmpFile() { #if DrtBmpFile_VS != 101 #error class DrtBmpFile has changed #endif // Check the object if (m_magic != DrtBmpFile_MAGIC or m_vers != DrtBmpFile_VS) { sys_errno = EINVAL; return; } // Deallocate if (m_fp != NULL) close(); m_fp = NULL; if (m_map != NULL) delete[] m_map; m_map = NULL; ::memset(m_data, 0, sizeof(m_data)); // Deinitialize m_magic = ~DrtBmpFile_MAGIC; } //------------------------------------------------------------------------------ // DrtBmpFile::DrtBmpFile() // Default constructor. // // @since // 1.1, 2008-04-27 //------------------------------------------------------------------------------ /*void*/ DrtBmpFile::DrtBmpFile(): m_magic(DrtBmpFile_MAGIC), m_vers(DrtBmpFile_VS), m_fp(NULL), m_hdr(), m_map(NULL), m_mode(M_NONE), m_flags(0x0000), m_ncols(0), m_linesz(0), m_byteno(0), m_rep(0), m_pix(0), m_byte(0), m_bitno(0), m_datapos(0), m_data() { #if DrtBmpFile_VS != 101 #error class DrtBmpFile has changed #endif // Initialize ::memset(&m_hdr, 0, sizeof(m_hdr)); m_hdr.id = BMP_HDR_MAGIC; m_hdr.biCompression = BMP_CMP_NONE; } //------------------------------------------------------------------------------ // DrtBmpFile::open() // Opens a BMP file. // // @param fname // Designates the name of the BMP file to open. // // @param mode // One of the M_XXX constants, specifying whether to open the file for // reading, writing, or both. // // @return // Pointer to an object referring to an newly opened BMP file, // or null if an error occurs (and ::errno is set). // // @since // 1.1, 2008-04-27 //------------------------------------------------------------------------------ /*static*/ DrtBmpFile * DrtBmpFile::open(const char *fname, int mode) { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif DrtBmpFile * fp; const char * m; int err; // Check the filename if (fname == NULL or fname[0] == '\0') { // Invalid file name sys_errno = EINVAL; return NULL; } // Check the mode switch (mode) { case M_READ: m = "rb"; break; case M_WRITE: m = "wb"; break; case M_READWRITE: m = "w+b"; break; default: // Invalid mode sys_errno = EINVAL; return NULL; } // Allocate a file control object fp = new DrtBmpFile(); if (fp == NULL) { // Out of memory sys_errno = ENOMEM; return NULL; } // Open the named BMP file fp->m_fp = ::fopen(fname, m); err = sys_errno; if (fp->m_fp == NULL) { // Can't open the file delete fp; sys_errno = err; return NULL; } // Initialize the file control info fp->m_mode = mode; return fp; } //------------------------------------------------------------------------------ // DrtBmpFile::close() // Close a previously opened BMP file. // // @return // Zero if successful, otherwise an (::errno) error code. // // @since // 1.1, 2008-04-27 //------------------------------------------------------------------------------ int DrtBmpFile::close() { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif int rc; // Check the object if (m_magic != DrtBmpFile_MAGIC or m_vers/100 != DrtBmpFile_VS/100) { sys_errno = EINVAL; return EINVAL; } // Check the file if (m_fp == NULL) { // File is already closed return 0; } // Close the file rc = fclose(m_fp); m_fp = NULL; return rc; } //------------------------------------------------------------------------------ // DrtBmpFile::is_open() // Determine if the BMP file is open. // // @return // True if the file is open, otherwise false. // // @since // 1.1, 2008-04-27 //------------------------------------------------------------------------------ bool DrtBmpFile::is_open() const { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif // Check the object if (m_magic != DrtBmpFile_MAGIC or m_vers/100 != DrtBmpFile_VS/100) { sys_errno = EINVAL; return false; } // Check the file return (m_fp != NULL); } //------------------------------------------------------------------------------ // DrtBmpFile::get_header() // Retrieve the file header for this BMP file. // // @return // File header information, or null if there is none yet associated with or // read from the file. // // @since // 1.2, 2008-04-28 //------------------------------------------------------------------------------ const struct bmp_header * DrtBmpFile::get_header() const { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif // Check the object if (m_magic != DrtBmpFile_MAGIC or m_vers/100 != DrtBmpFile_VS/100) { sys_errno = EINVAL; return NULL; } // Retrieve the BMP file header if (not (m_flags & F_HAS_HDR)) return NULL; return &m_hdr; } //------------------------------------------------------------------------------ // DrtBmpFile::get_palette() // Retrieve the palette map for this BMP file. // // @return // Array of tuples comprising the color palette of the BMP image, // or null if there is none. // // @since // 1.2, 2008-04-28 //------------------------------------------------------------------------------ const struct bmp_rgb * DrtBmpFile::get_palette() const { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif // Check the object if (m_magic != DrtBmpFile_MAGIC or m_vers/100 != DrtBmpFile_VS/100) { sys_errno = EINVAL; return NULL; } // Retrieve the color palette map return m_map; } //------------------------------------------------------------------------------ // DrtBmpFile::get_palette_size() // Retrieve the size of the palette map for this BMP file. // // @return // Number of tuples comprising the color palette of the BMP // image, or 0 if there is no palette. // // @since // 1.2, 2008-04-28 //------------------------------------------------------------------------------ int DrtBmpFile::get_palette_size() const { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif // Check the object if (m_magic != DrtBmpFile_MAGIC or m_vers/100 != DrtBmpFile_VS/100) { sys_errno = EINVAL; return -1; } // Retrieve the color palette map size if (not (m_flags & F_HAS_HDR)) return 0; if (m_hdr.bits > 0 and m_hdr.bits <= 8) { unsigned int len; // Determine the actual size of the color palette len = (1u << m_hdr.bits); if (m_hdr.biClrUsed > 0) len = m_hdr.biClrUsed; return (int)len; } else return 0; } //------------------------------------------------------------------------------ // DrtBmpFile::has_palette() // Determine if this BMP image file has (or needs) a palette map. // // @return // True if the BMP image has (or requires) a color palette, otherwise // false. // // @since // 1.2, 2008-04-28 //------------------------------------------------------------------------------ bool DrtBmpFile::has_palette() const { #if DrtBmpFile_VS/100 != 1 #error class DrtBmpFile has changed #endif // Check the image type for a palette return (get_palette_size() > 0); } // End bxopen.cpp