Download | Plain Text | Line Numbers
/**
* @module cwindowsbitmap
* @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
* @brief Implementation of CBitmap handling Windows Bitmaps.
* @date 17.04.2009
*/
#include <boost/lexical_cast.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <assert.h>
#ifdef DEBUG
# include <iostream>
#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<char *>(&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<char *>(&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<char *>(m_pixeldata), m_infoheader.biSizeImage);
}
/* get pixelformat instance */
m_pixelformat = NULL;
set<CPixelFormat *>::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<uint32_t>(
((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<char *>(&m_fileheader), sizeof(m_fileheader));
/* write info header */
out.write(reinterpret_cast<char *>(&m_infoheader), sizeof(m_infoheader));
/* write pixel data */
if (m_pixeldata != NULL)
out.write(reinterpret_cast<char *>(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: */