From aa139a7d2b3f26af7590edbf413df67195c5d900 Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 27 Apr 2009 00:25:16 +0200 Subject: Adding ue2 --- ue2/imgsynth2/cbitmap.cpp | 382 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 ue2/imgsynth2/cbitmap.cpp (limited to 'ue2/imgsynth2/cbitmap.cpp') diff --git a/ue2/imgsynth2/cbitmap.cpp b/ue2/imgsynth2/cbitmap.cpp new file mode 100644 index 0000000..fc1a7c0 --- /dev/null +++ b/ue2/imgsynth2/cbitmap.cpp @@ -0,0 +1,382 @@ +/** + * @module cbitmap + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief Implementation of CFile handling Windows Bitmaps. + * @date 17.04.2009 + */ + +#include +#include +#ifdef DEBUG +# include +#endif +#include "cbitmap.h" +#include "cpixelformat_bgr24.h" +#include "cpixelformat_bgr555.h" + +using namespace std; + +CBitmap::CBitmap() + : m_pixeldata(NULL), m_pixelformat(NULL) +{ + m_types.insert("BMP"); + + /* add our handlers */ + m_handlers.insert(new CPixelFormat_BGR24(this)); + m_handlers.insert(new CPixelFormat_BGR555(this)); +} + +/*----------------------------------------------------------------------------*/ + +CBitmap::~CBitmap() +{ + /* delete pixeldata */ + if (m_pixeldata != NULL) + delete[] m_pixeldata; + m_pixeldata = NULL; + + /* delete pixelformat handlers */ + set::iterator it; + for (it = m_handlers.begin(); it != m_handlers.end(); it++) + delete *it; + m_pixelformat = NULL; +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::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]; + 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."); +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::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); +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::callFunc(const std::string& func, const std::list& params) +{ + if (func.empty()) + throw FileError("Function name is empty."); + + if (func == "fillrect") + fillrect(params); + else if (func == "mirror_x") + mirror_x(params); + else if (func == "mirror_y") + mirror_y(params); + else if (func == "invert") + invert(params); + else + throw FileError("Unknown function '" + func + "'."); +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::fillrect(std::list params) +{ + /* check prerequirements */ + if (params.size() != 7) + throw FileError("Invalid number of function parameters (must be 7)."); + + /* do nothing if no pixel exists */ + if (m_pixeldata == NULL || m_pixelformat == NULL) + return; + + /* convert parameters */ + uint32_t pparams[7]; + int i = 0; + try + { + for(i = 0; i < 7; i++) + { + pparams[i] = boost::lexical_cast(params.front()); + params.pop_front(); + } + } + catch(boost::bad_lexical_cast& ex) + { + throw FileError("Invalid parameter (" + params.front() + ")."); + } + + /* width and height can be negativ */ + uint32_t width = static_cast(abs(m_infoheader.biWidth)); + uint32_t height = static_cast(abs(m_infoheader.biHeight)); + + /* check parameter values are in range */ + if (pparams[0] < 0 || pparams[0] > width + || pparams[1] < 0 || pparams[1] > height) + throw FileError("At least one x/y-parameter is out of range."); + + /* check parameter values are in range */ + unsigned int max[3]; + m_pixelformat->getMaxColor(&max[0], &max[1], &max[2]); + if (pparams[4] < 0 || pparams[4] > max[0] + || pparams[5] < 0 || pparams[5] > max[1] + || pparams[6] < 0 || pparams[6] > max[2]) + throw FileError("At least one pixel color parameter is out of range."); + + if (pparams[2] < 0 || pparams[2] + pparams[0] > width + || pparams[3] < 0 || pparams[3] + pparams[1] > height) + throw FileError("At least one w/h-parameter is out of range."); + + /* call setPixel for every pixel in the rectangel */ + for(uint32_t i = pparams[0]; i < pparams[2] + pparams[0]; i++) + { + for(uint32_t j = pparams[1]; j < pparams[3] + pparams[1]; j++) + { + try + { + m_pixelformat->setPixel(&pparams[4], i, j); + } + catch(CPixelFormat::PixelFormatError& ex) + { + stringstream errstr; + errstr << "Can't set pixel (pos=[" << i << "," << j << "] col=[" + << pparams[4] << "," << pparams[5] << "," << pparams[6] << "]): " + << ex.what(); + throw FileError(errstr.str()); + } + } + } +} + +/*----------------------------------------------------------------------------*/ + +#include +void CBitmap::invert(std::list params) +{ + /* check prerequirements */ + if (params.size() != 0) + throw FileError("Invalid number of function parameters (must be 0)."); + + /* do nothing if no pixel exists */ + if (m_pixeldata == NULL || m_pixelformat == NULL) + return; + + /* width and height can be negativ */ + uint32_t width = static_cast(abs(m_infoheader.biWidth)); + uint32_t height = static_cast(abs(m_infoheader.biHeight)); + unsigned int pixelwidth = m_pixelformat->getBitCount()/8; + + /* calc rowsize - boundary is 32 */ + uint32_t rowsize = 4 * static_cast( + ((m_pixelformat->getBitCount() * abs(m_infoheader.biWidth)) + 31) / 32 + ); + + for(uint32_t i = 0; i < height; i++) + { + for(uint32_t j = 0; j <= width; j++) + { + cout << j << endl; + } + } + +#if 0 +/* uint32_t offset = i * rowsize; + + for(uint32_t j = 0; j <= width/2; j++) + { + uint32_t poffset = offset + j * pixelwidth; + uint32_t pbackset = offset + width * pixelwidth - j * pixelwidth; + + /* boundary check */ + if (pbackset > m_infoheader.biSizeImage) + throw FileError("Mirrored pixel position is out of range."); + + /* mirroring, backup right data first */ + copy(m_pixeldata + pbackset - pixelwidth, m_pixeldata + pbackset, buf); + copy(m_pixeldata + poffset, m_pixeldata + poffset + pixelwidth, m_pixeldata + pbackset - pixelwidth); + copy(buf, buf + pixelwidth, m_pixeldata + poffset); + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::brightness(std::list params) +{ +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::mirror_y(std::list params) +{ + /* check prerequirements */ + if (params.size() != 0) + throw FileError("Invalid number of function parameters (must be 0)."); + + /* do nothing if no pixel exists */ + if (m_pixeldata == NULL || m_pixelformat == NULL) + return; + + /* height can be negativ */ + uint32_t height = static_cast(abs(m_infoheader.biHeight)); + + /* calc rowsize - boundary is 32 */ + uint32_t rowsize = 4 * static_cast( + ((m_pixelformat->getBitCount() * abs(m_infoheader.biWidth)) + 31) / 32 + ); + + uint8_t *buf = new uint8_t[rowsize]; + for(uint32_t i = 0; i < height/2; i++) + { + uint32_t j = height - i - 1; + uint32_t offset = i * rowsize; + uint32_t backset = j * rowsize; + + /* boundary check */ + if (offset + rowsize > m_infoheader.biSizeImage + || backset + rowsize > m_infoheader.biSizeImage) + throw FileError("Mirrored pixel position is out of range."); + + /* mirroring, backup lower data first */ + copy(m_pixeldata + backset, m_pixeldata + backset + rowsize, buf); + copy(m_pixeldata + offset, m_pixeldata + offset + rowsize, m_pixeldata + backset); + copy(buf, buf + rowsize, m_pixeldata + offset); + } + delete[] buf; +} + +/*----------------------------------------------------------------------------*/ + +void CBitmap::mirror_x(std::list params) +{ + /* check prerequirements */ + if (params.size() != 0) + throw FileError("Invalid number of function parameters (must be 0)."); + + /* do nothing if no pixel exists */ + if (m_pixeldata == NULL || m_pixelformat == NULL) + return; + + /* width and height can be negativ */ + uint32_t width = static_cast(abs(m_infoheader.biWidth)); + uint32_t height = static_cast(abs(m_infoheader.biHeight)); + + /* calc rowsize - boundary is 32 */ + uint32_t rowsize = 4 * static_cast( + ((m_pixelformat->getBitCount() * abs(m_infoheader.biWidth)) + 31) / 32 + ); + + /* calc pixelwidth */ + unsigned int pixelwidth = m_pixelformat->getBitCount()/8; + + uint8_t *buf = new uint8_t[pixelwidth]; + for(uint32_t i = 0; i < height; i++) + { + uint32_t offset = i * rowsize; + + for(uint32_t j = 0; j <= width/2; j++) + { + uint32_t poffset = offset + j * pixelwidth; + uint32_t pbackset = offset + width * pixelwidth - j * pixelwidth; + + /* boundary check */ + if (pbackset > m_infoheader.biSizeImage) + throw FileError("Mirrored pixel position is out of range."); + + /* mirroring, backup right data first */ + copy(m_pixeldata + pbackset - pixelwidth, m_pixeldata + pbackset, buf); + copy(m_pixeldata + poffset, m_pixeldata + poffset + pixelwidth, m_pixeldata + pbackset - pixelwidth); + copy(buf, buf + pixelwidth, m_pixeldata + poffset); + } + } + delete[] buf; +} + +/*----------------------------------------------------------------------------*/ + +#ifdef DEBUG +void CBitmap::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: */ -- cgit v1.2.3