From ff3c441023de46b0a551cc1f89f2d15b313a1f85 Mon Sep 17 00:00:00 2001 From: Mickael Savinaud Date: Thu, 17 Nov 2011 14:29:36 +0000 Subject: [PATCH] [trunk] WIP: fix bug when decoding an area or a tile with special resolution --- CHANGES | 1 + applications/codec/j2k_to_image.c | 21 +++++--- libopenjpeg/j2k.c | 69 ++++++++++++++++--------- libopenjpeg/t2.c | 19 +++++++ tests/nonregression/test_suite.ctest.in | 20 +++++-- 5 files changed, 96 insertions(+), 34 deletions(-) diff --git a/CHANGES b/CHANGES index b9c829ae..f63821b9 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ What's New for OpenJPEG + : added November 17, 2011 +* [mickael] WIP: fix bug when decoding an area or a tile with special resolution + [mickael] WIP: enhance j2k_to_image with new get_decoded_tile functionality + [mickael] WIP: clean j2k_dump and enhance j2k_dump with commit 1052. + [mickael] WIP: add a set decoded resolution factor function and update j2k_to_image help about decoded region. diff --git a/applications/codec/j2k_to_image.c b/applications/codec/j2k_to_image.c index 449a71e9..da39b25f 100644 --- a/applications/codec/j2k_to_image.c +++ b/applications/codec/j2k_to_image.c @@ -257,6 +257,7 @@ char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparamet return 0; } +/* -------------------------------------------------------------------------- */ #define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a" #define JP2_MAGIC "\x0d\x0a\x87\x0a" /* position 45: "\xff\x52" */ @@ -807,8 +808,7 @@ int main(int argc, char **argv) // Optional if you want decode the entire image if (!opj_set_decode_area(dinfo, image, parameters.DA_x0, parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)){ - fprintf(stderr, - "ERROR -> j2k_to_image: failed to set the decoded area\n"); + fprintf(stderr, "ERROR -> j2k_to_image: failed to set the decoded area\n"); opj_stream_destroy(cio); opj_destroy_codec(dinfo); opj_image_destroy(image); @@ -817,10 +817,8 @@ int main(int argc, char **argv) } /* Get the decoded image */ - if (!(opj_decode_v2(dinfo, cio, image) && opj_end_decompress(dinfo, - cio))) { - fprintf(stderr, - "ERROR -> j2k_to_image: failed to decode image!\n"); + if (!(opj_decode_v2(dinfo, cio, image) && opj_end_decompress(dinfo, cio))) { + fprintf(stderr,"ERROR -> j2k_to_image: failed to decode image!\n"); opj_destroy_codec(dinfo); opj_stream_destroy(cio); opj_image_destroy(image); @@ -829,6 +827,17 @@ int main(int argc, char **argv) } } else { + + // It is just here to illustrate how to use the resolution after set parameters + /*if (!opj_set_decoded_resolution_factor(dinfo, 5)) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to set the resolution factor tile!\n"); + opj_destroy_codec(dinfo); + opj_stream_destroy(cio); + opj_image_destroy(image); + fclose(fsrc); + return EXIT_FAILURE; + }*/ + if (!opj_get_decoded_tile(dinfo, cio, image, parameters.tile_index)) { fprintf(stderr, "ERROR -> j2k_to_image: failed to decode tile!\n"); opj_destroy_codec(dinfo); diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index 0de530f9..f1171d6a 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -6888,6 +6888,11 @@ opj_bool j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_ima /*-----*/ /* Current tile component size*/ + /*if (i == 0) { + fprintf(stdout, "SRC: l_res_x0=%d, l_res_x1=%d, l_res_y0=%d, l_res_y1=%d\n", + l_res->x0, l_res->x1, l_res->y0, l_res->y1); + }*/ + l_width_src = (l_res->x1 - l_res->x0); l_height_src = (l_res->y1 - l_res->y0); @@ -6897,6 +6902,11 @@ opj_bool j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_ima l_x1_dest = l_x0_dest + l_img_comp_dest->w; l_y1_dest = l_y0_dest + l_img_comp_dest->h; + /*if (i == 0) { + fprintf(stdout, "DEST: l_x0_dest=%d, l_x1_dest=%d, l_y0_dest=%d, l_y1_dest=%d (%d)\n", + l_x0_dest, l_x1_dest, l_y0_dest, l_y1_dest, l_img_comp_dest->factor ); + }*/ + /*-----*/ /* Compute the area (l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src) * of the input buffer (decoded tile component) which will be move @@ -7206,26 +7216,32 @@ opj_bool j2k_set_decode_area( opj_j2k_v2_t *p_j2k, l_img_comp = p_image->comps; for (it_comp=0; it_comp < p_image->numcomps; ++it_comp) { + OPJ_INT32 l_h,l_w; + l_img_comp->x0 = int_ceildiv(p_image->x0, l_img_comp->dx); l_img_comp->y0 = int_ceildiv(p_image->y0, l_img_comp->dy); l_comp_x1 = int_ceildiv(p_image->x1, l_img_comp->dx); l_comp_y1 = int_ceildiv(p_image->y1, l_img_comp->dy); - l_img_comp->w = int_ceildivpow2(l_comp_x1 - l_img_comp->x0, l_img_comp->factor); - if (l_img_comp->w <= 0){ + l_w = int_ceildivpow2(l_comp_x1, l_img_comp->factor) + - int_ceildivpow2(l_img_comp->x0, l_img_comp->factor); + if (l_w < 0){ opj_event_msg_v2(p_manager, EVT_ERROR, "Size x of the decoded component image is incorrect (comp[%d].w=%d).\n", - it_comp, l_img_comp->w); + it_comp, l_w); return OPJ_FALSE; } + l_img_comp->w = l_w; - l_img_comp->h = int_ceildivpow2(l_comp_y1 - l_img_comp->y0, l_img_comp->factor); - if (l_img_comp->h <= 0){ + l_h = int_ceildivpow2(l_comp_y1, l_img_comp->factor) + - int_ceildivpow2(l_img_comp->y0, l_img_comp->factor); + if (l_h < 0){ opj_event_msg_v2(p_manager, EVT_ERROR, "Size y of the decoded component image is incorrect (comp[%d].h=%d).\n", - it_comp, l_img_comp->h); + it_comp, l_h); return OPJ_FALSE; } + l_img_comp->h = l_h; l_img_comp++; } @@ -8371,9 +8387,8 @@ opj_bool j2k_get_tile( opj_j2k_v2_t *p_j2k, return OPJ_FALSE; } - if (tile_index >= p_j2k->m_cp.th * p_j2k->m_cp.tw) { - opj_event_msg_v2(p_manager, EVT_ERROR, "Decoded tile index is " - "inconsistent with the number of tiles in the codestream (%d vs %d).\n", tile_index, p_j2k->m_cp.th * p_j2k->m_cp.tw ); + if ( (tile_index < 0) && (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) ){ + opj_event_msg_v2(p_manager, EVT_ERROR, "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1); return OPJ_FALSE; } @@ -8400,13 +8415,15 @@ opj_bool j2k_get_tile( opj_j2k_v2_t *p_j2k, { OPJ_INT32 l_comp_x1, l_comp_y1; + l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; + l_img_comp->x0 = int_ceildiv(p_image->x0, l_img_comp->dx); l_img_comp->y0 = int_ceildiv(p_image->y0, l_img_comp->dy); l_comp_x1 = int_ceildiv(p_image->x1, l_img_comp->dx); l_comp_y1 = int_ceildiv(p_image->y1, l_img_comp->dy); - l_img_comp->w = int_ceildivpow2(l_comp_x1 - l_img_comp->x0, l_img_comp->factor); - l_img_comp->h = int_ceildivpow2(l_comp_y1 - l_img_comp->y0, l_img_comp->factor); + l_img_comp->w = int_ceildivpow2(l_comp_x1, l_img_comp->factor) - int_ceildivpow2(l_img_comp->x0, l_img_comp->factor); + l_img_comp->h = int_ceildivpow2(l_comp_y1, l_img_comp->factor) - int_ceildivpow2(l_img_comp->y0, l_img_comp->factor); l_img_comp++; } @@ -8422,11 +8439,6 @@ opj_bool j2k_get_tile( opj_j2k_v2_t *p_j2k, } opj_copy_image_header(p_image, p_j2k->m_output_image); - if ( (tile_index < 0) && (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) ){ - opj_event_msg_v2(p_manager, EVT_ERROR, "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1); - return OPJ_FALSE; - } - p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = tile_index; /* customization of the decoding */ @@ -8460,14 +8472,23 @@ opj_bool j2k_set_decoded_resolution_factor(opj_j2k_v2_t *p_j2k, OPJ_UINT32 res_f p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor; - if (!p_j2k->m_private_image) - - - for (it_comp = 0 ; it_comp < p_j2k->m_private_image->numcomps; it_comp++) - { - p_j2k->m_private_image->comps[it_comp].factor = res_factor; + if (p_j2k->m_private_image) { + if (p_j2k->m_private_image->comps) { + if (p_j2k->m_specific_param.m_decoder.m_default_tcp) { + if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps) { + for (it_comp = 0 ; it_comp < p_j2k->m_private_image->numcomps; it_comp++) { + OPJ_UINT32 max_res = p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[it_comp].numresolutions; + if ( res_factor >= max_res){ + opj_event_msg_v2(p_manager, EVT_ERROR, "Resolution factor is superior to the maximum resolution in the component.\n"); + return OPJ_FALSE; + } + p_j2k->m_private_image->comps[it_comp].factor = res_factor; + } + return OPJ_TRUE; + } + } + } } - - return OPJ_TRUE; + return OPJ_FALSE; } diff --git a/libopenjpeg/t2.c b/libopenjpeg/t2.c index 15029c31..f4af6eb7 100644 --- a/libopenjpeg/t2.c +++ b/libopenjpeg/t2.c @@ -878,12 +878,23 @@ opj_bool t2_decode_packets_v2( for (pino = 0; pino <= l_tcp->numpocs; ++pino) { + /* if the resolution needed is to low, one dim of the tilec could be equal to zero + * and no packets are used to encode this resolution and + * l_current_pi->resno is always >= p_tile->comps[l_current_pi->compno].minimum_num_resolutions + * and no l_img_comp->resno_decoded are computed + */ + opj_bool* first_pass_failed = (opj_bool*)opj_malloc(l_image->numcomps * sizeof(opj_bool)); + memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(opj_bool)); + while (pi_next(l_current_pi)) { + if (l_tcp->num_layers_to_decode > l_current_pi->layno && l_current_pi->resno < p_tile->comps[l_current_pi->compno].minimum_num_resolutions) { l_nb_bytes_read = 0; + first_pass_failed[l_current_pi->compno] = OPJ_FALSE; + if (! t2_decode_packet_v2(p_t2,p_tile,l_tcp,l_current_pi,l_current_data,&l_nb_bytes_read,p_max_len,l_pack_info)) { pi_destroy_v2(l_pi,l_nb_pocs); return OPJ_FALSE; @@ -900,6 +911,12 @@ opj_bool t2_decode_packets_v2( } } + if (first_pass_failed[l_current_pi->compno]) { + l_img_comp = &(l_image->comps[l_current_pi->compno]); + if (l_img_comp->resno_decoded == 0) + l_img_comp->resno_decoded = p_tile->comps[l_current_pi->compno].minimum_num_resolutions - 1; + } + l_current_data += l_nb_bytes_read; p_max_len -= l_nb_bytes_read; @@ -926,6 +943,8 @@ opj_bool t2_decode_packets_v2( /* << INDEX */ } ++l_current_pi; + + opj_free(first_pass_failed); } /* INDEX >> */ #ifdef TODO_MSD diff --git a/tests/nonregression/test_suite.ctest.in b/tests/nonregression/test_suite.ctest.in index 2fd4daf4..d61bb5de 100644 --- a/tests/nonregression/test_suite.ctest.in +++ b/tests/nonregression/test_suite.ctest.in @@ -80,6 +80,11 @@ j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_14.j2k.png -d 2 j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_15.j2k.png -d 260,520,360,660 -r 2 j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_16.j2k.png -d 360,520,400,600 -r 2 +j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_17_t63.j2k.png -t 63 +j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_17_t63_r2.j2k.png -t 63 -r 2 +j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_18.t12.j2k.png -t 12 +j2k_to_image -i @INPUT_CONF_PATH@/p1_04.j2k -o @TEMP_PATH@/p1_04_19_t12_r1.j2k.png -t 12 -r 1 + # prec=8; nb_c=3 j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06.j2k.png -d 0,0,12,12 j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_1.j2k.png -d 1,8,8,11 @@ -96,10 +101,17 @@ j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_4.j2k.png -d 3, j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_5.j2k.png -d 4,4,7,7 -r 1 j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_6.j2k.png -d 4,4,5,5 -r 1 -j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06.j2k_0.png -t 0 -j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_1.j2k_5.png -t 5 -j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_2.j2k_9.png -t 9 -j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_3.j2k_15.png -t 15 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_6.j2k.png -d 9,9,12,12 -r 2 + +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06.j2k_t0.png -t 0 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_1.j2k_t5.png -t 5 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_2.j2k_t9.png -t 9 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_3.j2k_t15.png -t 15 + +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06.j2k_t0.png -t 0 -r 2 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_1.j2k_t5.png -t 5 -r 2 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_2.j2k_t9.png -t 9 -r 2 +j2k_to_image -i @INPUT_CONF_PATH@/p1_06.j2k -o @TEMP_PATH@/p1_06_3.j2k_t15.png -t 15 -r 2 # prec=4; nb_c=3 ; signd=yes j2k_to_image -i @INPUT_CONF_PATH@/p0_04.j2k -o @TEMP_PATH@/p0_04.j2k.png -d 0,0,256,256