From 1a5c59326ab4836618f88caefa8b66760f624793 Mon Sep 17 00:00:00 2001 From: Mickael Savinaud Date: Mon, 19 Sep 2011 16:05:43 +0000 Subject: [PATCH] WIP: begin to test opj_read_tile_header with V2 style --- CHANGES | 1 + applications/codec/j2k_dump.c | 48 +++++-- libopenjpeg/j2k.c | 251 +++++++++++++++++++--------------- libopenjpeg/jp2.c | 44 +++--- libopenjpeg/openjpeg.c | 55 +++++++- libopenjpeg/openjpeg.h | 30 ++++ 6 files changed, 278 insertions(+), 151 deletions(-) diff --git a/CHANGES b/CHANGES index 01508eed..74403216 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ What's New for OpenJPEG + : added September 19, 2011 ++ [mickael] WIP: begin to test opj_read_tile_header with V2 style + [mickael] WIP: create a new framework to output file information + [mickael] WIP: remove a piece of code copy by the merge op at the wrong place + [mickael] WIP: begin to clean j2k_dump and some other small things diff --git a/applications/codec/j2k_dump.c b/applications/codec/j2k_dump.c index d1c1fb69..9c0a4452 100644 --- a/applications/codec/j2k_dump.c +++ b/applications/codec/j2k_dump.c @@ -195,8 +195,8 @@ char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparamet } /* -------------------------------------------------------------------------- */ +/* parse the command line */ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol) { - /* parse the command line */ int totlen, c; opj_option_t long_option[]={ {"ImgDir",REQ_ARG, NULL ,'y'}, @@ -231,7 +231,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i } break; - /* ------------------------------------------------------ */ + /* ------------------------------------------------------ */ case 'o': /* output file */ { @@ -257,6 +257,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i break; /* ----------------------------------------------------- */ + case 'd': /* Input decode ROI */ { int size_optarg = (int)strlen(optarg) + 1; @@ -264,7 +265,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i ROI_values[0] = '\0'; strncpy(ROI_values, optarg, strlen(optarg)); ROI_values[strlen(optarg)] = '\0'; - printf("ROI_values = %s [%d / %d]\n", ROI_values, strlen(ROI_values), size_optarg ); + /*printf("ROI_values = %s [%d / %d]\n", ROI_values, strlen(ROI_values), size_optarg ); */ parse_ROI_values( ROI_values, ¶meters->ROI_x0, ¶meters->ROI_y0, ¶meters->ROI_x1, ¶meters->ROI_y1); } break; @@ -371,8 +372,7 @@ int main(int argc, char *argv[]) opj_codec_t* dinfo = NULL; /* handle to a decompressor */ opj_stream_t *cio = NULL; opj_codestream_info_t* cstr_info =NULL; /* Codestream information structure */ - /* OPJ_INT32 l_tile_x0,l_tile_y0; */ - /* OPJ_UINT32 l_tile_width,l_tile_height,l_nb_tiles_x,l_nb_tiles_y; */ + opj_bool l_go_on = OPJ_TRUE; /* FIXME configure the event callbacks (not required) */ @@ -502,10 +502,40 @@ int main(int argc, char *argv[]) } printf("Setting decoding area to %d,%d,%d,%d\n", - parameters.ROI_x0, parameters.ROI_y0, parameters.ROI_x1, parameters.ROI_x1); - opj_set_decode_area(dinfo, - parameters.ROI_x0, parameters.ROI_y0, - parameters.ROI_x1, parameters.ROI_x1); + parameters.ROI_x0, parameters.ROI_y0, parameters.ROI_x1, parameters.ROI_y1); + + if (! opj_set_decode_area( dinfo, + parameters.ROI_x0, parameters.ROI_y0, + parameters.ROI_x1, parameters.ROI_y1)){ + fprintf(stderr, "ERROR -> j2k_dump: failed to set the decoded area\n"); + opj_stream_destroy(cio); + fclose(fsrc); + opj_destroy_codec(dinfo); + return EXIT_FAILURE; + } + + while (l_go_on) { + OPJ_INT32 l_current_tile_x0,l_current_tile_y0,l_current_tile_x1,l_current_tile_y1; + OPJ_UINT32 l_nb_comps, l_tile_index, l_data_size; + + if (! opj_read_tile_header( dinfo, + cio, + &l_tile_index, + &l_data_size, + &l_current_tile_x0, + &l_current_tile_y0, + &l_current_tile_x1, + &l_current_tile_y1, + &l_nb_comps, + &l_go_on + )) { + fprintf(stderr, "ERROR -> j2k_dump: failed read the tile header\n"); + opj_stream_destroy(cio); + fclose(fsrc); + opj_destroy_codec(dinfo); + return EXIT_FAILURE; + } + } /* Dump file informations from header */ dump_file_info(fout, &file_info); diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index 9375b618..aa58b3b3 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -5670,19 +5670,15 @@ void j2k_cp_destroy (opj_cp_v2_t *p_cp) * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -opj_bool j2k_read_tile_header ( - opj_j2k_v2_t * p_j2k, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - opj_bool * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +opj_bool j2k_read_tile_header( opj_j2k_v2_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + opj_bool * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ) { OPJ_UINT32 l_current_marker = J2K_MS_SOT; OPJ_UINT32 l_marker_size; @@ -5690,91 +5686,70 @@ opj_bool j2k_read_tile_header ( opj_tcp_v2_t * l_tcp = 00; OPJ_UINT32 l_nb_tiles; - // preconditions + /* preconditions */ assert(p_stream != 00); assert(p_j2k != 00); assert(p_manager != 00); - if - (p_j2k->m_specific_param.m_decoder.m_state == 0x0100)// FIXME J2K_DEC_STATE_EOC) - { + if (p_j2k->m_specific_param.m_decoder.m_state == 0x0100){// FIXME J2K_DEC_STATE_EOC) l_current_marker = J2K_MS_EOC; } - else if - (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) // FIXME J2K_DEC_STATE_TPHSOT) - { + else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT){ // FIXME J2K_DEC_STATE_TPHSOT) return OPJ_FALSE; } - while - (! p_j2k->m_specific_param.m_decoder.m_can_decode && l_current_marker != J2K_MS_EOC) - { - while - (l_current_marker != J2K_MS_SOD) - { - if - (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) - { + while (! p_j2k->m_specific_param.m_decoder.m_can_decode && l_current_marker != J2K_MS_EOC) { + while (l_current_marker != J2K_MS_SOD) { + + if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); - if - (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH) // FIXME J2K_DEC_STATE_TPH) - { + + if (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH){ // FIXME J2K_DEC_STATE_TPH) p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); } l_marker_size -= 2; l_marker_handler = j2k_get_marker_handler(l_current_marker); - // Check if the marker is known - if - (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) - { + + /* Check if the marker is known */ + if (! (p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states) ) { opj_event_msg_v2(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); return OPJ_FALSE; } - if - (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) - { + + if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { p_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE*) - opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size); - if - (p_j2k->m_specific_param.m_decoder.m_header_data == 00) - { + opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size); + if (p_j2k->m_specific_param.m_decoder.m_header_data == 00) { return OPJ_FALSE; } - p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; } - if - (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != l_marker_size) - { + + if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != l_marker_size) { opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } - if - (! (*(l_marker_handler->handler))(p_j2k,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager)) - { + + if (! (*(l_marker_handler->handler))(p_j2k,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager)) { opj_event_msg_v2(p_manager, EVT_ERROR, "Marker is not compliant with its position\n"); return OPJ_FALSE; } - if - (p_j2k->m_specific_param.m_decoder.m_skip_data) - { - if - (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) - { + + if (p_j2k->m_specific_param.m_decoder.m_skip_data) { + if (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) { opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } l_current_marker = J2K_MS_SOD; } - else - { - if - (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) - { + else { + if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } @@ -5782,23 +5757,17 @@ opj_bool j2k_read_tile_header ( } } - if - (! p_j2k->m_specific_param.m_decoder.m_skip_data) - { - if - (! j2k_read_sod_v2(p_j2k,p_stream,p_manager)) - { + if (! p_j2k->m_specific_param.m_decoder.m_skip_data) { + if (! j2k_read_sod_v2(p_j2k,p_stream,p_manager)) { return OPJ_FALSE; } } - else - { + else { p_j2k->m_specific_param.m_decoder.m_skip_data = 0; p_j2k->m_specific_param.m_decoder.m_can_decode = 0; p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; // FIXME J2K_DEC_STATE_TPHSOT; - if - (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) - { + + if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { opj_event_msg_v2(p_manager, EVT_ERROR, "Stream too short\n"); return OPJ_FALSE; } @@ -5806,55 +5775,47 @@ opj_bool j2k_read_tile_header ( } } - if - (l_current_marker == J2K_MS_EOC) - { - if - (p_j2k->m_specific_param.m_decoder.m_state != 0x0100 )// FIXME J2K_DEC_STATE_EOC) - { + if (l_current_marker == J2K_MS_EOC) { + if (p_j2k->m_specific_param.m_decoder.m_state != 0x0100 ){// FIXME J2K_DEC_STATE_EOC) p_j2k->m_current_tile_number = 0; - p_j2k->m_specific_param.m_decoder.m_state = 0x0100;// FIXMEJ2K_DEC_STATE_EOC; + p_j2k->m_specific_param.m_decoder.m_state = 0x0100;// FIXME J2K_DEC_STATE_EOC; } } - if - ( ! p_j2k->m_specific_param.m_decoder.m_can_decode) - { + + if ( ! p_j2k->m_specific_param.m_decoder.m_can_decode) { l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - while - ( - (p_j2k->m_current_tile_number < l_nb_tiles) - && (l_tcp->m_data == 00) - ) - { + + while( (p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data == 00) ) { ++p_j2k->m_current_tile_number; ++l_tcp; } - if - (p_j2k->m_current_tile_number == l_nb_tiles) - { + + if (p_j2k->m_current_tile_number == l_nb_tiles) { *p_go_on = OPJ_FALSE; return OPJ_TRUE; } } - if - (! tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) - { + + if (! tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) { opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); return OPJ_FALSE; } + *p_tile_index = p_j2k->m_current_tile_number; *p_go_on = OPJ_TRUE; *p_data_size = tcd_get_decoded_tile_size(p_j2k->m_tcd); - * p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; - * p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; - * p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; - * p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1; - * p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps; + *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; + *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; + *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; + *p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1; + *p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps; p_j2k->m_specific_param.m_decoder.m_state |= 0x0080;// FIXME J2K_DEC_STATE_DATA; + return OPJ_TRUE; } + opj_bool j2k_decode_tile ( opj_j2k_v2_t * p_j2k, OPJ_UINT32 p_tile_index, @@ -5941,27 +5902,89 @@ opj_bool j2k_decode_tile ( * * @return true if the area could be set. */ -opj_bool j2k_set_decode_area( - opj_j2k_v2_t *p_j2k, - OPJ_INT32 p_start_x, - OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, - OPJ_INT32 p_end_y, - struct opj_event_mgr * p_manager - ) +opj_bool j2k_set_decode_area( opj_j2k_v2_t *p_j2k, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager ) { opj_cp_v2_t * l_cp = &(p_j2k->m_cp); - if - (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT)// FIXME J2K_DEC_STATE_TPHSOT) - { + /* Check if we are read the main header */ + if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { // FIXME J2K_DEC_STATE_TPHSOT) + opj_event_msg_v2(p_manager, EVT_ERROR, "Need to decode the main header before begin to decode the remaining codestream"); return OPJ_FALSE; } - p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_start_x - l_cp->tx0) / l_cp->tdx; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_start_y - l_cp->ty0) / l_cp->tdy; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = int_ceildiv((p_end_x - l_cp->tx0), l_cp->tdx); - p_j2k->m_specific_param.m_decoder.m_end_tile_y = int_ceildiv((p_end_y - l_cp->ty0), l_cp->tdy); + + /* ----- */ + /* Check if the positions provided by the user are correct */ + + /* Left */ + if (p_start_x > l_cp->tw * l_cp->tdx) { + opj_event_msg_v2(p_manager, EVT_ERROR, + "Left position of the decoded area (ROI_x0=%d) is outside the tile area (nb_tw x XTsiz=%d).\n", + p_start_x, l_cp->tw * l_cp->tdx); + return OPJ_FALSE; + } + else if (p_start_x < l_cp->tx0){ + opj_event_msg_v2(p_manager, EVT_WARNING, + "Left position of the decoded area (ROI_x0=%d) is outside the tile area (XTOsiz=%d).\n", + p_start_x, l_cp->tx0); + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + } + else + p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_start_x - l_cp->tx0) / l_cp->tdx; + + /* Up */ + if (p_start_y > l_cp->th * l_cp->tdy){ + opj_event_msg_v2(p_manager, EVT_ERROR, + "Up position of the decoded area (ROI_y0=%d) is outside the tile area (nb_th x YTsiz=%d).\n", + p_start_y, l_cp->th * l_cp->tdy); + return OPJ_FALSE; + } + else if (p_start_y < l_cp->ty0){ + opj_event_msg_v2(p_manager, EVT_WARNING, + "Up position of the decoded area (ROI_y0=%d) is outside the tile area (YTOsiz=%d).\n", + p_start_y, l_cp->ty0); + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + } + else + p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_start_y - l_cp->ty0) / l_cp->tdy; + + /* Right */ + if (p_end_x < l_cp->tx0) { + opj_event_msg_v2(p_manager, EVT_ERROR, + "Right position of the decoded area (ROI_x1=%d) is outside the tile area (XTOsiz=%d).\n", + p_end_x, l_cp->tx0); + return OPJ_FALSE; + } + else if (p_end_x > l_cp->tw * l_cp->tdx) { + opj_event_msg_v2(p_manager, EVT_WARNING, + "Right position of the decoded area (ROI_x1=%d) is outside the tile area (nb_tw x XTsiz=%d).\n", + p_end_x, l_cp->tw * l_cp->tdx); + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; // FIXME (-1) ??? + } + else + p_j2k->m_specific_param.m_decoder.m_end_tile_x = int_ceildiv((p_end_x - l_cp->tx0), l_cp->tdx); + + /* Bottom */ + if (p_end_x < l_cp->ty0) { + opj_event_msg_v2(p_manager, EVT_ERROR, + "Right position of the decoded area (ROI_y1=%d) is outside the tile area (YTOsiz=%d).\n", + p_end_x, l_cp->ty0); + return OPJ_FALSE; + } + if (p_end_y > l_cp->th * l_cp->tdy){ + opj_event_msg_v2(p_manager, EVT_WARNING, + "Bottom position of the decoded area (ROI_y1=%d) is outside the tile area (nb_th x YTsiz=%d).\n", + p_end_y, l_cp->th * l_cp->tdy); + p_j2k->m_specific_param.m_decoder.m_start_tile_y = l_cp->th; // FIXME (-1) ??? + } + else + p_j2k->m_specific_param.m_decoder.m_end_tile_y = int_ceildiv((p_end_y - l_cp->ty0), l_cp->tdy); + /* ----- */ + p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1; + return OPJ_TRUE; } diff --git a/libopenjpeg/jp2.c b/libopenjpeg/jp2.c index efbf8d10..bfdf2cc8 100644 --- a/libopenjpeg/jp2.c +++ b/libopenjpeg/jp2.c @@ -2451,27 +2451,21 @@ void jp2_setup_header_reading (opj_jp2_v2_t *jp2) * @param p_stream the stream to write data to. * @param p_manager the user event manager. */ -opj_bool jp2_read_tile_header ( - opj_jp2_v2_t * p_jp2, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32 * p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - opj_bool * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) +opj_bool jp2_read_tile_header( opj_jp2_v2_t * p_jp2, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + opj_bool * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ) { - return j2k_read_tile_header (p_jp2->j2k, + return j2k_read_tile_header(p_jp2->j2k, p_tile_index, p_data_size, - p_tile_x0, - p_tile_y0, - p_tile_x1, - p_tile_y1, + p_tile_x0, p_tile_y0, + p_tile_x1, p_tile_y1, p_nb_comps, p_go_on, p_stream, @@ -2558,16 +2552,12 @@ void jp2_destroy(opj_jp2_v2_t *jp2) * * @return true if the area could be set. */ -opj_bool jp2_set_decode_area( - opj_jp2_v2_t *p_jp2, - OPJ_INT32 p_start_x, - OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, - OPJ_INT32 p_end_y, - struct opj_event_mgr * p_manager - ) +opj_bool jp2_set_decode_area( opj_jp2_v2_t *p_jp2, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager ) { - return j2k_set_decode_area(p_jp2->j2k,p_start_x,p_start_y,p_end_x,p_end_y,p_manager); + return j2k_set_decode_area(p_jp2->j2k, p_start_x, p_start_y, p_end_x, p_end_y, p_manager); } /* ----------------------------------------------------------------------- */ diff --git a/libopenjpeg/openjpeg.c b/libopenjpeg/openjpeg.c index 5b99d4d1..f69be8e1 100644 --- a/libopenjpeg/openjpeg.c +++ b/libopenjpeg/openjpeg.c @@ -736,8 +736,61 @@ opj_bool OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec, p_start_y, p_end_x, p_end_y, - &(l_info->m_event_mgr)); + l_info->m_event_mgr); } return OPJ_FALSE; } + +/** + * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. + * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case + * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same + * as depicted in opj_write_tile. + * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). + * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). + * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). + * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). + * @param p_nb_comps pointer to a value that will hold the number of components in the tile. + * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the + * codestream is over at the time of the call, the value will be set to false. The user should then stop + * the decoding. + * @param p_stream the stream to decode. + * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. + * returning false may be the result of a shortage of memory or an internal error. + */ +opj_bool OPJ_CALLCONV opj_read_tile_header( + opj_codec_t *p_codec, + opj_stream_t * p_stream, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + opj_bool * p_should_go_on) +{ + if (p_codec && p_stream && p_data_size && p_tile_index) { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; + + if (! l_info->is_decompressor) { + return OPJ_FALSE; + } + + return l_info->m_codec_data.m_decompression.opj_read_tile_header( + l_info->m_codec, + p_tile_index, + p_data_size, + p_tile_x0, p_tile_y0, + p_tile_x1, p_tile_y1, + p_nb_comps, + p_should_go_on, + l_cio, + l_info->m_event_mgr); + } + return OPJ_FALSE; +} diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h index 94fbdfa5..80c0f79b 100644 --- a/libopenjpeg/openjpeg.h +++ b/libopenjpeg/openjpeg.h @@ -1335,6 +1335,36 @@ OPJ_API opj_bool OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec, OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, OPJ_INT32 p_end_x, OPJ_INT32 p_end_y ); +/** + * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. + * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case + * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same + * as depicted in opj_write_tile. + * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). + * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). + * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). + * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). + * @param p_nb_comps pointer to a value that will hold the number of components in the tile. + * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the + * codestream is over at the time of the call, the value will be set to false. The user should then stop + * the decoding. + * @param p_stream the stream to decode. + * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. + * returning false may be the result of a shortage of memory or an internal error. + */ +OPJ_API opj_bool OPJ_CALLCONV opj_read_tile_header( opj_codec_t *p_codec, + opj_stream_t * p_stream, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + opj_bool * p_should_go_on ); + #ifdef __cplusplus } #endif