X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libopenjpeg%2Fj2k.c;h=509b627fadb44f3a91b2de1b79e70898884a83a3;hb=71e0106846294256faa3df75429e0a9ecd163233;hp=aa866346ba89a555199ebd2121191bcf0c6f0ffd;hpb=96d4d3f3bea1569daaf82937fd1934dc5eb35a32;p=openjpeg.git diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index aa866346..509b627f 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -8,7 +8,7 @@ * Copyright (c) 2008, Jerome Fimes, Communications & Systemes * Copyright (c) 2006-2007, Parvatha Elangovan * Copyright (c) 2010-2011, Kaori Hagihara - * Copyright (c) 2011, Mickael Savinaud, Communications & Systemes + * Copyright (c) 2011-2012, Mickael Savinaud, Communications & Systemes * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,11 +34,6 @@ */ #include "opj_includes.h" -#ifdef HAVE_INTTYPES_H -#include /* PRIi64 */ -#else -#define PRIi64 "I64i" -#endif /** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ /*@{*/ @@ -54,23 +49,22 @@ void j2k_setup_header_reading (opj_j2k_v2_t *p_j2k); /** * The read header procedure. */ -opj_bool j2k_read_header_procedure( - opj_j2k_v2_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager); +static opj_bool j2k_read_header_procedure( opj_j2k_v2_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * The default encoding validation procedure without any extension. * * @param p_j2k the jpeg2000 codec to validate. - * @param p_stream the input stream to validate. + * @param p_stream the input stream to validate. * @param p_manager the user event manager. * * @return true if the parameters are correct. */ -opj_bool j2k_encoding_validation ( opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static opj_bool j2k_encoding_validation ( opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * The default decoding validation procedure without any extension. @@ -81,11 +75,9 @@ opj_bool j2k_encoding_validation ( opj_j2k_v2_t * p_j2k, * * @return true if the parameters are correct. */ -opj_bool j2k_decoding_validation ( - opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ); +static opj_bool j2k_decoding_validation ( opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters @@ -114,29 +106,29 @@ static void j2k_setup_end_compress (opj_j2k_v2_t *p_j2k); * * @return true if the parameters are correct. */ -opj_bool j2k_mct_validation ( opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static opj_bool j2k_mct_validation (opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Builds the tcd decoder to use to decode tile. */ -opj_bool j2k_build_decoder (opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static opj_bool j2k_build_decoder ( opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Builds the tcd encoder to use to encode tile. */ -opj_bool j2k_build_encoder (opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static opj_bool j2k_build_encoder ( opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Creates a tile-coder decoder. * - * @param p_stream the stream to write data to. + * @param p_stream the stream to write data to. * @param p_j2k J2K codec. - * @param p_manager the user event manager. + * @param p_manager the user event manager. */ static opj_bool j2k_create_tcd( opj_j2k_v2_t *p_j2k, struct opj_stream_private *p_stream, @@ -146,18 +138,16 @@ static opj_bool j2k_create_tcd( opj_j2k_v2_t *p_j2k, * Excutes the given procedures on the given codec. * * @param p_procedure_list the list of procedures to execute - * @param p_j2k the jpeg2000 codec to execute the procedures on. - * @param p_stream the stream to execute the procedures on. + * @param p_j2k the jpeg2000 codec to execute the procedures on. + * @param p_stream the stream to execute the procedures on. * @param p_manager the user manager. * * @return true if all the procedures were successfully executed. */ -static opj_bool j2k_exec ( - opj_j2k_v2_t * p_j2k, - opj_procedure_list_t * p_procedure_list, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ); +static opj_bool j2k_exec ( opj_j2k_v2_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); /** * Updates the rates of the tcp. @@ -167,23 +157,23 @@ static opj_bool j2k_exec ( * @param p_manager the user event manager. */ static opj_bool j2k_update_rates( opj_j2k_v2_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager ); + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Copies the decoding tile parameters onto all the tile parameters. * Creates also the tile decoder. */ -opj_bool j2k_copy_default_tcp_and_create_tcd ( opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static opj_bool j2k_copy_default_tcp_and_create_tcd ( opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Destroys the memory associated with the decoding of headers. */ -opj_bool j2k_destroy_header_memory (opj_j2k_v2_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager ); +static opj_bool j2k_destroy_header_memory ( opj_j2k_v2_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager ); /** * Reads the lookup table containing all the marker, status and action, and returns the handler associated @@ -252,13 +242,11 @@ static OPJ_UINT32 j2k_get_SPCod_SPCoc_size (opj_j2k_v2_t *p_j2k, * @param p_header_size the size of the data contained in the COM marker. * @param p_manager the user event manager. */ -static opj_bool j2k_read_SPCod_SPCoc( - opj_j2k_v2_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager - ); +static opj_bool j2k_read_SPCod_SPCoc( opj_j2k_v2_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager ); /** * Gets the size taken by writing SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. @@ -289,8 +277,7 @@ static opj_bool j2k_write_SQcd_SQcc(opj_j2k_v2_t *p_j2k, OPJ_UINT32 p_comp_no, OPJ_BYTE * p_data, OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager - ); + opj_event_mgr_t * p_manager); /** * Updates the Tile Length Marker. @@ -308,38 +295,32 @@ static void j2k_update_tlm ( opj_j2k_v2_t * p_j2k, OPJ_UINT32 p_tile_part_size); * @param p_manager the user event manager. * */ -static opj_bool j2k_read_SQcd_SQcc( - opj_j2k_v2_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager - ); +static opj_bool j2k_read_SQcd_SQcc( opj_j2k_v2_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager ); /** * Copies the tile component parameters of all the component from the first tile component. * * @param p_j2k the J2k codec. */ -static void j2k_copy_tile_component_parameters( - opj_j2k_v2_t *p_j2k - ); +static void j2k_copy_tile_component_parameters( opj_j2k_v2_t *p_j2k ); /** * Copies the tile quantization parameters of all the component from the first tile component. * * @param p_j2k the J2k codec. */ -static void j2k_copy_tile_quantization_parameters( - opj_j2k_v2_t *p_j2k - ); +static void j2k_copy_tile_quantization_parameters( opj_j2k_v2_t *p_j2k ); /** * Reads the tiles. */ -opj_bool j2k_decode_tiles ( opj_j2k_v2_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager); +static opj_bool j2k_decode_tiles ( opj_j2k_v2_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); static opj_bool j2k_pre_write_tile ( opj_j2k_v2_t * p_j2k, @@ -361,7 +342,7 @@ static opj_bool j2k_post_write_tile (opj_j2k_v2_t * p_j2k, * Sets up the procedures to do on writing header. * Developers wanting to extend the library can add their own writing procedures. */ -void j2k_setup_header_writting (opj_j2k_v2_t *p_j2k); +static void j2k_setup_header_writting (opj_j2k_v2_t *p_j2k); static opj_bool j2k_write_first_tile_part( opj_j2k_v2_t *p_j2k, OPJ_BYTE * p_data, @@ -472,6 +453,18 @@ Write the COM marker (comment) @param j2k J2K handle */ static void j2k_write_com(opj_j2k_t *j2k); + +/** + * Writes the COM marker (comment) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static opj_bool j2k_write_com_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ); + /** Read the COM marker (comment) @param j2k J2K handle @@ -714,6 +707,17 @@ Write the POC marker (progression order change) */ static void j2k_write_poc(opj_j2k_t *j2k); +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static opj_bool j2k_write_poc_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ); + /** * Writes the POC marker (Progression Order Change) * @@ -905,6 +909,18 @@ Write the TLM marker (Mainheader) @param j2k J2K handle */ static void j2k_write_tlm(opj_j2k_t *j2k); + +/** + * Writes the TLM marker (Tile Length Marker) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static opj_bool j2k_write_tlm_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ); + /** Write the SOT marker (start of tile-part) @param j2k J2K handle @@ -1041,6 +1057,17 @@ static opj_bool j2k_read_rgn_v2 ( struct opj_event_mgr * p_manager ) ; +/** + * Writes the EOC marker (End of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static opj_bool j2k_write_eoc_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ); + /** Write the EOC marker (end of codestream) @param j2k J2K handle @@ -1293,6 +1320,25 @@ static opj_bool j2k_write_epc( opj_j2k_v2_t *p_j2k, struct opj_stream_private *p_stream, struct opj_event_mgr * p_manager ); +/** + * Checks the progression order changes values. Tells of the poc given as input are valid. + * A nice message is outputted at errors. + * + * @param p_pocs the progression order changes. + * @param p_nb_pocs the number of progression order changes. + * @param p_nb_resolutions the number of resolutions. + * @param numcomps the number of components + * @param numlayers the number of layers. + * + * @return true if the pocs are valid. + */ +static opj_bool j2k_check_poc_val( const opj_poc_t *p_pocs, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 numcomps, + OPJ_UINT32 numlayers, + opj_event_mgr_t * p_manager); + /** * Gets the number of tile parts used for the given change of progression (if any) and the given tile. * @@ -1676,6 +1722,120 @@ char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){ return po->str_prog; } +/** + * Checks the progression order changes values. Tells if the poc given as input are valid. + * + * @param p_pocs the progression order changes. + * @param p_nb_pocs the number of progression order changes. + * @param p_nb_resolutions the number of resolutions. + * @param numcomps the number of components + * @param numlayers the number of layers. + * @param p_manager the user event manager. + * + * @return true if the pocs are valid. + */ +opj_bool j2k_check_poc_val( const opj_poc_t *p_pocs, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_num_layers, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32* packet_array; + OPJ_UINT32 index , resno, compno, layno; + OPJ_UINT32 i; + OPJ_UINT32 step_c = 1; + OPJ_UINT32 step_r = p_num_comps * step_c; + OPJ_UINT32 step_l = p_nb_resolutions * step_r; + opj_bool loss = OPJ_FALSE; + OPJ_UINT32 layno0 = 0; + + packet_array = (OPJ_UINT32*) opj_calloc(step_l * p_num_layers, sizeof(OPJ_UINT32)); + if (packet_array == 00) { + opj_event_msg_v2(p_manager , EVT_ERROR, "Not enough memory for checking the poc values.\n"); + return OPJ_FALSE; + } + memset(packet_array,0,step_l * p_num_layers* sizeof(OPJ_UINT32)); + + if (p_nb_pocs == 0) { + return OPJ_TRUE; + } + + index = step_r * p_pocs->resno0; + // take each resolution for each poc + for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) + { + OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; + + // take each comp of each resolution for each poc + for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) { + OPJ_UINT32 comp_index = res_index + layno0 * step_l; + + // and finally take each layer of each res of ... + for (layno = layno0; layno < p_pocs->layno1 ; ++layno) { + //index = step_r * resno + step_c * compno + step_l * layno; + packet_array[comp_index] = 1; + comp_index += step_l; + } + + res_index += step_c; + } + + index += step_r; + } + ++p_pocs; + + // iterate through all the pocs + for (i = 1; i < p_nb_pocs ; ++i) { + OPJ_UINT32 l_last_layno1 = (p_pocs-1)->layno1 ; + + layno0 = (p_pocs->layno1 > l_last_layno1)? l_last_layno1 : 0; + index = step_r * p_pocs->resno0; + + // take each resolution for each poc + for (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) { + OPJ_UINT32 res_index = index + p_pocs->compno0 * step_c; + + // take each comp of each resolution for each poc + for (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) { + OPJ_UINT32 comp_index = res_index + layno0 * step_l; + + // and finally take each layer of each res of ... + for (layno = layno0; layno < p_pocs->layno1 ; ++layno) { + //index = step_r * resno + step_c * compno + step_l * layno; + packet_array[comp_index] = 1; + comp_index += step_l; + } + + res_index += step_c; + } + + index += step_r; + } + + ++p_pocs; + } + + index = 0; + for (layno = 0; layno < p_num_layers ; ++layno) { + for (resno = 0; resno < p_nb_resolutions; ++resno) { + for (compno = 0; compno < p_num_comps; ++compno) { + loss |= (packet_array[index]!=1); + //index = step_r * resno + step_c * compno + step_l * layno; + index += step_c; + } + } + } + + if (loss) { + opj_event_msg_v2(p_manager , EVT_ERROR, "Missing packets possible loss of data\n"); + } + + opj_free(packet_array); + + return !loss; +} + /* ----------------------------------------------------------------------- */ static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){ char *prog; @@ -2702,6 +2862,63 @@ static void j2k_write_com(opj_j2k_t *j2k) { } } +/** + * Writes the COM marker (comment) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +opj_bool j2k_write_com_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ) +{ + OPJ_UINT32 l_comment_size; + OPJ_UINT32 l_total_com_size; + const OPJ_CHAR *l_comment; + OPJ_BYTE * l_current_ptr = 00; + + // preconditions + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_comment = p_j2k->m_cp.comment; + l_comment_size = strlen(l_comment); + l_total_com_size = l_comment_size + 6; + + if (l_total_com_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = (OPJ_BYTE*)opj_realloc( p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_total_com_size); + + if(! p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + return OPJ_FALSE; + } + + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_total_com_size; + } + + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_ptr,J2K_MS_COM , 2); /* COM */ + l_current_ptr+=2; + + opj_write_bytes(l_current_ptr,l_total_com_size - 2 , 2); /* L_COM */ + l_current_ptr+=2; + + opj_write_bytes(l_current_ptr,1 , 2); /* General use (IS 8859-15:1999 (Latin) values) */ + l_current_ptr+=2; + + memcpy( l_current_ptr,l_comment,l_comment_size); + + if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_total_com_size,p_manager) != l_total_com_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + static void j2k_read_com(opj_j2k_t *j2k) { int len; @@ -3759,6 +3976,66 @@ static void j2k_write_poc(opj_j2k_t *j2k) { } } +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +opj_bool j2k_write_poc_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ) +{ + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + OPJ_UINT32 l_written_size = 0; + opj_tcp_v2_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_UINT32 l_poc_room; + + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_tccp = &l_tcp->tccps[0]; + l_nb_comp = p_j2k->m_private_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; + + if (l_nb_comp <= 256) { + l_poc_room = 1; + } + else { + l_poc_room = 2; + } + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + + if (l_poc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = (OPJ_BYTE*)opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_poc_size); + + if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + return OPJ_FALSE; + } + + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size; + } + + j2k_write_poc_in_memory(p_j2k,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_written_size,p_manager); + + if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_poc_size,p_manager) != l_poc_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + + /** * Writes the POC marker (Progression Order Change) * @@ -4291,7 +4568,7 @@ opj_bool j2k_read_plt_v2 ( assert(p_manager != 00); if (p_header_size < 1) { - opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PLT marker\n"); return OPJ_FALSE; } @@ -4314,7 +4591,7 @@ opj_bool j2k_read_plt_v2 ( } if (l_packet_len != 0) { - opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading PLT marker\n"); return OPJ_FALSE; } @@ -4778,29 +5055,89 @@ opj_bool j2k_read_ppt_v2 ( opj_j2k_v2_t *p_j2k, return OPJ_TRUE; } -static void j2k_write_tlm(opj_j2k_t *j2k){ - int lenp; - opj_cio_t *cio = j2k->cio; - j2k->tlm_start = cio_tell(cio); - cio_write(cio, J2K_MS_TLM, 2);/* TLM */ - lenp = 4 + (5*j2k->totnum_tp); - cio_write(cio,lenp,2); /* Ltlm */ - cio_write(cio, 0,1); /* Ztlm=0*/ - cio_write(cio,80,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ - cio_skip(cio,5*j2k->totnum_tp); -} +/** + * Writes the TLM marker (Tile Length Marker) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +opj_bool j2k_write_tlm_v2( opj_j2k_v2_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tlm_size; -static void j2k_write_sot(opj_j2k_t *j2k) { - int lenp, len; + // preconditions + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); - opj_cio_t *cio = j2k->cio; + l_tlm_size = 6 + (5*p_j2k->m_specific_param.m_encoder.m_total_tile_parts); + + if (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + p_j2k->m_specific_param.m_encoder.m_header_tile_data + = (OPJ_BYTE*)opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_tlm_size); + + if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + return OPJ_FALSE; + } - j2k->sot_start = cio_tell(cio); - cio_write(cio, J2K_MS_SOT, 2); /* SOT */ - lenp = cio_tell(cio); - cio_skip(cio, 2); /* Lsot (further) */ - cio_write(cio, j2k->curtileno, 2); /* Isot */ - cio_skip(cio, 4); /* Psot (further in j2k_write_sod) */ + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* change the way data is written to avoid seeking if possible */ + // TODO + p_j2k->m_specific_param.m_encoder.m_tlm_start = opj_stream_tell(p_stream); + + opj_write_bytes(l_current_data,J2K_MS_TLM,2); /* TLM */ + l_current_data += 2; + + opj_write_bytes(l_current_data,l_tlm_size-2,2); /* Lpoc */ + l_current_data += 2; + + opj_write_bytes(l_current_data,0,1); /* Ztlm=0*/ + ++l_current_data; + + opj_write_bytes(l_current_data,0x50,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ + ++l_current_data; + + /* do nothing on the 5 * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */ + if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_tlm_size,p_manager) != l_tlm_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static void j2k_write_tlm(opj_j2k_t *j2k){ + int lenp; + opj_cio_t *cio = j2k->cio; + j2k->tlm_start = cio_tell(cio); + cio_write(cio, J2K_MS_TLM, 2);/* TLM */ + lenp = 4 + (5*j2k->totnum_tp); + cio_write(cio,lenp,2); /* Ltlm */ + cio_write(cio, 0,1); /* Ztlm=0*/ + cio_write(cio,80,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ + cio_skip(cio,5*j2k->totnum_tp); +} + +static void j2k_write_sot(opj_j2k_t *j2k) { + int lenp, len; + + opj_cio_t *cio = j2k->cio; + + j2k->sot_start = cio_tell(cio); + cio_write(cio, J2K_MS_SOT, 2); /* SOT */ + lenp = cio_tell(cio); + cio_skip(cio, 2); /* Lsot (further) */ + cio_write(cio, j2k->curtileno, 2); /* Isot */ + cio_skip(cio, 4); /* Psot (further in j2k_write_sod) */ cio_write(cio, j2k->cur_tp_num , 1); /* TPsot */ cio_write(cio, j2k->cur_totnum_tp[j2k->curtileno], 1); /* TNsot */ len = cio_tell(cio) - lenp; @@ -4889,7 +5226,7 @@ static void j2k_read_sot(opj_j2k_t *j2k) { static int backup_tileno = 0; /* tileno is negative or larger than the number of tiles!!! */ - if ((tileno < 0) || (tileno > (cp->tw * cp->th))) { + if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) { opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: bad tile number (%d out of a maximum of %d)\n", tileno, (cp->tw * cp->th)); @@ -4906,8 +5243,18 @@ static void j2k_read_sot(opj_j2k_t *j2k) { /* keep your private count of tiles */ backup_tileno++; - }; + } + else #endif /* USE_JPWL */ + { + /* tileno is negative or larger than the number of tiles!!! */ + if ((tileno < 0) || (tileno >= (cp->tw * cp->th))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (cp->tw * cp->th)); + return; + } + } if (cp->tileno_size == 0) { cp->tileno[cp->tileno_size] = tileno; @@ -4946,8 +5293,18 @@ static void j2k_read_sot(opj_j2k_t *j2k) { totlen); } - }; + } + else #endif /* USE_JPWL */ + { + /* totlen is negative or larger than the bytes left!!! */ + if ((totlen < 0) || (totlen > (cio_numbytesleft(cio) + 8))) { + opj_event_msg(j2k->cinfo, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + totlen, cio_numbytesleft(cio) + 8); + return; + } + } if (!totlen) totlen = cio_numbytesleft(cio) + 8; @@ -5169,6 +5526,7 @@ opj_bool j2k_read_sot_v2 ( /* Index */ if (p_j2k->cstr_index) { + assert(p_j2k->cstr_index->tile_index != 00); p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = l_current_part; @@ -5660,6 +6018,45 @@ static void j2k_write_eoc(opj_j2k_t *j2k) { /* <m_specific_param.m_encoder.m_header_tile_data,J2K_MS_EOC,2); /* EOC */ + + +/* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /* + j2k_add_marker(p_j2k->cstr_info, J2K_MS_EOC, p_stream_tell(p_stream) - 2, 2); +*/ +#endif /* USE_JPWL */ + + if ( opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,2,p_manager) != 2) { + return OPJ_FALSE; + } + + if ( ! opj_stream_flush(p_stream,p_manager) ) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + + /** * Reads a RGN marker (Region Of Interest) * @@ -5915,7 +6312,7 @@ opj_bool j2k_update_rates( opj_j2k_v2_t *p_j2k, static void j2k_read_eoc(opj_j2k_t *j2k) { int i, tileno; - opj_bool success; + opj_bool success = OPJ_FALSE; /* if packets should be decoded */ if (j2k->cp->limit_decoding != DECODE_ALL_BUT_PACKETS) { @@ -5923,11 +6320,16 @@ static void j2k_read_eoc(opj_j2k_t *j2k) { tcd_malloc_decode(tcd, j2k->image, j2k->cp); for (i = 0; i < j2k->cp->tileno_size; i++) { tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info); - tileno = j2k->cp->tileno[i]; - success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); - opj_free(j2k->tile_data[tileno]); - j2k->tile_data[tileno] = NULL; - tcd_free_decode_tile(tcd, i); + if (j2k->cp->tileno[i] != -1) + { + tileno = j2k->cp->tileno[i]; + success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info); + opj_free(j2k->tile_data[tileno]); + j2k->tile_data[tileno] = NULL; + tcd_free_decode_tile(tcd, i); + } + else + success = OPJ_FALSE; if (success == OPJ_FALSE) { j2k->state |= J2K_STATE_ERR; break; @@ -7222,22 +7624,7 @@ opj_bool j2k_read_cbd ( opj_j2k_v2_t *p_j2k, /* J2K / JPT decoder interface */ /* ----------------------------------------------------------------------- */ -opj_j2k_t* j2k_create_decompress(opj_common_ptr cinfo) { - opj_j2k_t *j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); - if(!j2k) - return NULL; - - j2k->default_tcp = (opj_tcp_t*) opj_calloc(1, sizeof(opj_tcp_t)); - if(!j2k->default_tcp) { - opj_free(j2k); - return NULL; - } - - j2k->cinfo = cinfo; - j2k->tile_data = NULL; - return j2k; -} void j2k_destroy_decompress(opj_j2k_t *j2k) { int i = 0; @@ -7286,27 +7673,8 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) { opj_free(j2k); } -void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) { - if(j2k && parameters) { - /* create and initialize the coding parameters structure */ - opj_cp_t *cp = (opj_cp_t*) opj_calloc(1, sizeof(opj_cp_t)); - cp->reduce = parameters->cp_reduce; - cp->layer = parameters->cp_layer; - cp->limit_decoding = parameters->cp_limit_decoding; - -#ifdef USE_JPWL - cp->correct = parameters->jpwl_correct; - cp->exp_comps = parameters->jpwl_exp_comps; - cp->max_tiles = parameters->jpwl_max_tiles; -#endif /* USE_JPWL */ - - /* keep a link to cp so that we can destroy it later in j2k_destroy_decompress */ - j2k->cp = cp; - } -} - -void j2k_setup_decoder_v2(opj_j2k_v2_t *j2k, opj_dparameters_t *parameters) +void opj_j2k_setup_decoder(opj_j2k_v2_t *j2k, opj_dparameters_t *parameters) { if(j2k && parameters) { j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer; @@ -7838,6 +8206,322 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ } } +void j2k_setup_encoder_v2( opj_j2k_v2_t *p_j2k, + opj_cparameters_t *parameters, + opj_image_t *image, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 i, j, tileno, numpocs_tile; + opj_cp_v2_t *cp = 00; + opj_bool l_res; + + if(!p_j2k || !parameters || ! image) { + return; + } + + /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ + cp = &(p_j2k->m_cp); + + /* set default values for cp */ + cp->tw = 1; + cp->th = 1; + + /* + copy user encoding parameters + */ + cp->m_specific_param.m_enc.m_cinema = parameters->cp_cinema; + cp->m_specific_param.m_enc.m_max_comp_size = parameters->max_comp_size; + cp->rsiz = parameters->cp_rsiz; + cp->m_specific_param.m_enc.m_disto_alloc = parameters->cp_disto_alloc; + cp->m_specific_param.m_enc.m_fixed_alloc = parameters->cp_fixed_alloc; + cp->m_specific_param.m_enc.m_fixed_quality = parameters->cp_fixed_quality; + + /* mod fixed_quality */ + if (parameters->cp_matrice) { + size_t array_size = parameters->tcp_numlayers * parameters->numresolution * 3 * sizeof(OPJ_INT32); + cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); + memcpy(cp->m_specific_param.m_enc.m_matrice, parameters->cp_matrice, array_size); + } + + /* tiles */ + cp->tdx = parameters->cp_tdx; + cp->tdy = parameters->cp_tdy; + + /* tile offset */ + cp->tx0 = parameters->cp_tx0; + cp->ty0 = parameters->cp_ty0; + + /* comment string */ + if(parameters->cp_comment) { + cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1); + if(cp->comment) { + strcpy(cp->comment, parameters->cp_comment); + } + } + + /* + calculate other encoding parameters + */ + + if (parameters->tile_size_on) { + cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy); + } else { + cp->tdx = image->x1 - cp->tx0; + cp->tdy = image->y1 - cp->ty0; + } + + if (parameters->tp_on) { + cp->m_specific_param.m_enc.m_tp_flag = parameters->tp_flag; + cp->m_specific_param.m_enc.m_tp_on = 1; + } + +#ifdef USE_JPWL + /* + calculate JPWL encoding parameters + */ + + if (parameters->jpwl_epc_on) { + OPJ_INT32 i; + + /* set JPWL on */ + cp->epc_on = OPJ_TRUE; + cp->info_on = OPJ_FALSE; /* no informative technique */ + + /* set EPB on */ + if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { + cp->epb_on = OPJ_TRUE; + + cp->hprot_MH = parameters->jpwl_hprot_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i]; + cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i]; + } + /* if tile specs are not specified, copy MH specs */ + if (cp->hprot_TPH[0] == -1) { + cp->hprot_TPH_tileno[0] = 0; + cp->hprot_TPH[0] = parameters->jpwl_hprot_MH; + } + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i]; + cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i]; + cp->pprot[i] = parameters->jpwl_pprot[i]; + } + } + + /* set ESD writing */ + if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { + cp->esd_on = OPJ_TRUE; + + cp->sens_size = parameters->jpwl_sens_size; + cp->sens_addr = parameters->jpwl_sens_addr; + cp->sens_range = parameters->jpwl_sens_range; + + cp->sens_MH = parameters->jpwl_sens_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i]; + cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i]; + } + } + + /* always set RED writing to false: we are at the encoder */ + cp->red_on = OPJ_FALSE; + + } else { + cp->epc_on = OPJ_FALSE; + } +#endif /* USE_JPWL */ + + + /* initialize the mutiple tiles */ + /* ---------------------------- */ + cp->tcps = (opj_tcp_v2_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_v2_t)); + if (parameters->numpocs) { + /* initialisation of POC */ + l_res = j2k_check_poc_val(parameters->POC,parameters->numpocs, parameters->numresolution, image->numcomps, parameters->tcp_numlayers, p_manager); + // TODO + } + + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_tcp_v2_t *tcp = &cp->tcps[tileno]; + tcp->numlayers = parameters->tcp_numlayers; + + for (j = 0; j < tcp->numlayers; j++) { + if(cp->m_specific_param.m_enc.m_cinema){ + if (cp->m_specific_param.m_enc.m_fixed_quality) { + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } + tcp->rates[j] = parameters->tcp_rates[j]; + }else{ + if (cp->m_specific_param.m_enc.m_fixed_quality) { /* add fixed_quality */ + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } else { + tcp->rates[j] = parameters->tcp_rates[j]; + } + } + } + + tcp->csty = parameters->csty; + tcp->prg = parameters->prog_order; + tcp->mct = parameters->tcp_mct; + + numpocs_tile = 0; + tcp->POC = 0; + + if (parameters->numpocs) { + /* initialisation of POC */ + tcp->POC = 1; + // TODO + for (i = 0; i < (unsigned int) parameters->numpocs; i++) { + if((tileno == parameters->POC[i].tile - 1) || (parameters->POC[i].tile == -1)) { + opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; + + tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0; + tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0; + tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1; + tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1; + tcp_poc->compno1 = parameters->POC[numpocs_tile].compno1; + tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; + tcp_poc->tile = parameters->POC[numpocs_tile].tile; + + numpocs_tile++; + } + } + + tcp->numpocs = numpocs_tile -1 ; + }else{ + tcp->numpocs = 0; + } + + tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); + + if (parameters->mct_data) { + + opj_event_msg_v2(p_manager, EVT_ERROR, "MCT not supported for now\n"); + return; + + /* TODO MSD : merge v2 add invert.c or used a external lib ? + OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * sizeof(OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpBuf = (OPJ_FLOAT32*)opj_malloc(lMctSize); + OPJ_INT32 * l_dc_shift = (OPJ_INT32 *) ((OPJ_BYTE *) parameters->mct_data + lMctSize); + + tcp->mct = 2; + tcp->m_mct_coding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); + memcpy(tcp->m_mct_coding_matrix,parameters->mct_data,lMctSize); + memcpy(lTmpBuf,parameters->mct_data,lMctSize); + + tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); + assert(opj_matrix_inversion_f(lTmpBuf,(tcp->m_mct_decoding_matrix),image->numcomps)); + + tcp->mct_norms = (OPJ_FLOAT64*) + opj_malloc(image->numcomps * sizeof(OPJ_FLOAT64)); + + opj_calculate_norms(tcp->mct_norms,image->numcomps,tcp->m_mct_decoding_matrix); + opj_free(lTmpBuf); + + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->m_dc_level_shift = l_dc_shift[i]; + } + + j2k_setup_mct_encoding(tcp,image); + */ + } + else { + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + opj_image_comp_t * l_comp = &(image->comps[i]); + + if (! l_comp->sgnd) { + tccp->m_dc_level_shift = 1 << (l_comp->prec - 1); + } + } + } + + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + + tccp->csty = parameters->csty & 0x01; /* 0 => one precinct || 1 => custom precinct */ + tccp->numresolutions = parameters->numresolution; + tccp->cblkw = int_floorlog2(parameters->cblockw_init); + tccp->cblkh = int_floorlog2(parameters->cblockh_init); + tccp->cblksty = parameters->mode; + tccp->qmfbid = parameters->irreversible ? 0 : 1; + tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT; + tccp->numgbits = 2; + + if (i == parameters->roi_compno) { + tccp->roishift = parameters->roi_shift; + } else { + tccp->roishift = 0; + } + + if(parameters->cp_cinema) { + //Precinct size for lowest frequency subband=128 + tccp->prcw[0] = 7; + tccp->prch[0] = 7; + //Precinct size at all other resolutions = 256 + for (j = 1; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 8; + tccp->prch[j] = 8; + } + }else{ + if (parameters->csty & J2K_CCP_CSTY_PRT) { + OPJ_INT32 p = 0, it_res; + for (it_res = tccp->numresolutions - 1; it_res >= 0; it_res--) { + if (p < parameters->res_spec) { + + if (parameters->prcw_init[p] < 1) { + tccp->prcw[it_res] = 1; + } else { + tccp->prcw[it_res] = int_floorlog2(parameters->prcw_init[p]); + } + + if (parameters->prch_init[p] < 1) { + tccp->prch[it_res] = 1; + }else { + tccp->prch[it_res] = int_floorlog2(parameters->prch_init[p]); + } + + } else { + int res_spec = parameters->res_spec; + int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); + int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); + + if (size_prcw < 1) { + tccp->prcw[it_res] = 1; + } else { + tccp->prcw[it_res] = int_floorlog2(size_prcw); + } + + if (size_prch < 1) { + tccp->prch[it_res] = 1; + } else { + tccp->prch[it_res] = int_floorlog2(size_prch); + } + } + p++; + /*printf("\nsize precinct for level %d : %d,%d\n", it_res,tccp->prcw[it_res], tccp->prch[it_res]); */ + } //end for + } else { + for (j = 0; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 15; + tccp->prch[j] = 15; + } + } + } + + dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); + } + } + + if (parameters->mct_data) { + opj_free(parameters->mct_data); + parameters->mct_data = 00; + } +} + + opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { int tileno; OPJ_UINT32 compno; @@ -8219,6 +8903,10 @@ opj_bool j2k_read_header( struct opj_stream_private *p_stream, /* Copy codestream image information to the output image */ opj_copy_image_header(p_j2k->m_private_image, *p_image); + /*Allocate and initialize some elements of codestrem index*/ + if (!j2k_allocate_tile_element_cstr_index(p_j2k)){ + return OPJ_FALSE; + } return OPJ_TRUE; } @@ -8296,6 +8984,140 @@ opj_bool j2k_mct_validation ( opj_j2k_v2_t * p_j2k, return l_is_valid; } +opj_bool j2k_setup_mct_encoding(opj_tcp_v2_t * p_tcp, opj_image_t * p_image) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_indix = 1; + opj_mct_data_t * l_mct_deco_data = 00,* l_mct_offset_data = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_data; + OPJ_UINT32 l_mct_size,l_nb_elem; + OPJ_FLOAT32 * l_data, * l_current_data; + opj_tccp_t * l_tccp; + + // preconditions + assert(p_tcp != 00); + + if (p_tcp->mct != 2) { + return OPJ_TRUE; + } + + if (p_tcp->m_mct_decoding_matrix) { + if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { + p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; + + p_tcp->m_mct_records = (opj_mct_data_t*)opj_realloc(p_tcp->m_mct_records,p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! p_tcp->m_mct_records) { + return OPJ_FALSE; + } + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + memset(l_mct_deco_data ,0,(p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + } + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + if (l_mct_deco_data->m_data) { + opj_free(l_mct_deco_data->m_data); + l_mct_deco_data->m_data = 00; + } + + l_mct_deco_data->m_index = l_indix++; + l_mct_deco_data->m_array_type = MCT_TYPE_DECORRELATION; + l_mct_deco_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_deco_data->m_element_type]; + l_mct_deco_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size ); + + if (! l_mct_deco_data->m_data) { + return OPJ_FALSE; + } + + j2k_mct_write_functions_from_float[l_mct_deco_data->m_element_type](p_tcp->m_mct_decoding_matrix,l_mct_deco_data->m_data,l_nb_elem); + + l_mct_deco_data->m_data_size = l_mct_size; + ++p_tcp->m_nb_mct_records; + } + + if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { + p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; + p_tcp->m_mct_records = (opj_mct_data_t*)opj_realloc(p_tcp->m_mct_records,p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + + if (! p_tcp->m_mct_records) { + return OPJ_FALSE; + } + + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + memset(l_mct_offset_data ,0,(p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof(opj_mct_data_t)); + + if (l_mct_deco_data) { + l_mct_deco_data = l_mct_offset_data - 1; + } + } + + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + if (l_mct_offset_data->m_data) { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + } + + l_mct_offset_data->m_index = l_indix++; + l_mct_offset_data->m_array_type = MCT_TYPE_OFFSET; + l_mct_offset_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_offset_data->m_element_type]; + l_mct_offset_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size ); + + if (! l_mct_offset_data->m_data) { + return OPJ_FALSE; + } + + l_data = (OPJ_FLOAT32*)opj_malloc(l_nb_elem * sizeof(OPJ_FLOAT32)); + if (! l_data) { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + return OPJ_FALSE; + } + + l_tccp = p_tcp->tccps; + l_current_data = l_data; + + for (i=0;im_dc_level_shift); + ++l_tccp; + } + + j2k_mct_write_functions_from_float[l_mct_offset_data->m_element_type](l_data,l_mct_offset_data->m_data,l_nb_elem); + + opj_free(l_data); + + l_mct_offset_data->m_data_size = l_mct_size; + + ++p_tcp->m_nb_mct_records; + + if (p_tcp->m_nb_mcc_records == p_tcp->m_nb_max_mcc_records) { + p_tcp->m_nb_max_mcc_records += J2K_MCT_DEFAULT_NB_RECORDS; + p_tcp->m_mcc_records = (opj_simple_mcc_decorrelation_data_t*) + opj_realloc(p_tcp->m_mcc_records,p_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t)); + + if (! p_tcp->m_mcc_records) { + return OPJ_FALSE; + } + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + memset(l_mcc_data ,0,(p_tcp->m_nb_max_mcc_records - p_tcp->m_nb_mcc_records) * sizeof(opj_simple_mcc_decorrelation_data_t)); + + } + + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + l_mcc_data->m_decorrelation_array = l_mct_deco_data; + l_mcc_data->m_is_irreversible = 1; + l_mcc_data->m_nb_comps = p_image->numcomps; + l_mcc_data->m_index = l_indix++; + l_mcc_data->m_offset_array = l_mct_offset_data; + ++p_tcp->m_nb_mcc_records; + + return OPJ_TRUE; +} + /** * Builds the cp decoder parameters to use to decode tile. */ @@ -9554,8 +10376,8 @@ opj_bool j2k_set_decode_area( opj_j2k_v2_t *p_j2k, /* Check if the positions provided by the user are correct */ /* Left */ - assert(p_start_x > 0 ); - assert(p_start_y > 0 ); + assert(p_start_x >= 0 ); + assert(p_start_y >= 0 ); if ((OPJ_UINT32)p_start_x > l_image->x1 ) { opj_event_msg_v2(p_manager, EVT_ERROR, @@ -9686,7 +10508,7 @@ opj_bool j2k_set_decode_area( opj_j2k_v2_t *p_j2k, * * @return a handle to a J2K decompressor if successful, NULL otherwise. */ -opj_j2k_v2_t* j2k_create_decompress_v2(void) +opj_j2k_v2_t* opj_j2k_create_decompress(void) { opj_j2k_v2_t *l_j2k = (opj_j2k_v2_t*) opj_malloc(sizeof(opj_j2k_v2_t)); if (!l_j2k) { @@ -10394,33 +11216,43 @@ void j2k_dump_MH_index(opj_j2k_v2_t* p_j2k, FILE* out_stream) if (cstr_index->tile_index){ - fprintf(out_stream, "\t Tile index: {\n"); - - for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){ - OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps; - fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, nb_of_tile_part); - - if (cstr_index->tile_index[it_tile].tp_index){ - for (it_tile_part =0; it_tile_part < nb_of_tile_part; it_tile_part++){ - fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%" PRIi64 ", end_header=%" PRIi64 ", end_pos=%" PRIi64 ".\n", - it_tile_part, - cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos, - cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header, - cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos); - } - } - - if (cstr_index->tile_index[it_tile].marker){ - for (it_marker=0; it_marker < cstr_index->tile_index[it_tile].marknum ; it_marker++){ - fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", - cstr_index->tile_index[it_tile].marker[it_marker].type, - cstr_index->tile_index[it_tile].marker[it_marker].pos, - cstr_index->tile_index[it_tile].marker[it_marker].len ); - } - } - } - fprintf(out_stream,"\t }\n"); + /* Simple test to avoid to write empty information*/ + OPJ_UINT32 l_acc_nb_of_tile_part = 0; + for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){ + l_acc_nb_of_tile_part += cstr_index->tile_index[it_tile].nb_tps; + } + + if (l_acc_nb_of_tile_part) + { + fprintf(out_stream, "\t Tile index: {\n"); + + for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){ + OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps; + + fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, nb_of_tile_part); + + if (cstr_index->tile_index[it_tile].tp_index){ + for (it_tile_part =0; it_tile_part < nb_of_tile_part; it_tile_part++){ + fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%" PRIi64 ", end_header=%" PRIi64 ", end_pos=%" PRIi64 ".\n", + it_tile_part, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos); + } + } + + if (cstr_index->tile_index[it_tile].marker){ + for (it_marker=0; it_marker < cstr_index->tile_index[it_tile].marknum ; it_marker++){ + fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", + cstr_index->tile_index[it_tile].marker[it_marker].type, + cstr_index->tile_index[it_tile].marker[it_marker].pos, + cstr_index->tile_index[it_tile].marker[it_marker].len ); + } + } + } + fprintf(out_stream,"\t }\n"); + } } fprintf(out_stream,"}\n"); @@ -10792,11 +11624,7 @@ opj_bool j2k_decode_tiles ( opj_j2k_v2_t *p_j2k, } l_max_data_size = 1000; - /*Allocate and initialize some elements of codestrem index*/ - if (!j2k_allocate_tile_element_cstr_index(p_j2k)){ - opj_free(l_current_data); - return OPJ_FALSE; - } + while (OPJ_TRUE) { if (! j2k_read_tile_header( p_j2k, @@ -10957,7 +11785,7 @@ static opj_bool j2k_decode_one_tile ( opj_j2k_v2_t *p_j2k, if(l_current_tile_no == l_tile_no_to_dec) { /* move into the codestream to the the first SOT (FIXME or not move?)*/ - if (opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) { + if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) ) { opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n"); return OPJ_FALSE; } @@ -11251,7 +12079,20 @@ opj_bool j2k_start_compress(opj_j2k_v2_t *p_j2k, assert(p_stream != 00); assert(p_manager != 00); - p_j2k->m_private_image = p_image; + p_j2k->m_private_image = opj_image_create0(); + opj_copy_image_header(p_image, p_j2k->m_private_image); + + // TODO_MSD: Find a better way + if (p_image->comps) { + OPJ_UINT32 it_comp; + for (it_comp = 0 ; it_comp < p_image->numcomps; it_comp++) { + if (p_image->comps[it_comp].data) { + p_j2k->m_private_image->comps[it_comp].data =p_image->comps[it_comp].data; + p_image->comps[it_comp].data = NULL; + + } + } + } /* customization of the validation */ j2k_setup_encoding_validation (p_j2k); @@ -11439,7 +12280,7 @@ opj_bool j2k_post_write_tile ( opj_j2k_v2_t * p_j2k, l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data; if (! tcd_copy_tile_data(l_tcd,p_data,p_data_size)) { - opj_event_msg_v2(p_manager, EVT_ERROR, "Size mismtach between tile data and sent data." ); + opj_event_msg_v2(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." ); return OPJ_FALSE; } @@ -11458,7 +12299,9 @@ opj_bool j2k_post_write_tile ( opj_j2k_v2_t * p_j2k, l_available_data -= l_nb_bytes_written; l_nb_bytes_written = l_tile_size - l_available_data; - if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_encoded_tile_data,l_nb_bytes_written,p_manager) != l_nb_bytes_written) { + if ( opj_stream_write_data( p_stream, + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data, + l_nb_bytes_written,p_manager) != l_nb_bytes_written) { return OPJ_FALSE; } @@ -11478,7 +12321,7 @@ void j2k_setup_end_compress (opj_j2k_v2_t *p_j2k) assert(p_j2k != 00); /* DEVELOPER CORNER, insert your custom procedures */ - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_eoc ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_eoc_v2 ); if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) { opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_updated_tlm); @@ -11524,17 +12367,17 @@ void j2k_setup_header_writting (opj_j2k_v2_t *p_j2k) if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) { opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_image_components ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_tlm ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_tlm_v2 ); if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == CINEMA4K_24) { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_poc ); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_poc_v2 ); } } opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_regions); if (p_j2k->m_cp.comment != 00) { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_com); + opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(opj_procedure)j2k_write_com_v2); } /* DEVELOPER CORNER, insert your custom procedures */ @@ -11948,8 +12791,15 @@ opj_bool j2k_write_tile (opj_j2k_v2_t * p_j2k, opj_event_mgr_t * p_manager ) { if (! j2k_pre_write_tile(p_j2k,p_tile_index,p_stream,p_manager)) { + opj_event_msg_v2(p_manager, EVT_ERROR, "Error while j2k_pre_write_tile with tile index = %d\n", p_tile_index); return OPJ_FALSE; } + else { + if (! j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager)) { + opj_event_msg_v2(p_manager, EVT_ERROR, "Error while j2k_post_write_tile with tile index = %d\n", p_tile_index); + return OPJ_FALSE; + } + } - return j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager); + return OPJ_TRUE; }