diff --git a/CHANGES b/CHANGES index e1f2f533..75a962fa 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ What's New for OpenJPEG + : added October 11, 2011 +* [mickael] WIP: add stream length value to read unknown marker size, backport 855 into V2 framework, correct memory leak into get_cstr_info * [mickael] WIP: add output elements about decoding of jp2 files with last tile part lenght equal zero * [mickael] WIP: correct mistake with JP2 files and manage correctly the text_GBR.jp2 filecase diff --git a/libopenjpeg/cio.c b/libopenjpeg/cio.c index a65ff5c4..85a320c8 100644 --- a/libopenjpeg/cio.c +++ b/libopenjpeg/cio.c @@ -439,11 +439,11 @@ OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream) OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function) { opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - if - ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) - { + + if ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) { return; } + l_stream->m_read_fn = p_function; } @@ -501,6 +501,18 @@ OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void l_stream->m_user_data = p_data; } +/** + * Sets the given data to be used as a user data for the stream. + * @param p_stream the stream to modify + * @param p_data the data to set. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT32 data_length) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + l_stream->m_user_data_length = data_length; +} + /** * Reads some bytes from the stream. * @param p_stream the stream to read data from. @@ -852,6 +864,21 @@ OPJ_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream) return p_stream->m_byte_offset; } + +/** + * Get the number of bytes left before the end of the stream (similar to cio_numbytesleft). + * + * @param p_stream the stream to get the information from. + * + * @return Number of bytes left before the end of the stream. + */ +OPJ_SIZE_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream) +{ + return p_stream->m_user_data_length ? + p_stream->m_user_data_length - p_stream->m_byte_offset : + 0; +} + /** * Skips a number of bytes from the stream. * @param p_stream the stream to skip data from. diff --git a/libopenjpeg/cio.h b/libopenjpeg/cio.h index d98aa861..55df189f 100644 --- a/libopenjpeg/cio.h +++ b/libopenjpeg/cio.h @@ -125,6 +125,11 @@ typedef struct opj_stream_private */ void * m_user_data; + /** + * User data length + */ + OPJ_UINT32 m_user_data_length; + /** * Pointer to actual read function (NULL at the initialization of the cio. */ @@ -326,6 +331,16 @@ OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_SIZE_T p_size, s */ OPJ_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream); + +/** + * Get the number of bytes left before the end of the stream (similar to cio_numbytesleft). + * + * @param p_stream the stream to get the information from. + * + * @return Number of bytes left before the end of the stream. + */ +OPJ_SIZE_T opj_stream_get_number_byte_left (const opj_stream_private_t * p_stream); + /** * Skips a number of bytes from the stream. * @param p_stream the stream to skip data from. diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index 4bd37eac..2de55b5e 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -3352,10 +3352,9 @@ opj_bool j2k_read_sot_v2 ( /* Ref A.4.2: Psot could be equal zero if it is the last tile-part of the codestream.*/ if (!l_tot_len) { - opj_event_msg_v2(p_manager, EVT_ERROR, "Psot value of the current tile-part is equal to zero, " - "for the moment we couldn't manage this case (need to compute the number of byte left" - " in the codestream).\n"); - return OPJ_FALSE; + opj_event_msg_v2(p_manager, EVT_INFO, "Psot value of the current tile-part is equal to zero, " + "we assuming it is the last tile-part of the codestream.\n"); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; } opj_read_bytes(p_header_data,&l_current_part ,1); /* TPsot */ @@ -3575,7 +3574,11 @@ opj_bool j2k_read_sod_v2 ( assert(p_stream != 00); l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); - p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; + + if (p_j2k->m_specific_param.m_decoder.m_last_tile_part) + p_j2k->m_specific_param.m_decoder.m_sot_length = opj_stream_get_number_byte_left(p_stream) - 2; + else + p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; l_current_data = &(l_tcp->m_data); l_tile_len = &l_tcp->m_data_size; @@ -6765,7 +6768,7 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_v2_t* p_j2k) cstr_info->m_default_tile_info.numlayers = l_default_tile->numlayers; cstr_info->m_default_tile_info.mct = l_default_tile->mct; - cstr_info->m_default_tile_info.tccp_info = (opj_tccp_info_t*) opj_calloc(1,sizeof(opj_tccp_info_t)); + cstr_info->m_default_tile_info.tccp_info = (opj_tccp_info_t*) opj_calloc(cstr_info->nbcomps, sizeof(opj_tccp_info_t)); for (compno = 0; compno < numcomps; compno++) { opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); @@ -6781,8 +6784,8 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_v2_t* p_j2k) l_tccp_info->qmfbid = l_tccp->qmfbid; if (l_tccp->numresolutions < J2K_MAXRLVLS) { - memcpy(l_tccp_info->prch, l_tccp->prch, l_tccp->numresolutions); - memcpy(l_tccp_info->prcw, l_tccp->prcw, l_tccp->numresolutions); + memcpy(l_tccp_info->prch, l_tccp->prch, l_tccp->numresolutions - 1); + memcpy(l_tccp_info->prcw, l_tccp->prcw, l_tccp->numresolutions - 1); } /* quantization style*/ diff --git a/libopenjpeg/openjpeg.c b/libopenjpeg/openjpeg.c index bec5f225..629fc312 100644 --- a/libopenjpeg/openjpeg.c +++ b/libopenjpeg/openjpeg.c @@ -126,6 +126,17 @@ OPJ_UINT32 opj_read_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_ return l_nb_read ? l_nb_read : -1; } +OPJ_UINT32 opj_get_data_length_from_file (FILE * p_file) +{ + OPJ_UINT32 file_length = 0; + + fseek(p_file, 0, SEEK_END); + file_length = ftell(p_file); + fseek(p_file, 0, SEEK_SET); + + return file_length; +} + OPJ_UINT32 opj_write_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file) { return fwrite(p_buffer,1,p_nb_bytes,p_file); @@ -586,6 +597,7 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (FILE * p_file, OPJ_UIN } opj_stream_set_user_data(l_stream, p_file); + opj_stream_set_user_data_length(l_stream, opj_get_data_length_from_file(p_file)); opj_stream_set_read_function(l_stream, (opj_stream_read_fn) opj_read_from_file); opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_file); opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_file); diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h index 5cc8de1b..34ad7ab8 100644 --- a/libopenjpeg/openjpeg.h +++ b/libopenjpeg/openjpeg.h @@ -1085,6 +1085,13 @@ OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, o */ OPJ_API void OPJ_CALLCONV opj_stream_set_user_data (opj_stream_t* p_stream, void * p_data); +/** + * Sets the length of the user data for the stream. + * @param p_stream the stream to modify + * @param data_length length of the user_data. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UINT32 data_length); + /** * Helper function. diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index 537e95cf..e3a7dd32 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -2458,53 +2458,60 @@ opj_bool tcd_mct_decode ( opj_tcd_v2_t *p_tcd ) } l_samples = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0); - if (l_tcp->mct == 2) { - OPJ_BYTE ** l_data; - if (! l_tcp->m_mct_decoding_matrix) { - return OPJ_TRUE; - } + if (l_tile->numcomps >= 3 ){ + if (l_tcp->mct == 2) { + OPJ_BYTE ** l_data; - l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); - if (! l_data) { - return OPJ_FALSE; - } + if (! l_tcp->m_mct_decoding_matrix) { + return OPJ_TRUE; + } - for (i=0;inumcomps;++i) { - l_data[i] = (OPJ_BYTE*) l_tile_comp->data; - ++l_tile_comp; - } + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); + if (! l_data) { + return OPJ_FALSE; + } + + for (i=0;inumcomps;++i) { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + ++l_tile_comp; + } + + if (! mct_decode_custom(// MCT data + (OPJ_BYTE*) l_tcp->m_mct_decoding_matrix, + // size of components + l_samples, + // components + l_data, + // nb of components (i.e. size of pData) + l_tile->numcomps, + // tells if the data is signed + p_tcd->image->comps->sgnd)) { + opj_free(l_data); + return OPJ_FALSE; + } - if (! mct_decode_custom(// MCT data - (OPJ_BYTE*) l_tcp->m_mct_decoding_matrix, - // size of components - l_samples, - // components - l_data, - // nb of components (i.e. size of pData) - l_tile->numcomps, - // tells if the data is signed - p_tcd->image->comps->sgnd)) { opj_free(l_data); - return OPJ_FALSE; - } - - opj_free(l_data); - } - else { - if (l_tcp->tccps->qmfbid == 1) { - mct_decode( l_tile->comps[0].data, - l_tile->comps[1].data, - l_tile->comps[2].data, - l_samples); } else { - mct_decode_real( (float*)l_tile->comps[0].data, - (float*)l_tile->comps[1].data, - (float*)l_tile->comps[2].data, - l_samples); + if (l_tcp->tccps->qmfbid == 1) { + mct_decode( l_tile->comps[0].data, + l_tile->comps[1].data, + l_tile->comps[2].data, + l_samples); + } + else { + mct_decode_real( (float*)l_tile->comps[0].data, + (float*)l_tile->comps[1].data, + (float*)l_tile->comps[2].data, + l_samples); + } } } + else { + /* FIXME need to use opj_event_msg_v2 function */ + fprintf(stderr,"Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n",l_tile->numcomps); + } return OPJ_TRUE; }