00001 #include <vrs/image/memoryimage.h>
00002 #include <vrs/color.h>
00003
00004 using VRS::SO;
00005 using VRS::Image;
00006 using VRS::MemoryImage;
00007 using VRS::Color;
00008
00009 #if !defined(WIN32) && !defined(WIN64)
00010 #ifdef __APPLE__
00011 #define strcpy_s(dest,size,src) strlcpy(dest,src,size)
00012 #else
00013 #define strcpy_s(dest,size,src) strcpy(dest,src)
00014 #endif
00015 #define strncpy_s(dest,size,src,count) strncpy(dest,src,size)
00016 #define strtok_s strtok_r
00017 #define sscanf_s sscanf
00018 #endif
00019
00020 class XPMInterpreter
00021 {
00022 public:
00023 XPMInterpreter(char *data[])
00024 {
00025 interpret(&(data[0]));
00026 }
00027
00028 unsigned int width() const { return m_imgWidth; }
00029 unsigned int height() const { return m_imgHeight; }
00030
00031 SO<Image> image() const { return m_image; }
00032
00033 static SO<Image> image(char *data[])
00034 {
00035 XPMInterpreter tmp(data);
00036 return tmp.image();
00037 }
00038
00039 static std::map<std::string, Color> initKnownColors()
00040 {
00041 std::map<std::string, Color> knownColors;
00042 knownColors["none"] = Color(0.0, 0.0, 0.0, 0.0);
00043 knownColors["black"] = Color(0.0, 0.0, 0.0);
00044 knownColors["white"] = Color(1.0, 1.0, 1.0);
00045
00046 knownColors["red"] = Color(1.0, 0.0, 0.0);
00047 knownColors["green"] = Color(0.0, 1.0, 0.0);
00048 knownColors["blue"] = Color(0.0, 0.0, 1.0);
00049
00050 knownColors["cyan"] = Color(0.0, 1.0, 1.0);
00051 knownColors["magenta"] = Color(1.0, 0.0, 1.0);
00052 knownColors["yellow"] = Color(1.0, 1.0, 0.0);
00053
00054 return knownColors;
00055 }
00056
00057 private:
00058 unsigned int m_imgWidth;
00059 unsigned int m_imgHeight;
00060 unsigned int m_colorCount;
00061 unsigned int m_charsPerColor;
00062 std::map<std::string, Color> m_colorMap;
00063 SO<Image> m_image;
00064 std::vector<std::vector<Color> > m_colorData;
00065
00066 static std::map<std::string, Color> s_knownColors;
00067
00068
00069 bool parseValueLine(const std::string &values, unsigned int &width, unsigned int &height, unsigned int &numColors, unsigned int &charsPerColor, unsigned int &hotspotX, unsigned int hotspotY)
00070 {
00071 char *context = NULL, *token = NULL;
00072
00073 const size_t len = values.size() + 1;
00074 char *tokenString = new char[len];
00075 char seps[] = " \t";
00076 tokenString[len - 1] = 0;
00077 strcpy_s(&tokenString[0], len, values.c_str());
00078
00079 unsigned int i = 0;
00080 unsigned int results[6] = { 0, 0, 0, 0, 0, 0 };
00081
00082 token = strtok_s(tokenString, seps, &context);
00083
00084 while (token && i < 6)
00085 {
00086 int count = sscanf_s(token, "%u", &(results[i]));
00087 if (count == 1)
00088 {
00089 ++i;
00090 token = strtok_s(NULL, seps, &context);
00091 }
00092 else
00093 {
00094 token = NULL;
00095 }
00096 }
00097
00098 delete [] tokenString;
00099 if (i >= 4)
00100 {
00101 width = results[0];
00102 height = results[1];
00103 numColors = results[2];
00104 charsPerColor = results[3];
00105 hotspotX = results[4];
00106 hotspotY = results[5];
00107
00108 return true;
00109 }
00110
00111 return false;
00112 }
00113
00114
00115 bool getColorFromString(const std::string &color, Color &result)
00116 {
00117 std::string lcColor = color;
00118 for (size_t i = 0, iEnd = lcColor.size(); i < iEnd; ++i)
00119 {
00120 lcColor[i] = tolower(lcColor[i]);
00121 }
00122
00123 std::map<std::string, Color>::iterator iter = s_knownColors.find(lcColor);
00124 if (iter != s_knownColors.end())
00125 {
00126 result = iter->second;
00127 }
00128 else if (lcColor[0] == '#')
00129 {
00130 unsigned int r = 0, g = 0, b = 0;
00131 if (sscanf(lcColor.c_str(), "#%2x%2x%2x", &r, &g, &b) != 3)
00132 {
00133 return false;
00134 }
00135
00136 result = Color(r / 255.0, g / 255.0, b / 255.0);
00137 }
00138 else if (lcColor[0] == '%')
00139 {
00140 unsigned int h = 0, s = 0, v = 0;
00141 if (sscanf(lcColor.c_str(), "%%%2x%2x%2x", &h, &s, &v) != 3)
00142 {
00143 return false;
00144 }
00145
00146 result = Color::hsv(360.0 * h / 256.0, s / 255.0, v / 255.0);
00147 }
00148 else
00149 {
00150 return false;
00151 }
00152 return true;
00153 }
00154
00155
00156 bool parseColorLine(const std::string &color)
00157 {
00158 bool returnValue = false;
00159
00160 char *context = NULL, *token = NULL;
00161
00162
00163 const int len = (int)color.size() + 1;
00164 char *tokenString = new char[len];
00165 static char colorRep[5];
00166 static const char seps[] = " \t";
00167
00168 colorRep[m_charsPerColor] = 0;
00169 tokenString[len - 1] = 0;
00170 strcpy_s(&tokenString[0], len, color.c_str());
00171
00172 strncpy_s(&colorRep[0], m_charsPerColor + 1, tokenString, m_charsPerColor);
00173 context = tokenString + m_charsPerColor;
00174
00175
00176 std::vector<std::string> colorElements;
00177
00178 token = strtok_s(NULL, seps, &context);
00179
00180 unsigned int cElement = -1;
00181 for (unsigned int i = 0; token; ++i)
00182 {
00183 colorElements.push_back(token);
00184 if (cElement == -1 && strcmp(token, "c") == 0)
00185 {
00186 cElement = i;
00187 }
00188
00189 token = strtok_s(NULL, seps, &context);
00190 }
00191
00192 Color result;
00193 if (cElement != -1 && getColorFromString(colorElements[cElement + 1], result))
00194 {
00195 m_colorMap[std::string(colorRep)] = result;
00196 returnValue = true;
00197 }
00198
00199 delete [] tokenString;
00200
00201 return returnValue;
00202 }
00203
00204
00205 bool parsePixelLine(const std::string &pixels, std::vector<Color> &pixelRow)
00206 {
00207 size_t expectedLength = m_imgWidth * m_charsPerColor;
00208 VRS_Warning(!(pixels.length() > expectedLength), "pixel data corrupt. truncating surplus values");
00209 VRS_Warning(!(pixels.length() < expectedLength), "pixel data corrupt. filling up missing values");
00210
00211 static const Color none(0.0, 0.0, 0.0, 0.0);
00212 std::string pixel;
00213 std::map<std::string, Color>::iterator iter;
00214 for (size_t i = 0, iEnd = (pixels.length() / m_charsPerColor), offset = 0; i < iEnd; ++i, offset += m_charsPerColor)
00215 {
00216 pixel = pixels.substr(offset, m_charsPerColor);
00217 iter = m_colorMap.find(pixel);
00218 pixelRow[i] = (iter != m_colorMap.end() ? iter->second : none);
00219 }
00220
00221 return true;
00222 }
00223
00224
00225 bool interpret(char *data[])
00226 {
00227 bool good = true, success = false;
00228 unsigned int i = 0, pixelRow = 0;
00229 std::string str;
00230 static unsigned int colorBlock, pixelBlock;
00231 while (good)
00232 {
00233 if (good = (data[i] != NULL))
00234 {
00235 str = data[i];
00236
00237 if (i < 1)
00238 {
00239 unsigned int dummy1 = 0, dummy2 = 0;
00240 good = parseValueLine(str, m_imgWidth, m_imgHeight, m_colorCount, m_charsPerColor, dummy1, dummy2);
00241 good &= m_charsPerColor < 5;
00242 VRS_Warning(m_charsPerColor < 5, "only four characters for color represenation allowed");
00243
00244 std::vector<std::vector<Color> > newData(m_imgHeight, std::vector<Color>(m_imgWidth));
00245 m_colorData.swap(newData);
00246 colorBlock = 1 + m_colorCount;
00247 pixelBlock = 1 + m_colorCount + m_imgHeight;
00248 }
00249 else if (i < colorBlock)
00250 {
00251
00252 good = parseColorLine(str);
00253 }
00254 else if (i < pixelBlock)
00255 {
00256
00257 good = parsePixelLine(str, m_colorData[pixelRow]);
00258 success = good;
00259 ++pixelRow;
00260 }
00261 else
00262 {
00263
00264 good = false;
00265 }
00266 ++i;
00267 }
00268 }
00269
00270 if (success)
00271 {
00272 m_image = new MemoryImage(m_imgWidth, m_imgHeight, Image::RGBA);
00273 for (unsigned int r = 0; r < m_imgHeight; ++r)
00274 {
00275 for (unsigned int c = 0; c < m_imgWidth; ++c)
00276 {
00277 m_image->setColor(c, m_imgHeight - r - 1, m_colorData[r][c]);
00278 }
00279 }
00280 }
00281
00282 return good;
00283 }
00284 };
00285
00286 std::map<std::string, Color> XPMInterpreter::s_knownColors = XPMInterpreter::initKnownColors();