/src/FreeImage/Source/FreeImage/J2KHelper.cpp

https://bitbucket.org/cabalistic/ogredeps/ · C++ · 500 lines · 346 code · 82 blank · 72 comment · 85 complexity · bf9d7cf11c3e1a51f8606d4418237116 MD5 · raw file

  1. // ==========================================================
  2. // JPEG2000 helpers
  3. //
  4. // Design and implementation by
  5. // - Hervé Drolon (drolon@infonie.fr)
  6. //
  7. // This file is part of FreeImage 3
  8. //
  9. // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
  10. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
  11. // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
  12. // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
  13. // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
  14. // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
  15. // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
  16. // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
  17. // THIS DISCLAIMER.
  18. //
  19. // Use at your own risk!
  20. // ==========================================================
  21. #include "FreeImage.h"
  22. #include "Utilities.h"
  23. #include "../LibOpenJPEG/openjpeg.h"
  24. /**
  25. Divide an integer by a power of 2 and round upwards
  26. @return Returns a divided by 2^b
  27. */
  28. static int int_ceildivpow2(int a, int b) {
  29. return (a + (1 << b) - 1) >> b;
  30. }
  31. /**
  32. Convert a OpenJPEG image to a FIBITMAP
  33. @param format_id Plugin ID
  34. @param image OpenJPEG image
  35. @return Returns the converted image if successful, returns NULL otherwise
  36. */
  37. FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image) {
  38. FIBITMAP *dib = NULL;
  39. try {
  40. // compute image width and height
  41. //int w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
  42. int wr = image->comps[0].w;
  43. int wrr = int_ceildivpow2(image->comps[0].w, image->comps[0].factor);
  44. //int h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
  45. //int hr = image->comps[0].h;
  46. int hrr = int_ceildivpow2(image->comps[0].h, image->comps[0].factor);
  47. // check the number of components
  48. int numcomps = image->numcomps;
  49. BOOL bIsValid = TRUE;
  50. for(int c = 0; c < numcomps - 1; c++) {
  51. if( (image->comps[c].dx == image->comps[c+1].dx) &&
  52. (image->comps[c].dy == image->comps[c+1].dy) &&
  53. (image->comps[c].prec == image->comps[c+1].prec) ) {
  54. continue;
  55. } else {
  56. bIsValid = FALSE;
  57. break;
  58. }
  59. }
  60. bIsValid &= ((numcomps == 1) || (numcomps == 3) || (numcomps == 4));
  61. if(!bIsValid) {
  62. if(numcomps) {
  63. FreeImage_OutputMessageProc(format_id, "Warning: image contains %d greyscale components. Only the first will be loaded.\n", numcomps);
  64. numcomps = 1;
  65. } else {
  66. // unknown type
  67. throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
  68. }
  69. }
  70. // create a new DIB
  71. if(image->comps[0].prec <= 8) {
  72. switch(numcomps) {
  73. case 1:
  74. dib = FreeImage_Allocate(wrr, hrr, 8);
  75. break;
  76. case 3:
  77. dib = FreeImage_Allocate(wrr, hrr, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
  78. break;
  79. case 4:
  80. dib = FreeImage_Allocate(wrr, hrr, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
  81. break;
  82. }
  83. } else if(image->comps[0].prec <= 16) {
  84. switch(numcomps) {
  85. case 1:
  86. dib = FreeImage_AllocateT(FIT_UINT16, wrr, hrr);
  87. break;
  88. case 3:
  89. dib = FreeImage_AllocateT(FIT_RGB16, wrr, hrr);
  90. break;
  91. case 4:
  92. dib = FreeImage_AllocateT(FIT_RGBA16, wrr, hrr);
  93. break;
  94. }
  95. } else {
  96. throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
  97. }
  98. if(!dib) {
  99. throw FI_MSG_ERROR_DIB_MEMORY;
  100. }
  101. if(image->comps[0].prec <= 8) {
  102. if(numcomps == 1) {
  103. // 8-bit greyscale
  104. // ----------------------------------------------------------
  105. // build a greyscale palette
  106. RGBQUAD *pal = FreeImage_GetPalette(dib);
  107. for (int i = 0; i < 256; i++) {
  108. pal[i].rgbRed = (BYTE)i;
  109. pal[i].rgbGreen = (BYTE)i;
  110. pal[i].rgbBlue = (BYTE)i;
  111. }
  112. // load pixel data
  113. unsigned pixel_count = 0;
  114. for(int y = 0; y < hrr; y++) {
  115. BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y);
  116. for(int x = 0; x < wrr; x++) {
  117. const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
  118. int index = image->comps[0].data[pixel_pos];
  119. index += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
  120. bits[x] = (BYTE)index;
  121. pixel_count++;
  122. }
  123. }
  124. }
  125. else if(numcomps == 3) {
  126. // 24-bit RGB
  127. // ----------------------------------------------------------
  128. // load pixel data
  129. unsigned pixel_count = 0;
  130. for(int y = 0; y < hrr; y++) {
  131. BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y);
  132. for(int x = 0; x < wrr; x++) {
  133. const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
  134. int r = image->comps[0].data[pixel_pos];
  135. r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
  136. int g = image->comps[1].data[pixel_pos];
  137. g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
  138. int b = image->comps[2].data[pixel_pos];
  139. b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
  140. bits[FI_RGBA_RED] = (BYTE)r;
  141. bits[FI_RGBA_GREEN] = (BYTE)g;
  142. bits[FI_RGBA_BLUE] = (BYTE)b;
  143. bits += 3;
  144. pixel_count++;
  145. }
  146. }
  147. }
  148. else if(numcomps == 4) {
  149. // 32-bit RGBA
  150. // ----------------------------------------------------------
  151. // load pixel data
  152. unsigned pixel_count = 0;
  153. for(int y = 0; y < hrr; y++) {
  154. BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y);
  155. for(int x = 0; x < wrr; x++) {
  156. const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
  157. int r = image->comps[0].data[pixel_pos];
  158. r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
  159. int g = image->comps[1].data[pixel_pos];
  160. g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
  161. int b = image->comps[2].data[pixel_pos];
  162. b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
  163. int a = image->comps[3].data[pixel_pos];
  164. a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0);
  165. bits[FI_RGBA_RED] = (BYTE)r;
  166. bits[FI_RGBA_GREEN] = (BYTE)g;
  167. bits[FI_RGBA_BLUE] = (BYTE)b;
  168. bits[FI_RGBA_ALPHA] = (BYTE)a;
  169. bits += 4;
  170. pixel_count++;
  171. }
  172. }
  173. }
  174. }
  175. else if(image->comps[0].prec <= 16) {
  176. if(numcomps == 1) {
  177. // 16-bit greyscale
  178. // ----------------------------------------------------------
  179. // load pixel data
  180. unsigned pixel_count = 0;
  181. for(int y = 0; y < hrr; y++) {
  182. unsigned short *bits = (unsigned short*)FreeImage_GetScanLine(dib, hrr - 1 - y);
  183. for(int x = 0; x < wrr; x++) {
  184. const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
  185. int index = image->comps[0].data[pixel_pos];
  186. index += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
  187. bits[x] = (unsigned short)index;
  188. pixel_count++;
  189. }
  190. }
  191. }
  192. else if(numcomps == 3) {
  193. // 48-bit RGB
  194. // ----------------------------------------------------------
  195. // load pixel data
  196. unsigned pixel_count = 0;
  197. for(int y = 0; y < hrr; y++) {
  198. FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, hrr - 1 - y);
  199. for(int x = 0; x < wrr; x++) {
  200. const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
  201. int r = image->comps[0].data[pixel_pos];
  202. r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
  203. int g = image->comps[1].data[pixel_pos];
  204. g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
  205. int b = image->comps[2].data[pixel_pos];
  206. b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
  207. bits[x].red = (WORD)r;
  208. bits[x].green = (WORD)g;
  209. bits[x].blue = (WORD)b;
  210. pixel_count++;
  211. }
  212. }
  213. }
  214. else if(numcomps == 4) {
  215. // 64-bit RGBA
  216. // ----------------------------------------------------------
  217. // load pixel data
  218. unsigned pixel_count = 0;
  219. for(int y = 0; y < hrr; y++) {
  220. FIRGBA16 *bits = (FIRGBA16*)FreeImage_GetScanLine(dib, hrr - 1 - y);
  221. for(int x = 0; x < wrr; x++) {
  222. const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
  223. int r = image->comps[0].data[pixel_pos];
  224. r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
  225. int g = image->comps[1].data[pixel_pos];
  226. g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
  227. int b = image->comps[2].data[pixel_pos];
  228. b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
  229. int a = image->comps[3].data[pixel_pos];
  230. a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0);
  231. bits[x].red = (WORD)r;
  232. bits[x].green = (WORD)g;
  233. bits[x].blue = (WORD)b;
  234. bits[x].alpha = (WORD)a;
  235. pixel_count++;
  236. }
  237. }
  238. }
  239. }
  240. return dib;
  241. } catch(const char *text) {
  242. if(dib) FreeImage_Unload(dib);
  243. FreeImage_OutputMessageProc(format_id, text);
  244. return NULL;
  245. }
  246. }
  247. /**
  248. Convert a FIBITMAP to a OpenJPEG image
  249. @param format_id Plugin ID
  250. @param dib FreeImage image
  251. @param parameters Compression parameters
  252. @return Returns the converted image if successful, returns NULL otherwise
  253. */
  254. opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters) {
  255. int prec, numcomps, x, y, index;
  256. OPJ_COLOR_SPACE color_space;
  257. opj_image_cmptparm_t cmptparm[4]; // maximum of 4 components
  258. opj_image_t *image = NULL; // image to encode
  259. try {
  260. int w = FreeImage_GetWidth(dib);
  261. int h = FreeImage_GetHeight(dib);
  262. // get image characteristics
  263. FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
  264. if(image_type == FIT_BITMAP) {
  265. // standard image ...
  266. prec = 8;
  267. switch(FreeImage_GetColorType(dib)) {
  268. case FIC_MINISBLACK:
  269. numcomps = 1;
  270. color_space = CLRSPC_GRAY;
  271. break;
  272. case FIC_RGB:
  273. if(FreeImage_GetBPP(dib) == 32) {
  274. // 32-bit image with a fully opaque layer
  275. numcomps = 4;
  276. color_space = CLRSPC_SRGB;
  277. } else {
  278. // 24-bit image
  279. numcomps = 3;
  280. color_space = CLRSPC_SRGB;
  281. }
  282. break;
  283. case FIC_RGBALPHA:
  284. numcomps = 4;
  285. color_space = CLRSPC_SRGB;
  286. break;
  287. default:
  288. return NULL;
  289. }
  290. } else {
  291. // HDR image ...
  292. prec = 16;
  293. switch(image_type) {
  294. case FIT_UINT16:
  295. numcomps = 1;
  296. color_space = CLRSPC_GRAY;
  297. break;
  298. case FIT_RGB16:
  299. numcomps = 3;
  300. color_space = CLRSPC_SRGB;
  301. break;
  302. case FIT_RGBA16:
  303. numcomps = 4;
  304. color_space = CLRSPC_SRGB;
  305. break;
  306. default:
  307. return NULL;
  308. }
  309. }
  310. // initialize image components
  311. memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
  312. for(int i = 0; i < numcomps; i++) {
  313. cmptparm[i].dx = parameters->subsampling_dx;
  314. cmptparm[i].dy = parameters->subsampling_dy;
  315. cmptparm[i].w = w;
  316. cmptparm[i].h = h;
  317. cmptparm[i].prec = prec;
  318. cmptparm[i].bpp = prec;
  319. cmptparm[i].sgnd = 0;
  320. }
  321. // create the image
  322. image = opj_image_create(numcomps, &cmptparm[0], color_space);
  323. if(!image) {
  324. throw FI_MSG_ERROR_DIB_MEMORY;
  325. }
  326. // set image offset and reference grid
  327. image->x0 = parameters->image_offset_x0;
  328. image->y0 = parameters->image_offset_y0;
  329. image->x1 = parameters->image_offset_x0 + (w - 1) * parameters->subsampling_dx + 1;
  330. image->y1 = parameters->image_offset_y0 + (h - 1) * parameters->subsampling_dy + 1;
  331. // set image data
  332. if(prec == 8) {
  333. switch(numcomps) {
  334. case 1:
  335. index = 0;
  336. for(y = 0; y < h; y++) {
  337. BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y);
  338. for(x = 0; x < w; x++) {
  339. image->comps[0].data[index] = bits[x];
  340. index++;
  341. }
  342. }
  343. break;
  344. case 3:
  345. index = 0;
  346. for(y = 0; y < h; y++) {
  347. BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y);
  348. for(x = 0; x < w; x++) {
  349. image->comps[0].data[index] = bits[FI_RGBA_RED];
  350. image->comps[1].data[index] = bits[FI_RGBA_GREEN];
  351. image->comps[2].data[index] = bits[FI_RGBA_BLUE];
  352. bits += 3;
  353. index++;
  354. }
  355. }
  356. break;
  357. case 4:
  358. index = 0;
  359. for(y = 0; y < h; y++) {
  360. BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y);
  361. for(x = 0; x < w; x++) {
  362. image->comps[0].data[index] = bits[FI_RGBA_RED];
  363. image->comps[1].data[index] = bits[FI_RGBA_GREEN];
  364. image->comps[2].data[index] = bits[FI_RGBA_BLUE];
  365. image->comps[3].data[index] = bits[FI_RGBA_ALPHA];
  366. bits += 4;
  367. index++;
  368. }
  369. }
  370. break;
  371. }
  372. }
  373. else if(prec == 16) {
  374. switch(numcomps) {
  375. case 1:
  376. index = 0;
  377. for(y = 0; y < h; y++) {
  378. WORD *bits = (WORD*)FreeImage_GetScanLine(dib, h - 1 - y);
  379. for(x = 0; x < w; x++) {
  380. image->comps[0].data[index] = bits[x];
  381. index++;
  382. }
  383. }
  384. break;
  385. case 3:
  386. index = 0;
  387. for(y = 0; y < h; y++) {
  388. FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, h - 1 - y);
  389. for(x = 0; x < w; x++) {
  390. image->comps[0].data[index] = bits[x].red;
  391. image->comps[1].data[index] = bits[x].green;
  392. image->comps[2].data[index] = bits[x].blue;
  393. index++;
  394. }
  395. }
  396. break;
  397. case 4:
  398. index = 0;
  399. for(y = 0; y < h; y++) {
  400. FIRGBA16 *bits = (FIRGBA16*)FreeImage_GetScanLine(dib, h - 1 - y);
  401. for(x = 0; x < w; x++) {
  402. image->comps[0].data[index] = bits[x].red;
  403. image->comps[1].data[index] = bits[x].green;
  404. image->comps[2].data[index] = bits[x].blue;
  405. image->comps[3].data[index] = bits[x].alpha;
  406. index++;
  407. }
  408. }
  409. break;
  410. }
  411. }
  412. return image;
  413. } catch (const char *text) {
  414. if(image) opj_image_destroy(image);
  415. FreeImage_OutputMessageProc(format_id, text);
  416. return NULL;
  417. }
  418. }