PolyImage.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /*
  2. Copyright (C) 2011 by Ivan Safrin
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include "png.h"
  20. #include <math.h>
  21. #include "PolyImage.h"
  22. #include "PolyString.h"
  23. #include "PolyLogger.h"
  24. #include "OSBasics.h"
  25. #include "PolyPerlin.h"
  26. #include <algorithm>
  27. #include <stdlib.h>
  28. #include "rgbe.h"
  29. using namespace Polycode;
  30. void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) {
  31. OSFILE *file = (OSFILE*)png_get_io_ptr(png_ptr);
  32. OSBasics::read(data, length, 1, file);
  33. }
  34. Image::Image(const String& fileName) : imageData(NULL) {
  35. setPixelType(IMAGE_RGBA);
  36. loaded = false;
  37. if(!loadImage(fileName)) {
  38. Logger::log("Error loading %s\n", fileName.c_str());
  39. } else {
  40. loaded = true;
  41. // Logger::log("image loaded!");
  42. }
  43. }
  44. Image *Image::BlankImage(int width, int height, int type) {
  45. return new Image(width, height, type);
  46. }
  47. void Image::setPixelType(int type) {
  48. imageType = type;
  49. switch(imageType) {
  50. case IMAGE_RGB:
  51. pixelSize = 3;
  52. break;
  53. case IMAGE_RGBA:
  54. pixelSize = 4;
  55. break;
  56. case IMAGE_FP16:
  57. pixelSize = 6;
  58. break;
  59. default:
  60. pixelSize = 4;
  61. break;
  62. }
  63. }
  64. bool Image::isLoaded() const {
  65. return loaded;
  66. }
  67. Image::Image(int width, int height, int type) : imageData(NULL) {
  68. setPixelType(type);
  69. createEmpty(width, height);
  70. }
  71. Image::Image(Image *copyImage) {
  72. setPixelType(copyImage->getType());
  73. width = copyImage->getWidth();
  74. height = copyImage->getHeight();
  75. imageData = (char*)malloc(width*height*pixelSize);
  76. memcpy(imageData, copyImage->getPixels(), width*height*pixelSize);
  77. }
  78. Image::Image(char *data, int width, int height, int type) {
  79. setPixelType(type);
  80. imageData = (char*)malloc(width*height*pixelSize);
  81. memcpy(imageData, data, width*height*pixelSize);
  82. this->width = width;
  83. this->height = height;
  84. }
  85. void Image::pasteImage(Image *image, int x, int y, int blendingMode , Number blendAmount, Color blendColor ) {
  86. for(int iy=0; iy<image->getHeight(); iy++) {
  87. for(int ix=0; ix<image->getWidth(); ix++) {
  88. Color src = image->getPixel(ix,iy);
  89. Color destColor = getPixel(x+ix, y+iy);
  90. Color finalColor = destColor.blendColor(src, blendingMode, blendAmount, blendColor);
  91. setPixel(x+ix, y+iy, finalColor);
  92. }
  93. }
  94. }
  95. Image::Image() {
  96. imageData = NULL;
  97. }
  98. Image::~Image() {
  99. free(imageData);
  100. }
  101. char *Image::getPixels() {
  102. return imageData;
  103. }
  104. char *Image::getPixelsInRect(int x, int y, int width, int height) {
  105. transformCoordinates(&x, &y, &width, &height);
  106. char *retBuf = (char*) malloc(pixelSize * width * height);
  107. memset(retBuf, 0, pixelSize * width * height);
  108. if(x < this->width-1 && y < this->height-1) {
  109. width = std::min(width, this->width - x);
  110. height = std::min(height, this->height - y);
  111. for(int i=0; i < height; i++) {
  112. long srcOffset = ((pixelSize*this->width) * (y+i)) + (pixelSize*x);
  113. long dstOffset = (pixelSize*width) * i;
  114. memcpy(retBuf + dstOffset, imageData+srcOffset, pixelSize * width);
  115. }
  116. }
  117. return retBuf;
  118. }
  119. Image *Image::getImagePart(Rectangle subRect) {
  120. char *newData = getPixelsInRect( (int) subRect.x, (int) subRect.y, (int) subRect.w, (int) subRect.h);
  121. return new Image(newData, subRect.w, subRect.h, this->imageType);
  122. }
  123. Color Image::getPixel(int x, int y) {
  124. transformCoordinates(&x, &y);
  125. if(x < 0 || x >= width || y < 0 || y >= height)
  126. return Color(0,0,0,0);
  127. unsigned int *imageData32 = (unsigned int*)imageData;
  128. unsigned int hex = imageData32[x+(y*width)];
  129. int ta = (hex >> 24) & 0xFF;
  130. int tb = (hex >> 16) & 0xFF;
  131. int tg = (hex >> 8) & 0xFF;
  132. int tr = (hex ) & 0xFF;
  133. return Color(((Number)tr)/255.0f, ((Number)tg)/255.0f, ((Number)tb)/255.0f,((Number)ta)/255.0f);
  134. }
  135. int Image::getWidth() const {
  136. return width;
  137. }
  138. int Image::getHeight() const {
  139. return height;
  140. }
  141. void Image::createEmpty(int width, int height) {
  142. free(imageData);
  143. imageData = (char*)malloc(width*height*pixelSize);
  144. this->width = width;
  145. this->height = height;
  146. fill(Color(0,0,0,0));
  147. }
  148. void Image::perlinNoise(int seed, bool alpha) {
  149. Perlin perlin = Perlin(12,33,1,seed);
  150. unsigned int *imageData32 = (unsigned int*)imageData;
  151. Color pixelColor;
  152. Number noiseVal;
  153. for(int i=0; i < width*height;i++) {
  154. noiseVal = fabs(1.0f/perlin.Get( 0.1+(0.9f/((Number)width)) * (i%width), (1.0f/((Number)height)) * (i - (i%width))));
  155. if(alpha)
  156. pixelColor.setColor(noiseVal, noiseVal, noiseVal, noiseVal);
  157. else
  158. pixelColor.setColor(noiseVal, noiseVal, noiseVal, 1.0f);
  159. imageData32[i] = pixelColor.getUint();
  160. }
  161. }
  162. void Image::fillRect(int x, int y, int w, int h, Color col) {
  163. for(int i=0; i < w; i++) {
  164. for(int j=0; j < h; j++) {
  165. setPixel(x+i,y+j,col);
  166. }
  167. }
  168. }
  169. void Image::setPixel(int x, int y, Color col) {
  170. transformCoordinates(&x, &y);
  171. if(x < 0 || x >= width || y < 0 || y >= height)
  172. return;
  173. unsigned int *imageData32 = (unsigned int*)imageData;
  174. imageData32[x+(y*width)] = col.getUint();
  175. }
  176. void Image::moveBrush(int x, int y) {
  177. brushPosX += x;
  178. brushPosY -= y;
  179. }
  180. void Image::moveBrushTo(int x, int y) {
  181. brushPosX = x;
  182. brushPosY = y;
  183. }
  184. int Image::getBrushX() const {
  185. return brushPosX;
  186. }
  187. int Image::getBrushY() const {
  188. return brushPosY;
  189. }
  190. void Image::drawLineTo(int x, int y, Color col) {
  191. drawLine(brushPosX, brushPosY, brushPosX+x, brushPosY+y, col);
  192. }
  193. void Image::setPixel(int x, int y, Number r, Number g, Number b, Number a) {
  194. transformCoordinates(&x, &y);
  195. if(x < 0 || x > width || y < 0 || y > height)
  196. return;
  197. Color color;
  198. color.setColor(r,g,b,a);
  199. unsigned int *imageData32 = (unsigned int*)imageData;
  200. imageData32[x+(y*width)] = color.getUint();
  201. }
  202. void Image::fastBlurHor(int blurSize) {
  203. if(blurSize == 0)
  204. return;
  205. unsigned char *blurImage = (unsigned char*)malloc(width*height*pixelSize);
  206. int total_r;
  207. int total_g;
  208. int total_b;
  209. int total_a;
  210. unsigned int *imageData32 = (unsigned int*)imageData;
  211. unsigned char *pixel;
  212. int amt;
  213. for (int y = 1; y < height; y++) {
  214. for (int x = 0; x < width; x++) {
  215. total_r = 0;
  216. total_g = 0;
  217. total_b = 0;
  218. total_a = 0;
  219. amt = 0;
  220. for (int kx = -blurSize; kx <= blurSize; kx++) {
  221. if((x+kx > 0 && x+kx < width) && (x+kx+((y)*width) > 0 && x+kx+((y)*width) < width*height)) {
  222. pixel = (unsigned char*)&(imageData32[(x+kx)+((y)*width)]);
  223. total_r += pixel[0];
  224. total_g += pixel[1];
  225. total_b += pixel[2];
  226. total_a += pixel[3];
  227. amt++;
  228. }
  229. }
  230. // Logger::log("%d / %d = %d\n",total_r, amt, (total_r/amt));
  231. blurImage[((x+(y*width))*pixelSize)] = (total_r/amt);
  232. blurImage[((x+(y*width))*pixelSize)+1] = (total_g / amt);
  233. blurImage[((x+(y*width))*pixelSize)+2] = (total_b / amt);
  234. blurImage[((x+(y*width))*pixelSize)+3] = (total_a / amt);
  235. }
  236. }
  237. free(imageData);
  238. imageData = (char*)blurImage;
  239. // free(imageData32);
  240. }
  241. void Image::fastBlurVert(int blurSize) {
  242. if(blurSize == 0)
  243. return;
  244. unsigned char *blurImage = (unsigned char*)malloc(width*height*pixelSize);
  245. int total_r;
  246. int total_g;
  247. int total_b;
  248. int total_a;
  249. unsigned int *imageData32 = (unsigned int*)imageData;
  250. unsigned char *pixel;
  251. int amt;
  252. for (int y = 0; y < height; y++) {
  253. for (int x = 0; x < width; x++) {
  254. total_r = 0;
  255. total_g = 0;
  256. total_b = 0;
  257. total_a = 0;
  258. amt = 0;
  259. for (int ky = -blurSize; ky <= blurSize; ky++) {
  260. if((y+ky > 0 && y+ky < height) && (x+((y+ky)*width) > 0 && x+((y+ky)*width) < width*height)) {
  261. pixel = (unsigned char*)&(imageData32[(x)+((y+ky)*width)]);
  262. total_r += pixel[0];
  263. total_g += pixel[1];
  264. total_b += pixel[2];
  265. total_a += pixel[3];
  266. amt++;
  267. }
  268. }
  269. //Logger::log("%d / %d = %d\n",total_r, amt, (total_r/amt));
  270. blurImage[((x+(y*width))*pixelSize)] = (total_r/amt);
  271. blurImage[((x+(y*width))*pixelSize)+1] = (total_g / amt);
  272. blurImage[((x+(y*width))*pixelSize)+2] = (total_b / amt);
  273. blurImage[((x+(y*width))*pixelSize)+3] = (total_a / amt);
  274. }
  275. }
  276. free(imageData);
  277. imageData = (char*)blurImage;
  278. // free(imageData32);
  279. }
  280. void Image::fastBlur(int blurSize) {
  281. fastBlurHor(blurSize);
  282. fastBlurVert(blurSize);
  283. }
  284. void Image::swap(int *v1, int *v2) {
  285. int tv = *v1;
  286. *v1 = *v2;
  287. *v2 = tv;
  288. }
  289. void Image::drawLine(int x0, int y0, int x1, int y1, Color col) {
  290. bool steep = abs(y1 - y0) > abs(x1 - x0);
  291. if(steep) {
  292. swap(&x0, &y0);
  293. swap(&x1, &y1);
  294. }
  295. if(x0 > x1) {
  296. swap(&x0, &x1);
  297. swap(&y0, &y1);
  298. }
  299. int deltax = x1 - x0;
  300. int deltay = abs(y1 - y0);
  301. Number error = 0;
  302. Number deltaerr = ((Number)deltay) / ((Number)deltax);
  303. int ystep;
  304. int y = y0;
  305. if(y0 < y1)
  306. ystep = 1;
  307. else
  308. ystep = -1;
  309. for(int x=x0; x < x1;x++) {
  310. if(steep) {
  311. setPixel(y,x,col);
  312. } else {
  313. setPixel(x,y,col);
  314. }
  315. error = error + ((Number)deltaerr);
  316. if(error >= 0.5) {
  317. y = y + ystep;
  318. error = error - 1.0;
  319. }
  320. }
  321. }
  322. void Image::fill(Color color) {
  323. unsigned int val = color.getUint();
  324. unsigned int *imageData32 = (unsigned int*) imageData;
  325. for(int i=0; i< width*height; i++) {
  326. imageData32[i] = val;
  327. }
  328. }
  329. bool Image::saveImage(const String &fileName) {
  330. return savePNG(fileName);
  331. }
  332. void Image::premultiplyAlpha() {
  333. unsigned int *imageData32 = (unsigned int*)imageData;
  334. for(int x=0; x < width; x++) {
  335. for(int y=0; y < height; y++) {
  336. unsigned int hex = imageData32[x+(y*width)];
  337. int ta = (hex >> 24) & 0xFF;
  338. int tb = (hex >> 16) & 0xFF;
  339. int tg = (hex >> 8) & 0xFF;
  340. int tr = (hex ) & 0xFF;
  341. Number r = ((Number)tr)/255.0f;
  342. Number g = ((Number)tg)/255.0f;
  343. Number b = ((Number)tb)/255.0f;
  344. Number a = ((Number)ta)/255.0f;
  345. r *= a;
  346. g *= a;
  347. b *= a;
  348. unsigned int ir = 255.0f*r;
  349. unsigned int ig = 255.0f*g;
  350. unsigned int ib = 255.0f*b;
  351. unsigned int ia = 255.0f*a;
  352. unsigned int newVal = ((ia & 0xFF) << 24) | ((ib & 0xFF) << 16) | ((ig & 0xFF) << 8) | (ir & 0xFF);
  353. imageData32[x+(y*width)] = newVal;
  354. }
  355. }
  356. }
  357. bool Image::savePNG(const String &fileName) {
  358. printf("Saving %dx%d image\n", width, height);
  359. FILE *fp;
  360. png_structp png_ptr;
  361. png_infop info_ptr;
  362. fp = fopen(fileName.c_str(), "wb");
  363. if (fp == NULL)
  364. return false;
  365. png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  366. if (png_ptr == NULL)
  367. {
  368. fclose(fp);
  369. return false;
  370. }
  371. info_ptr = png_create_info_struct(png_ptr);
  372. if (info_ptr == NULL)
  373. {
  374. fclose(fp);
  375. png_destroy_write_struct(&png_ptr, NULL);
  376. return false;
  377. }
  378. if (setjmp(png_jmpbuf(png_ptr)))
  379. {
  380. /* If we get here, we had a problem writing the file */
  381. fclose(fp);
  382. png_destroy_write_struct(&png_ptr, &info_ptr);
  383. return false;
  384. }
  385. png_init_io(png_ptr, fp);
  386. png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
  387. PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
  388. png_write_info(png_ptr, info_ptr);
  389. png_uint_32 k;
  390. png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
  391. if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
  392. png_error (png_ptr, "Image is too tall to process in memory");
  393. for (k = 0; k < height; k++)
  394. row_pointers[height-k-1] = (png_byte*)(imageData + k*width*4);
  395. /* One of the following output methods is REQUIRED */
  396. png_write_image(png_ptr, row_pointers);
  397. free(row_pointers);
  398. png_free(png_ptr, 0);
  399. png_destroy_write_struct(&png_ptr, &info_ptr);
  400. fclose(fp);
  401. return true;
  402. }
  403. bool Image::loadImage(const String& fileName) {
  404. String extension;
  405. size_t found;
  406. found=fileName.rfind(".");
  407. if (found != -1) {
  408. extension = fileName.substr(found+1);
  409. } else {
  410. extension = "";
  411. }
  412. if(extension == "png") {
  413. return loadPNG(fileName);
  414. } else if(extension == "hdr") {
  415. return loadHDR(fileName);
  416. } else {
  417. Logger::log("Error: Invalid image format.\n");
  418. return false;
  419. }
  420. }
  421. inline hfloat Image::convertFloatToHFloat(float f) {
  422. float _f = f;
  423. uint32_t x = *(uint32_t *)(&_f);
  424. uint32_t sign = (uint32_t)(x >> 31);
  425. uint32_t mantissa;
  426. uint32_t exp;
  427. hfloat hf;
  428. // get mantissa
  429. mantissa = x & ((1 << 23) - 1);
  430. // get exponent bits
  431. exp = x & FLOAT_MAX_BIASED_EXP;
  432. if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
  433. {
  434. // check if the original single precision float number is a NaN
  435. if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
  436. {
  437. // we have a single precision NaN
  438. mantissa = (1 << 23) - 1;
  439. }
  440. else
  441. {
  442. // 16-bit half-float representation stores number as Inf
  443. mantissa = 0;
  444. }
  445. hf = (((hfloat)sign) << 15) | (hfloat)(HALF_FLOAT_MAX_BIASED_EXP) |
  446. (hfloat)(mantissa >> 13);
  447. }
  448. // check if exponent is <= -15
  449. else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
  450. {
  451. // store a denorm half-float value or zero
  452. exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
  453. mantissa >>= (14 + exp);
  454. hf = (((hfloat)sign) << 15) | (hfloat)(mantissa);
  455. }
  456. else
  457. {
  458. hf = (((hfloat)sign) << 15) |
  459. (hfloat)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
  460. (hfloat)(mantissa >> 13);
  461. }
  462. return hf;
  463. }
  464. TokenArray Image::readTokens(char *line, const char *tokenString) {
  465. char **tokens = (char**)malloc(sizeof(void*));
  466. char *pch;
  467. int numTokens = 0;
  468. pch = strtok (line, tokenString);
  469. while (pch != NULL) {
  470. numTokens++;
  471. tokens = (char**)realloc(tokens, sizeof(void*) *numTokens);
  472. tokens[numTokens-1] = (char*) malloc(strlen(pch)+1);
  473. memcpy(tokens[numTokens-1], pch, strlen(pch)+1);
  474. pch = strtok (NULL, tokenString);
  475. }
  476. TokenArray ta;
  477. ta.size = numTokens;
  478. ta.tokens = tokens;
  479. return ta;
  480. }
  481. void Image::freeTokens(TokenArray tokens) {
  482. int i;
  483. for(i =0; i < tokens.size; i++) {
  484. free(tokens.tokens[i]);
  485. }
  486. free(tokens.tokens);
  487. }
  488. bool Image::loadHDR(const String &fileName) {
  489. setPixelType(IMAGE_FP16);
  490. FILE *file = fopen (fileName.c_str(), "rb");
  491. if(!file) {
  492. return false;
  493. }
  494. if(RGBE_ReadHeader(file, &width, &height, NULL) != RGBE_RETURN_SUCCESS) {
  495. // if ReadHeader failed, try reading info manually.
  496. char line [ 128 ];
  497. Number exposure;
  498. fseek(file, 0, SEEK_SET);
  499. while ( fgets ( line, sizeof(line), file ) != NULL ) {
  500. TokenArray ta = readTokens(line, "=");
  501. if(strcmp(ta.tokens[0], "EXPOSURE") == 0) {
  502. exposure = atof(ta.tokens[1]);
  503. }
  504. if(strcmp(ta.tokens[0], "FORMAT") == 0) {
  505. //printf("format is %s\n", ta.tokens[1]);
  506. }
  507. freeTokens(ta);
  508. ta = readTokens(line, " ");
  509. if(strcmp(ta.tokens[0], "-Y") == 0) {
  510. //printf("image size is %d x %d\n", atoi(ta.tokens[1]), atoi(ta.tokens[3]));
  511. width = atoi(ta.tokens[1]);
  512. height = atoi(ta.tokens[3]);
  513. freeTokens(ta);
  514. break;
  515. }
  516. freeTokens(ta);
  517. }
  518. }
  519. float *data = (float *)malloc(sizeof(float)*3*width*height);
  520. RGBE_ReadPixels_RLE(file, data, width, height);
  521. float *hFloatImageData = (float*) malloc(sizeof(float)*3*width*height);
  522. /*
  523. for(int i=0; i < width*height; i++) {
  524. hFloatImageData[i*3] = convertFloatToHFloat(data[i*3]);
  525. hFloatImageData[(i*3)+1] = convertFloatToHFloat(data[(i*3)+1]);
  526. hFloatImageData[(i*3)+2] = convertFloatToHFloat(data[(i*3)+2]);
  527. }
  528. */
  529. imageData = (char*) data; //(char*)hFloatImageData;
  530. // free(data);
  531. fclose(file);
  532. return true;
  533. }
  534. bool Image::loadPNG(const String& fileName) {
  535. OSFILE *infile;
  536. png_structp png_ptr;
  537. png_infop info_ptr;
  538. char *image_data;
  539. char sig[8];
  540. int bit_depth;
  541. int color_type;
  542. png_uint_32 width;
  543. png_uint_32 height;
  544. unsigned int rowbytes;
  545. image_data = NULL;
  546. int i;
  547. png_bytepp row_pointers = NULL;
  548. infile = OSBasics::open(fileName.c_str(), "rb");
  549. if (!infile) {
  550. Logger::log("Error opening png file (\"%s\")\n", fileName.c_str());
  551. return false;
  552. }
  553. OSBasics::read(sig, 1, 8, infile);
  554. if (!png_check_sig((unsigned char *) sig, 8)) {
  555. Logger::log("Error reading png signature (\"%s\")\n", fileName.c_str());
  556. OSBasics::close(infile);
  557. return false;
  558. }
  559. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  560. if (!png_ptr) {
  561. Logger::log("Error creating png struct (\"%s\")\n", fileName.c_str());
  562. OSBasics::close(infile);
  563. return false; /* out of memory */
  564. }
  565. info_ptr = png_create_info_struct(png_ptr);
  566. if (!info_ptr) {
  567. Logger::log("Error creating info struct (\"%s\")\n", fileName.c_str());
  568. png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
  569. OSBasics::close(infile);
  570. return false; /* out of memory */
  571. }
  572. if (setjmp(png_jmpbuf(png_ptr))) {
  573. Logger::log("Error setting jump thingie (\"%s\")\n", fileName.c_str());
  574. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  575. OSBasics::close(infile);
  576. return false;
  577. }
  578. //png_init_io(png_ptr, infile);
  579. png_set_read_fn(png_ptr, (png_voidp)infile, user_read_data);
  580. png_set_sig_bytes(png_ptr, 8);
  581. png_read_info(png_ptr, info_ptr);
  582. png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
  583. &color_type, NULL, NULL, NULL);
  584. this->width = width;
  585. this->height = height;
  586. /* Set up some transforms. */
  587. if (color_type & PNG_COLOR_MASK_ALPHA) {
  588. // png_set_strip_alpha(png_ptr);
  589. }
  590. if (bit_depth > 8) {
  591. png_set_strip_16(png_ptr);
  592. }
  593. if (color_type == PNG_COLOR_TYPE_GRAY ||
  594. color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
  595. png_set_gray_to_rgb(png_ptr);
  596. }
  597. if (color_type == PNG_COLOR_TYPE_PALETTE) {
  598. png_set_palette_to_rgb(png_ptr);
  599. }
  600. if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
  601. png_set_add_alpha(png_ptr, 0xffffff, PNG_FILLER_AFTER);
  602. }
  603. /* Update the png info struct.*/
  604. png_read_update_info(png_ptr, info_ptr);
  605. /* Rowsize in bytes. */
  606. rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  607. /* Allocate the image_data buffer. */
  608. if ((image_data = (char *) malloc(rowbytes * height))==NULL) {
  609. Logger::log("Error allocating image memory (\"%s\")\n", fileName.c_str());
  610. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  611. return false;
  612. }
  613. if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
  614. Logger::log("Error allocating image memory (\"%s\")\n", fileName.c_str());
  615. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  616. free(image_data);
  617. image_data = NULL;
  618. return false;
  619. }
  620. for (i = 0; i < height; ++i)
  621. row_pointers[height - 1 - i] = (png_byte*)image_data + i*rowbytes;
  622. png_read_image(png_ptr, row_pointers);
  623. free(row_pointers);
  624. png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  625. OSBasics::close(infile);
  626. imageData = image_data;
  627. return true;
  628. }
  629. void Image::transformCoordinates(int *x, int *y) {
  630. *y = this->height - *y - 1;
  631. }
  632. void Image::transformCoordinates(int *x, int *y, int *w, int *h) {
  633. *y = this->height - *h - *y - 1;
  634. }