/** * @module cwindowsbitmap * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Implementation of CBitmap handling Windows Bitmaps. * @date 17.04.2009 */ #include #include #include #ifdef DEBUG # include #endif #include "cwindowsbitmap.h" #include "cpixelformat_bgr24.h" #include "cpixelformat_bgr555.h" using namespace std; CWindowsBitmap::CWindowsBitmap() { m_types.insert("BMP"); /* add our handlers */ m_handlers.insert(new CPixelFormat_BGR24(this)); m_handlers.insert(new CPixelFormat_BGR555(this)); } /*----------------------------------------------------------------------------*/ void CWindowsBitmap::read(std::ifstream& in) { /* read and check file header */ in.read(reinterpret_cast(&m_fileheader), sizeof(m_fileheader)); if (m_fileheader.bfType[0] != 'B' || m_fileheader.bfType[1] != 'M') throw FileError("Imagefile has invalid Bitmap header."); /* bfSize is unreliable (http://de.wikipedia.org/wiki/Windows_Bitmap) */ if (m_fileheader.bfSize < 0) throw FileError("Bitmap filesize is less than zero?"); /* read and check info header */ in.read(reinterpret_cast(&m_infoheader), sizeof(m_infoheader)); if (m_infoheader.biSize != 40) throw FileError("Bitmap info header size is invalid."); if (m_infoheader.biPlanes != 1) throw FileError("Bitmap color planes is not set to 1."); if (m_infoheader.biCompression != 0) throw FileError("Bitmap compression is set but not supported."); if (m_infoheader.biSizeImage < 0) throw FileError("Bitmap image size is less than zero?"); if (m_infoheader.biClrUsed != 0 || m_infoheader.biClrImportant != 0) throw FileError("Bitmap colortable is used but not supported."); /* read pixel data using separate class */ if (m_infoheader.biSizeImage > 0) { if (m_pixeldata != NULL) delete[] m_pixeldata; m_pixeldata = new uint8_t[m_infoheader.biSizeImage]; assert(m_fileheader.bfOffBits > 0); in.seekg(m_fileheader.bfOffBits); in.read(reinterpret_cast(m_pixeldata), m_infoheader.biSizeImage); } /* get pixelformat instance */ m_pixelformat = NULL; set::iterator it; for (it = m_handlers.begin(); it != m_handlers.end(); it++) { if (m_infoheader.biBitCount == (*it)->getBitCount()) { m_pixelformat = *it; break; } } if (m_pixelformat == NULL) throw FileError("Bitmap bitcount is not supported."); /* calc rowsize - boundary is 32 */ m_rowsize = 4 * static_cast( ((m_pixelformat->getBitCount() * m_infoheader.biWidth) + 31) / 32 ); } /*----------------------------------------------------------------------------*/ void CWindowsBitmap::write(std::ofstream& out) { /* set header values */ m_fileheader.bfSize = m_infoheader.biSizeImage + sizeof(m_infoheader) + sizeof(m_fileheader); /* write file header */ out.write(reinterpret_cast(&m_fileheader), sizeof(m_fileheader)); /* write info header */ out.write(reinterpret_cast(&m_infoheader), sizeof(m_infoheader)); /* write pixel data */ if (m_pixeldata != NULL) out.write(reinterpret_cast(m_pixeldata), m_infoheader.biSizeImage); } /*----------------------------------------------------------------------------*/ #ifdef DEBUG void CWindowsBitmap::dump(std::ostream& out) { out << "Bitmap File Header:" << endl << " bfType=" << m_fileheader.bfType[0] << m_fileheader.bfType[1] << ", bfSize=" << m_fileheader.bfSize << ", bfReserved=" << m_fileheader.bfReserved << ", bfOffBits=" << m_fileheader.bfOffBits << endl; out << "Bitmap Info Header:" << endl << " biSize=" << m_infoheader.biSize << ", biWidth=" << m_infoheader.biWidth << ", biHeight=" << m_infoheader.biHeight << ", biPlanes=" << m_infoheader.biPlanes << endl << " biBitCount=" << m_infoheader.biBitCount << ", biCompression=" << m_infoheader.biCompression << ", biSizeImage=" << m_infoheader.biSizeImage << endl << " biXPelsPerMeter=" << m_infoheader.biXPelsPerMeter << ", biYPelsPerMeter=" << m_infoheader.biYPelsPerMeter << ", biClrUsed=" << m_infoheader.biClrUsed << ", biClrImportant=" << m_infoheader.biClrImportant << endl; } #endif /* vim: set et sw=2 ts=2: */