2 * The copyright in this software is being made available under the 2-clauses
3 * BSD License, included below. This software may be subject to other third
4 * party and contributor rights, including patent rights, and no such rights
5 * are granted under this license.
7 * Copyright (c) 2017, IntoPix SA <contact@intopix.com>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
36 #include "format_defs.h"
39 /* -------------------------------------------------------------------------- */
40 #define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
41 #define JP2_MAGIC "\x0d\x0a\x87\x0a"
42 /* position 45: "\xff\x52" */
43 #define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
45 static int infile_format(const char *fname)
48 unsigned char buf[12];
49 unsigned int l_nb_read;
51 reader = fopen(fname, "rb");
58 l_nb_read = (unsigned int)fread(buf, 1, 12, reader);
60 if (l_nb_read != 12) {
64 if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buf, JP2_MAGIC, 4) == 0) {
66 } else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
74 /* -------------------------------------------------------------------------- */
77 sample error debug callback expecting no client object
79 static void error_callback(const char *msg, void *client_data)
82 fprintf(stdout, "[ERROR] %s", msg);
85 sample warning debug callback expecting no client object
87 static void warning_callback(const char *msg, void *client_data)
90 fprintf(stdout, "[WARNING] %s", msg);
93 sample debug callback expecting no client object
95 static void info_callback(const char *msg, void *client_data)
99 /*fprintf(stdout, "[INFO] %s", msg);*/
102 static opj_codec_t* create_codec_and_stream(const char* input_file,
103 opj_stream_t** pOutStream)
105 opj_dparameters_t l_param;
106 opj_codec_t * l_codec = NULL;
107 opj_stream_t * l_stream = NULL;
109 l_stream = opj_stream_create_default_file_stream(input_file, OPJ_TRUE);
111 fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
115 /* Set the default decoding parameters */
116 opj_set_default_decoder_parameters(&l_param);
119 l_param.decod_format = infile_format(input_file);
122 switch (l_param.decod_format) {
123 case J2K_CFMT: { /* JPEG-2000 codestream */
124 /* Get a decoder handle */
125 l_codec = opj_create_decompress(OPJ_CODEC_J2K);
128 case JP2_CFMT: { /* JPEG 2000 compressed image data */
129 /* Get a decoder handle */
130 l_codec = opj_create_decompress(OPJ_CODEC_JP2);
134 fprintf(stderr, "ERROR -> Not a valid JPEG2000 file!\n");
135 opj_stream_destroy(l_stream);
140 /* catch events using our callbacks and give a local context */
141 opj_set_info_handler(l_codec, info_callback, 00);
142 opj_set_warning_handler(l_codec, warning_callback, 00);
143 opj_set_error_handler(l_codec, error_callback, 00);
145 /* Setup the decoder decoding parameters using user parameters */
146 if (! opj_setup_decoder(l_codec, &l_param)) {
147 fprintf(stderr, "ERROR ->failed to setup the decoder\n");
148 opj_stream_destroy(l_stream);
149 opj_destroy_codec(l_codec);
153 *pOutStream = l_stream;
160 const char* input_file,
170 opj_codec_t * l_codec = NULL;
171 opj_image_t * l_image = NULL;
172 opj_stream_t * l_stream = NULL;
175 if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) {
176 printf("Decoding %d,%d,%d,%d\n", x0, y0, x1, y1);
178 printf("Decoding full image\n");
182 l_codec = create_codec_and_stream(input_file, &l_stream);
183 if (l_codec == NULL) {
187 /* Read the main header of the codestream and if necessary the JP2 boxes*/
188 if (! opj_read_header(l_stream, l_codec, &l_image)) {
189 fprintf(stderr, "ERROR -> failed to read the header\n");
190 opj_stream_destroy(l_stream);
191 opj_destroy_codec(l_codec);
196 opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(l_codec);
198 *ptilew = pCodeStreamInfo->tdx;
201 *ptilew = pCodeStreamInfo->tdy;
203 //int numResolutions = pCodeStreamInfo->m_default_tile_info.tccp_info[0].numresolutions;
205 *pcblkw = 1U << pCodeStreamInfo->m_default_tile_info.tccp_info[0].cblkw;
208 *pcblkh = 1U << pCodeStreamInfo->m_default_tile_info.tccp_info[0].cblkh;
210 opj_destroy_cstr_info(&pCodeStreamInfo);
213 if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) {
214 if (!opj_set_decode_area(l_codec, l_image, x0, y0, x1, y1)) {
215 fprintf(stderr, "ERROR -> failed to set the decoded area\n");
216 opj_stream_destroy(l_stream);
217 opj_destroy_codec(l_codec);
218 opj_image_destroy(l_image);
223 /* Get the decoded image */
224 if (!(opj_decode(l_codec, l_stream, l_image))) {
225 fprintf(stderr, "ERROR -> failed to decode image!\n");
226 opj_stream_destroy(l_stream);
227 opj_destroy_codec(l_codec);
228 opj_image_destroy(l_image);
232 if (! opj_end_decompress(l_codec, l_stream)) {
233 opj_stream_destroy(l_stream);
234 opj_destroy_codec(l_codec);
235 opj_image_destroy(l_image);
240 opj_stream_destroy(l_stream);
241 opj_destroy_codec(l_codec);
245 int decode_by_strip(OPJ_BOOL quiet,
246 const char* input_file,
247 OPJ_UINT32 strip_height,
248 opj_image_t* full_image)
250 /* OPJ_UINT32 tilew, tileh; */
251 opj_codec_t * l_codec = NULL;
252 opj_image_t * l_image = NULL;
253 opj_stream_t * l_stream = NULL;
254 OPJ_UINT32 x0, y0, x1, y1, y;
256 l_codec = create_codec_and_stream(input_file, &l_stream);
257 if (l_codec == NULL) {
261 /* Read the main header of the codestream and if necessary the JP2 boxes*/
262 if (! opj_read_header(l_stream, l_codec, &l_image)) {
263 fprintf(stderr, "ERROR -> failed to read the header\n");
264 opj_stream_destroy(l_stream);
265 opj_destroy_codec(l_codec);
273 for (y = y0; y < y1; y += strip_height) {
274 OPJ_UINT32 h_req = strip_height;
275 if (y + h_req > y1) {
279 printf("Decoding %u...%u\n", y, y + h_req);
281 if (!opj_set_decode_area(l_codec, l_image, (OPJ_INT32)x0, (OPJ_INT32)y,
282 (OPJ_INT32)x1, (OPJ_INT32)(y + h_req))) {
283 fprintf(stderr, "ERROR -> failed to set the decoded area\n");
284 opj_stream_destroy(l_stream);
285 opj_destroy_codec(l_codec);
286 opj_image_destroy(l_image);
290 /* Get the decoded image */
291 if (!(opj_decode(l_codec, l_stream, l_image))) {
292 fprintf(stderr, "ERROR -> failed to decode image!\n");
293 opj_stream_destroy(l_stream);
294 opj_destroy_codec(l_codec);
295 opj_image_destroy(l_image);
300 OPJ_UINT32 y_check, x;
302 for (compno = 0; compno < l_image->numcomps; compno ++) {
303 for (y_check = 0; y_check < h_req; y_check++) {
304 for (x = x0; x < x1; x++) {
305 OPJ_INT32 sub_image_val =
306 l_image->comps[compno].data[y_check * (x1 - x0) + x];
307 OPJ_INT32 image_val =
308 full_image->comps[compno].data[(y + y_check) * (x1 - x0) + x];
309 if (sub_image_val != image_val) {
311 "Difference found at subimage pixel (%u,%u) "
312 "of compno=%u: got %d, expected %d\n",
313 x, y_check + y, compno, sub_image_val, image_val);
323 /* If image is small enough, try a final whole image read */
324 if (x1 - x0 < 10000 && y1 - y0 < 10000) {
326 printf("Decoding full image\n");
328 if (!opj_set_decode_area(l_codec, l_image, (OPJ_INT32)x0, (OPJ_INT32)y0,
329 (OPJ_INT32)x1, (OPJ_INT32)y1)) {
330 fprintf(stderr, "ERROR -> failed to set the decoded area\n");
331 opj_stream_destroy(l_stream);
332 opj_destroy_codec(l_codec);
333 opj_image_destroy(l_image);
337 /* Get the decoded image */
338 if (!(opj_decode(l_codec, l_stream, l_image))) {
339 fprintf(stderr, "ERROR -> failed to decode image!\n");
340 opj_stream_destroy(l_stream);
341 opj_destroy_codec(l_codec);
342 opj_image_destroy(l_image);
347 if (! opj_end_decompress(l_codec, l_stream)) {
348 opj_stream_destroy(l_stream);
349 opj_destroy_codec(l_codec);
350 opj_image_destroy(l_image);
355 opj_stream_destroy(l_stream);
356 opj_destroy_codec(l_codec);
357 opj_image_destroy(l_image);
361 OPJ_BOOL check_consistency(opj_image_t* p_image, opj_image_t* p_sub_image)
364 for (compno = 0; compno < p_image->numcomps; compno ++) {
366 OPJ_UINT32 shift_y = p_sub_image->comps[compno].y0 - p_image->comps[compno].y0;
367 OPJ_UINT32 shift_x = p_sub_image->comps[compno].x0 - p_image->comps[compno].x0;
368 OPJ_UINT32 image_w = p_image->comps[compno].w;
369 OPJ_UINT32 sub_image_w = p_sub_image->comps[compno].w;
370 for (y = 0; y < p_sub_image->comps[compno].h; y++) {
373 for (x = 0; x < sub_image_w; x++) {
374 OPJ_INT32 sub_image_val =
375 p_sub_image->comps[compno].data[y * sub_image_w + x];
376 OPJ_INT32 image_val =
377 p_image->comps[compno].data[(y + shift_y) * image_w + x + shift_x];
378 if (sub_image_val != image_val) {
380 "Difference found at subimage pixel (%u,%u) "
381 "of compno=%u: got %d, expected %d\n",
382 x, y, compno, sub_image_val, image_val);
391 static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b)
393 return (a < b) ? a : b;
396 int main(int argc, char** argv)
398 opj_image_t * l_image = NULL;
399 opj_image_t * l_sub_image = NULL;
400 OPJ_INT32 da_x0 = 0, da_y0 = 0, da_x1 = 0, da_y1 = 0;
401 const char* input_file = NULL;
402 OPJ_UINT32 tilew, tileh, cblkw, cblkh;
405 OPJ_UINT32 step_x, step_y;
406 OPJ_BOOL quiet = OPJ_FALSE;
407 OPJ_UINT32 nsteps = 100;
408 OPJ_UINT32 strip_height = 0;
409 OPJ_BOOL strip_check = OPJ_FALSE;
413 "Usage: test_decode_area [-q] [-steps n] input_file_jp2_or_jk2 [x0 y0 x1 y1]\n"
414 "or : test_decode_area [-q] [-strip_height h] [-strip_check] input_file_jp2_or_jk2\n");
420 for (iarg = 1; iarg < argc; iarg++) {
421 if (strcmp(argv[iarg], "-q") == 0) {
423 } else if (strcmp(argv[iarg], "-steps") == 0 && iarg + 1 < argc) {
424 nsteps = (OPJ_UINT32)atoi(argv[iarg + 1]);
426 } else if (strcmp(argv[iarg], "-strip_height") == 0 && iarg + 1 < argc) {
427 strip_height = (OPJ_UINT32)atoi(argv[iarg + 1]);
429 } else if (strcmp(argv[iarg], "-strip_check") == 0) {
430 strip_check = OPJ_TRUE;
431 } else if (input_file == NULL) {
432 input_file = argv[iarg];
433 } else if (iarg + 3 < argc) {
434 da_x0 = atoi(argv[iarg]);
435 da_y0 = atoi(argv[iarg + 1]);
436 da_x1 = atoi(argv[iarg + 2]);
437 da_y1 = atoi(argv[iarg + 3]);
443 if (!strip_height || strip_check) {
444 l_image = decode(quiet, input_file, 0, 0, 0, 0,
445 &tilew, &tileh, &cblkw, &cblkh);
452 int ret = decode_by_strip(quiet, input_file, strip_height, l_image);
454 opj_image_destroy(l_image);
459 if (da_x0 != 0 || da_x1 != 0 || da_y0 != 0 || da_y1 != 0) {
460 l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
461 NULL, NULL, NULL, NULL);
463 fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
464 da_x0, da_y0, da_x1, da_y1);
465 opj_image_destroy(l_sub_image);
466 opj_image_destroy(l_image);
470 if (!check_consistency(l_image, l_sub_image)) {
471 fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
472 da_x0, da_y0, da_x1, da_y1);
473 opj_image_destroy(l_sub_image);
474 opj_image_destroy(l_image);
477 opj_image_destroy(l_sub_image);
478 opj_image_destroy(l_image);
482 w = l_image->x1 - l_image->x0;
483 h = l_image->y1 - l_image->y0;
484 step_x = w > nsteps ? w / nsteps : 1;
485 step_y = h > nsteps ? h / nsteps : 1;
486 for (y = 0; y < h; y += step_y) {
487 for (x = 0; x < w; x += step_x) {
488 da_x0 = (OPJ_INT32)(l_image->x0 + x);
489 da_y0 = (OPJ_INT32)(l_image->y0 + y);
490 da_x1 = (OPJ_INT32)opj_uint_min(l_image->x1, l_image->x0 + x + 1);
491 da_y1 = (OPJ_INT32)opj_uint_min(l_image->y1, l_image->y0 + y + 1);
492 l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
493 NULL, NULL, NULL, NULL);
495 fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
496 da_x0, da_y0, da_x1, da_y1);
497 opj_image_destroy(l_sub_image);
498 opj_image_destroy(l_image);
502 if (!check_consistency(l_image, l_sub_image)) {
503 fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
504 da_x0, da_y0, da_x1, da_y1);
505 opj_image_destroy(l_sub_image);
506 opj_image_destroy(l_image);
509 opj_image_destroy(l_sub_image);
511 if (step_x > 1 || step_y > 1) {
513 da_x0 = (OPJ_INT32)opj_uint_min(l_image->x1, (OPJ_UINT32)da_x0 + 1);
514 da_x1 = (OPJ_INT32)opj_uint_min(l_image->x1, (OPJ_UINT32)da_x1 + 1);
517 da_y0 = (OPJ_INT32)opj_uint_min(l_image->y1, (OPJ_UINT32)da_y0 + 1);
518 da_y1 = (OPJ_INT32)opj_uint_min(l_image->y1, (OPJ_UINT32)da_y1 + 1);
520 if (da_x0 < (OPJ_INT32)l_image->x1 && da_y0 < (OPJ_INT32)l_image->y1) {
521 l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
522 NULL, NULL, NULL, NULL);
524 fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
525 da_x0, da_y0, da_x1, da_y1);
526 opj_image_destroy(l_sub_image);
527 opj_image_destroy(l_image);
531 if (!check_consistency(l_image, l_sub_image)) {
532 fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
533 da_x0, da_y0, da_x1, da_y1);
534 opj_image_destroy(l_sub_image);
535 opj_image_destroy(l_image);
538 opj_image_destroy(l_sub_image);
544 opj_image_destroy(l_image);