PolyImage.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  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 <math.h>
  20. #include "polycode/core/PolyImage.h"
  21. #include "polycode/core/PolyString.h"
  22. #include "polycode/core/PolyLogger.h"
  23. #include "polycode/core/PolyPerlin.h"
  24. #include "polycode/core/PolyCore.h"
  25. #include "polycode/core/PolyCoreServices.h"
  26. #include <algorithm>
  27. #include <stdlib.h>
  28. #include "rgbe.h"
  29. #define STB_IMAGE_IMPLEMENTATION
  30. #include "stb_image.h"
  31. #include "lodepng.h"
  32. using namespace Polycode;
  33. Image::Image(const String& fileName) : imageData(NULL) {
  34. setPixelType(IMAGE_RGBA);
  35. loaded = false;
  36. if(!loadImage(fileName)) {
  37. Logger::log("Error loading %s\n", fileName.c_str());
  38. } else {
  39. loaded = true;
  40. // Logger::log("image loaded!");
  41. }
  42. }
  43. Image *Image::BlankImage(int width, int height, int type) {
  44. return new Image(width, height, type);
  45. }
  46. void Image::setPixelType(int type) {
  47. imageType = type;
  48. switch(imageType) {
  49. case IMAGE_RGB:
  50. pixelSize = 3;
  51. break;
  52. case IMAGE_RGBA:
  53. pixelSize = 4;
  54. break;
  55. case IMAGE_FP16:
  56. pixelSize = 6;
  57. break;
  58. default:
  59. pixelSize = 4;
  60. break;
  61. }
  62. }
  63. bool Image::isLoaded() const {
  64. return loaded;
  65. }
  66. Image::Image(int width, int height, int type) : imageData(NULL) {
  67. setPixelType(type);
  68. createEmpty(width, height, Color(0.0, 0.0, 0.0, 0.0));
  69. }
  70. Image::Image(Image *copyImage) {
  71. setPixelType(copyImage->getType());
  72. width = copyImage->getWidth();
  73. height = copyImage->getHeight();
  74. imageData = (char*)malloc(width*height*pixelSize);
  75. memcpy(imageData, copyImage->getPixels(), width*height*pixelSize);
  76. }
  77. Image::Image(char *data, int width, int height, int type) {
  78. setPixelType(type);
  79. imageData = (char*)malloc(width*height*pixelSize);
  80. memcpy(imageData, data, width*height*pixelSize);
  81. this->width = width;
  82. this->height = height;
  83. }
  84. void Image::pasteImage(Image *image, int x, int y, int blendingMode , Number blendAmount, Color blendColor ) {
  85. for(int iy=0; iy<image->getHeight(); iy++) {
  86. for(int ix=0; ix<image->getWidth(); ix++) {
  87. Color src = image->getPixel(ix,iy);
  88. Color destColor = getPixel(x+ix, y+iy);
  89. Color finalColor = destColor.blendColor(src, blendingMode, blendAmount, blendColor);
  90. setPixel(x+ix, y+iy, finalColor);
  91. }
  92. }
  93. }
  94. Image::Image() {
  95. imageData = NULL;
  96. }
  97. Image::~Image() {
  98. free(imageData);
  99. }
  100. char *Image::getPixels() {
  101. return imageData;
  102. }
  103. char *Image::getPixelsInRect(int x, int y, int width, int height) {
  104. transformCoordinates(&x, &y, &width, &height);
  105. char *retBuf = (char*) malloc(pixelSize * width * height);
  106. memset(retBuf, 0, pixelSize * width * height);
  107. if(x < this->width-1 && y < this->height-1) {
  108. width = std::min(width, this->width - x);
  109. height = std::min(height, this->height - y);
  110. for(int i=0; i < height; i++) {
  111. long srcOffset = ((pixelSize*this->width) * (y+i)) + (pixelSize*x);
  112. long dstOffset = (pixelSize*width) * i;
  113. memcpy(retBuf + dstOffset, imageData+srcOffset, pixelSize * width);
  114. }
  115. }
  116. return retBuf;
  117. }
  118. Image *Image::getImagePart(Rectangle subRect) {
  119. char *newData = getPixelsInRect( (int) subRect.x, (int) subRect.y, (int) subRect.w, (int) subRect.h);
  120. return new Image(newData, subRect.w, subRect.h, this->imageType);
  121. }
  122. Color Image::getPixel(int x, int y) {
  123. transformCoordinates(&x, &y);
  124. if(x < 0 || x >= width || y < 0 || y >= height)
  125. return Color(0,0,0,0);
  126. unsigned int *imageData32 = (unsigned int*)imageData;
  127. unsigned int hex = imageData32[x+(y*width)];
  128. int ta = (hex >> 24) & 0xFF;
  129. int tb = (hex >> 16) & 0xFF;
  130. int tg = (hex >> 8) & 0xFF;
  131. int tr = (hex ) & 0xFF;
  132. return Color(((Number)tr)/255.0f, ((Number)tg)/255.0f, ((Number)tb)/255.0f,((Number)ta)/255.0f);
  133. }
  134. int Image::getWidth() const {
  135. return width;
  136. }
  137. int Image::getHeight() const {
  138. return height;
  139. }
  140. void Image::createEmpty(int width, int height, const Color &fillColor) {
  141. free(imageData);
  142. imageData = (char*)malloc(width*height*pixelSize);
  143. this->width = width;
  144. this->height = height;
  145. fill(fillColor);
  146. }
  147. void Image::perlinNoise(int seed, bool alpha) {
  148. Perlin perlin = Perlin(12,33,1,seed);
  149. unsigned int *imageData32 = (unsigned int*)imageData;
  150. Color pixelColor;
  151. Number noiseVal;
  152. for(int i=0; i < width*height;i++) {
  153. noiseVal = fabs(1.0f/perlin.Get( 0.1+(0.9f/((Number)width)) * (i%width), (1.0f/((Number)height)) * (i - (i%width))));
  154. if(alpha)
  155. pixelColor.setColor(noiseVal, noiseVal, noiseVal, noiseVal);
  156. else
  157. pixelColor.setColor(noiseVal, noiseVal, noiseVal, 1.0f);
  158. imageData32[i] = pixelColor.getUint();
  159. }
  160. }
  161. void Image::fillRect(int x, int y, int w, int h, Color col) {
  162. for(int i=0; i < w; i++) {
  163. for(int j=0; j < h; j++) {
  164. setPixel(x+i,y+j,col);
  165. }
  166. }
  167. }
  168. void Image::setPixel(int x, int y, Color col) {
  169. transformCoordinates(&x, &y);
  170. if(x < 0 || x >= width || y < 0 || y >= height)
  171. return;
  172. unsigned int *imageData32 = (unsigned int*)imageData;
  173. imageData32[x+(y*width)] = col.getUint();
  174. }
  175. void Image::moveBrush(int x, int y) {
  176. brushPosX += x;
  177. brushPosY -= y;
  178. }
  179. void Image::moveBrushTo(int x, int y) {
  180. brushPosX = x;
  181. brushPosY = y;
  182. }
  183. int Image::getBrushX() const {
  184. return brushPosX;
  185. }
  186. int Image::getBrushY() const {
  187. return brushPosY;
  188. }
  189. void Image::drawLineTo(int x, int y, Color col) {
  190. drawLine(brushPosX, brushPosY, brushPosX+x, brushPosY+y, col);
  191. }
  192. void Image::setPixel(int x, int y, Number r, Number g, Number b, Number a) {
  193. transformCoordinates(&x, &y);
  194. if(x < 0 || x > width || y < 0 || y > height)
  195. return;
  196. Color color;
  197. color.setColor(r,g,b,a);
  198. unsigned int *imageData32 = (unsigned int*)imageData;
  199. imageData32[x+(y*width)] = color.getUint();
  200. }
  201. void Image::fastBlurHor(int blurSize) {
  202. if(blurSize == 0)
  203. return;
  204. unsigned char *blurImage = (unsigned char*)malloc(width*height*pixelSize);
  205. int total_r;
  206. int total_g;
  207. int total_b;
  208. int total_a;
  209. unsigned int *imageData32 = (unsigned int*)imageData;
  210. unsigned char *pixel;
  211. int amt;
  212. for (int y = 1; y < height; y++) {
  213. for (int x = 0; x < width; x++) {
  214. total_r = 0;
  215. total_g = 0;
  216. total_b = 0;
  217. total_a = 0;
  218. amt = 0;
  219. for (int kx = -blurSize; kx <= blurSize; kx++) {
  220. if((x+kx > 0 && x+kx < width) && (x+kx+((y)*width) > 0 && x+kx+((y)*width) < width*height)) {
  221. pixel = (unsigned char*)&(imageData32[(x+kx)+((y)*width)]);
  222. total_r += pixel[0];
  223. total_g += pixel[1];
  224. total_b += pixel[2];
  225. total_a += pixel[3];
  226. amt++;
  227. }
  228. }
  229. // Logger::log("%d / %d = %d\n",total_r, amt, (total_r/amt));
  230. blurImage[((x+(y*width))*pixelSize)] = (total_r/amt);
  231. blurImage[((x+(y*width))*pixelSize)+1] = (total_g / amt);
  232. blurImage[((x+(y*width))*pixelSize)+2] = (total_b / amt);
  233. blurImage[((x+(y*width))*pixelSize)+3] = (total_a / amt);
  234. }
  235. }
  236. free(imageData);
  237. imageData = (char*)blurImage;
  238. // free(imageData32);
  239. }
  240. void Image::fastBlurVert(int blurSize) {
  241. if(blurSize == 0)
  242. return;
  243. unsigned char *blurImage = (unsigned char*)malloc(width*height*pixelSize);
  244. int total_r;
  245. int total_g;
  246. int total_b;
  247. int total_a;
  248. unsigned int *imageData32 = (unsigned int*)imageData;
  249. unsigned char *pixel;
  250. int amt;
  251. for (int y = 0; y < height; y++) {
  252. for (int x = 0; x < width; x++) {
  253. total_r = 0;
  254. total_g = 0;
  255. total_b = 0;
  256. total_a = 0;
  257. amt = 0;
  258. for (int ky = -blurSize; ky <= blurSize; ky++) {
  259. if((y+ky > 0 && y+ky < height) && (x+((y+ky)*width) > 0 && x+((y+ky)*width) < width*height)) {
  260. pixel = (unsigned char*)&(imageData32[(x)+((y+ky)*width)]);
  261. total_r += pixel[0];
  262. total_g += pixel[1];
  263. total_b += pixel[2];
  264. total_a += pixel[3];
  265. amt++;
  266. }
  267. }
  268. //Logger::log("%d / %d = %d\n",total_r, amt, (total_r/amt));
  269. blurImage[((x+(y*width))*pixelSize)] = (total_r/amt);
  270. blurImage[((x+(y*width))*pixelSize)+1] = (total_g / amt);
  271. blurImage[((x+(y*width))*pixelSize)+2] = (total_b / amt);
  272. blurImage[((x+(y*width))*pixelSize)+3] = (total_a / amt);
  273. }
  274. }
  275. free(imageData);
  276. imageData = (char*)blurImage;
  277. // free(imageData32);
  278. }
  279. void Image::fastBlur(int blurSize) {
  280. fastBlurHor(blurSize);
  281. fastBlurVert(blurSize);
  282. }
  283. void Image::swap(int *v1, int *v2) {
  284. int tv = *v1;
  285. *v1 = *v2;
  286. *v2 = tv;
  287. }
  288. void Image::drawLine(int x0, int y0, int x1, int y1, Color col) {
  289. bool steep = abs(y1 - y0) > abs(x1 - x0);
  290. if(steep) {
  291. swap(&x0, &y0);
  292. swap(&x1, &y1);
  293. }
  294. if(x0 > x1) {
  295. swap(&x0, &x1);
  296. swap(&y0, &y1);
  297. }
  298. int deltax = x1 - x0;
  299. int deltay = abs(y1 - y0);
  300. Number error = 0;
  301. Number deltaerr = ((Number)deltay) / ((Number)deltax);
  302. int ystep;
  303. int y = y0;
  304. if(y0 < y1)
  305. ystep = 1;
  306. else
  307. ystep = -1;
  308. for(int x=x0; x < x1;x++) {
  309. if(steep) {
  310. setPixel(y,x,col);
  311. } else {
  312. setPixel(x,y,col);
  313. }
  314. error = error + ((Number)deltaerr);
  315. if(error >= 0.5) {
  316. y = y + ystep;
  317. error = error - 1.0;
  318. }
  319. }
  320. }
  321. void Image::fill(const Color &color) {
  322. if(imageType == Image::IMAGE_RGB) {
  323. for(int i = 0; i < width*height*pixelSize; i+=3) {
  324. imageData[i] = color.r;
  325. imageData[i+1] = color.g;
  326. imageData[i+2] = color.b;
  327. }
  328. } else {
  329. unsigned int val = color.getUint();
  330. unsigned int *imageData32 = (unsigned int*) imageData;
  331. for(int i=0; i< width*height; i++) {
  332. imageData32[i] = val;
  333. }
  334. }
  335. }
  336. bool Image::saveImage(const String &fileName) {
  337. return savePNG(fileName);
  338. }
  339. bool Image::savePNG(const String &fileName) {
  340. unsigned char *png = NULL;
  341. size_t pngsize;
  342. unsigned error = lodepng_encode32(&png, &pngsize, (const unsigned char*) imageData, width, height);
  343. if(!error) {
  344. CoreFile *file = Services()->getCore()->openFile(fileName, "wb");
  345. if(file) {
  346. file->write(png, pngsize, 1);
  347. free(png);
  348. return true;
  349. } else {
  350. free(png);
  351. return false;
  352. }
  353. } else {
  354. free(png);
  355. return false;
  356. }
  357. }
  358. void Image::premultiplyAlpha() {
  359. unsigned int *imageData32 = (unsigned int*)imageData;
  360. for(int x=0; x < width; x++) {
  361. for(int y=0; y < height; y++) {
  362. unsigned int hex = imageData32[x+(y*width)];
  363. int ta = (hex >> 24) & 0xFF;
  364. int tb = (hex >> 16) & 0xFF;
  365. int tg = (hex >> 8) & 0xFF;
  366. int tr = (hex ) & 0xFF;
  367. Number r = ((Number)tr)/255.0f;
  368. Number g = ((Number)tg)/255.0f;
  369. Number b = ((Number)tb)/255.0f;
  370. Number a = ((Number)ta)/255.0f;
  371. r *= a;
  372. g *= a;
  373. b *= a;
  374. unsigned int ir = 255.0f*r;
  375. unsigned int ig = 255.0f*g;
  376. unsigned int ib = 255.0f*b;
  377. unsigned int ia = 255.0f*a;
  378. unsigned int newVal = ((ia & 0xFF) << 24) | ((ib & 0xFF) << 16) | ((ig & 0xFF) << 8) | (ir & 0xFF);
  379. imageData32[x+(y*width)] = newVal;
  380. }
  381. }
  382. }
  383. bool Image::loadImage(const String& fileName) {
  384. String extension;
  385. size_t found;
  386. found=fileName.rfind(".");
  387. if (found != -1) {
  388. extension = fileName.substr(found+1);
  389. } else {
  390. extension = "";
  391. }
  392. if(extension == "hdr") {
  393. return loadHDR(fileName);
  394. } else if(extension == "png" || extension == "jpg" || extension == "tga" || extension == "psd") {
  395. return loadSTB(fileName);
  396. } else {
  397. Logger::log("Error: Invalid image format.\n");
  398. return false;
  399. }
  400. }
  401. inline hfloat Image::convertFloatToHFloat(float f) {
  402. float _f = f;
  403. uint32_t x = *(uint32_t *)(&_f);
  404. uint32_t sign = (uint32_t)(x >> 31);
  405. uint32_t mantissa;
  406. uint32_t exp;
  407. hfloat hf;
  408. // get mantissa
  409. mantissa = x & ((1 << 23) - 1);
  410. // get exponent bits
  411. exp = x & FLOAT_MAX_BIASED_EXP;
  412. if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
  413. {
  414. // check if the original single precision float number is a NaN
  415. if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
  416. {
  417. // we have a single precision NaN
  418. mantissa = (1 << 23) - 1;
  419. }
  420. else
  421. {
  422. // 16-bit half-float representation stores number as Inf
  423. mantissa = 0;
  424. }
  425. hf = (((hfloat)sign) << 15) | (hfloat)(HALF_FLOAT_MAX_BIASED_EXP) |
  426. (hfloat)(mantissa >> 13);
  427. }
  428. // check if exponent is <= -15
  429. else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
  430. {
  431. // store a denorm half-float value or zero
  432. exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
  433. mantissa >>= (14 + exp);
  434. hf = (((hfloat)sign) << 15) | (hfloat)(mantissa);
  435. }
  436. else
  437. {
  438. hf = (((hfloat)sign) << 15) |
  439. (hfloat)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
  440. (hfloat)(mantissa >> 13);
  441. }
  442. return hf;
  443. }
  444. TokenArray Image::readTokens(char *line, const char *tokenString) {
  445. char **tokens = (char**)malloc(sizeof(void*));
  446. char *pch;
  447. int numTokens = 0;
  448. pch = strtok (line, tokenString);
  449. while (pch != NULL) {
  450. numTokens++;
  451. tokens = (char**)realloc(tokens, sizeof(void*) *numTokens);
  452. tokens[numTokens-1] = (char*) malloc(strlen(pch)+1);
  453. memcpy(tokens[numTokens-1], pch, strlen(pch)+1);
  454. pch = strtok (NULL, tokenString);
  455. }
  456. TokenArray ta;
  457. ta.size = numTokens;
  458. ta.tokens = tokens;
  459. return ta;
  460. }
  461. void Image::freeTokens(TokenArray tokens) {
  462. int i;
  463. for(i =0; i < tokens.size; i++) {
  464. free(tokens.tokens[i]);
  465. }
  466. free(tokens.tokens);
  467. }
  468. bool Image::loadSTB(const String &fileName) {
  469. CoreFile *infile = Services()->getCore()->openFile(fileName.c_str(), "rb");
  470. if(!infile) {
  471. Logger::log("Error opening image file: %s\n", fileName.c_str());
  472. return false;
  473. }
  474. infile->seek(0, SEEK_END);
  475. long bufferLen = infile->tell();
  476. infile->seek(0, SEEK_SET);
  477. char *buffer = (char*) malloc(bufferLen);
  478. infile->read(buffer, bufferLen, 1);
  479. int x,y,n;
  480. stbi_uc *data = stbi_load_from_memory((const stbi_uc*)buffer, bufferLen, &x, &y, &n, 4);
  481. if(!data) {
  482. Logger::log("Error reading image data: %s\n", fileName.c_str());
  483. return false;
  484. }
  485. imageType = Image::IMAGE_RGBA;
  486. width = x;
  487. height = y;
  488. free(buffer);
  489. imageData = (char*)data;
  490. Services()->getCore()->closeFile(infile);
  491. return true;
  492. }
  493. bool Image::loadHDR(const String &fileName) {
  494. imageType = Image::IMAGE_FP16;
  495. CoreFile *infile = Services()->getCore()->openFile(fileName.c_str(), "rb");
  496. if(!infile) {
  497. Logger::log("Error opening HDR %s\n", fileName.c_str());
  498. return false;
  499. }
  500. infile->seek(0, SEEK_END);
  501. long bufferLen = infile->tell();
  502. infile->seek(0, SEEK_SET);
  503. char *buffer = (char*) malloc(bufferLen);
  504. infile->read(buffer, bufferLen, 1);
  505. int x,y,n;
  506. float *data = stbi_loadf_from_memory((const stbi_uc*)buffer, bufferLen, &x, &y, &n, 0);
  507. if(!data) {
  508. Logger::log("Error reading image data: %s\n", fileName.c_str());
  509. return false;
  510. }
  511. width = x;
  512. height = y;
  513. free(buffer);
  514. imageData = (char*)data;
  515. Services()->getCore()->closeFile(infile);
  516. return true;
  517. }
  518. void Image::transformCoordinates(int *x, int *y) {
  519. *y = this->height - *y - 1;
  520. }
  521. void Image::transformCoordinates(int *x, int *y, int *w, int *h) {
  522. *y = this->height - *h - *y;
  523. }