test_tile_encoder.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /*
  2. * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  18. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <math.h>
  30. #include "opj_config.h"
  31. #include "openjpeg.h"
  32. #include "stdlib.h"
  33. /* -------------------------------------------------------------------------- */
  34. /**
  35. sample error debug callback expecting no client object
  36. */
  37. static void error_callback(const char *msg, void *client_data)
  38. {
  39. (void)client_data;
  40. fprintf(stdout, "[ERROR] %s", msg);
  41. }
  42. /**
  43. sample warning debug callback expecting no client object
  44. */
  45. static void warning_callback(const char *msg, void *client_data)
  46. {
  47. (void)client_data;
  48. fprintf(stdout, "[WARNING] %s", msg);
  49. }
  50. /**
  51. sample debug callback expecting no client object
  52. */
  53. static void info_callback(const char *msg, void *client_data)
  54. {
  55. (void)client_data;
  56. fprintf(stdout, "[INFO] %s", msg);
  57. }
  58. static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b)
  59. {
  60. return (a > b) ? a : b;
  61. }
  62. static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b)
  63. {
  64. return (a < b) ? a : b;
  65. }
  66. /* -------------------------------------------------------------------------- */
  67. #define NUM_COMPS_MAX 4
  68. int main(int argc, char *argv[])
  69. {
  70. opj_cparameters_t l_param;
  71. opj_codec_t * l_codec;
  72. opj_image_t * l_image;
  73. opj_image_cmptparm_t l_params [NUM_COMPS_MAX];
  74. opj_stream_t * l_stream;
  75. OPJ_UINT32 l_nb_tiles_width, l_nb_tiles_height, l_nb_tiles;
  76. OPJ_UINT32 l_data_size;
  77. size_t len;
  78. #ifdef USING_MCT
  79. const OPJ_FLOAT32 l_mct [] = {
  80. 1, 0, 0,
  81. 0, 1, 0,
  82. 0, 0, 1
  83. };
  84. const OPJ_INT32 l_offsets [] = {
  85. 128, 128, 128
  86. };
  87. #endif
  88. opj_image_cmptparm_t * l_current_param_ptr;
  89. OPJ_UINT32 i;
  90. OPJ_BYTE *l_data;
  91. OPJ_UINT32 num_comps;
  92. int image_width;
  93. int image_height;
  94. int tile_width;
  95. int tile_height;
  96. int comp_prec;
  97. int irreversible;
  98. const char *output_file;
  99. int cblockw_init = 64;
  100. int cblockh_init = 64;
  101. int numresolution = 6;
  102. OPJ_UINT32 offsetx = 0;
  103. OPJ_UINT32 offsety = 0;
  104. int quality_loss = 1;
  105. int is_rand = 0;
  106. opj_set_default_encoder_parameters(&l_param);
  107. /* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k [64 64] [6] [0 0] [0] [256 256] */
  108. if (argc >= 9) {
  109. num_comps = (OPJ_UINT32)atoi(argv[1]);
  110. image_width = atoi(argv[2]);
  111. image_height = atoi(argv[3]);
  112. tile_width = atoi(argv[4]);
  113. tile_height = atoi(argv[5]);
  114. comp_prec = atoi(argv[6]);
  115. irreversible = atoi(argv[7]);
  116. output_file = argv[8];
  117. if (argc >= 11) {
  118. quality_loss = 0;
  119. cblockw_init = atoi(argv[9]);
  120. cblockh_init = atoi(argv[10]);
  121. }
  122. if (argc >= 12) {
  123. numresolution = atoi(argv[11]);
  124. }
  125. if (argc >= 14) {
  126. offsetx = (OPJ_UINT32)atoi(argv[12]);
  127. offsety = (OPJ_UINT32)atoi(argv[13]);
  128. }
  129. if (argc >= 15) {
  130. is_rand = atoi(argv[14]);
  131. }
  132. for (i = 15; i + 1 < (OPJ_UINT32)argc &&
  133. l_param.res_spec < OPJ_J2K_MAXRLVLS; i += 2) {
  134. l_param.csty |= 0x01;
  135. l_param.prcw_init[l_param.res_spec] = atoi(argv[i]);
  136. l_param.prch_init[l_param.res_spec] = atoi(argv[i + 1]);
  137. l_param.res_spec ++;
  138. }
  139. } else {
  140. num_comps = 3;
  141. image_width = 2000;
  142. image_height = 2000;
  143. tile_width = 1000;
  144. tile_height = 1000;
  145. comp_prec = 8;
  146. irreversible = 1;
  147. output_file = "test.j2k";
  148. }
  149. if (num_comps > NUM_COMPS_MAX) {
  150. return 1;
  151. }
  152. l_nb_tiles_width = (offsetx + (OPJ_UINT32)image_width +
  153. (OPJ_UINT32)tile_width - 1) / (OPJ_UINT32)tile_width;
  154. l_nb_tiles_height = (offsety + (OPJ_UINT32)image_height +
  155. (OPJ_UINT32)tile_height - 1) / (OPJ_UINT32)tile_height;
  156. l_nb_tiles = l_nb_tiles_width * l_nb_tiles_height;
  157. l_data_size = (OPJ_UINT32)tile_width * (OPJ_UINT32)tile_height *
  158. (OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
  159. l_data = (OPJ_BYTE*) malloc(l_data_size * sizeof(OPJ_BYTE));
  160. if (l_data == NULL) {
  161. return 1;
  162. }
  163. fprintf(stdout,
  164. "Encoding random values -> keep in mind that this is very hard to compress\n");
  165. for (i = 0; i < l_data_size; ++i) {
  166. if (is_rand) {
  167. l_data[i] = (OPJ_BYTE)rand();
  168. } else {
  169. l_data[i] = (OPJ_BYTE)i;
  170. }
  171. }
  172. /** you may here add custom encoding parameters */
  173. /* rate specifications */
  174. /** number of quality layers in the stream */
  175. if (quality_loss) {
  176. l_param.tcp_numlayers = 1;
  177. l_param.cp_fixed_quality = 1;
  178. l_param.tcp_distoratio[0] = 20;
  179. }
  180. /* is using others way of calculation */
  181. /* l_param.cp_disto_alloc = 1 or l_param.cp_fixed_alloc = 1 */
  182. /* l_param.tcp_rates[0] = ... */
  183. /* tile definitions parameters */
  184. /* position of the tile grid aligned with the image */
  185. l_param.cp_tx0 = 0;
  186. l_param.cp_ty0 = 0;
  187. /* tile size, we are using tile based encoding */
  188. l_param.tile_size_on = OPJ_TRUE;
  189. l_param.cp_tdx = tile_width;
  190. l_param.cp_tdy = tile_height;
  191. /* code block size */
  192. l_param.cblockw_init = cblockw_init;
  193. l_param.cblockh_init = cblockh_init;
  194. /* use irreversible encoding ?*/
  195. l_param.irreversible = irreversible;
  196. /* do not bother with mct, the rsiz is set when calling opj_set_MCT*/
  197. /*l_param.cp_rsiz = OPJ_STD_RSIZ;*/
  198. /* no cinema */
  199. /*l_param.cp_cinema = 0;*/
  200. /* no not bother using SOP or EPH markers, do not use custom size precinct */
  201. /* number of precincts to specify */
  202. /* l_param.csty = 0;*/
  203. /* l_param.res_spec = ... */
  204. /* l_param.prch_init[i] = .. */
  205. /* l_param.prcw_init[i] = .. */
  206. /* do not use progression order changes */
  207. /*l_param.numpocs = 0;*/
  208. /* l_param.POC[i].... */
  209. /* do not restrain the size for a component.*/
  210. /* l_param.max_comp_size = 0; */
  211. /** block encoding style for each component, do not use at the moment */
  212. /** J2K_CCP_CBLKSTY_TERMALL, J2K_CCP_CBLKSTY_LAZY, J2K_CCP_CBLKSTY_VSC, J2K_CCP_CBLKSTY_SEGSYM, J2K_CCP_CBLKSTY_RESET */
  213. /* l_param.mode = 0;*/
  214. /** number of resolutions */
  215. l_param.numresolution = numresolution;
  216. /** progression order to use*/
  217. /** OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */
  218. l_param.prog_order = OPJ_LRCP;
  219. /** no "region" of interest, more precisally component */
  220. /* l_param.roi_compno = -1; */
  221. /* l_param.roi_shift = 0; */
  222. /* we are not using multiple tile parts for a tile. */
  223. /* l_param.tp_on = 0; */
  224. /* l_param.tp_flag = 0; */
  225. /* if we are using mct */
  226. #ifdef USING_MCT
  227. opj_set_MCT(&l_param, l_mct, l_offsets, NUM_COMPS);
  228. #endif
  229. /* image definition */
  230. l_current_param_ptr = l_params;
  231. for (i = 0; i < num_comps; ++i) {
  232. /* do not bother bpp useless */
  233. /*l_current_param_ptr->bpp = COMP_PREC;*/
  234. l_current_param_ptr->dx = 1;
  235. l_current_param_ptr->dy = 1;
  236. l_current_param_ptr->h = (OPJ_UINT32)image_height;
  237. l_current_param_ptr->w = (OPJ_UINT32)image_width;
  238. l_current_param_ptr->sgnd = 0;
  239. l_current_param_ptr->prec = (OPJ_UINT32)comp_prec;
  240. l_current_param_ptr->x0 = offsetx;
  241. l_current_param_ptr->y0 = offsety;
  242. ++l_current_param_ptr;
  243. }
  244. /* should we do j2k or jp2 ?*/
  245. len = strlen(output_file);
  246. if (strcmp(output_file + len - 4, ".jp2") == 0) {
  247. l_codec = opj_create_compress(OPJ_CODEC_JP2);
  248. } else {
  249. l_codec = opj_create_compress(OPJ_CODEC_J2K);
  250. }
  251. if (!l_codec) {
  252. free(l_data);
  253. return 1;
  254. }
  255. /* catch events using our callbacks and give a local context */
  256. opj_set_info_handler(l_codec, info_callback, 00);
  257. opj_set_warning_handler(l_codec, warning_callback, 00);
  258. opj_set_error_handler(l_codec, error_callback, 00);
  259. l_image = opj_image_tile_create(num_comps, l_params, OPJ_CLRSPC_SRGB);
  260. if (! l_image) {
  261. free(l_data);
  262. opj_destroy_codec(l_codec);
  263. return 1;
  264. }
  265. l_image->x0 = offsetx;
  266. l_image->y0 = offsety;
  267. l_image->x1 = offsetx + (OPJ_UINT32)image_width;
  268. l_image->y1 = offsety + (OPJ_UINT32)image_height;
  269. l_image->color_space = OPJ_CLRSPC_SRGB;
  270. if (! opj_setup_encoder(l_codec, &l_param, l_image)) {
  271. fprintf(stderr, "ERROR -> test_tile_encoder: failed to setup the codec!\n");
  272. opj_destroy_codec(l_codec);
  273. opj_image_destroy(l_image);
  274. free(l_data);
  275. return 1;
  276. }
  277. l_stream = opj_stream_create_default_file_stream(output_file, OPJ_FALSE);
  278. if (! l_stream) {
  279. fprintf(stderr,
  280. "ERROR -> test_tile_encoder: failed to create the stream from the output file %s !\n",
  281. output_file);
  282. opj_destroy_codec(l_codec);
  283. opj_image_destroy(l_image);
  284. free(l_data);
  285. return 1;
  286. }
  287. if (! opj_start_compress(l_codec, l_image, l_stream)) {
  288. fprintf(stderr, "ERROR -> test_tile_encoder: failed to start compress!\n");
  289. opj_stream_destroy(l_stream);
  290. opj_destroy_codec(l_codec);
  291. opj_image_destroy(l_image);
  292. free(l_data);
  293. return 1;
  294. }
  295. for (i = 0; i < l_nb_tiles; ++i) {
  296. OPJ_UINT32 tile_y = i / l_nb_tiles_width;
  297. OPJ_UINT32 tile_x = i % l_nb_tiles_width;
  298. OPJ_UINT32 tile_x0 = opj_uint_max(l_image->x0, tile_x * (OPJ_UINT32)tile_width);
  299. OPJ_UINT32 tile_y0 = opj_uint_max(l_image->y0,
  300. tile_y * (OPJ_UINT32)tile_height);
  301. OPJ_UINT32 tile_x1 = opj_uint_min(l_image->x1,
  302. (tile_x + 1) * (OPJ_UINT32)tile_width);
  303. OPJ_UINT32 tile_y1 = opj_uint_min(l_image->y1,
  304. (tile_y + 1) * (OPJ_UINT32)tile_height);
  305. OPJ_UINT32 tilesize = (tile_x1 - tile_x0) * (tile_y1 - tile_y0) *
  306. (OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
  307. if (! opj_write_tile(l_codec, i, l_data, tilesize, l_stream)) {
  308. fprintf(stderr, "ERROR -> test_tile_encoder: failed to write the tile %d!\n",
  309. i);
  310. opj_stream_destroy(l_stream);
  311. opj_destroy_codec(l_codec);
  312. opj_image_destroy(l_image);
  313. free(l_data);
  314. return 1;
  315. }
  316. }
  317. if (! opj_end_compress(l_codec, l_stream)) {
  318. fprintf(stderr, "ERROR -> test_tile_encoder: failed to end compress!\n");
  319. opj_stream_destroy(l_stream);
  320. opj_destroy_codec(l_codec);
  321. opj_image_destroy(l_image);
  322. free(l_data);
  323. return 1;
  324. }
  325. opj_stream_destroy(l_stream);
  326. opj_destroy_codec(l_codec);
  327. opj_image_destroy(l_image);
  328. free(l_data);
  329. /* Print profiling*/
  330. /*PROFPRINT();*/
  331. return 0;
  332. }