summaryrefslogtreecommitdiffstats
path: root/ue2/imgsynth2/cpixmap.cpp
diff options
context:
space:
mode:
authormanuel <manuel@nc8430.lan>2009-05-01 20:18:51 +0200
committermanuel <manuel@nc8430.lan>2009-05-01 20:18:51 +0200
commitb9ce1555b2baf9be209775dbd4c8b217db5cd735 (patch)
tree9c4b74f4a3f9e323e6d799313f9f59dd7b940fb4 /ue2/imgsynth2/cpixmap.cpp
parent6431d84ffec82db10030d918cfed8e791e62f42c (diff)
downloadooprog-b9ce1555b2baf9be209775dbd4c8b217db5cd735.tar.gz
ooprog-b9ce1555b2baf9be209775dbd4c8b217db5cd735.tar.bz2
ooprog-b9ce1555b2baf9be209775dbd4c8b217db5cd735.zip
rewrote pixmap::read to do more sanity checks
Diffstat (limited to 'ue2/imgsynth2/cpixmap.cpp')
-rw-r--r--ue2/imgsynth2/cpixmap.cpp422
1 files changed, 243 insertions, 179 deletions
diff --git a/ue2/imgsynth2/cpixmap.cpp b/ue2/imgsynth2/cpixmap.cpp
index 6f8c8d6..d3e10d8 100644
--- a/ue2/imgsynth2/cpixmap.cpp
+++ b/ue2/imgsynth2/cpixmap.cpp
@@ -5,25 +5,23 @@
5 * @date 27.04.2009 5 * @date 27.04.2009
6 */ 6 */
7 7
8#include <sstream>
9#include <iomanip>
10#include <vector>
11#include <boost/algorithm/string/split.hpp>
12#include <boost/algorithm/string.hpp>
8#include <boost/lexical_cast.hpp> 13#include <boost/lexical_cast.hpp>
9#include <boost/numeric/conversion/cast.hpp>
10
11#ifdef DEBUG 14#ifdef DEBUG
12# include <iostream> 15# include <iostream>
13#endif 16#endif
14#include <cstdlib>
15#include <stdint.h>
16# include <string>
17# include <map>
18
19
20
21#include "cpixmap.h" 17#include "cpixmap.h"
22#include "cpixelformat_indexed8.h" 18#include "cpixelformat_indexed8.h"
23 19
24using namespace std; 20using namespace std;
21using namespace boost;
25 22
26CPixmap::CPixmap() 23CPixmap::CPixmap()
24 : m_imagename("")
27{ 25{
28 m_types.insert("XPM"); 26 m_types.insert("XPM");
29 27
@@ -33,236 +31,302 @@ CPixmap::CPixmap()
33 31
34/*----------------------------------------------------------------------------*/ 32/*----------------------------------------------------------------------------*/
35 33
36void CPixmap::read(std::ifstream& in) 34std::string CPixmap::getLine(std::ifstream& in, bool ignore_comments)
37{ 35{
36 string line("");
37 while(!in.eof() && in.good())
38 {
39 getline(in, line);
40 trim(line);
41 /* ignore simple ansi c comments. only one-liners */
42 if (ignore_comments && line.find_first_of("/*") == 0)
43 continue;
44 if (!line.empty())
45 break;
46 }
47 return line;
48}
38 49
39 string str; 50/*----------------------------------------------------------------------------*/
40 m_fileheader._XPMEXT = false;
41 m_fileheader._HOTSPOT = false;
42 51
43 /* parse the values section */ 52std::string CPixmap::getArrayLine(std::ifstream& in, bool ignore_comments)
44 getline( in, str, '"'); 53{
45 getline( in, str, '"'); 54 string line = getLine(in, ignore_comments);
46 stringstream istr (str ); 55 if (line.empty())
56 return line;
57
58 /* this stuff isn't correct too, but we are no c-parser anyway */
59 if (line[0] != '"')
60 throw FileError("Pixmap array has invalid c-syntax.");
61 if (line[line.length() - 1] != ',' && line[line.length() - 1] != '}')
62 throw FileError("Pixmap array has invalid c-syntax.");
63 size_t end = line.find_last_of("\"");
64 if (end == string::npos)
65 throw FileError("Pixmap array has invalid c-syntax.");
66
67 return line.substr(1, end - 1);
68}
47 69
48 istr >> m_fileheader.xpmWidth ; 70/*----------------------------------------------------------------------------*/
49 istr >> m_fileheader.xpmHeight ; 71
50 istr >> m_fileheader.nColor ; 72void CPixmap::read(std::ifstream& in)
51 istr >> m_fileheader.nChar ; 73{
74 /*
75 * <C-Comment> XPM <C-Comment>
76 * static char * <pixmap_name>[] = {
77 * <Values>
78 * <Colors>
79 * <Pixels>
80 * <Extensions>
81 * };
82 */
83
84 string line, tmp;
85 stringstream istr;
86 std::vector<std::string> list;
87 m_fileheader._XPMEXT = false;
88 m_fileheader._HOTSPOT = false;
52 89
53 /*optional values */ 90 /* first line has to be PIXMAP_IDENTIFIER */
54 if (istr.good()) 91 line = getLine(in, false);
92 if (line != PIXMAP_IDENTIFIER)
93 throw FileError("Pixmap has no identifier.");
94
95 /* second line is a c array. we don't do much syntax checking */
96 line = getLine(in);
97 istr.str(line);
98 while(m_imagename.empty() && !istr.eof() && istr.good())
55 { 99 {
56 string tmp; 100 size_t end;
57 istr >> tmp; 101 istr >> tmp;
58 if(tmp.compare("XPMEXT") == 0) 102 if ((end = tmp.find_first_of("[]")) != string::npos)
59 m_fileheader._XPMEXT = true;
60 else
61 { 103 {
62 m_fileheader._HOTSPOT = true; 104 /* <xxx>*<imagename>[]<yyy> */
63 m_fileheader.xHotspot = static_cast<unsigned int>(strtoul(tmp.c_str(), NULL, 16)); 105 size_t start = tmp.find_first_of('*');
64 istr >> m_fileheader.yHotspot; 106 start = (start == string::npos) ? 0 : start + 1;
107 m_imagename = tmp.substr(start, end - start);
65 } 108 }
66 if (istr.good()) 109 }
110 if (m_imagename.empty())
111 throw FileError("Pixmap has no imagename.");
112
113 /* additional: check "{" exists */
114 if (line[line.length() - 1] != '{')
115 throw FileError("Pixmap array has no opening bracket.");
116
117 /* parse <Values>-section */
118 line = getArrayLine(in);
119 if (line.empty())
120 throw FileError("Pixmap has no Values-section.");
121 algorithm::split(list, line, is_any_of(" \t"));
122 if (list.size() < 4)
123 throw FileError("Pixmap has invalid Values-section.");
124 try
125 {
126 m_fileheader.width = lexical_cast<uint32_t>(list[0]);
127 m_fileheader.height = lexical_cast<uint32_t>(list[1]);
128 m_fileheader.nColor = lexical_cast<uint32_t>(list[2]);
129 m_fileheader.nChar = lexical_cast<uint32_t>(list[3]);
130
131 if (list.size() > 4)
67 { 132 {
68 istr >> tmp; 133 if (list.size() >= 6)
69 if (tmp.compare("XPMEXT") == 0) 134 {
70 m_fileheader._XPMEXT = true; 135 m_fileheader._HOTSPOT = true;
136 m_fileheader.xHotspot = lexical_cast<uint32_t>(list[4]);
137 m_fileheader.yHotspot = lexical_cast<uint32_t>(list[5]);
138 }
139 if (list.size() != 6)
140 {
141 if (list[list.size() - 1] != "XPMEXT")
142 throw FileError("Unknown parameter count in Values-Section.");
143 else
144 m_fileheader._XPMEXT = true;
145 }
71 } 146 }
72 } 147 }
148 catch(bad_lexical_cast& ex)
149 {
150 throw FileError("Value of Values-section is invalid: " + string(ex.what()));
151 }
73 152
153 /* parse <Colors>-table */
154 string character;
155 map<string, CPixelFormat::RGBPIXEL *> colors;
156 for(uint32_t i = 0; i < m_fileheader.nColor; i++)
157 {
158 line = getArrayLine(in);
159 if (line.empty())
160 throw FileError("Pixmap has missing colortable-entry.");
161 algorithm::split(list, line, is_any_of(" \t"));
162 if (list.size() < 3)
163 throw FileError("Pixmap colortable-entry is invalid.");
164
165 /* read pixel character */
166 character = list[0];
167 if (character.length() != m_fileheader.nChar)
168 throw FileError("Pixmap colorcharacter is invalid.");
169
170 /* read colors */
171 string color("");
172 if ((list.size() - 1) % 2 != 0)
173 throw FileError("Pixmap color entrys are invalid.");
174 for(uint32_t j = 1; j < list.size(); j = j + 2)
175 {
176 if (list[j + 1].length() != 7)
177 throw FileError("Pixmap color value is invalid.");
178 if (list[j + 1].at(0) != '#')
179 throw FileError("Pixmap color table value is not hexadecimal.");
180
181 /* we only support c-colors! */
182 if (list[j] != "c")
183 continue;
184
185 CPixelFormat::RGBPIXEL *pixel = new CPixelFormat::RGBPIXEL;
186 pixel->red = strtoul(list[j + 1].substr(1, 2).c_str(), NULL, 16);
187 pixel->green = strtoul(list[j + 1].substr(3, 2).c_str(), NULL, 16);
188 pixel->blue = strtoul(list[j + 1].substr(5, 2).c_str(), NULL, 16);
189 colors[ list[j] ] = pixel;
190 }
74 191
192 /* we only support c-colors! */
193 if (colors.find("c") == colors.end())
194 throw FileError("Pixmap color entry has missing c-value.");
75 195
76 /* parse color table*/ 196 /* add pixel to colortable */
77 getline( in, str, '"'); 197 m_colortable[character] = colors["c"];
78 string character, mode, colors;
79 for (unsigned int i = 0; i < m_fileheader.nColor; i++ )
80 {
81 getline( in, str, '"' );
82 stringstream istr2 (str );
83
84 istr2 >> character;
85 istr2 >> mode;
86 istr2 >> colors;
87
88 if ( colors.size() != 7)
89 throw FileError("Pixmap color tabel is invalid.");
90 if ( colors.at(0) != '#')
91 throw FileError("Pixmap color tabel value is not hexadecimal.");
92
93 xpmColors[character][mode] = new (nothrow) unsigned int[3];
94 if (xpmColors[character][mode] == 0)
95 throw FileError("Bad color table allocation.");
96
97 xpmColors[character][mode][0] =
98 static_cast<unsigned int>(strtoul(colors.substr(1,2).c_str(), NULL, 16));
99 xpmColors[character][mode][1] =
100 static_cast<unsigned int>(strtoul(colors.substr(3,2).c_str(), NULL, 16));
101 xpmColors[character][mode][2] =
102 static_cast<unsigned int>(strtoul(colors.substr(5,2).c_str(), NULL, 16));
103
104
105
106
107
108
109 getline( in, str, '"' );
110 } 198 }
111 199
112 /* read pixel data using separate class */ 200 /* read pixel data */
113 if (getPixelDataSize() > 0) 201 if (getPixelDataSize() > 0)
114 { 202 {
115 if (m_pixeldata != NULL) 203 if (m_pixeldata != NULL)
116 delete[] m_pixeldata; 204 delete[] m_pixeldata;
117 m_pixeldata = new uint8_t[getPixelDataSize()]; 205 m_pixeldata = new uint8_t[getPixelDataSize()];
118
119 for (unsigned int y = 0; y < getHeight(); y++ )
120 {
121 for (unsigned int x = 0; x < getWidth(); x++ )
122 m_pixeldata[y * getWidth() + x] = static_cast<uint8_t>(in.get());
123 206
124 getline( in, str); 207 for (uint32_t y = 0; y < getHeight(); y++)
125 if ( y != ( getHeight() - 1 )) 208 {
126 in.get(); 209 line = getArrayLine(in);
127 210 if (line.empty())
211 throw FileError("Pixmap has no pixel data.");
212 if (line.length() != getWidth())
213 throw FileError("Pixmap pixeldata width is larger than header width.");
214 copy(line.c_str(), line.c_str() + line.length(), m_pixeldata + y * getWidth());
128 } 215 }
129 } 216 }
130 217
131 /* parse extension */ 218 /* get extension */
132 if ( m_fileheader._XPMEXT ) 219 if (m_fileheader._XPMEXT)
133 getline( in, m_fileheader.extension, '}' ); 220 getline(in, m_fileheader.extension, '}');
134 /* debug*/ 221 if (!in.good())
135 CPixmap::dump (cout); 222 throw FileError("Pixmap array isn't closed properly.");
136 223
137 /* get pixelformat instance */ 224 /* get pixelformat instance */
138 m_pixelformat = NULL; 225 m_pixelformat = NULL;
139 set<CPixelFormat *>::iterator it; 226 set<CPixelFormat *>::iterator it;
140 for (it = m_handlers.begin(); it != m_handlers.end(); it++) 227 for (it = m_handlers.begin(); it != m_handlers.end(); it++)
141 { 228 {
142 /* check color mode */ 229 /* we only have one! */
143 //TODO if (mode.compare((*it)->getColorMode()) == 0) 230 m_pixelformat = *it;
144 if (mode == "c") 231 break;
145 {
146 m_pixelformat = *it;
147 break;
148 }
149 } 232 }
150 if (m_pixelformat == NULL) 233 if (m_pixelformat == NULL)
151 throw FileError("Pixmap color mode \""+mode+"\" is not supported."); 234 throw FileError("Pixmap color mode is not supported.");
235
236#ifdef DEBUG
237 /* debug*/
238 CPixmap::dump(cout);
239#endif
152} 240}
153 241
154/*----------------------------------------------------------------------------*/ 242/*----------------------------------------------------------------------------*/
155 243
156void CPixmap::write(std::ofstream& out, std::string& filename) 244void CPixmap::write(std::ofstream& out)
157{ 245{
158
159 /* header comment */ 246 /* header comment */
160 out<<"/* XPM */"<<endl; 247 out << PIXMAP_IDENTIFIER << endl;
161 248
162 /* variables*/ 249 /* variables*/
163 out<<"static char * " 250 out << "static char * " << m_imagename << "[] = {" << endl;
164 <<filename.substr(filename.find_last_of("/\\") + 1, filename.size()) 251 out << "\"" << m_fileheader.width << " " << m_fileheader.height
165 <<"[] = {"<<endl; 252 << " " << m_fileheader.nColor << " " << m_fileheader.nChar;
166 out<<"\""<<m_fileheader.xpmWidth<<" "<<m_fileheader.xpmHeight 253
167 <<" "<<m_fileheader.nColor<<" "<<m_fileheader.nChar; 254 /* optional values */
168 255 if (m_fileheader._HOTSPOT)
169 /*optional values*/ 256 out << " " << m_fileheader.xHotspot << " " << m_fileheader.yHotspot;
170 if( m_fileheader._HOTSPOT ) 257 if (m_fileheader._XPMEXT)
171 out<<" "<<m_fileheader.xHotspot<<" "<<m_fileheader.yHotspot; 258 out << " " << "XPMEXT";
172 if( m_fileheader._XPMEXT ) 259 out << "\"," << endl;
173 out<<" "<<"XPMEXT"; 260
174 out <<"\","<<endl; 261 /* color table */
175 262 map<string, CPixelFormat::RGBPIXEL *>::iterator it;
176 /* color table */ 263 for (it = m_colortable.begin(); it != m_colortable.end(); it++)
177 map<string, map<string, uint32_t* > >::iterator it1; 264 {
178 map<string, uint32_t* >::iterator it2; 265 out << "\"" << (*it).first;
179 266 /* we only support c-colors! */
180 for ( it1= xpmColors.begin() ; it1 != xpmColors.end(); it1++ ) 267 out << "\tc #";
181 { 268 out << setfill('0') << setw(2) << hex << uppercase << (*it).second->red
182 out << "\""<<(*it1).first; 269 << setfill('0') << setw(2) << hex << uppercase << (*it).second->green
183 for ( it2=(*it1).second.begin() ; it2 != (*it1).second.end(); it2++ ) 270 << setfill('0') << setw(2) << hex << uppercase << (*it).second->blue;
184 { 271 out << "\"," << endl;
185
186 out<<"\t" <<(*it2).first<<"\t#";
187
188 for (int i = 0 ; i < 3; i++ )
189 {
190 out.width(2);
191 out << hex <<uppercase<<(*it2).second[i];
192 out.fill('0');
193 }
194 }
195 out<<"\","<<endl;
196 } 272 }
197 273
198 /* pixel data */ 274 /* pixel data */
199 for (unsigned int y = 0; y < getHeight(); y++ ){ 275 //TODO: better via copy?
200 out <<"\""; 276 for (uint32_t y = 0; y < getHeight(); y++)
201 for (unsigned int x = 0; x < getWidth(); x++ ) 277 {
278 out << "\"";
279 for (uint32_t x = 0; x < getWidth(); x++)
202 out << m_pixeldata[y * getWidth() + x]; 280 out << m_pixeldata[y * getWidth() + x];
203 out <<"\""; 281 out << "\"," << endl;
204 if ( y != ( getHeight() - 1 ))
205 out <<",";
206 out <<endl;
207 } 282 }
208 283
209 /* extension */ 284 /* extension */
210 if (m_fileheader._XPMEXT) 285 if (m_fileheader._XPMEXT)
211 out << m_fileheader.extension; 286 out << m_fileheader.extension;
212
213 out <<"};";
214 287
288 out <<"};";
215} 289}
216 290
217
218/*----------------------------------------------------------------------------*/ 291/*----------------------------------------------------------------------------*/
219 292
220#ifdef DEBUG 293#ifdef DEBUG
221void CPixmap::dump(std::ostream& out) 294void CPixmap::dump(std::ostream& out)
222{ 295{
223 296 /* pixeldata */
224 /* pixeldata */ 297 cout << "[XPM Pixel Data]" << endl;
225 cout<<endl<<"(_Pixel data:_)"<<endl; 298 for (uint32_t y = 0; y < getHeight(); y++)
226 for (unsigned int y = 0; y < getHeight(); y++ ){ 299 {
227 for (unsigned int x = 0; x < getWidth(); x++ ) 300 for (uint32_t x = 0; x < getWidth(); x++)
228 out << m_pixeldata[y * getWidth() + x]; 301 out << m_pixeldata[y * getWidth() + x];
229 out << endl; 302 out << endl;
230 } 303 }
231 304 out << endl;
305
232 /* values*/ 306 /* values*/
233 cout<<endl<<"(_Values:_)"<<endl; 307 cout << "[XPM Header Values]" << endl
234 out << "XPM Header:" << endl 308 << "width=" << m_fileheader.width << endl
235 << "xpmWidth=" << m_fileheader.xpmWidth<< endl 309 << "height=" << m_fileheader.height << endl
236 << "xpmHeight=" << m_fileheader.xpmHeight<< endl 310 << "nColor=" << m_fileheader.nColor << endl
237 << "nColor=" << m_fileheader.nColor<< endl 311 << "nChar=" << m_fileheader.nChar << endl
238 << "nChar=" << m_fileheader.nChar<< endl 312 << "Hotspot=" << m_fileheader.xHotspot << endl
239 << "Hotspot=" << m_fileheader.xHotspot<< endl 313 << "yHotspot=" << m_fileheader.yHotspot << endl
240 << "yHotspot=" << m_fileheader.yHotspot<< endl 314 << "_HOTSPOT=" << m_fileheader._HOTSPOT << endl
241 << "_HOTSPOT=" << m_fileheader._HOTSPOT<< endl 315 << "_XPMEXT=" << m_fileheader._XPMEXT << endl
242 << "_XPMEXT=" << m_fileheader._XPMEXT<< endl 316 << "extension=" << m_fileheader.extension << endl
243 << "extension=" << m_fileheader.extension<< endl 317 << endl;
244 << endl;
245 318
246 /* colors*/ 319 /* colors*/
247 map<string, map<string, uint32_t* > >::iterator it1; 320 map<string, CPixelFormat::RGBPIXEL *>::iterator it;
248 map<string, uint32_t* >::iterator it2; 321 cout << "[Color Table]" << endl;
249 cout<<"(_Color table:_)"<<endl; 322 for (it = m_colortable.begin(); it != m_colortable.end(); it++)
250 for ( it1= xpmColors.begin() ; it1 != xpmColors.end(); it1++ ) 323 {
251 { 324 out << (*it).first << " "
252 out << (*it1).first; 325 << setfill('0') << setw(3) << (*it).second->red << " "
253 for ( it2=(*it1).second.begin() ; it2 != (*it1).second.end(); it2++ ) 326 << setfill('0') << setw(3) << (*it).second->green << " "
254 { 327 << setfill('0') << setw(3) << (*it).second->blue << " "
255 out <<" "<< (*it2).first <<" "; 328 << endl;
256 for (int i = 0 ; i < 3; i++ )
257 {
258 out.width(3);
259 out << (*it2).second[i]<<" ";
260 out.fill('0');
261 }
262 out<<endl;
263 }
264 } 329 }
265
266} 330}
267#endif 331#endif
268 332