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: */