From bcadfa267f976fe9f29afa50a635cbe3ea174e38 Mon Sep 17 00:00:00 2001 From: manuel Date: Sat, 2 May 2009 16:44:53 +0200 Subject: - colortable now uses uint32_t as identifier - rewrote xpm colortable parsing to convert their identifiers to our own and vica vi - implemented indexed8::setpixel/getpixel - moved rowsize to member variable in cbitmap - added second test for xpm/indexed8 --- ue2/imgsynth2/cbitmap.cpp | 41 +++----- ue2/imgsynth2/cbitmap.h | 34 ++++++- ue2/imgsynth2/cpixelformat_bgr24.cpp | 14 +-- ue2/imgsynth2/cpixelformat_bgr555.cpp | 14 +-- ue2/imgsynth2/cpixelformat_indexed8.cpp | 88 ++++++++--------- ue2/imgsynth2/cpixelformat_indexed8.h | 8 +- ue2/imgsynth2/cpixmap.cpp | 125 ++++++++++++++++-------- ue2/imgsynth2/cpixmap.h | 85 +++++++++++++--- ue2/imgsynth2/cwindowsbitmap.cpp | 5 + ue2/imgsynth2/test/input_yellow_man1_indexed8 | 4 +- ue2/imgsynth2/test/input_yellow_man2_indexed8 | 13 +++ ue2/imgsynth2/test/yellow_man1_indexed8_ref.xpm | 27 ++--- ue2/imgsynth2/test/yellow_man2_indexed8_in.xpm | 27 +++++ ue2/imgsynth2/test/yellow_man2_indexed8_ref.xpm | 29 ++++++ 14 files changed, 345 insertions(+), 169 deletions(-) create mode 100644 ue2/imgsynth2/test/input_yellow_man2_indexed8 create mode 100644 ue2/imgsynth2/test/yellow_man2_indexed8_in.xpm create mode 100644 ue2/imgsynth2/test/yellow_man2_indexed8_ref.xpm (limited to 'ue2/imgsynth2') diff --git a/ue2/imgsynth2/cbitmap.cpp b/ue2/imgsynth2/cbitmap.cpp index 2e135db..3d206f5 100644 --- a/ue2/imgsynth2/cbitmap.cpp +++ b/ue2/imgsynth2/cbitmap.cpp @@ -28,7 +28,8 @@ CBitmap::~CBitmap() m_pixelformat = NULL; /* delete colortable content */ - map::iterator it2; + //map::iterator it2; + map::iterator it2; for(it2 = m_colortable.begin(); it2 != m_colortable.end(); it2++) delete (*it2).second; } @@ -144,7 +145,7 @@ void CBitmap::invert(std::list params) if (hasColorTable()) { /* invert every entry in the colortable */ - map::iterator it; + map::iterator it; for (it = m_colortable.begin(); it != m_colortable.end(); it++) { (*it).second->red = max.red - (*it).second->red; @@ -212,8 +213,8 @@ void CBitmap::brightness(std::list params) m_pixelformat->getMaxColor(max); if (hasColorTable()) { - /* invert every entry in the colortable */ - map::iterator it; + /* change every entry in the colortable */ + map::iterator it; for (it = m_colortable.begin(); it != m_colortable.end(); it++) { (*it).second->red = min(max.red, static_cast((*it).second->red * factor)); @@ -223,7 +224,7 @@ void CBitmap::brightness(std::list params) } else { - /* invert per pixel */ + /* change per pixel */ for(uint32_t y = 0; y < getHeight(); y++) { for(uint32_t x = 0; x < getWidth(); x++) @@ -260,27 +261,22 @@ void CBitmap::mirror_y(std::list params) if (m_pixeldata == NULL || m_pixelformat == NULL) return; - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((m_pixelformat->getBitCount() * getWidth()) + 31) / 32 - ); - - uint8_t *buf = new uint8_t[rowsize]; + uint8_t *buf = new uint8_t[m_rowsize]; for(uint32_t i = 0; i < getHeight()/2; i++) { uint32_t j = getHeight() - i - 1; - uint32_t offset = i * rowsize; - uint32_t backset = j * rowsize; + uint32_t offset = i * m_rowsize; + uint32_t backset = j * m_rowsize; /* boundary check */ - if (offset + rowsize > getPixelDataSize() - || backset + rowsize > getPixelDataSize()) + if (offset + m_rowsize > getPixelDataSize() + || backset + m_rowsize > getPixelDataSize()) 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); + copy(m_pixeldata + backset, m_pixeldata + backset + m_rowsize, buf); + copy(m_pixeldata + offset, m_pixeldata + offset + m_rowsize, m_pixeldata + backset); + copy(buf, buf + m_rowsize, m_pixeldata + offset); } delete[] buf; } @@ -297,18 +293,13 @@ void CBitmap::mirror_x(std::list params) if (m_pixeldata == NULL || m_pixelformat == NULL) return; - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((m_pixelformat->getBitCount() * getWidth()) + 31) / 32 - ); - /* calc pixelwidth */ - unsigned int pixelwidth = m_pixelformat->getBitCount()/8; + unsigned int pixelwidth = (hasColorTable()) ? sizeof(uint32_t) : m_pixelformat->getBitCount()/8; uint8_t *buf = new uint8_t[pixelwidth]; for(uint32_t i = 0; i < getHeight(); i++) { - uint32_t offset = i * rowsize; + uint32_t offset = i * m_rowsize; for(uint32_t j = 0; j <= getWidth()/2; j++) { diff --git a/ue2/imgsynth2/cbitmap.h b/ue2/imgsynth2/cbitmap.h index f48ada7..785e2f1 100644 --- a/ue2/imgsynth2/cbitmap.h +++ b/ue2/imgsynth2/cbitmap.h @@ -36,7 +36,7 @@ class CBitmap : public CFile * @conditions none */ CBitmap() - : m_pixeldata(NULL), m_pixelformat(NULL) + : m_pixeldata(NULL), m_pixelformat(NULL), m_rowsize(0) {} @@ -90,6 +90,34 @@ class CBitmap : public CFile return m_pixeldata; } + /** + * @method getColorTable + * @brief Returns reference to colortable + * @param - + * @return reference to colortable + * @globalvars none + * @exception none + * @conditions none + */ + std::map& getColorTable() + { + return m_colortable; + } + + /** + * @method getRowSize + * @brief Returns number of bytes of one row + * @param - + * @return number of bytes of one row + * @globalvars none + * @exception none + * @conditions none + */ + uint32_t getRowSize() + { + return m_rowsize; + } + /** * @method getPixelDataSize * @brief Return size of pixelbuffer @@ -230,11 +258,13 @@ class CBitmap : public CFile /** pointer to pixelbuffer */ uint8_t *m_pixeldata; /** colortable map */ - std::map m_colortable; + std::map m_colortable; /** set of supported PixelFormat handlers */ std::set m_handlers; /** pointer to CPixelFormat implementation */ CPixelFormat *m_pixelformat; + /** number of bytes of one row in the image */ + uint32_t m_rowsize; }; #endif diff --git a/ue2/imgsynth2/cpixelformat_bgr24.cpp b/ue2/imgsynth2/cpixelformat_bgr24.cpp index e7476d7..bc95ab9 100644 --- a/ue2/imgsynth2/cpixelformat_bgr24.cpp +++ b/ue2/imgsynth2/cpixelformat_bgr24.cpp @@ -16,15 +16,10 @@ void CPixelFormat_BGR24::getPixel(RGBPIXEL& pixel, uint32_t x, uint32_t y) if (m_bitmap->getPixelData() == NULL) throw PixelFormatError("No pixelbuffer allocated."); - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((getBitCount() * m_bitmap->getWidth()) + 31) / 32 - ); - /* if the y-coordinates are mirrored */ if (m_bitmap->isMirrored()) y = m_bitmap->getHeight() - y - 1; - uint32_t offset = y * rowsize + x * (4 * getBitCount() / 32); + uint32_t offset = y * m_bitmap->getRowSize() + x * (4 * getBitCount() / 32); /* boundary check */ if (offset + getBitCount()/8 > m_bitmap->getPixelDataSize()) @@ -43,15 +38,10 @@ void CPixelFormat_BGR24::setPixel(const RGBPIXEL& pixel, uint32_t x, uint32_t y) if (m_bitmap->getPixelData() == NULL) throw PixelFormatError("No pixelbuffer allocated."); - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((getBitCount() * m_bitmap->getWidth()) + 31) / 32 - ); - /* if the y-coordinates are mirrored */ if (m_bitmap->isMirrored()) y = m_bitmap->getHeight() - y - 1; - uint32_t offset = y * rowsize + x * (4 * getBitCount() / 32); + uint32_t offset = y * m_bitmap->getRowSize() + x * (4 * getBitCount() / 32); /* boundary check */ if (offset + getBitCount()/8 > m_bitmap->getPixelDataSize()) diff --git a/ue2/imgsynth2/cpixelformat_bgr555.cpp b/ue2/imgsynth2/cpixelformat_bgr555.cpp index 2f98cc7..657c148 100644 --- a/ue2/imgsynth2/cpixelformat_bgr555.cpp +++ b/ue2/imgsynth2/cpixelformat_bgr555.cpp @@ -17,15 +17,10 @@ void CPixelFormat_BGR555::getPixel(RGBPIXEL& pixel, uint32_t x, uint32_t y) if (m_bitmap->getPixelData() == NULL) throw PixelFormatError("No pixelbuffer allocated."); - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((getBitCount() * m_bitmap->getWidth()) + 31) / 32 - ); - /* if the y-coordinates are mirrored */ if (m_bitmap->isMirrored()) y = m_bitmap->getHeight() - y - 1; - uint32_t offset = y * rowsize + x * (4 * getBitCount() / 32); + uint32_t offset = y * m_bitmap->getRowSize() + x * (4 * getBitCount() / 32); /* boundary check */ if (offset + getBitCount()/8 > m_bitmap->getPixelDataSize()) @@ -45,15 +40,10 @@ void CPixelFormat_BGR555::setPixel(const RGBPIXEL& pixel, uint32_t x, uint32_t y if (m_bitmap->getPixelData() == NULL) throw PixelFormatError("No pixelbuffer allocated."); - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((getBitCount() * m_bitmap->getWidth()) + 31) / 32 - ); - /* if the y-coordinates are mirrored */ if (m_bitmap->isMirrored()) y = m_bitmap->getHeight() - y - 1; - uint32_t offset = y * rowsize + x * (4 * getBitCount() / 32); + uint32_t offset = y * m_bitmap->getRowSize() + x * (4 * getBitCount() / 32); /* boundary check */ if (offset + getBitCount()/8 > m_bitmap->getPixelDataSize()) diff --git a/ue2/imgsynth2/cpixelformat_indexed8.cpp b/ue2/imgsynth2/cpixelformat_indexed8.cpp index 6453fad..21b0988 100644 --- a/ue2/imgsynth2/cpixelformat_indexed8.cpp +++ b/ue2/imgsynth2/cpixelformat_indexed8.cpp @@ -1,8 +1,8 @@ /** * @module CPixelFormat_Indexed8 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief Implementation of CPixelFormat handling 24bit color Windows Bitmaps TODO. - * @date 18.04.2009 + * @brief Implementation of CPixelFormat handling 24bit indexed bitmaps. + * @date 02.05.2009 */ #include @@ -12,73 +12,67 @@ using namespace std; void CPixelFormat_Indexed8::getPixel(RGBPIXEL& pixel, uint32_t x, uint32_t y) { -#if 0 if (m_bitmap->getPixelData() == NULL) throw PixelFormatError("No pixelbuffer allocated."); + if (m_bitmap->getColorTable().size() == 0) + return; - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((getBitCount() * abs(m_bitmap->getInfoHeader().biWidth)) + 31) / 32 - );*/ - - /* if height is positive the y-coordinates are mirrored */ - if (m_bitmap->getInfoHeader().biHeight > 0) - y = m_bitmap->getInfoHeader().biHeight - y - 1; - uint32_t offset = y * rowsize + x * (4 * getBitCount() / 32); + uint32_t offset = y * m_bitmap->getWidth() + x; /* boundary check */ - if (offset + getBitCount()/8 > m_bitmap->getInfoHeader().biSizeImage) + if (offset * sizeof(uint32_t) + sizeof(uint32_t) > m_bitmap->getPixelDataSize()) throw PixelFormatError("Pixel position is out of range."); - /* get pixel */ - try - { - pixel[0] = boost::numeric_cast(*(m_bitmap->getPixelData() + offset + 2)); - pixel[1] = boost::numeric_cast(*(m_bitmap->getPixelData() + offset + 1)); - pixel[2] = boost::numeric_cast(*(m_bitmap->getPixelData() + offset)); - } - catch(boost::numeric::bad_numeric_cast& ex) - { - throw PixelFormatError("Unable to convert pixelcolor to correct size: " + string(ex.what())); - } -#endif + uint32_t color = *((uint32_t *)m_bitmap->getPixelData() + offset); + + map::iterator it; + if ((it = m_bitmap->getColorTable().find(color)) == m_bitmap->getColorTable().end()) + throw PixelFormatError("Pixel has no reference in colortable."); + + pixel.red = (*it).second->red; + pixel.green = (*it).second->green; + pixel.blue = (*it).second->blue; } +/*----------------------------------------------------------------------------*/ + void CPixelFormat_Indexed8::setPixel(const RGBPIXEL& pixel, uint32_t x, uint32_t y) { -#if 0 - if (m_bitmap->getPixelData() == NULL) + if (m_bitmap->getPixelData() == NULL) throw PixelFormatError("No pixelbuffer allocated."); + if (m_bitmap->getColorTable().size() == 0) + return; - /* calc rowsize - boundary is 32 */ - uint32_t rowsize = 4 * static_cast( - ((getBitCount() * abs(m_bitmap->getInfoHeader().biWidth)) + 31) / 32 - ); - - /* if height is positive the y-coordinates are mirrored */ - if (m_bitmap->getInfoHeader().biHeight > 0) - y = m_bitmap->getInfoHeader().biHeight - y - 1; - uint32_t offset = y * rowsize + x * (4 * getBitCount() / 32); + uint32_t offset = y * m_bitmap->getWidth() + x; /* boundary check */ - if (offset + getBitCount()/8 > m_bitmap->getInfoHeader().biSizeImage) + if (offset * sizeof(uint32_t) + sizeof(uint32_t) > m_bitmap->getPixelDataSize()) throw PixelFormatError("Pixel position is out of range."); - /* convert color values to correct types */ - uint8_t data[3]; - try + /* try to look up color in colortable */ + map::iterator it; + for(it = m_bitmap->getColorTable().begin(); it != m_bitmap->getColorTable().end(); it++) { - data[0] = boost::numeric_cast(pixel[2]); - data[1] = boost::numeric_cast(pixel[1]); - data[2] = boost::numeric_cast(pixel[0]); + if ((*it).second->red == pixel.red && + (*it).second->green == pixel.green && + (*it).second->blue == pixel.blue) + break; } - catch(boost::numeric::bad_numeric_cast& ex) + + uint32_t index = (*it).first; + /* need to get a new character for our color */ + if (it == m_bitmap->getColorTable().end()) { - throw PixelFormatError("Unable to convert pixelcolor to correct size: " + string(ex.what())); + index = (*it).first + 1; + RGBPIXEL *pixelptr = new RGBPIXEL; + pixelptr->red = pixel.red; + pixelptr->green = pixel.green; + pixelptr->blue = pixel.blue; + m_bitmap->getColorTable()[ index ] = pixelptr; } - copy(data, data + 3, m_bitmap->getPixelData() + offset); -#endif + /* set color */ + *((uint32_t *)m_bitmap->getPixelData() + offset) = index; } /* vim: set et sw=2 ts=2: */ diff --git a/ue2/imgsynth2/cpixelformat_indexed8.h b/ue2/imgsynth2/cpixelformat_indexed8.h index f1bb0f0..331d423 100644 --- a/ue2/imgsynth2/cpixelformat_indexed8.h +++ b/ue2/imgsynth2/cpixelformat_indexed8.h @@ -1,8 +1,8 @@ /** * @module cpixelformat_bgr24 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief Implementation of CPixelFormat handling 24bit color Windows Bitmaps TODO. - * @date 18.04.2009 + * @brief Implementation of CPixelFormat handling 24bit indexed bitmaps. + * @date 02.05.2009 */ #ifndef CPixelFormat_Indexed8_H @@ -14,7 +14,7 @@ /** * @class CPixelFormat_Indexed8 - * @brief Implementation of CPixelFormat handling 24bit color Windows Bitmaps TODO. + * @brief Implementation of CPixelFormat handling 24bit indexed bitmaps. * * On error CPixelFormat::PixelFormatError is thrown. */ @@ -83,7 +83,7 @@ class CPixelFormat_Indexed8 : public CPixelFormat */ uint32_t getBitCount() { - return 8; + return 24; } /** diff --git a/ue2/imgsynth2/cpixmap.cpp b/ue2/imgsynth2/cpixmap.cpp index 9e03d86..94f0310 100644 --- a/ue2/imgsynth2/cpixmap.cpp +++ b/ue2/imgsynth2/cpixmap.cpp @@ -49,9 +49,9 @@ std::string CPixmap::getLine(std::ifstream& in, bool ignore_comments) /*----------------------------------------------------------------------------*/ -std::string CPixmap::getArrayLine(std::ifstream& in, bool ignore_comments) +std::string CPixmap::getCArrayLine(std::ifstream& in) { - string line = getLine(in, ignore_comments); + string line = getLine(in, true); if (line.empty()) return line; @@ -87,6 +87,18 @@ void CPixmap::read(std::ifstream& in) m_fileheader._XPMEXT = false; m_fileheader._HOTSPOT = false; + /* get pixelformat instance first */ + m_pixelformat = NULL; + set::iterator it; + for (it = m_handlers.begin(); it != m_handlers.end(); it++) + { + /* we only have one! */ + m_pixelformat = *it; + break; + } + if (m_pixelformat == NULL) + throw FileError("Pixmap color mode is not supported."); + /* first line has to be PIXMAP_IDENTIFIER */ line = getLine(in, false); if (line != PIXMAP_IDENTIFIER) @@ -115,7 +127,7 @@ void CPixmap::read(std::ifstream& in) throw FileError("Pixmap array has no opening bracket."); /* parse -section */ - line = getArrayLine(in); + line = getCArrayLine(in); if (line.empty()) throw FileError("Pixmap has no Values-section."); algorithm::split(list, line, is_any_of(" \t")); @@ -152,10 +164,14 @@ void CPixmap::read(std::ifstream& in) /* parse -table */ string character; - map colors; + /* map[id][colortype] = color */ + map > colors; + /* map[id] = indices */ + map colornr; + uint32_t index = 0; for(uint32_t i = 0; i < m_fileheader.nColor; i++) { - line = getArrayLine(in); + line = getCArrayLine(in); if (line.empty()) throw FileError("Pixmap has missing colortable-entry."); algorithm::split(list, line, is_any_of(" \t")); @@ -166,19 +182,21 @@ void CPixmap::read(std::ifstream& in) character = list[0]; if (character.length() != m_fileheader.nChar) throw FileError("Pixmap colorcharacter is invalid."); + if (colors.find(character) != colors.end()) + throw FileError("Duplicate colorcharacter found."); /* read colors */ - string color(""); if ((list.size() - 1) % 2 != 0) throw FileError("Pixmap color entrys are invalid."); for(uint32_t j = 1; j < list.size(); j = j + 2) { + /* we only support hex-color notations */ if (list[j + 1].length() != 7) throw FileError("Pixmap color value is invalid."); if (list[j + 1].at(0) != '#') throw FileError("Pixmap color table value is not hexadecimal."); - /* we only support c-colors! */ + /* we only support c-colors! - remove only if you free the pixels */ if (list[j] != "c") continue; @@ -186,15 +204,17 @@ void CPixmap::read(std::ifstream& in) pixel->red = strtoul(list[j + 1].substr(1, 2).c_str(), NULL, 16); pixel->green = strtoul(list[j + 1].substr(3, 2).c_str(), NULL, 16); pixel->blue = strtoul(list[j + 1].substr(5, 2).c_str(), NULL, 16); - colors[ list[j] ] = pixel; + colors[ character ][ list[j] ] = pixel; } /* we only support c-colors! */ - if (colors.find("c") == colors.end()) + if (colors[ character ].find("c") == colors[ character ].end()) throw FileError("Pixmap color entry has missing c-value."); /* add pixel to colortable */ - m_colortable[character] = colors["c"]; + colornr[ character ] = index; + m_colortable[ index ] = colors[ character ]["c"]; + index++; } /* read pixel data */ @@ -206,12 +226,27 @@ void CPixmap::read(std::ifstream& in) for (uint32_t y = 0; y < getHeight(); y++) { - line = getArrayLine(in); + line = getCArrayLine(in); if (line.empty()) throw FileError("Pixmap has no pixel data."); if (line.length() != getWidth()) throw FileError("Pixmap pixeldata width is larger than header width."); - copy(line.c_str(), line.c_str() + line.length(), m_pixeldata + y * getWidth()); + + /* convert color identifier to our own identifiers */ + for(uint32_t x = 0; x < getWidth(); x++) + { + character = line.substr(x * m_fileheader.nChar, m_fileheader.nChar); + if (colornr.find(character) == colornr.end()) + throw FileError("Pixel has no reference in colortable."); + + uint32_t offset = y * getWidth() + x; + + /* boundary check */ + if (offset * sizeof(uint32_t) + sizeof(uint32_t) > getPixelDataSize()) + throw FileError("Pixel position is out of range."); + + *((uint32_t *)m_pixeldata + offset) = colornr[ character ]; + } } } @@ -221,28 +256,32 @@ void CPixmap::read(std::ifstream& in) if (!in.good()) throw FileError("Pixmap array isn't closed properly."); - /* get pixelformat instance */ - m_pixelformat = NULL; - set::iterator it; - for (it = m_handlers.begin(); it != m_handlers.end(); it++) + /* set rowsize */ + m_rowsize = sizeof(uint32_t) * getWidth(); +} + +/*----------------------------------------------------------------------------*/ + +const std::string CPixmap::getXPMColorID(unsigned int index, unsigned int length) +{ + static const char code[] = PIXMAP_COLORCHARS; + string str(""); + for(unsigned int i = length - 1; i > 0; i--) { - /* we only have one! */ - m_pixelformat = *it; - break; + str += code[index % strlen(code)]; + index /= strlen(code); } - if (m_pixelformat == NULL) - throw FileError("Pixmap color mode is not supported."); - -#ifdef DEBUG - /* debug*/ - CPixmap::dump(cout); -#endif + str += code[index]; + return str; } /*----------------------------------------------------------------------------*/ void CPixmap::write(std::ofstream& out) { + m_fileheader.nColor = m_colortable.size(); + m_fileheader.nChar = m_fileheader.nColor / strlen(PIXMAP_COLORCHARS) + 1; + /* header comment */ out << PIXMAP_IDENTIFIER << endl; @@ -259,10 +298,10 @@ void CPixmap::write(std::ofstream& out) out << "\"," << endl; /* color table */ - map::iterator it; + map::iterator it; for (it = m_colortable.begin(); it != m_colortable.end(); it++) { - out << "\"" << (*it).first; + out << "\"" << getXPMColorID((*it).first, m_fileheader.nChar); /* we only support c-colors! */ out << "\tc #"; out << setfill('0') << setw(2) << hex << uppercase << (*it).second->red @@ -275,8 +314,20 @@ void CPixmap::write(std::ofstream& out) for (uint32_t y = 0; y < getHeight(); y++) { out << "\""; - uint32_t offset = y * getWidth(); - copy(m_pixeldata + offset, m_pixeldata + offset + getWidth(), ostream_iterator(out)); + for(uint32_t x = 0; x < getWidth(); x++) + { + uint32_t offset = y * getWidth() + x; + + /* boundary check */ + if (offset * sizeof(uint32_t) + sizeof(uint32_t) > getPixelDataSize()) + throw FileError("Pixel position is out of range."); + + uint32_t color = *((uint32_t *)m_pixeldata + offset); + + if ((it = m_colortable.find(color)) == m_colortable.end()) + throw FileError("Pixel has no reference in colortable."); + out << getXPMColorID((*it).first, m_fileheader.nChar); + } out << "\"," << endl; } @@ -292,16 +343,6 @@ void CPixmap::write(std::ofstream& out) #ifdef DEBUG void CPixmap::dump(std::ostream& out) { - /* pixeldata */ - cout << "[XPM Pixel Data]" << endl; - for (uint32_t y = 0; y < getHeight(); y++) - { - uint32_t offset = y * getWidth(); - copy(m_pixeldata + offset, m_pixeldata + offset + getWidth(), ostream_iterator(cout)); - out << endl; - } - out << endl; - /* values*/ cout << "[XPM Header Values]" << endl << "width=" << m_fileheader.width << endl @@ -316,11 +357,11 @@ void CPixmap::dump(std::ostream& out) << endl; /* colors*/ - map::iterator it; + map::iterator it; cout << "[Color Table]" << endl; for (it = m_colortable.begin(); it != m_colortable.end(); it++) { - out << (*it).first << " " + out << (*it).first << ": " << setfill('0') << setw(3) << (*it).second->red << " " << setfill('0') << setw(3) << (*it).second->green << " " << setfill('0') << setw(3) << (*it).second->blue << " " diff --git a/ue2/imgsynth2/cpixmap.h b/ue2/imgsynth2/cpixmap.h index 66aa1c1..10f2b33 100644 --- a/ue2/imgsynth2/cpixmap.h +++ b/ue2/imgsynth2/cpixmap.h @@ -12,6 +12,8 @@ #include "cbitmap.h" #define PIXMAP_IDENTIFIER "/* XPM */" +#define PIXMAP_COLORCHARS ".#abcdefghijklmnopqrstuvwxyzABCD" \ + "EFGHIJKLMNOPQRSTUVWXYZ0123456789" /** * @class CPixmap @@ -87,23 +89,45 @@ class CPixmap : public CBitmap void dump(std::ostream& out); #endif - /* TODO */ + /** + * @method getPixelDataSize + * @brief Return size of pixelbuffer + * @param - + * @return size of pixelbuffer + * @globalvars none + * @exception none + * @conditions none + */ const uint32_t getPixelDataSize() { - return m_fileheader.width * m_fileheader.height * m_fileheader.nChar; + return m_fileheader.width * m_fileheader.height * sizeof(uint32_t); } - /* TODO */ + /** + * @method getHeight + * @brief Return height of bitmap in pixel + * @param - + * @return height of bitmap in pixel + * @globalvars none + * @exception none + * @conditions none + */ const uint32_t getHeight() { - /* width and height can be negativ */ return m_fileheader.height; } - /* TODO */ + /** + * @method getWidth + * @brief Return width of bitmap in pixel + * @param - + * @return width of bitmap in pixel + * @globalvars none + * @exception none + * @conditions none + */ const uint32_t getWidth() { - /* width and height can be negativ */ return m_fileheader.width; } @@ -122,7 +146,15 @@ class CPixmap : public CBitmap return true; } - /* TODO */ + /** + * @method isMirrored + * @brief Windows Bitmaps can be stored upside down + * @param - + * @return true if bitmap is stored upside down. false otherwise + * @globalvars none + * @exception none + * @conditions none + */ const bool isMirrored() { /* pixmap is never mirrored */ @@ -130,10 +162,40 @@ class CPixmap : public CBitmap } protected: - /** TODO */ + /** + * @method getLine + * @brief read trimmed line (terminated by \n) from filestream + * @param in filestream to read data from + * @param ignore_comments true: ignore c-like comments + * @return return trimmed line from filestream + * @globalvars none + * @exception none + * @conditions none + */ std::string getLine(std::ifstream& in, bool ignore_comments = true); - /** TODO */ - std::string getArrayLine(std::ifstream& in, bool ignore_comments = true); + + /** + * @method getArrayLine + * @brief read trimmed c-arrayline from filestream + * @param in filestream to read data from + * @return return trimmed c-arrayline from filestream + * @globalvars none + * @exception FileError + * @conditions none + */ + std::string getCArrayLine(std::ifstream& in); + + /** + * @method getXPMColorID + * @brief get xpm color identifier, generated using an index + * @param index index used to generate the xpm color identifier + * @param length length of xpm color identifier + * @return return xpm color identifier, generated using index + * @globalvars none + * @exception FileError + * @conditions none + */ + const std::string getXPMColorID(unsigned int index, unsigned int length); /** * @brief Pixmap Header structure @@ -163,9 +225,8 @@ class CPixmap : public CBitmap /* members */ /** fileheader */ PIXMAP_FILEHEADER m_fileheader; - /** TODO */ + /** name of image/c-array */ std::string m_imagename; - /** TODO convert PIXMAP_FILEHEADER to member variables */ }; #endif diff --git a/ue2/imgsynth2/cwindowsbitmap.cpp b/ue2/imgsynth2/cwindowsbitmap.cpp index ddacab9..d561465 100644 --- a/ue2/imgsynth2/cwindowsbitmap.cpp +++ b/ue2/imgsynth2/cwindowsbitmap.cpp @@ -75,6 +75,11 @@ void CWindowsBitmap::read(std::ifstream& in) } 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 + ); } /*----------------------------------------------------------------------------*/ diff --git a/ue2/imgsynth2/test/input_yellow_man1_indexed8 b/ue2/imgsynth2/test/input_yellow_man1_indexed8 index c0385c3..84c4604 100644 --- a/ue2/imgsynth2/test/input_yellow_man1_indexed8 +++ b/ue2/imgsynth2/test/input_yellow_man1_indexed8 @@ -4,7 +4,7 @@ read(XPM, test/yellow_man1_indexed8_in.xpm) -#fillrect(0,3,6,5,0,255,0) -#fillrect(2,13,7,4,0,0,255) +fillrect(0,3,6,5,0,255,0) +fillrect(2,13,7,4,0,0,255) write(XPM, test/yellow_man1_indexed8_out.xpm) diff --git a/ue2/imgsynth2/test/input_yellow_man2_indexed8 b/ue2/imgsynth2/test/input_yellow_man2_indexed8 new file mode 100644 index 0000000..440c653 --- /dev/null +++ b/ue2/imgsynth2/test/input_yellow_man2_indexed8 @@ -0,0 +1,13 @@ +#in: test/yellow_man2_indexed8_in.xpm +#out: test/yellow_man2_indexed8_out.xpm +#ref: test/yellow_man2_indexed8_ref.xpm + +read(XPM, test/yellow_man2_indexed8_in.xpm) + +fillrect(0,3,6,5,0,255,0) +fillrect(2,13,7,4,0,0,255) +mirror_x() +mirror_y() +invert() + +write(XPM, test/yellow_man2_indexed8_out.xpm) diff --git a/ue2/imgsynth2/test/yellow_man1_indexed8_ref.xpm b/ue2/imgsynth2/test/yellow_man1_indexed8_ref.xpm index bd3beb4..7526656 100644 --- a/ue2/imgsynth2/test/yellow_man1_indexed8_ref.xpm +++ b/ue2/imgsynth2/test/yellow_man1_indexed8_ref.xpm @@ -3,22 +3,27 @@ static char * yellow_man1_default_xpm[] = { "9 17 4 1 0 0 XPMEXT", ". c #000000", "# c #FFF200", -"+ c #00FF00", -"@ c #0000FF", +"b c #00FF00", +"c c #0000FF", ".........", ".........", "...###...", -"++++++...", -"++++++...", -"++++++...", -"++++++#..", -"++++++.#.", +"bbbbbb...", +"bbbbbb...", +"bbbbbb...", +"bbbbbb#..", +"bbbbbb.#.", ".#.###.#.", ".#.###.#.", ".#.###.#.", "...#.#...", "...#.#...", -"..@@@@@@@", -"..@@@@@@@", -"..@@@@@@@", -"..@@@@@@@"}; +"..ccccccc", +"..ccccccc", +"..ccccccc", +"..ccccccc", +"XPMEXT ext1 data1", +"XPMEXT ext2", +"data2_1", +"data2_2", +"XPMENDEXT"}; \ No newline at end of file diff --git a/ue2/imgsynth2/test/yellow_man2_indexed8_in.xpm b/ue2/imgsynth2/test/yellow_man2_indexed8_in.xpm new file mode 100644 index 0000000..bd11b48 --- /dev/null +++ b/ue2/imgsynth2/test/yellow_man2_indexed8_in.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static char * yellow_man1_default_xpm[] = { +"9 17 2 1 0 0 XPMEXT", +". c #000000 g4 #000000", +"# c #FFF200", +".........", +".........", +"...###...", +"...###...", +"...###...", +"....#....", +"..#####..", +".#.###.#.", +".#.###.#.", +".#.###.#.", +".#.###.#.", +"...#.#...", +"...#.#...", +"...#.#...", +"...#.#...", +".........", +".........", +"XPMEXT ext1 data1", +"XPMEXT ext2", +"data2_1", +"data2_2", +"XPMENDEXT"}; diff --git a/ue2/imgsynth2/test/yellow_man2_indexed8_ref.xpm b/ue2/imgsynth2/test/yellow_man2_indexed8_ref.xpm new file mode 100644 index 0000000..5ff048f --- /dev/null +++ b/ue2/imgsynth2/test/yellow_man2_indexed8_ref.xpm @@ -0,0 +1,29 @@ +/* XPM */ +static char * yellow_man1_default_xpm[] = { +"9 17 4 1 0 0 XPMEXT", +". c #FFFFFF", +"# c #000DFF", +"b c #FF00FF", +"c c #FFFF00", +"ccccccc..", +"ccccccc..", +"ccccccc..", +"ccccccc..", +"...#.#...", +"...#.#...", +".#.###.#.", +".#.###.#.", +".#.###.#.", +".#.bbbbbb", +"..#bbbbbb", +"...bbbbbb", +"...bbbbbb", +"...bbbbbb", +"...###...", +".........", +".........", +"XPMEXT ext1 data1", +"XPMEXT ext2", +"data2_1", +"data2_2", +"XPMENDEXT"}; \ No newline at end of file -- cgit v1.2.3