+ 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) {
+ int p = 0;
+ for (j = tccp->numresolutions - 1; j >= 0; j--) {
+ if (p < parameters->res_spec) {
+
+ if (parameters->prcw_init[p] < 1) {
+ tccp->prcw[j] = 1;
+ } else {
+ tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]);
+ }
+
+ if (parameters->prch_init[p] < 1) {
+ tccp->prch[j] = 1;
+ }else {
+ tccp->prch[j] = 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[j] = 1;
+ } else {
+ tccp->prcw[j] = int_floorlog2(size_prcw);
+ }
+
+ if (size_prch < 1) {
+ tccp->prch[j] = 1;
+ } else {
+ tccp->prch[j] = int_floorlog2(size_prch);
+ }
+ }
+ p++;
+ /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */
+ } //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);
+ }
+ }
+}
+
+opj_bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
+ int tileno, compno;
+ opj_cp_t *cp = NULL;
+
+ opj_tcd_t *tcd = NULL; /* TCD component */
+
+ j2k->cio = cio;
+ j2k->image = image;
+
+ cp = j2k->cp;
+
+ /* INDEX >> */
+ j2k->cstr_info = cstr_info;
+ if (cstr_info) {
+ int compno;
+ cstr_info->tile = (opj_tile_info_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tile_info_t));
+ cstr_info->image_w = image->x1 - image->x0;
+ cstr_info->image_h = image->y1 - image->y0;
+ cstr_info->prog = (&cp->tcps[0])->prg;
+ cstr_info->tw = cp->tw;
+ cstr_info->th = cp->th;
+ cstr_info->tile_x = cp->tdx; /* new version parser */
+ cstr_info->tile_y = cp->tdy; /* new version parser */
+ cstr_info->tile_Ox = cp->tx0; /* new version parser */
+ cstr_info->tile_Oy = cp->ty0; /* new version parser */
+ cstr_info->numcomps = image->numcomps;
+ cstr_info->numlayers = (&cp->tcps[0])->numlayers;
+ cstr_info->numdecompos = (int*) opj_malloc(image->numcomps * sizeof(int));
+ for (compno=0; compno < image->numcomps; compno++) {
+ cstr_info->numdecompos[compno] = (&cp->tcps[0])->tccps->numresolutions - 1;
+ }
+ cstr_info->D_max = 0.0; /* ADD Marcela */
+ cstr_info->main_head_start = cio_tell(cio); /* position of SOC */
+ cstr_info->maxmarknum = 100;
+ cstr_info->marker = (opj_marker_info_t *) opj_malloc(cstr_info->maxmarknum * sizeof(opj_marker_info_t));
+ cstr_info->marknum = 0;
+ }
+ /* << INDEX */
+
+ j2k_write_soc(j2k);
+ j2k_write_siz(j2k);
+ j2k_write_cod(j2k);
+ j2k_write_qcd(j2k);
+
+ if(cp->cinema){
+ for (compno = 1; compno < image->numcomps; compno++) {
+ j2k_write_coc(j2k, compno);
+ j2k_write_qcc(j2k, compno);
+ }
+ }
+
+ for (compno = 0; compno < image->numcomps; compno++) {
+ opj_tcp_t *tcp = &cp->tcps[0];
+ if (tcp->tccps[compno].roishift)
+ j2k_write_rgn(j2k, compno, 0);
+ }
+ if (cp->comment != NULL) {
+ j2k_write_com(j2k);
+ }
+
+ j2k->totnum_tp = j2k_calculate_tp(cp,image->numcomps,image,j2k);
+ /* TLM Marker*/
+ if(cp->cinema){
+ j2k_write_tlm(j2k);
+ if (cp->cinema == CINEMA4K_24) {
+ j2k_write_poc(j2k);
+ }
+ }
+
+ /* uncomment only for testing JPSEC marker writing */
+ /* j2k_write_sec(j2k); */
+
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->main_head_end = cio_tell(cio) - 1;
+ }
+ /* << INDEX */
+ /**** Main Header ENDS here ***/
+
+ /* create the tile encoder */
+ tcd = tcd_create(j2k->cinfo);
+
+ /* encode each tile */
+ for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+ int pino;
+ int tilepartno=0;
+ /* UniPG>> */
+ int acc_pack_num = 0;
+ /* <<UniPG */
+
+
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ opj_event_msg(j2k->cinfo, EVT_INFO, "tile number %d / %d\n", tileno + 1, cp->tw * cp->th);
+
+ j2k->curtileno = tileno;
+ j2k->cur_tp_num = 0;
+ tcd->cur_totnum_tp = j2k->cur_totnum_tp[j2k->curtileno];
+ /* initialisation before tile encoding */
+ if (tileno == 0) {
+ tcd_malloc_encode(tcd, image, cp, j2k->curtileno);
+ } else {
+ tcd_init_encode(tcd, image, cp, j2k->curtileno);
+ }
+
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->tile[j2k->curtileno].start_pos = cio_tell(cio) + j2k->pos_correction;
+ cstr_info->tile[j2k->curtileno].maxmarknum = 10;
+ cstr_info->tile[j2k->curtileno].marker = (opj_marker_info_t *) opj_malloc(cstr_info->tile[j2k->curtileno].maxmarknum * sizeof(opj_marker_info_t));
+ cstr_info->tile[j2k->curtileno].marknum = 0;
+ }
+ /* << INDEX */
+
+ for(pino = 0; pino <= tcp->numpocs; pino++) {
+ int tot_num_tp;
+ tcd->cur_pino=pino;
+
+ /*Get number of tile parts*/
+ tot_num_tp = j2k_get_num_tp(cp,pino,tileno);
+ tcd->tp_pos = cp->tp_pos;
+
+ for(tilepartno = 0; tilepartno < tot_num_tp ; tilepartno++){
+ j2k->tp_num = tilepartno;
+ /* INDEX >> */
+ if(cstr_info)
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_start_pos =
+ cio_tell(cio) + j2k->pos_correction;
+ /* << INDEX */
+ j2k_write_sot(j2k);
+
+ if(j2k->cur_tp_num == 0 && cp->cinema == 0){
+ for (compno = 1; compno < image->numcomps; compno++) {
+ j2k_write_coc(j2k, compno);
+ j2k_write_qcc(j2k, compno);
+ }
+ if (cp->tcps[tileno].numpocs) {
+ j2k_write_poc(j2k);
+ }
+ }
+
+ /* INDEX >> */
+ if(cstr_info)
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_header =
+ cio_tell(cio) + j2k->pos_correction + 1;
+ /* << INDEX */
+
+ j2k_write_sod(j2k, tcd);
+
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_pos =
+ cio_tell(cio) + j2k->pos_correction - 1;
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_start_pack =
+ acc_pack_num;
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_numpacks =
+ cstr_info->packno - acc_pack_num;
+ acc_pack_num = cstr_info->packno;
+ }
+ /* << INDEX */
+
+ j2k->cur_tp_num++;
+ }
+ }
+ if(cstr_info) {
+ cstr_info->tile[j2k->curtileno].end_pos = cio_tell(cio) + j2k->pos_correction - 1;
+ }
+
+
+ /*
+ if (tile->PPT) { // BAD PPT !!!
+ FILE *PPT_file;
+ int i;
+ PPT_file=fopen("PPT","rb");
+ fprintf(stderr,"%c%c%c%c",255,97,tile->len_ppt/256,tile->len_ppt%256);
+ for (i=0;i<tile->len_ppt;i++) {
+ unsigned char elmt;
+ fread(&elmt, 1, 1, PPT_file);
+ fwrite(&elmt,1,1,f);
+ }
+ fclose(PPT_file);
+ unlink("PPT");
+ }
+ */
+
+ }
+
+ /* destroy the tile encoder */
+ tcd_free_encode(tcd);
+ tcd_destroy(tcd);
+
+ opj_free(j2k->cur_totnum_tp);
+
+ j2k_write_eoc(j2k);
+
+ if(cstr_info) {
+ cstr_info->codestream_size = cio_tell(cio) + j2k->pos_correction;
+ /* UniPG>> */
+ /* The following adjustment is done to adjust the codestream size */
+ /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */
+ /* the first bunch of bytes is not in the codestream */
+ cstr_info->codestream_size -= cstr_info->main_head_start;
+ /* <<UniPG */
+ }
+
+#ifdef USE_JPWL
+ /*
+ preparation of JPWL marker segments
+ */
+ if(cp->epc_on) {
+
+ /* encode according to JPWL */
+ jpwl_encode(j2k, cio, image);
+
+ }
+#endif /* USE_JPWL */
+
+ return OPJ_TRUE;
+}
+
+static void j2k_add_mhmarker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
+
+ if (!cstr_info)
+ return;
+
+ /* expand the list? */
+ if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {
+ cstr_info->maxmarknum = 100 + (int) ((float) cstr_info->maxmarknum * 1.0F);
+ cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum);
+ }
+
+ /* add the marker */
+ cstr_info->marker[cstr_info->marknum].type = type;
+ cstr_info->marker[cstr_info->marknum].pos = pos;
+ cstr_info->marker[cstr_info->marknum].len = len;
+ cstr_info->marknum++;
+
+}
+
+static void j2k_add_mhmarker_v2(opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) {
+
+ if (!cstr_index)
+ return;
+
+ /* expand the list? */
+ if ((cstr_index->marknum + 1) > cstr_index->maxmarknum) {
+ cstr_index->maxmarknum = 100 + (int) ((float) cstr_index->maxmarknum * 1.0F);
+ cstr_index->marker = (opj_marker_info_t*)opj_realloc(cstr_index->marker, cstr_index->maxmarknum *sizeof(opj_marker_info_t));
+ }
+
+ /* add the marker */
+ cstr_index->marker[cstr_index->marknum].type = (OPJ_UINT16)type;
+ cstr_index->marker[cstr_index->marknum].pos = (OPJ_INT32)pos;
+ cstr_index->marker[cstr_index->marknum].len = (OPJ_INT32)len;
+ cstr_index->marknum++;
+
+}
+
+static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {
+
+
+ opj_marker_info_t *marker;
+
+ if (!cstr_info)
+ return;
+
+ /* expand the list? */
+ if ((cstr_info->tile[tileno].marknum + 1) > cstr_info->tile[tileno].maxmarknum) {
+ cstr_info->tile[tileno].maxmarknum = 100 + (int) ((float) cstr_info->tile[tileno].maxmarknum * 1.0F);
+ cstr_info->tile[tileno].marker = (opj_marker_info_t*)opj_realloc(cstr_info->tile[tileno].marker, cstr_info->maxmarknum);
+ }
+
+ marker = &(cstr_info->tile[tileno].marker[cstr_info->tile[tileno].marknum]);
+
+ /* add the marker */
+ marker->type = type;
+ marker->pos = pos;
+ marker->len = len;
+ cstr_info->tile[tileno].marknum++;
+}
+
+static void j2k_add_tlmarker_v2(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len)
+{
+
+ if (!cstr_index)
+ return;
+
+ if (!cstr_index->tile_index)
+
+ /* expand the list? */
+ if ((cstr_index->tile_index[tileno].marknum + 1) > cstr_index->tile_index[tileno].maxmarknum) {
+ cstr_index->tile_index[tileno].maxmarknum = 100 + (int) ((float) cstr_index->tile_index[tileno].maxmarknum * 1.0F);
+ cstr_index->tile_index[tileno].marker =
+ (opj_marker_info_t*)opj_realloc(cstr_index->tile_index[tileno].marker,
+ cstr_index->tile_index[tileno].maxmarknum *sizeof(opj_marker_info_t));
+ }
+
+ /* add the marker */
+ cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].type = (OPJ_UINT16)type;
+ cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].pos = (OPJ_INT32)pos;
+ cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].len = (OPJ_INT32)len;
+ cstr_index->tile_index[tileno].marknum++;
+
+ if (type == J2K_MS_SOT) {
+ OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno;
+
+ if (cstr_index->tile_index[tileno].tp_index)
+ cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos;
+
+ }
+
+}
+
+
+
+
+/*
+ * -----------------------------------------------------------------------
+ * -----------------------------------------------------------------------
+ * -----------------------------------------------------------------------
+ */
+
+/**
+ * Ends the decompression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool j2k_end_decompress(
+ opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager)
+{
+ return OPJ_TRUE;
+}
+
+/**
+ * Reads a jpeg2000 codestream header structure.
+
+ *
+ * @param p_stream the stream to read data from.
+ * @param p_j2k the jpeg2000 codec.
+ * @param p_manager the user event manager.
+ *
+ * @return true if the box is valid.
+ */
+opj_bool j2k_read_header( struct opj_stream_private *p_stream,
+ opj_j2k_v2_t* p_j2k,
+ opj_image_t** p_image,
+ struct opj_event_mgr* p_manager )
+{
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ /* create an empty image header */
+ p_j2k->m_private_image = opj_image_create0();
+ if (! p_j2k->m_private_image) {
+ return OPJ_FALSE;
+ }
+
+ /* customization of the validation */
+ j2k_setup_decoding_validation(p_j2k);
+
+ /* validation of the parameters codec */
+ if (! j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream,p_manager)) {
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+ return OPJ_FALSE;
+ }
+
+ /* customization of the encoding */
+ j2k_setup_header_reading(p_j2k);
+
+ /* read header */
+ if (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+ return OPJ_FALSE;
+ }
+
+ *p_image = opj_image_create0();
+ if (! (*p_image)) {
+ return OPJ_FALSE;
+ }
+
+ /* Copy codestream image information to the output image */
+ opj_copy_image_header(p_j2k->m_private_image, *p_image);
+
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures.
+ */
+void j2k_setup_header_reading (opj_j2k_v2_t *p_j2k)
+{
+ // preconditions
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_read_header_procedure);
+
+ /* DEVELOPER CORNER, add your custom procedures */
+ opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_copy_default_tcp_and_create_tcd);
+
+}
+
+/**
+ * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
+ * are valid. Developpers wanting to extend the library can add their own validation procedures.
+ */
+void j2k_setup_decoding_validation (opj_j2k_v2_t *p_j2k)
+{
+ // preconditions
+ assert(p_j2k != 00);
+
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_build_decoder);
+ opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_decoding_validation);
+ /* DEVELOPER CORNER, add your custom validation procedure */
+
+}
+
+/**
+ * Builds the cp decoder parameters 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
+ )
+{
+ // add here initialization of cp
+ // copy paste of setup_decoder
+ return OPJ_TRUE;
+}
+
+/**
+ * The default decoding validation procedure without any extension.
+ *
+ * @param p_j2k the jpeg2000 codec 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_decoding_validation (
+ opj_j2k_v2_t *p_j2k,
+ opj_stream_private_t *p_stream,
+ opj_event_mgr_t * p_manager
+ )
+{
+ opj_bool l_is_valid = OPJ_TRUE;
+
+ // preconditions
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+
+ /* STATE checking */
+ /* make sure the state is at 0 */
+#ifdef TODO_MSD
+ l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE);
+#endif
+ l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == 0x0000);
+
+ /* POINTER validation */
+ /* make sure a p_j2k codec is present */
+ /* make sure a procedure list is present */
+ l_is_valid &= (p_j2k->m_procedure_list != 00);
+ /* make sure a validation list is present */
+ l_is_valid &= (p_j2k->m_validation_list != 00);
+
+ /* PARAMETER VALIDATION */
+ return l_is_valid;
+}
+
+opj_bool j2k_read_header_procedure( opj_j2k_v2_t *p_j2k,
+ struct opj_stream_private *p_stream,
+ struct opj_event_mgr * p_manager)
+{
+ OPJ_UINT32 l_current_marker;
+ OPJ_UINT32 l_marker_size;
+ const opj_dec_memory_marker_handler_t * l_marker_handler = 00;
+
+ /* preconditions */
+ assert(p_stream != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ /* We enter in the main header */
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSOC;
+
+ /* Try to read the SOC marker, the codestream must begin with SOC marker */
+ if (! j2k_read_soc_v2(p_j2k,p_stream,p_manager)) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Expected a SOC marker \n");
+ return OPJ_FALSE;
+ }
+
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+ 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;
+ }
+
+ /* Read 2 bytes as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+
+ /* Try to read until the SOT is detected */
+ while (l_current_marker != J2K_MS_SOT) {
+
+ /* Check if the current marker ID is valid */
+ if (l_current_marker < 0xff00) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "We expected read a marker ID (0xff--) instead of %.8x\n", l_current_marker);
+ return OPJ_FALSE;
+ }
+
+ /* Get the marker handler from the marker ID */
+ l_marker_handler = j2k_get_marker_handler(l_current_marker);
+
+ /* Manage case where marker is unknown */
+ if (l_marker_handler->id == J2K_MS_UNK) {
+ if (! j2k_read_unk_v2(p_j2k, p_stream, &l_current_marker, p_manager)){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Unknow marker have been detected and generated error.\n");
+ return OPJ_FALSE;
+ }
+
+ if (l_current_marker == J2K_MS_SOT)
+ break; /* SOT marker is detected main header is completely read */
+ else /* Get the marker handler from the marker ID */
+ l_marker_handler = j2k_get_marker_handler(l_current_marker);
+ }
+
+ /* Check if the marker is known and if it is the right place to find it */
+ 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;
+ }
+
+ /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */
+ 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;
+ }
+
+ /* read 2 bytes as the marker size */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2);
+ l_marker_size -= 2; // Subtract the size of the marker ID already read
+
+ /* Check if the marker size is compatible with the 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) {
+ return OPJ_FALSE;
+ }
+ p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size;
+ }
+
+ /* Try to read the rest of the marker segment from stream and copy them into the buffer */
+ 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;
+ }
+
+ /* Read the marker segment with the correct marker handler */
+ 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 handler function failed to read the marker segment\n");
+ return OPJ_FALSE;
+ }
+
+ /* Add the marker to the codestream index*/
+ j2k_add_mhmarker_v2(p_j2k->cstr_index,
+ l_marker_handler->id,
+ (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4,
+ l_marker_size + 4 );
+
+ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+ 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;
+ }
+
+ /* read 2 bytes as the new marker ID */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2);
+ }
+
+ opj_event_msg_v2(p_manager, EVT_INFO, "Main header has been correctly decode.\n");
+
+ /* Position of the last element if the main header */
+ p_j2k->cstr_index->main_head_end = (OPJ_UINT32) opj_stream_tell(p_stream) - 2;
+
+ /* Next step: read a tile-part header */
+ p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
+
+ return OPJ_TRUE;
+}
+
+/**
+ * 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_manager the user manager.
+ *
+ * @return true if all the procedures were successfully executed.
+ */
+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 )
+{
+ opj_bool (** l_procedure) (opj_j2k_v2_t * ,opj_stream_private_t *,opj_event_mgr_t *) = 00;
+ opj_bool l_result = OPJ_TRUE;
+ OPJ_UINT32 l_nb_proc, i;
+
+ // preconditions
+ assert(p_procedure_list != 00);
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+
+ l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list);
+ l_procedure = (opj_bool (**) (opj_j2k_v2_t * ,opj_stream_private_t *,opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list);
+
+ for (i=0;i<l_nb_proc;++i) {
+ l_result = l_result && ((*l_procedure) (p_j2k,p_stream,p_manager));
+ ++l_procedure;
+ }
+
+ // and clear the procedure list at the end.
+ opj_procedure_list_clear(p_procedure_list);
+ return l_result;
+}
+
+/* FIXME DOC*/
+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
+ )
+{
+ opj_tcp_v2_t * l_tcp = 00;
+ opj_tcp_v2_t * l_default_tcp = 00;
+ OPJ_UINT32 l_nb_tiles;
+ OPJ_UINT32 i,j;
+ opj_tccp_t *l_current_tccp = 00;
+ OPJ_UINT32 l_tccp_size;
+ OPJ_UINT32 l_mct_size;
+ opj_image_t * l_image;
+ OPJ_UINT32 l_mcc_records_size,l_mct_records_size;
+ opj_mct_data_t * l_src_mct_rec, *l_dest_mct_rec;
+ opj_simple_mcc_decorrelation_data_t * l_src_mcc_rec, *l_dest_mcc_rec;
+ OPJ_UINT32 l_offset;
+
+ /* preconditions */
+ assert(p_j2k != 00);
+ assert(p_stream != 00);
+ assert(p_manager != 00);
+
+ l_image = p_j2k->m_private_image;
+ l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
+ l_tcp = p_j2k->m_cp.tcps;
+ l_tccp_size = l_image->numcomps * sizeof(opj_tccp_t);
+ l_default_tcp = p_j2k->m_specific_param.m_decoder.m_default_tcp;
+ l_mct_size = l_image->numcomps * l_image->numcomps * sizeof(OPJ_FLOAT32);
+
+ /* For each tile */
+ for (i=0; i<l_nb_tiles; ++i) {
+ /* keep the tile-compo coding parameters pointer of the current tile coding parameters*/
+ l_current_tccp = l_tcp->tccps;
+ /*Copy default coding parameters into the current tile coding parameters*/
+ memcpy(l_tcp, l_default_tcp, sizeof(opj_tcp_v2_t));
+ /* Initialize some values of the current tile coding parameters*/
+ l_tcp->ppt = 0;
+ l_tcp->ppt_data = 00;
+ /* Reconnect the tile-compo coding parameters pointer to the current tile coding parameters*/
+ l_tcp->tccps = l_current_tccp;
+
+ /* Get the mct_decoding_matrix of the dflt_tile_cp and copy them into the current tile cp*/
+ if (l_default_tcp->m_mct_decoding_matrix) {
+ l_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size);
+ if (! l_tcp->m_mct_decoding_matrix ) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_tcp->m_mct_decoding_matrix,l_default_tcp->m_mct_decoding_matrix,l_mct_size);
+ }
+
+ /* Get the mct_record of the dflt_tile_cp and copy them into the current tile cp*/
+ l_mct_records_size = l_default_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t);
+ l_tcp->m_mct_records = (opj_mct_data_t*)opj_malloc(l_mct_records_size);
+ if (! l_tcp->m_mct_records) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records,l_mct_records_size);
+
+ /* Copy the mct record data from dflt_tile_cp to the current tile*/
+ l_src_mct_rec = l_default_tcp->m_mct_records;
+ l_dest_mct_rec = l_tcp->m_mct_records;
+
+ for (j=0;j<l_default_tcp->m_nb_mct_records;++j) {
+
+ if (l_src_mct_rec->m_data) {
+
+ l_dest_mct_rec->m_data = (OPJ_BYTE*) opj_malloc(l_src_mct_rec->m_data_size);
+ if(! l_dest_mct_rec->m_data) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_dest_mct_rec->m_data,l_src_mct_rec->m_data,l_src_mct_rec->m_data_size);
+ }
+
+ ++l_src_mct_rec;
+ ++l_dest_mct_rec;
+ }
+
+ /* Get the mcc_record of the dflt_tile_cp and copy them into the current tile cp*/
+ l_mcc_records_size = l_default_tcp->m_nb_max_mcc_records * sizeof(opj_simple_mcc_decorrelation_data_t);
+ l_tcp->m_mcc_records = (opj_simple_mcc_decorrelation_data_t*) opj_malloc(l_mcc_records_size);
+ if (! l_tcp->m_mcc_records) {
+ return OPJ_FALSE;
+ }
+ memcpy(l_tcp->m_mcc_records,l_default_tcp->m_mcc_records,l_mcc_records_size);
+
+ /* Copy the mcc record data from dflt_tile_cp to the current tile*/
+ l_src_mcc_rec = l_default_tcp->m_mcc_records;
+ l_dest_mcc_rec = l_tcp->m_mcc_records;
+
+ for (j=0;j<l_default_tcp->m_nb_max_mcc_records;++j) {
+
+ if (l_src_mcc_rec->m_decorrelation_array) {
+ l_offset = l_src_mcc_rec->m_decorrelation_array - l_default_tcp->m_mct_records;
+ l_dest_mcc_rec->m_decorrelation_array = l_tcp->m_mct_records + l_offset;
+ }
+
+ if (l_src_mcc_rec->m_offset_array) {
+ l_offset = l_src_mcc_rec->m_offset_array - l_default_tcp->m_mct_records;
+ l_dest_mcc_rec->m_offset_array = l_tcp->m_mct_records + l_offset;
+ }
+
+ ++l_src_mcc_rec;
+ ++l_dest_mcc_rec;
+ }
+
+ /* Copy all the dflt_tile_compo_cp to the current tile cp */
+ memcpy(l_current_tccp,l_default_tcp->tccps,l_tccp_size);
+
+ /* Move to next tile cp*/
+ ++l_tcp;
+ }
+
+ /* Create the current tile decoder*/
+ p_j2k->m_tcd = (opj_tcd_v2_t*)tcd_create_v2(OPJ_TRUE); // FIXME why a cast ?
+ if (! p_j2k->m_tcd ) {
+ return OPJ_FALSE;
+ }
+
+ if ( !tcd_init_v2(p_j2k->m_tcd, l_image, &(p_j2k->m_cp)) ) {
+ tcd_destroy_v2(p_j2k->m_tcd);
+ p_j2k->m_tcd = 00;
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n");
+ return OPJ_FALSE;
+ }
+
+ return OPJ_TRUE;
+}
+
+/**
+ * Reads the lookup table containing all the marker, status and action, and returns the handler associated
+ * with the marker value.
+ * @param p_id Marker value to look up
+ *
+ * @return the handler associated with the id.
+*/
+const opj_dec_memory_marker_handler_t * j2k_get_marker_handler (OPJ_UINT32 p_id)
+{
+ const opj_dec_memory_marker_handler_t *e;
+ for (e = j2k_memory_marker_handler_tab; e->id != 0; ++e) {
+ if (e->id == p_id) {
+ break; // we find a handler corresponding to the marker ID
+ }
+ }
+ return e;
+}
+
+
+/**
+ * Destroys a jpeg2000 codec.
+ *
+ * @param p_j2k the jpeg20000 structure to destroy.
+ */
+void j2k_destroy (opj_j2k_v2_t *p_j2k)
+{
+ if (p_j2k == 00) {
+ return;
+ }
+
+ if (p_j2k->m_is_decoder) {
+
+ if (p_j2k->m_specific_param.m_decoder.m_default_tcp != 00) {
+ j2k_tcp_destroy(p_j2k->m_specific_param.m_decoder.m_default_tcp);
+ opj_free(p_j2k->m_specific_param.m_decoder.m_default_tcp);
+ p_j2k->m_specific_param.m_decoder.m_default_tcp = 00;
+ }
+
+ if (p_j2k->m_specific_param.m_decoder.m_header_data != 00) {
+ opj_free(p_j2k->m_specific_param.m_decoder.m_header_data);
+ p_j2k->m_specific_param.m_decoder.m_header_data = 00;
+ p_j2k->m_specific_param.m_decoder.m_header_data_size = 0;
+ }
+ }
+ else {
+
+ if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) {
+ opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data);
+ p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 00;
+ }
+
+ if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) {
+ opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer);
+ p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 00;
+ p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 00;
+ }
+
+ if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+ opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data);
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data = 00;
+ p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+ }
+ }
+
+ tcd_destroy_v2(p_j2k->m_tcd);
+
+ j2k_cp_destroy(&(p_j2k->m_cp));
+ memset(&(p_j2k->m_cp),0,sizeof(opj_cp_v2_t));
+
+ opj_procedure_list_destroy(p_j2k->m_procedure_list);
+ p_j2k->m_procedure_list = 00;
+
+ opj_procedure_list_destroy(p_j2k->m_validation_list);
+ p_j2k->m_procedure_list = 00;
+
+ j2k_destroy_cstr_index(p_j2k->cstr_index);
+ p_j2k->cstr_index = NULL;
+
+ opj_image_destroy(p_j2k->m_private_image);
+ p_j2k->m_private_image = NULL;
+
+ opj_image_destroy(p_j2k->m_output_image);
+ p_j2k->m_output_image = NULL;
+
+ opj_free(p_j2k);
+}
+
+void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind)
+{
+ if (p_cstr_ind) {
+
+ if (p_cstr_ind->marker) {
+ opj_free(p_cstr_ind->marker);
+ p_cstr_ind->marker = NULL;
+ }
+
+ if (p_cstr_ind->tile_index) {
+ OPJ_UINT32 it_tile = 0;
+
+ for (it_tile=0; it_tile < p_cstr_ind->nb_of_tiles; it_tile++) {
+
+ if(p_cstr_ind->tile_index[it_tile].packet_index) {
+ opj_free(p_cstr_ind->tile_index[it_tile].packet_index);
+ p_cstr_ind->tile_index[it_tile].packet_index = NULL;
+ }
+
+ if(p_cstr_ind->tile_index[it_tile].tp_index){
+ opj_free(p_cstr_ind->tile_index[it_tile].tp_index);
+ p_cstr_ind->tile_index[it_tile].tp_index = NULL;
+ }
+
+ if(p_cstr_ind->tile_index[it_tile].marker){
+ opj_free(p_cstr_ind->tile_index[it_tile].marker);
+ p_cstr_ind->tile_index[it_tile].marker = NULL;
+
+ }
+ }
+
+ opj_free( p_cstr_ind->tile_index);
+ p_cstr_ind->tile_index = NULL;
+ }
+
+ opj_free(p_cstr_ind);
+ }
+}
+
+
+
+/**
+ * Destroys a tile coding parameter structure.
+ *
+ * @param p_tcp the tile coding parameter to destroy.
+ */
+void j2k_tcp_destroy (opj_tcp_v2_t *p_tcp)
+{
+ if (p_tcp == 00) {
+ return;
+ }
+
+ if (p_tcp->ppt_buffer != 00) {
+ opj_free(p_tcp->ppt_buffer);
+ p_tcp->ppt_buffer = 00;
+ }
+
+ if (p_tcp->tccps != 00) {
+ opj_free(p_tcp->tccps);
+ p_tcp->tccps = 00;
+ }
+
+ if (p_tcp->m_mct_coding_matrix != 00) {
+ opj_free(p_tcp->m_mct_coding_matrix);
+ p_tcp->m_mct_coding_matrix = 00;
+ }
+
+ if (p_tcp->m_mct_decoding_matrix != 00) {
+ opj_free(p_tcp->m_mct_decoding_matrix);
+ p_tcp->m_mct_decoding_matrix = 00;
+ }
+
+ if (p_tcp->m_mcc_records) {
+ opj_free(p_tcp->m_mcc_records);
+ p_tcp->m_mcc_records = 00;
+ p_tcp->m_nb_max_mcc_records = 0;
+ p_tcp->m_nb_mcc_records = 0;
+ }
+
+ if (p_tcp->m_mct_records) {
+ opj_mct_data_t * l_mct_data = p_tcp->m_mct_records;
+ OPJ_UINT32 i;
+
+ for (i=0;i<p_tcp->m_nb_mct_records;++i) {
+ if (l_mct_data->m_data) {
+ opj_free(l_mct_data->m_data);
+ l_mct_data->m_data = 00;
+ }
+
+ ++l_mct_data;
+ }
+
+ opj_free(p_tcp->m_mct_records);
+ p_tcp->m_mct_records = 00;
+ }
+
+ if (p_tcp->mct_norms != 00) {
+ opj_free(p_tcp->mct_norms);
+ p_tcp->mct_norms = 00;
+ }
+
+ j2k_tcp_data_destroy(p_tcp);
+
+}
+
+/**
+ * Destroys the data inside a tile coding parameter structure.
+ *
+ * @param p_tcp the tile coding parameter which contain data to destroy.
+ */
+void j2k_tcp_data_destroy (opj_tcp_v2_t *p_tcp)
+{
+ if (p_tcp->m_data) {
+ opj_free(p_tcp->m_data);
+ p_tcp->m_data = NULL;
+ p_tcp->m_data_size = 0;
+ }
+}
+
+/**
+ * Destroys a coding parameter structure.
+ *
+ * @param p_cp the coding parameter to destroy.
+ */
+void j2k_cp_destroy (opj_cp_v2_t *p_cp)
+{
+ OPJ_UINT32 l_nb_tiles;
+ opj_tcp_v2_t * l_current_tile = 00;
+ OPJ_UINT32 i;
+
+ if
+ (p_cp == 00)
+ {
+ return;
+ }
+ if
+ (p_cp->tcps != 00)
+ {
+ l_current_tile = p_cp->tcps;
+ l_nb_tiles = p_cp->th * p_cp->tw;
+
+ for
+ (i = 0; i < l_nb_tiles; ++i)
+ {
+ j2k_tcp_destroy(l_current_tile);
+ ++l_current_tile;
+ }
+ opj_free(p_cp->tcps);
+ p_cp->tcps = 00;
+ }
+ if
+ (p_cp->ppm_buffer != 00)
+ {
+ opj_free(p_cp->ppm_buffer);
+ p_cp->ppm_buffer = 00;
+ }
+ if
+ (p_cp->comment != 00)
+ {
+ opj_free(p_cp->comment);
+ p_cp->comment = 00;
+ }
+ if
+ (! p_cp->m_is_decoder)
+ {
+ if
+ (p_cp->m_specific_param.m_enc.m_matrice)
+ {
+ opj_free(p_cp->m_specific_param.m_enc.m_matrice);
+ p_cp->m_specific_param.m_enc.m_matrice = 00;
+ }
+ }
+}
+
+
+
+/**
+ * Reads a tile header.
+ * @param p_j2k the jpeg2000 codec.
+ * @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_UINT32 l_current_marker = J2K_MS_SOT;
+ OPJ_UINT32 l_marker_size;
+ const opj_dec_memory_marker_handler_t * l_marker_handler = 00;
+ opj_tcp_v2_t * l_tcp = NULL;
+ OPJ_UINT32 l_nb_tiles;
+
+ /* preconditions */
+ assert(p_stream != 00);
+ assert(p_j2k != 00);
+ assert(p_manager != 00);
+
+ /* Reach the End Of Codestream ?*/
+ if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC){
+ l_current_marker = J2K_MS_EOC;
+ }
+ /* We need to encounter a SOT marker (a new tile-part header) */
+ else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT){
+ return OPJ_FALSE;
+ }
+
+ /* Read into the codestream until reach the EOC or ! can_decode ??? FIXME */
+ while ( (!p_j2k->m_specific_param.m_decoder.m_can_decode) && (l_current_marker != J2K_MS_EOC) ) {
+
+ /* Try to read until the Start Of Data is detected */
+ while (l_current_marker != J2K_MS_SOD) {
+
+ /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */
+ 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;
+ }
+
+ /* Read 2 bytes from the buffer as the marker size */
+ opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2);
+
+ /* Why this condition? FIXME */
+ if (p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH){
+ p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2);
+ }
+ l_marker_size -= 2; /* Subtract the size of the marker ID already read */
+
+ /* Get the marker handler from the marker ID */
+ l_marker_handler = j2k_get_marker_handler(l_current_marker);
+
+ /* Check if the marker is known and if it is the right place to find it */
+ 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;
+ }
+/* FIXME manage case of unknown marker as in the main header ? */
+
+ /* Check if the marker size is compatible with the 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) {
+ return OPJ_FALSE;