Download | Plain Text | No Line Numbers


  1. /**
  2.  * @module cbitmap
  3.  * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
  4.  * @brief Abstract implementation of CFile handling Bitmaps.
  5.  * @date 17.04.2009
  6.  */
  7.  
  8. #include <algorithm>
  9. #include <boost/lexical_cast.hpp>
  10. #include <boost/numeric/conversion/cast.hpp>
  11. #include <assert.h>
  12. #include "cbitmap.h"
  13.  
  14. using namespace std;
  15.  
  16. /*----------------------------------------------------------------------------*/
  17.  
  18. CBitmap::~CBitmap()
  19. {
  20. /* delete pixeldata */
  21. if (m_pixeldata != NULL)
  22. delete[] m_pixeldata;
  23. m_pixeldata = NULL;
  24.  
  25. /* delete pixelformat handlers */
  26. set<CPixelFormat *>::iterator it;
  27. for (it = m_handlers.begin(); it != m_handlers.end(); it++)
  28. delete *it;
  29. m_pixelformat = NULL;
  30.  
  31. /* delete colortable content */
  32. map<uint32_t, CPixelFormat::RGBPIXEL *>::iterator it2;
  33. for(it2 = m_colortable.begin(); it2 != m_colortable.end(); it2++)
  34. delete (*it2).second;
  35. }
  36.  
  37. /*----------------------------------------------------------------------------*/
  38.  
  39. void CBitmap::callFunc(const std::string& func, const std::list<std::string>& params)
  40. {
  41. if (func.empty())
  42. throw FileError("Function name is empty.");
  43.  
  44. if (func == "fillrect")
  45. fillrect(params);
  46. else if (func == "brightness")
  47. brightness(params);
  48. else if (func == "mirror_x")
  49. mirror_x(params);
  50. else if (func == "mirror_y")
  51. mirror_y(params);
  52. else if (func == "invert")
  53. invert(params);
  54. else
  55. throw FileError("Unknown function '" + func + "'.");
  56. }
  57.  
  58. /*----------------------------------------------------------------------------*/
  59.  
  60. void CBitmap::fillrect(std::list<std::string> params)
  61. {
  62. /* check prerequirements */
  63. if (params.size() != 7)
  64. throw FileError("Invalid number of function parameters (must be 7).");
  65.  
  66. /* do nothing if no pixel exists */
  67. if (m_pixeldata == NULL || m_pixelformat == NULL)
  68. return;
  69.  
  70. /* convert parameters */
  71. uint32_t pparams[7];
  72. int i = 0;
  73. try
  74. {
  75. for(i = 0; i < 7; i++)
  76. {
  77. pparams[i] = boost::lexical_cast<uint32_t>(params.front());
  78. params.pop_front();
  79. }
  80. }
  81. catch(boost::bad_lexical_cast& ex)
  82. {
  83. throw FileError("Invalid parameter (" + params.front() + ").");
  84. }
  85.  
  86. /* check parameter values are in range */
  87. if (pparams[0] < 0 || pparams[0] > getWidth()
  88. || pparams[1] < 0 || pparams[1] > getHeight())
  89. throw FileError("At least one x/y-parameter is out of range.");
  90.  
  91. /* check parameter values are in range */
  92. CPixelFormat::RGBPIXEL pixel;
  93. m_pixelformat->getMaxColor(pixel);
  94. if (pparams[4] < 0 || pparams[4] > pixel.red
  95. || pparams[5] < 0 || pparams[5] > pixel.green
  96. || pparams[6] < 0 || pparams[6] > pixel.blue)
  97. throw FileError("At least one pixel color parameter is out of range.");
  98.  
  99. if (pparams[2] < 0 || pparams[2] + pparams[0] > getWidth()
  100. || pparams[3] < 0 || pparams[3] + pparams[1] > getHeight())
  101. throw FileError("At least one w/h-parameter is out of range.");
  102.  
  103. /* new pixel data */
  104. pixel.red = pparams[4];
  105. pixel.green = pparams[5];
  106. pixel.blue = pparams[6];
  107.  
  108. /* call setPixel for every pixel in the rectangel */
  109. /* NOTE: maybe use std::fill() here? */
  110. for(uint32_t i = pparams[0]; i < pparams[2] + pparams[0]; i++)
  111. {
  112. for(uint32_t j = pparams[1]; j < pparams[3] + pparams[1]; j++)
  113. {
  114. try
  115. {
  116. m_pixelformat->setPixel(pixel, i, j);
  117. }
  118. catch(CPixelFormat::PixelFormatError& ex)
  119. {
  120. stringstream errstr;
  121. errstr << "Can't set pixel (pos=[" << i << "," << j << "] col=["
  122. << pparams[4] << "," << pparams[5] << "," << pparams[6] << "]): "
  123. << ex.what();
  124. throw FileError(errstr.str());
  125. }
  126. }
  127. }
  128. }
  129.  
  130. /*----------------------------------------------------------------------------*/
  131.  
  132. void CBitmap::invert(std::list<std::string> params)
  133. {
  134. /* check prerequirements */
  135. if (params.size() != 0)
  136. throw FileError("Invalid number of function parameters (must be 0).");
  137.  
  138. /* do nothing if no pixel exists */
  139. if (m_pixeldata == NULL || m_pixelformat == NULL)
  140. return;
  141.  
  142. CPixelFormat::RGBPIXEL pixel;
  143. CPixelFormat::RGBPIXEL max;
  144. m_pixelformat->getMaxColor(max);
  145. if (hasColorTable())
  146. {
  147. /* invert every entry in the colortable */
  148. map<uint32_t, CPixelFormat::RGBPIXEL *>::iterator it;
  149. for (it = m_colortable.begin(); it != m_colortable.end(); it++)
  150. {
  151. (*it).second->red = max.red - (*it).second->red;
  152. (*it).second->green = max.green - (*it).second->green;
  153. (*it).second->blue = max.blue - (*it).second->blue;
  154. }
  155. }
  156. else
  157. {
  158. /* invert per pixel */
  159. for(uint32_t y = 0; y < getHeight(); y++)
  160. {
  161. for(uint32_t x = 0; x < getWidth(); x++)
  162. {
  163. try
  164. {
  165. m_pixelformat->getPixel(pixel, x, y);
  166. pixel.red = max.red - pixel.red;
  167. pixel.green = max.green - pixel.green;
  168. pixel.blue = max.blue - pixel.blue;
  169. m_pixelformat->setPixel(pixel, x, y);
  170. }
  171. catch(CPixelFormat::PixelFormatError& ex)
  172. {
  173. stringstream errstr;
  174. errstr << "Can't invert pixel (pos=[" << x << "," << y << "]): "
  175. << ex.what();
  176. throw FileError(errstr.str());
  177. }
  178. }
  179. }
  180. }
  181. }
  182.  
  183. /*----------------------------------------------------------------------------*/
  184.  
  185. void CBitmap::brightness(std::list<std::string> params)
  186. {
  187. /* check prerequirements */
  188. if (params.size() != 1)
  189. throw FileError("Invalid number of function parameters (must be 1).");
  190.  
  191. /* do nothing if no pixel exists */
  192. if (m_pixeldata == NULL || m_pixelformat == NULL)
  193. return;
  194.  
  195. /* convert parameters */
  196. float factor;
  197. try
  198. {
  199. factor = boost::lexical_cast<float>(params.front());
  200. params.pop_front();
  201. }
  202. catch(boost::bad_lexical_cast& ex)
  203. {
  204. throw FileError("Invalid parameter (" + params.front() + ").");
  205. }
  206.  
  207. /* negative factor doesn't make sense */
  208. if (factor < 0)
  209. throw FileError("Brightness parameter must be positive.");
  210.  
  211. CPixelFormat::RGBPIXEL pixel;
  212. CPixelFormat::RGBPIXEL max;
  213. m_pixelformat->getMaxColor(max);
  214. if (hasColorTable())
  215. {
  216. /* change every entry in the colortable */
  217. map<uint32_t, CPixelFormat::RGBPIXEL *>::iterator it;
  218. for (it = m_colortable.begin(); it != m_colortable.end(); it++)
  219. {
  220. (*it).second->red = min(max.red, static_cast<uint32_t>((*it).second->red * factor));
  221. (*it).second->green = min(max.green, static_cast<uint32_t>((*it).second->green * factor));
  222. (*it).second->blue = min(max.blue, static_cast<uint32_t>((*it).second->blue * factor));
  223. }
  224. }
  225. else
  226. {
  227. /* change per pixel */
  228. for(uint32_t y = 0; y < getHeight(); y++)
  229. {
  230. for(uint32_t x = 0; x < getWidth(); x++)
  231. {
  232. try
  233. {
  234. m_pixelformat->getPixel(pixel, x, y);
  235. pixel.red = min(max.red, static_cast<uint32_t>(pixel.red * factor));
  236. pixel.green = min(max.green, static_cast<uint32_t>(pixel.green * factor));
  237. pixel.blue = min(max.blue, static_cast<uint32_t>(pixel.blue * factor));
  238. m_pixelformat->setPixel(pixel, x, y);
  239. }
  240. catch(CPixelFormat::PixelFormatError& ex)
  241. {
  242. stringstream errstr;
  243. errstr << "Can't invert pixel (pos=[" << x << "," << y << "]): "
  244. << ex.what();
  245. throw FileError(errstr.str());
  246. }
  247. }
  248. }
  249. }
  250. }
  251.  
  252. /*----------------------------------------------------------------------------*/
  253.  
  254. void CBitmap::mirror_y(std::list<std::string> params)
  255. {
  256. /* check prerequirements */
  257. if (params.size() != 0)
  258. throw FileError("Invalid number of function parameters (must be 0).");
  259.  
  260. /* do nothing if no pixel exists */
  261. if (m_pixeldata == NULL || m_pixelformat == NULL)
  262. return;
  263.  
  264. uint8_t *buf = new uint8_t[m_rowsize];
  265. for(uint32_t i = 0; i < getHeight()/2; i++)
  266. {
  267. uint32_t j = getHeight() - i - 1;
  268. uint32_t offset = i * m_rowsize;
  269. uint32_t backset = j * m_rowsize;
  270.  
  271. /* boundary check */
  272. if (offset + m_rowsize > getPixelDataSize()
  273. || backset + m_rowsize > getPixelDataSize())
  274. throw FileError("Mirrored pixel position is out of range.");
  275.  
  276. /* mirroring, backup lower data first */
  277. copy(m_pixeldata + backset, m_pixeldata + backset + m_rowsize, buf);
  278. copy(m_pixeldata + offset, m_pixeldata + offset + m_rowsize, m_pixeldata + backset);
  279. copy(buf, buf + m_rowsize, m_pixeldata + offset);
  280. }
  281. delete[] buf;
  282. }
  283.  
  284. /*----------------------------------------------------------------------------*/
  285.  
  286. void CBitmap::mirror_x(std::list<std::string> params)
  287. {
  288. /* check prerequirements */
  289. if (params.size() != 0)
  290. throw FileError("Invalid number of function parameters (must be 0).");
  291.  
  292. /* do nothing if no pixel exists */
  293. if (m_pixeldata == NULL || m_pixelformat == NULL)
  294. return;
  295.  
  296. /* calc pixelwidth */
  297. unsigned int pixelwidth = (hasColorTable()) ? sizeof(uint32_t) : m_pixelformat->getBitCount()/8;
  298.  
  299. assert(m_rowsize > 0);
  300. assert(getHeight() > 0);
  301. assert(getWidth() > 0);
  302. assert(getPixelDataSize() > 0);
  303.  
  304. uint8_t *buf = new uint8_t[pixelwidth];
  305. for(uint32_t i = 0; i < getHeight(); i++)
  306. {
  307. uint32_t offset = i * m_rowsize;
  308.  
  309. for(uint32_t j = 0; j <= getWidth()/2; j++)
  310. {
  311. uint32_t poffset = offset + j * pixelwidth;
  312. uint32_t pbackset = offset + getWidth() * pixelwidth - j * pixelwidth;
  313.  
  314. /* boundary check */
  315. if (pbackset > getPixelDataSize())
  316. throw FileError("Mirrored pixel position is out of range.");
  317.  
  318. /* mirroring, backup right data first */
  319. copy(m_pixeldata + pbackset - pixelwidth, m_pixeldata + pbackset, buf);
  320. copy(m_pixeldata + poffset, m_pixeldata + poffset + pixelwidth, m_pixeldata + pbackset - pixelwidth);
  321. copy(buf, buf + pixelwidth, m_pixeldata + poffset);
  322. }
  323. }
  324. delete[] buf;
  325. }
  326.  
  327. /* vim: set et sw=2 ts=2: */
  328.