Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

MtkImage.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852
  1. /*================================================================
  2. *
  3. * Project : Freyja
  4. * Author : Mongoose
  5. * Website : http://www.westga.edu/~stu7440/
  6. * Email : stu7440@westga.edu
  7. * Object : MtkImage
  8. * License : GPL See file COPYING, also (C) 2000 Mongoose
  9. * Comments: This is the new mtkImage class for mtk
  10. *
  11. *
  12. * This file was generated using Mongoose's C++
  13. * template generator script. <stu7440@westga.edu>
  14. *
  15. *-- History -------------------------------------------------
  16. *
  17. * 2000-10-05:
  18. * Mongoose - Created
  19. =================================================================*/
  20. #include "MtkImage.h"
  21. #ifdef DEBUG_MEMEORY
  22. # include "memeory_test.h"
  23. #endif
  24. #include <dlfcn.h>
  25. static const char *mtk_image_module_names[] = {
  26. "pcx",
  27. "ppm",
  28. "tga",
  29. "jpeg",
  30. "png"
  31. };
  32. #define MTK_IMAGE_MODULE_NAME_COUNT (sizeof(mtk_image_module_names) / sizeof(mtk_image_module_names[0]))
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <math.h>
  36. int mtkExtCheck(char *filename, char *ext)
  37. {
  38. unsigned int len_f, len_e;
  39. len_f = strlen(filename) - 1;
  40. len_e = strlen(ext) - 1;
  41. while (len_f+1 && len_e+1)
  42. {
  43. //printf("extcheck: %c %c\n", filename[len_f], ext[len_e]);
  44. if (filename[len_f] == ext[len_e])
  45. {
  46. if (ext[len_e] == '.')
  47. {
  48. //printf("extcheck: match\n");
  49. return 0;
  50. }
  51. }
  52. else if (filename[len_f] < ext[len_e])
  53. return -1;
  54. else if (filename[len_f] > ext[len_e])
  55. return 1;
  56. len_f--;
  57. len_e--;
  58. }
  59. return 1;
  60. }
  61. //////////////////////////////////////////////
  62. MtkImage::MtkImage()
  63. {
  64. _image = NULL;
  65. _palette = NULL;
  66. _width = 0;
  67. _height = 0;
  68. _original_width = 0;
  69. _original_height = 0;
  70. _color_mode = COLORMODE_RGB;
  71. _image_bpp = 0;
  72. _palette_bpp = 0;
  73. }
  74. MtkImage::~MtkImage()
  75. {
  76. Clear();
  77. }
  78. void MtkImage::Clear()
  79. {
  80. if (_image)
  81. delete [] _image;
  82. if (_palette)
  83. delete [] _palette;
  84. _width = 0;
  85. _height = 0;
  86. _original_width = 0;
  87. _original_height = 0;
  88. _palette_bpp = 0;
  89. }
  90. int MtkImage::Width()
  91. {
  92. return _width;
  93. }
  94. int MtkImage::Height()
  95. {
  96. return _height;
  97. }
  98. int MtkImage::OriginalWidth()
  99. {
  100. return _original_width;
  101. }
  102. int MtkImage::OriginalHeight()
  103. {
  104. return _original_height;
  105. }
  106. void MtkImage::Mode(mtk_colormode mode)
  107. {
  108. fprintf(stderr, "MtkImage::Mode> ERROR not implemented, %s:%i\n",
  109. __FILE__, __LINE__);
  110. }
  111. //FIXME: Add support for 32bit!
  112. int MtkImage::PaletteLoad(unsigned char *buffer, int bpp)
  113. {
  114. if (buffer && buffer != _palette &&
  115. (bpp == 8 || bpp == 16 || bpp == 24))
  116. {
  117. if (_palette)
  118. delete [] _palette;
  119. _palette_bpp = bpp;
  120. _palette = new unsigned char[768];
  121. memcpy(_palette, buffer, 768);
  122. return 0;
  123. }
  124. printf("MtkImage::LoadPaletteBuffer()> Assertion Error bpp not {8,16,24}\n");
  125. return -1;
  126. }
  127. int MtkImage::LoadIndexed(unsigned char *image, int width, int height)
  128. {
  129. int i, size, index;
  130. if (!image || !_palette || !width || !height || image == _image)
  131. {
  132. printf("MtkImage::LoadIndexedBuffer> Assertion failed\n");
  133. return -1;
  134. }
  135. if (_image)
  136. delete [] _image;
  137. size = width * height;
  138. _width = _original_width = width;
  139. _height = _original_height = height;
  140. _image = new unsigned char[size * 3];
  141. _color_mode = COLORMODE_RGB;
  142. for (i = 0; i < size; i++)
  143. {
  144. index = image[i];
  145. if (index * 3 + 2 > 768)
  146. printf("Index outside of palette!\n");
  147. else
  148. {
  149. _image[i*3] = _palette[index*3];
  150. _image[i*3+1] = _palette[index*3+1];
  151. _image[i*3+2] = _palette[index*3+2];
  152. }
  153. }
  154. return 0;
  155. }
  156. void MtkImage::PaletteBrighten(float p)
  157. {
  158. int i;
  159. if (p <= 0.0 || p > 0.999)
  160. {
  161. printf("MtkImage::BrightenPalette> %f isn't a postive percentage\n", p);
  162. return;
  163. }
  164. if (_palette)
  165. {
  166. for (i = 0; i < 255; i++)
  167. {
  168. _palette[i*3] += (unsigned char)(_palette[i*3] * p);
  169. _palette[i*3+1] += (unsigned char)(_palette[i*3+1] * p);
  170. _palette[i*3+2] += (unsigned char)(_palette[i*3+2] * p);
  171. }
  172. }
  173. }
  174. void MtkImage::Image(unsigned char **buffer)
  175. {
  176. *buffer = NULL;
  177. if (!_image)
  178. {
  179. printf("Image::ImageBuffer> No image allocated\n");
  180. return;
  181. }
  182. switch (_color_mode)
  183. {
  184. case COLORMODE_RGB:
  185. *buffer = new unsigned char[_width*_height*3];
  186. memcpy(*buffer, _image, _width*_height*3);
  187. break;
  188. case COLORMODE_RGBA:
  189. *buffer = new unsigned char[_width*_height*4];
  190. memcpy(*buffer, _image, _width*_height*4);
  191. break;
  192. case COLORMODE_INDEXED:
  193. break;
  194. }
  195. }
  196. void MtkImage::Palette(unsigned char **buffer)
  197. {
  198. *buffer = NULL;
  199. if (!_palette)
  200. {
  201. printf("Image::PaletteBuffer> No palette allocated\n");
  202. return;
  203. }
  204. *buffer = new unsigned char[768];
  205. memcpy(*buffer, _palette, 768);
  206. }
  207. void MtkImage::IndexedImage(unsigned char **buffer)
  208. {
  209. int size = _width * _height;
  210. float rgb[3];
  211. int i;
  212. *buffer = NULL;
  213. if (!_image || !_palette)
  214. {
  215. printf("MtkImage::IndexedImage> No image or palette allocated\n");
  216. return;
  217. }
  218. *buffer = new unsigned char[size];
  219. for (i = 0; i < size; i++)
  220. {
  221. rgb[0] = _image[i*3]/255.0;
  222. rgb[1] = _image[i*3+1]/255.0;
  223. rgb[2] = _image[i*3+2]/255.0;
  224. (*buffer)[i] = PaletteMatchColor(rgb);
  225. }
  226. }
  227. void MtkImage::FlipVertical()
  228. {
  229. int i, j;
  230. unsigned char *swap_row = NULL;
  231. if (!_image)
  232. return;
  233. switch(_color_mode)
  234. {
  235. case COLORMODE_INDEXED:
  236. // We don't store images as indexed, they're computed
  237. break;
  238. case COLORMODE_RGB:
  239. swap_row = new unsigned char[_width*3];
  240. for (i = 0, j = _height-1; i < _height/2; i++, j--)
  241. {
  242. memcpy(swap_row, &_image[i*_width*3], _width*3);
  243. memcpy(&_image[i*_width*3], &_image[j*_width*3], _width*3);
  244. memcpy(&_image[j*_width*3], swap_row, _width*3);
  245. }
  246. delete [] swap_row;
  247. break;
  248. case COLORMODE_RGBA:
  249. swap_row = new unsigned char[_width*4];
  250. for (i = 0, j = _height-1; i < _height/2; i++, j--)
  251. {
  252. memcpy(swap_row, &_image[i*_width*4], _width*4);
  253. memcpy(&_image[i*_width*4], &_image[j*_width*4], _width*4);
  254. memcpy(&_image[j*_width*4], swap_row, _width*4);
  255. }
  256. delete [] swap_row;
  257. break;
  258. }
  259. }
  260. // FIXME: static only for now
  261. int MtkImage::Load(char *filename)
  262. {
  263. int (*load)(char *filename, unsigned char **image,
  264. unsigned int *width, unsigned int *height, char *type);
  265. int (*check)(char *filename);
  266. void *handle;
  267. char *error;
  268. FILE *f;
  269. unsigned int i;
  270. char module_filename[128];
  271. char module_check[128];
  272. char module_load[128];
  273. char *name;
  274. unsigned char *image;
  275. unsigned int w, h;
  276. bool loaded = false;
  277. char type;
  278. f = fopen(filename, "rb");
  279. if (!f)
  280. {
  281. perror("MtkImage::Load> File open failed.\n");
  282. return -1;
  283. }
  284. printf("[MtkImage module loader invoked]\n");
  285. for (i = 0; i < MTK_IMAGE_MODULE_NAME_COUNT && !loaded; i++)
  286. {
  287. name = (char *)mtk_image_module_names[i];
  288. snprintf(module_filename, 128, "libmtk_loader-%s.so", name);
  289. snprintf(module_load, 128, "mtk_image__%s_load", name);
  290. snprintf(module_check, 128, "mtk_image__%s_check", name);
  291. if (!(handle = dlopen (module_filename, RTLD_NOW))) //RTLD_LAZY)))
  292. {
  293. fprintf(stderr, "\tERROR: Couldn't find module '%s'.\n", module_filename);
  294. return -1;
  295. }
  296. else
  297. {
  298. printf("\tModule '%s' opened.\n", module_filename);
  299. check = (int (*)(char *filename))dlsym(handle, module_check);
  300. load = (int (*)(char * filename, unsigned char **image,
  301. unsigned int *w, unsigned int *h,
  302. char *type))dlsym(handle, module_load);
  303. if ((error = dlerror()) != NULL)
  304. {
  305. fprintf (stderr, "\tERROR: %s\n", error);
  306. return -5;
  307. }
  308. loaded = (loaded || (!(*check)(filename) &&
  309. !(*load)(filename, &image, &w, &h, &type)));
  310. if ((error = dlerror()) != NULL)
  311. return -10;
  312. dlclose(handle);
  313. }
  314. }
  315. if (loaded)
  316. {
  317. Clear();
  318. _image = image;
  319. _original_width = _width = w;
  320. _original_height = _height = h;
  321. switch (type)
  322. {
  323. case 4:
  324. case 2:
  325. _color_mode = COLORMODE_RGBA;
  326. break;
  327. default:
  328. _color_mode = COLORMODE_RGB;
  329. }
  330. return 0;
  331. }
  332. else
  333. return -2;
  334. }
  335. int MtkImage::Save(char *filename, char *format)
  336. {
  337. extern int mtk_image__tga_save(FILE *f, unsigned char *image,
  338. unsigned int width, unsigned int height,
  339. char bpp);
  340. FILE *f;
  341. int ret;
  342. f = fopen(filename, "wb");
  343. ret = mtk_image__tga_save(f, _image, _width, _height, _color_mode+1);
  344. if (f)
  345. fclose(f);
  346. return ret;
  347. }
  348. int MtkImage::Load(unsigned char *image, unsigned int w, unsigned int h,
  349. mtk_colormode mode)
  350. {
  351. switch (mode)
  352. {
  353. case COLORMODE_INDEXED:
  354. return LoadIndexed(image, w, h);
  355. break;
  356. case COLORMODE_RGB:
  357. if (!image || !w || !h || image == _image)
  358. return -1;
  359. _width = _original_width = w;
  360. _height = _original_height = h;
  361. if (_image)
  362. delete [] _image;
  363. _color_mode = COLORMODE_RGB;
  364. _image = new unsigned char[w * h * 3];
  365. memcpy(_image, image, w * h * 3);
  366. return 0;
  367. break;
  368. case COLORMODE_RGBA:
  369. if (!image || !w || !h || image == _image)
  370. return -1;
  371. _width = _original_width = w;
  372. _height = _original_height = h;
  373. if (_image)
  374. delete [] _image;
  375. _color_mode = COLORMODE_RGBA;
  376. _image = new unsigned char[w * h * 4];
  377. memcpy(_image, image, w * h * 4);
  378. return 0;
  379. break;
  380. }
  381. return -1;
  382. }
  383. // Palette ////////////////////////////////////////////
  384. // Search palette for matching ( or closest ) rgb color
  385. // Colors *must be 0.0 to 1.0 form!
  386. //
  387. // Note if you have a small palette this may 'wash' to black
  388. // quickly after running through a few times ( 0.0 is default )
  389. int MtkImage::PaletteMatchColor(float rgb[3])
  390. {
  391. float color[3];
  392. float best_weight, current_weight;
  393. int i, best;
  394. if (!_palette)
  395. {
  396. printf("MtkImage::MatchColor> ERROR no palette loaded\n");
  397. return -1;
  398. }
  399. best_weight = current_weight = 0.0;
  400. for (best = 0, i = 0; i < 256; i++)
  401. {
  402. // Convert from 0-255 to 0.0-1.0 color scale
  403. PaletteColor(i, color);
  404. //color[0] = _palette[i*3]/255.0;
  405. //color[1] = _palette[i*3+1]/255.0;
  406. //color[2] = _palette[i*3+2]/255.0;
  407. // FIXME: Should be 0.0 (far off) to 1.0 (exact match)
  408. current_weight = 1.0 - ((fabs(rgb[0] - color[0]) +
  409. fabs(rgb[1] - color[1]) +
  410. fabs(rgb[2] - color[2])) / 3.0);
  411. if (current_weight > best_weight)
  412. {
  413. best_weight = current_weight;
  414. best = i;
  415. if (best_weight == 1.0)
  416. i = 1024; // break;
  417. }
  418. }
  419. return best;
  420. }
  421. void MtkImage::PaletteColor(int i, float rgb[3])
  422. {
  423. if (i > 0 && i < 256 && rgb && _palette)
  424. {
  425. rgb[0] = (float)_palette[i*3]/255.0;
  426. rgb[1] = (float)_palette[i*3+1]/255.0;
  427. rgb[2] = (float)_palette[i*3+2]/255.0;
  428. }
  429. }
  430. int MtkImage::PaletteLoadLMP(char *filename)
  431. {
  432. FILE *f;
  433. f = fopen(filename, "rb");
  434. if (f)
  435. {
  436. if (!_palette)
  437. _palette = new unsigned char[768];
  438. fread(_palette, 1, 768, f);
  439. fclose(f);
  440. return 0;
  441. }
  442. return -1;
  443. }
  444. int MtkImage::PaletteLoad(char *filename)
  445. {
  446. FILE *f;
  447. int i;
  448. unsigned int rgb[3];
  449. if (!filename)
  450. return -1;
  451. f = fopen(filename, "r");
  452. if (f)
  453. {
  454. if (_palette)
  455. delete [] _palette;
  456. _palette = new unsigned char[768];
  457. for (i = 0; i < 768; i+=3)
  458. {
  459. fscanf(f, "%u %u %u\n",
  460. &rgb[0],
  461. &rgb[1],
  462. &rgb[2]);
  463. _palette[i] = rgb[0];
  464. _palette[i+1] = rgb[1];
  465. _palette[i+2] = rgb[2];
  466. }
  467. fclose(f);
  468. return 0;
  469. }
  470. return 1;
  471. }
  472. int MtkImage::PaletteSave(char *filename)
  473. {
  474. FILE *f;
  475. int i;
  476. if (!_palette || !filename)
  477. return -1;
  478. f = fopen(filename, "w");
  479. if (f)
  480. {
  481. for (i = 0; i < 768; i+=3)
  482. {
  483. fprintf(f, "%i %i %i\n",
  484. (int)_palette[i],
  485. (int)_palette[i+1],
  486. (int)_palette[i+2]);
  487. }
  488. fclose(f);
  489. return 0;
  490. }
  491. return 1;
  492. }
  493. mtk_colormode MtkImage::Mode()
  494. {
  495. return _color_mode;
  496. }
  497. /* This code based off on gluScaleImage() */
  498. void MtkImage::Scale()
  499. {
  500. int i, j, k;
  501. float* tempin;
  502. float* tempout;
  503. float sx, sy;
  504. int components = 3;
  505. unsigned char *image;
  506. if (!_image || !_width || !_height)
  507. return;
  508. _height = NextPower(_height);
  509. _width = NextPower(_width);
  510. if (_height > 256)
  511. _height = 256;
  512. if (_width > 256)
  513. _width = 256;
  514. // Check to see if scaling is needed
  515. if (_height == _original_height && _width == _original_width)
  516. return;
  517. image = new unsigned char[_height * _width * 3];
  518. tempin = new float[_original_width * _original_height *
  519. components * sizeof(float)];
  520. tempout = new float[_width * _height * components * sizeof(float)];
  521. if (!tempout || !tempin)
  522. {
  523. if (tempout)
  524. delete [] tempout;
  525. if (tempin)
  526. delete [] tempin;
  527. printf("Oh shit out of memory!\n");
  528. return;
  529. }
  530. // Copy user data to float format.
  531. for (i = 0; i < _original_height * _original_width * components; i++)
  532. {
  533. tempin[i] = (float)_image[i];
  534. }
  535. // Determine which filter to use by checking ratios.
  536. if (_width > 1)
  537. {
  538. sx = (float)(_original_width - 1) / (float)(_width - 1);
  539. }
  540. else
  541. {
  542. sx = (float)(_original_width - 1);
  543. }
  544. if (_height > 1)
  545. {
  546. sy = (float)(_original_height - 1) / (float) (_height - 1);
  547. }
  548. else
  549. {
  550. sy = (float)(_original_height - 1);
  551. }
  552. if (sx < 1.0 && sy < 1.0)
  553. {
  554. /* Magnify both width and height: use weighted sample of 4 pixels */
  555. int i0, i1, j0, j1;
  556. float alpha, beta;
  557. float* src00;
  558. float* src01;
  559. float* src10;
  560. float* src11;
  561. float s1, s2;
  562. float* dst;
  563. for(i = 0; i < _height; i++)
  564. {
  565. i0 = (int)(i * sy);
  566. i1 = i0 + 1;
  567. if (i1 >= _original_height)
  568. {
  569. i1 = _original_height - 1;
  570. }
  571. alpha = i * sy - i0;
  572. for (j = 0; j < _width; j++)
  573. {
  574. j0 = (int) (j * sx);
  575. j1 = j0 + 1;
  576. if (j1 >= _original_width)
  577. {
  578. j1 = _original_width - 1;
  579. }
  580. beta = j * sx - j0;
  581. /* Compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
  582. src00 = tempin + (i0 * _original_width + j0) * components;
  583. src01 = tempin + (i0 * _original_width + j1) * components;
  584. src10 = tempin + (i1 * _original_width + j0) * components;
  585. src11 = tempin + (i1 * _original_width + j1) * components;
  586. dst = tempout + (i * _width + j) * components;
  587. for (k = 0; k < components; k++)
  588. {
  589. s1 = *src00++ * (1.0 - beta) + *src01++ * beta;
  590. s2 = *src10++ * (1.0 - beta) + *src11++ * beta;
  591. *dst++ = s1 * (1.0 - alpha) + s2 * alpha;
  592. }
  593. }
  594. }
  595. }
  596. else
  597. {
  598. /* Shrink width and/or height: use an unweighted box filter */
  599. int i0, i1;
  600. int j0, j1;
  601. int ii, jj;
  602. float sum;
  603. float* dst;
  604. for (i = 0; i < _height; i++)
  605. {
  606. i0 = (int) (i * sy);
  607. i1 = i0 + 1;
  608. if (i1 >= _original_height)
  609. {
  610. i1 = _original_height - 1;
  611. }
  612. for (j = 0; j < _width; j++)
  613. {
  614. j0 = (int) (j * sx);
  615. j1 = j0 + 1;
  616. if (j1 >= _original_width)
  617. {
  618. j1 = _original_width - 1;
  619. }
  620. dst = tempout + (i * _width + j) * components;
  621. /* Compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
  622. for (k = 0; k < components; k++)
  623. {
  624. sum = 0.0;
  625. for (ii = i0; ii <= i1; ii++)
  626. {
  627. for (jj = j0; jj <= j1; jj++)
  628. {
  629. sum += *(tempin + (ii * _original_width + jj)
  630. * components + k);
  631. }
  632. }
  633. sum /= ( j1 - j0 + 1 ) * ( i1 - i0 + 1 );
  634. *dst++ = sum;
  635. }
  636. }
  637. }
  638. }
  639. // Copy to our results.
  640. for( i = 0; i < _height * _width * components; i++ )
  641. {
  642. image[i] = (unsigned char) tempout[i];
  643. }
  644. // Delete our temp buffers.
  645. delete[] tempin;
  646. delete[] tempout;
  647. delete[] _image;
  648. _image = image;
  649. }
  650. int MtkImage::NextPower(int seed)
  651. {
  652. int i;
  653. for(i = 1; i < seed; i *= 2)
  654. ;
  655. return i;
  656. }