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/cpixmap.cpp | 125 ++++++++++++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 42 deletions(-) (limited to 'ue2/imgsynth2/cpixmap.cpp') 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 << " " -- cgit v1.2.3