From d44375aece5dea2af83ffb8c9de4ade2ad35c593 Mon Sep 17 00:00:00 2001 From: Mickael Savinaud Date: Mon, 19 Sep 2011 16:01:49 +0000 Subject: [PATCH] WIP: create a new framework to output file information --- CHANGES | 1 + applications/codec/index.c | 106 +++++++++++++++++++ applications/codec/index.h | 2 + applications/codec/j2k_dump.c | 67 ++++++++++-- libopenjpeg/image.c | 5 + libopenjpeg/j2k.c | 189 ++++++++++++++++++++++++++++------ libopenjpeg/j2k.h | 5 +- libopenjpeg/jp2.c | 6 +- libopenjpeg/jp2.h | 3 +- libopenjpeg/openjpeg.c | 189 ++++++++++++++++++++++------------ libopenjpeg/openjpeg.h | 144 ++++++++++++++++++++++++-- libopenjpeg/t2.c | 4 +- libopenjpeg/t2.h | 7 +- libopenjpeg/tcd.c | 8 +- libopenjpeg/tcd.h | 6 +- 15 files changed, 611 insertions(+), 131 deletions(-) diff --git a/CHANGES b/CHANGES index 581b63c1..01508eed 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ What's New for OpenJPEG + : added September 19, 2011 ++ [mickael] WIP: create a new framework to output file information + [mickael] WIP: remove a piece of code copy by the merge op at the wrong place + [mickael] WIP: begin to clean j2k_dump and some other small things + [mickael] WIP: enchance the new version with some bug fixes from v1 and from me diff --git a/applications/codec/index.c b/applications/codec/index.c index 3765819b..2879f47f 100644 --- a/applications/codec/index.c +++ b/applications/codec/index.c @@ -742,3 +742,109 @@ int write_index_file_v2(FILE* stream, opj_codestream_info_t *cstr_info) { return EXIT_SUCCESS; } + +/* ------------------------------------------------------------------------------------ */ + +/** +Dump the file info structure into a file +@param stream output stream +@param file_info informations read into the JPG2000 file +@return Returns 0 if successful, returns 1 otherwise +*/ +int dump_file_info(FILE* stream, opj_file_info_t *file_info) +{ + /* IMAGE HEADER */ + if ( file_info->file_info_flag & OPJ_IMG_INFO ) { + opj_image_header_t img_header = file_info->img_info; + int compno; + + fprintf(stream, "Image info {\n"); + fprintf(stream, "\t x0=%d, y0=%d\n",img_header.x0, img_header.y0); + fprintf(stream, "\t x1=%d, y1=%d\n",img_header.x1, img_header.y1); + fprintf(stream, "\t numcomps=%d\n", img_header.numcomps); + for (compno = 0; compno < img_header.numcomps; compno++) { + opj_image_comp_header_t comp = img_header.comps[compno]; + + fprintf(stream, "\t component %d {\n", compno); + fprintf(stream, "\t\t dx=%d, dy=%d\n", comp.dx, comp.dy); + fprintf(stream, "\t\t prec=%d\n", comp.prec); + fprintf(stream, "\t\t sgnd=%d\n", comp.sgnd); + fprintf(stream, "\t}\n"); + } + fprintf(stream, "}\n"); + } + + /* CODESTREAM INFO */ + if ( file_info->file_info_flag & OPJ_J2K_INFO ) { + opj_codestream_info_v2_t cstr_info = file_info->codestream_info; + int tileno, compno, layno, bandno, resno, numbands; + + fprintf(stream, "Codestream info {\n"); + fprintf(stream, "\t tx0=%d, ty0=%d\n", cstr_info.tx0, cstr_info.ty0); + fprintf(stream, "\t tdx=%d, tdy=%d\n", cstr_info.tdx, cstr_info.tdy); + fprintf(stream, "\t tw=%d, th=%d\n", cstr_info.tw, cstr_info.th); + + for (tileno = 0; tileno < cstr_info.tw * cstr_info.th; tileno++) { + opj_tile_info_v2_t tile_info = cstr_info.tile[tileno]; + + fprintf(stream, "\t tile %d {\n", tileno); + fprintf(stream, "\t\t csty=%x\n", tile_info.csty); + fprintf(stream, "\t\t prg=%d\n", tile_info.prg); + fprintf(stream, "\t\t numlayers=%d\n", tile_info.numlayers); + fprintf(stream, "\t\t mct=%d\n", tile_info.mct); + fprintf(stream, "\t\t rates="); + + for (layno = 0; layno < tile_info.numlayers; layno++) { + fprintf(stream, "%.1f ", tile_info.rates[layno]); + } + fprintf(stream, "\n"); + + for (compno = 0; compno < cstr_info.numcomps; compno++) { + opj_tccp_info_t tccp_info = tile_info.tccp_info[compno]; + + fprintf(stream, "\t\t comp %d {\n", compno); + fprintf(stream, "\t\t\t csty=%x\n", tccp_info.csty); + fprintf(stream, "\t\t\t numresolutions=%d\n", tccp_info.numresolutions); + fprintf(stream, "\t\t\t cblkw=%d\n", tccp_info.cblkw); + fprintf(stream, "\t\t\t cblkh=%d\n", tccp_info.cblkh); + fprintf(stream, "\t\t\t cblksty=%x\n", tccp_info.cblksty); + fprintf(stream, "\t\t\t qmfbid=%d\n", tccp_info.qmfbid); + fprintf(stream, "\t\t\t qntsty=%d\n", tccp_info.qntsty); + fprintf(stream, "\t\t\t numgbits=%d\n", tccp_info.numgbits); + fprintf(stream, "\t\t\t roishift=%d\n", tccp_info.roishift); + +#ifdef TODO_MSD + fprintf(stream, "\t\t\t stepsizes="); + numbands = tccp_info->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp_info->numresolutions * 3 - 2; + for (bandno = 0; bandno < numbands; bandno++) { + fprintf(stream, "(%d,%d) ", tccp_info->stepsizes[bandno].mant, + tccp_info->stepsizes[bandno].expn); + } + fprintf(stream, "\n"); + + if (tccp_info->csty & J2K_CCP_CSTY_PRT) { + fprintf(stream, " prcw="); + for (resno = 0; resno < tccp_info->numresolutions; resno++) { + fprintf(stream, "%d ", tccp_info->prcw[resno]); + } + fprintf(stream, "\n"); + + fprintf(stream, " prch="); + for (resno = 0; resno < tccp_info->numresolutions; resno++) { + fprintf(stream, "%d ", tccp_info->prch[resno]); + } + fprintf(stream, "\n"); + } +#endif + fprintf(stream, "\t\t\t }\n"); + } /*end of component*/ + fprintf(stream, "\t\t }\n"); + } /*end of tile */ + fprintf(stream, "\t }\n"); + } + + if ( file_info->file_info_flag & OPJ_JP2_INFO ) { + // not yet coded + } + return EXIT_SUCCESS; +} diff --git a/applications/codec/index.h b/applications/codec/index.h index 29f673a1..aefce665 100644 --- a/applications/codec/index.h +++ b/applications/codec/index.h @@ -41,6 +41,8 @@ Write a structured index to a file */ int write_index_file(opj_codestream_info_t *cstr_info, char *index); +int dump_file_info(FILE* stream, opj_file_info_t *file_info); + #ifdef __cplusplus } #endif diff --git a/applications/codec/j2k_dump.c b/applications/codec/j2k_dump.c index 7f584400..d1c1fb69 100644 --- a/applications/codec/j2k_dump.c +++ b/applications/codec/j2k_dump.c @@ -201,7 +201,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i opj_option_t long_option[]={ {"ImgDir",REQ_ARG, NULL ,'y'}, }; - const char optlist[] = "i:o:h"; + const char optlist[] = "i:o:d:h"; totlen=sizeof(long_option); img_fol->set_out_format = 0; @@ -257,7 +257,19 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i break; /* ----------------------------------------------------- */ + case 'd': /* Input decode ROI */ + { + int size_optarg = (int)strlen(optarg) + 1; + char *ROI_values = (char*) malloc(size_optarg); + ROI_values[0] = '\0'; + strncpy(ROI_values, optarg, strlen(optarg)); + ROI_values[strlen(optarg)] = '\0'; + printf("ROI_values = %s [%d / %d]\n", ROI_values, strlen(ROI_values), size_optarg ); + parse_ROI_values( ROI_values, ¶meters->ROI_x0, ¶meters->ROI_y0, ¶meters->ROI_x1, ¶meters->ROI_y1); + } + break; + /* ----------------------------------------------------- */ default: fprintf(stderr,"WARNING -> this option is not valid \"-%c %s\"\n",c, opj_optarg); break; @@ -290,6 +302,34 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i return 0; } +/******************************************************************************* + * Parse ROI input values + * separator = "," + *******************************************************************************/ +int parse_ROI_values( char* inArg, unsigned int *ROI_x0, unsigned int *ROI_y0, unsigned int *ROI_x1, unsigned int *ROI_y1) +{ + int it = 0; + int values[4]; + char delims[] = ","; + char *result = NULL; + result = strtok( inArg, delims ); + + while( (result != NULL) && (it < 4 ) ) { + values[it] = atoi(result); + result = strtok( NULL, delims ); + it++; + } + + if (it != 4) { + return EXIT_FAILURE; + } + else{ + *ROI_x0 = values[0]; *ROI_y0 = values[1]; + *ROI_x1 = values[2]; *ROI_y1 = values[3]; + return EXIT_SUCCESS; + } +} + /* -------------------------------------------------------------------------- */ /** @@ -323,6 +363,7 @@ int main(int argc, char *argv[]) img_fol_t img_fol; opj_event_mgr_t event_mgr; /* event manager */ opj_image_header_t* image = NULL; + opj_file_info_t file_info; FILE *fsrc = NULL, *fout = NULL; int num_images; int i,imageno; @@ -394,7 +435,7 @@ int main(int argc, char *argv[]) /* Read the header of each image one by one */ for(imageno = 0; imageno < num_images ; imageno++){ - image = NULL; + fprintf(stderr,"\n"); if(img_fol.set_imgdir==1){ @@ -404,7 +445,6 @@ int main(int argc, char *argv[]) } } - /*NEW V2 STYLE*/ /* read the input file and put it in memory */ /* ---------------------------------------- */ fsrc = fopen(parameters.infile, "rb"); @@ -414,6 +454,10 @@ int main(int argc, char *argv[]) } cio = opj_stream_create_default_file_stream(fsrc,1); + if (!cio){ + fprintf(stderr, "ERROR -> failed to create the stream from the file\n"); + return EXIT_FAILURE; + } /* decode the code-stream */ /* ---------------------- */ @@ -449,7 +493,7 @@ int main(int argc, char *argv[]) /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder_v2(dinfo, ¶meters, &event_mgr); - if(! opj_read_header(cio, dinfo, &image, &cstr_info)){ + if(! opj_read_header(cio, dinfo, &file_info, OPJ_IMG_INFO | OPJ_J2K_INFO)){ fprintf(stderr, "ERROR -> j2k_dump: failed to read the header\n"); opj_stream_destroy(cio); fclose(fsrc); @@ -457,8 +501,14 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - /* Dump file informations from header */ + printf("Setting decoding area to %d,%d,%d,%d\n", + parameters.ROI_x0, parameters.ROI_y0, parameters.ROI_x1, parameters.ROI_x1); + opj_set_decode_area(dinfo, + parameters.ROI_x0, parameters.ROI_y0, + parameters.ROI_x1, parameters.ROI_x1); + /* Dump file informations from header */ + dump_file_info(fout, &file_info); /* close the byte stream */ opj_stream_destroy(cio); @@ -471,9 +521,10 @@ int main(int argc, char *argv[]) opj_image_header_destroy(image); + //FIXME opj_file_info_destroy(file_info); } -/*NEW V2 STYLE*/ + /* Close the output file */ fclose(fout); @@ -496,8 +547,8 @@ static void j2k_dump_image(FILE *fd, opj_image_header_t * img) { fprintf(fd, " sgnd=%d\n", comp->sgnd); fprintf(fd, " }\n"); } - fprintf(fd, " XTOsiz=%d, YTOsiz=%d, XTsiz=%d, YTsiz=%d\n", img->tile_x0, img->tile_y0, img->tile_width, img->tile_height); - fprintf(fd, " Nb of tiles in x direction=%d, Nb of tiles in y direction=%d\n", img->nb_tiles_x, img->nb_tiles_y); + //fprintf(fd, " XTOsiz=%d, YTOsiz=%d, XTsiz=%d, YTsiz=%d\n", img->tile_x0, img->tile_y0, img->tile_width, img->tile_height); + //fprintf(fd, " Nb of tiles in x direction=%d, Nb of tiles in y direction=%d\n", img->nb_tiles_x, img->nb_tiles_y); fprintf(fd, "}\n"); } diff --git a/libopenjpeg/image.c b/libopenjpeg/image.c index 0869b9af..9941b1d8 100644 --- a/libopenjpeg/image.c +++ b/libopenjpeg/image.c @@ -141,3 +141,8 @@ void opj_image_comp_header_update(opj_image_header_t * p_image_header, const opj } } +void opj_initialise_file_info(opj_file_info_t *file_info, OPJ_INT32 file_info_flag, OPJ_INT32 codec_format) { + + file_info->file_info_flag = file_info_flag; + file_info->file_format = codec_format; +} diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index f551c10c..9375b618 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -1476,23 +1476,34 @@ opj_bool j2k_read_siz_v2 ( /* Index */ if (p_j2k->cstr_info) { - //opj_codestream_info_t *cstr_info = p_j2k->cstr_info; + int it_tile = 0; + p_j2k->cstr_info->image_w = l_image->x1 - l_image->x0; p_j2k->cstr_info->image_h = l_image->y1 - l_image->y0; p_j2k->cstr_info->numcomps = l_image->numcomps; p_j2k->cstr_info->tw = l_cp->tw; p_j2k->cstr_info->th = l_cp->th; - p_j2k->cstr_info->tile_x = l_cp->tdx; - p_j2k->cstr_info->tile_y = l_cp->tdy; - p_j2k->cstr_info->tile_Ox = l_cp->tx0; - p_j2k->cstr_info->tile_Oy = l_cp->ty0; - p_j2k->cstr_info->tile = (opj_tile_info_t*) opj_calloc(l_nb_tiles, sizeof(opj_tile_info_t)); - if (p_j2k->cstr_info->tile == 00) { - opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); + p_j2k->cstr_info->tdx = l_cp->tdx; + p_j2k->cstr_info->tdy = l_cp->tdy; + p_j2k->cstr_info->tx0 = l_cp->tx0; + p_j2k->cstr_info->ty0 = l_cp->ty0; + + p_j2k->cstr_info->tile = (opj_tile_info_v2_t*) opj_calloc(l_nb_tiles, sizeof(opj_tile_info_v2_t)); + if (! p_j2k->cstr_info->tile) { + opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory [SIZ marker]\n"); return OPJ_FALSE; } - memset(p_j2k->cstr_info->tile,0,l_nb_tiles * sizeof(opj_tile_info_t)); + + for (it_tile = 0; it_tile < l_nb_tiles; it_tile++ ) { + p_j2k->cstr_info->tile[it_tile].tccp_info = + (opj_tccp_info_t*) opj_calloc( l_image->numcomps, sizeof(opj_tccp_info_t)); + if (! p_j2k->cstr_info->tile[it_tile].tccp_info) { + opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory [SIZ marker]\n"); + return OPJ_FALSE; + } + } } + return OPJ_TRUE; } @@ -1706,20 +1717,20 @@ opj_bool j2k_read_cod_v2 ( opj_tcp_v2_t *l_tcp = 00; opj_image_header_t *l_image = 00; - // preconditions + /* preconditions */ assert(p_header_data != 00); assert(p_j2k != 00); assert(p_manager != 00); l_image = p_j2k->m_image_header; l_cp = &(p_j2k->m_cp); - // If we are in a tile-part header + + /* If we are in the first tile-part header of the current tile */ l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? /*FIXME J2K_DEC_STATE_TPH)*/ &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; - - // Make sure room is sufficient + /* Make sure room is sufficient */ if (p_header_size < 5) { opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading COD marker\n"); return OPJ_FALSE; @@ -3505,7 +3516,7 @@ opj_bool j2k_read_sod_v2 ( ) { OPJ_UINT32 l_current_read_size; - opj_codestream_info_t * l_cstr_info = 00; + opj_codestream_info_v2_t * l_cstr_info = 00; OPJ_BYTE ** l_current_data = 00; opj_tcp_v2_t * l_tcp = 00; OPJ_UINT32 * l_tile_len = 00; @@ -4894,17 +4905,14 @@ opj_bool j2k_end_decompress( */ opj_bool j2k_read_header( struct opj_stream_private *p_stream, opj_j2k_v2_t* p_j2k, - struct opj_image_header** image_header, - struct opj_codestream_info** cstr_info, + opj_file_info_t* p_file_info, struct opj_event_mgr* p_manager ) { - // preconditions + /* preconditions */ assert(p_j2k != 00); assert(p_stream != 00); assert(p_manager != 00); - //p_image_header = NULL; - /* create an empty image header */ p_j2k->m_image_header = opj_image_header_create0(); if (! p_j2k->m_image_header) { @@ -4931,19 +4939,121 @@ opj_bool j2k_read_header( struct opj_stream_private *p_stream, return OPJ_FALSE; } - *cstr_info = p_j2k->cstr_info; + /* If necessary copy j2k header information into the output structure */ + if (p_file_info->file_info_flag & OPJ_J2K_INFO){ + fill_cstr_info( &(p_file_info->codestream_info), p_j2k, p_manager); + } - *image_header = p_j2k->m_image_header; - (*image_header)->tile_x0 = p_j2k->m_cp.tx0; - (*image_header)->tile_y0 = p_j2k->m_cp.ty0; - (*image_header)->tile_width = p_j2k->m_cp.tdx; - (*image_header)->tile_height = p_j2k->m_cp.tdy; - (*image_header)->nb_tiles_x = p_j2k->m_cp.tw; - (*image_header)->nb_tiles_y = p_j2k->m_cp.th; + /* If necessary copy image header information into the output structure */ + if (p_file_info->file_info_flag & OPJ_IMG_INFO){ + fill_img_info( &(p_file_info->img_info), p_j2k, p_manager); + } return OPJ_TRUE; } +/** + * Fill the image info struct from information read from main header. + */ +opj_bool fill_img_info(opj_image_header_t* img_info, opj_j2k_v2_t* p_j2k, struct opj_event_mgr* p_manager) +{ + opj_image_header_t* l_image_header = p_j2k->m_image_header; + + img_info->x0 = l_image_header->x0; + img_info->y0 = l_image_header->y0; + img_info->x1 = l_image_header->x1; + img_info->y1 = l_image_header->y1; + img_info->numcomps = l_image_header->numcomps; + + if (img_info->numcomps) { + img_info->comps = (opj_image_comp_header_t*)opj_malloc(img_info->numcomps * sizeof(opj_image_comp_header_t)); + if (!img_info->comps){ + opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory\n"); + return OPJ_FALSE; + } + + memcpy(img_info->comps, l_image_header->comps, img_info->numcomps * sizeof(opj_image_comp_header_t) ); + } + + + img_info->icc_profile_len = l_image_header->icc_profile_len; + if (img_info->icc_profile_len) { + img_info->icc_profile_buf = (unsigned char*)opj_malloc(img_info->icc_profile_len * sizeof(unsigned char)); + if (!img_info->icc_profile_buf){ + opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory\n"); + return OPJ_FALSE; + } + + memcpy(img_info->icc_profile_buf, l_image_header->icc_profile_buf, img_info->icc_profile_len); + } + + return OPJ_TRUE; +} + +/** + * Fill the codestream info struct from information read from main header. + */ +opj_bool fill_cstr_info(opj_codestream_info_v2_t* cstr_info, opj_j2k_v2_t* p_j2k, struct opj_event_mgr* p_manager) +{ + + //opj_cp_v2_t l_cp = p_j2k->m_cp; + opj_image_header_t* l_image_header = p_j2k->m_image_header; + int it_tile, it_comp; + int nb_tiles, nb_comps; + + cstr_info->image_w = l_image_header->x1 - l_image_header->x0; + cstr_info->image_h = l_image_header->y1 - l_image_header->y0; + cstr_info->numcomps = l_image_header->numcomps; + cstr_info->tw = p_j2k->m_cp.tw; + cstr_info->th = p_j2k->m_cp.th; + cstr_info->tdx = p_j2k->m_cp.tdx; + cstr_info->tdy = p_j2k->m_cp.tdy; + cstr_info->tx0 = p_j2k->m_cp.tx0; + cstr_info->ty0 = p_j2k->m_cp.ty0; + + nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + nb_comps = l_image_header->numcomps; + + cstr_info->tile = (opj_tile_info_v2_t*) opj_calloc(nb_tiles, sizeof(opj_tile_info_v2_t)); + if (! p_j2k->cstr_info->tile) { + opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory\n"); + return OPJ_FALSE; + } + + for (it_tile=0; it_tile < nb_tiles; it_tile++){ + cstr_info->tile[it_tile].tileno = it_tile; + cstr_info->tile[it_tile].csty = p_j2k->m_cp.tcps[it_tile].csty; + cstr_info->tile[it_tile].prg = p_j2k->m_cp.tcps[it_tile].prg; + cstr_info->tile[it_tile].mct = p_j2k->m_cp.tcps[it_tile].mct; + cstr_info->tile[it_tile].numlayers = p_j2k->m_cp.tcps[it_tile].numlayers; + // FIXME Number of tile part l_cstr_info->tile[it_tile].num_tps = ; + + cstr_info->tile[it_tile].tccp_info = + (opj_tccp_info_t*) opj_calloc(nb_comps, sizeof(opj_tccp_info_t)); + if (! p_j2k->cstr_info->tile[it_tile].tccp_info) { + opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory\n"); + return OPJ_FALSE; + } + + for (it_comp=0; it_comp < nb_comps; it_comp++){ + cstr_info->tile[it_tile].tccp_info[it_comp].compno = it_comp; + cstr_info->tile[it_tile].tccp_info[it_comp].cblkh = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].cblkh; + cstr_info->tile[it_tile].tccp_info[it_comp].cblkw = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].cblkw; + cstr_info->tile[it_tile].tccp_info[it_comp].cblksty = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].cblksty; + cstr_info->tile[it_tile].tccp_info[it_comp].csty = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].csty; + cstr_info->tile[it_tile].tccp_info[it_comp].numgbits = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].numgbits; + cstr_info->tile[it_tile].tccp_info[it_comp].numresolutions = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].numresolutions; + cstr_info->tile[it_tile].tccp_info[it_comp].qmfbid = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].qmfbid; + cstr_info->tile[it_tile].tccp_info[it_comp].qntsty = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].qntsty; + cstr_info->tile[it_tile].tccp_info[it_comp].roishift = p_j2k->m_cp.tcps[it_tile].tccps[it_comp].roishift; + } + } + + return OPJ_TRUE; +} + + + /** * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures. */ @@ -5891,7 +6001,7 @@ opj_j2k_v2_t* j2k_create_decompress_v2() l_j2k->m_specific_param.m_decoder.m_header_data_size = J2K_DEFAULT_HEADER_SIZE; // codestream info creation - l_j2k->cstr_info = (opj_codestream_info_t*) opj_malloc(sizeof(opj_codestream_info_t)); + l_j2k->cstr_info = (opj_codestream_info_v2_t*) opj_malloc(sizeof(opj_codestream_info_v2_t)); if (!l_j2k->cstr_info){ opj_free(l_j2k); return NULL; @@ -5936,7 +6046,7 @@ opj_bool j2k_read_SPCod_SPCoc( opj_tccp_t *l_tccp = NULL; OPJ_BYTE * l_current_ptr = NULL; - // preconditions + /* preconditions */ assert(p_j2k != 00); assert(p_manager != 00); assert(p_header_data != 00); @@ -5946,22 +6056,23 @@ opj_bool j2k_read_SPCod_SPCoc( &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; - // precondition again + /* precondition again */ assert(compno < p_j2k->m_image_header->numcomps); l_tccp = &l_tcp->tccps[compno]; l_current_ptr = p_header_data; - // make sure room is sufficient + /* make sure room is sufficient */ if (*p_header_size < 5) { opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); return OPJ_FALSE; } + opj_read_bytes(l_current_ptr, &l_tccp->numresolutions ,1); /* SPcox (D) */ ++l_tccp->numresolutions; /* tccp->numresolutions = read() + 1 */ ++l_current_ptr; - // If user wants to remove more resolutions than the codestream contains, return error + /* If user wants to remove more resolutions than the codestream contains, return error */ if (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) { opj_event_msg_v2(p_manager, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number " "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); @@ -5985,18 +6096,20 @@ opj_bool j2k_read_SPCod_SPCoc( *p_header_size = *p_header_size - 5; - // use custom precinct size ? + /* use custom precinct size ? */ if (l_tccp->csty & J2K_CCP_CSTY_PRT) { if (*p_header_size < l_tccp->numresolutions) { opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); return OPJ_FALSE; } + for (i = 0; i < l_tccp->numresolutions; ++i) { opj_read_bytes(l_current_ptr,&l_tmp ,1); /* SPcoc (I_i) */ ++l_current_ptr; l_tccp->prcw[i] = l_tmp & 0xf; l_tccp->prch[i] = l_tmp >> 4; } + *p_header_size = *p_header_size - l_tccp->numresolutions; } else { @@ -6010,6 +6123,14 @@ opj_bool j2k_read_SPCod_SPCoc( /* INDEX >> */ if (p_j2k->cstr_info && compno == 0) { OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32); + + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkh = l_tccp->cblkh; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkw = l_tccp->cblkw; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].numresolutions = l_tccp->numresolutions; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblksty = l_tccp->cblksty; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].qmfbid = l_tccp->qmfbid; + + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdx,l_tccp->prcw, l_data_size); memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdy,l_tccp->prch, l_data_size); } @@ -6031,7 +6152,7 @@ void j2k_copy_tile_component_parameters( opj_j2k_v2_t *p_j2k ) opj_tccp_t *l_ref_tccp = NULL, *l_copied_tccp = NULL; OPJ_UINT32 l_prc_size; - // preconditions + /* preconditions */ assert(p_j2k != 00); l_cp = &(p_j2k->m_cp); diff --git a/libopenjpeg/j2k.h b/libopenjpeg/j2k.h index 0835e09a..e2d8429b 100644 --- a/libopenjpeg/j2k.h +++ b/libopenjpeg/j2k.h @@ -767,7 +767,7 @@ typedef struct opj_j2k_v2 struct opj_procedure_list * m_validation_list; /** helper used to write the index file */ - opj_codestream_info_t *cstr_info; + opj_codestream_info_v2_t *cstr_info; /** the current tile coder/decoder **/ struct opj_tcd_v2 * m_tcd; @@ -884,8 +884,7 @@ opj_bool j2k_end_decompress(opj_j2k_v2_t *j2k, struct opj_stream_private *cio, s */ opj_bool j2k_read_header( struct opj_stream_private *p_stream, opj_j2k_v2_t* p_j2k, - struct opj_image_header** image_header, - struct opj_codestream_info** cstr_info, + opj_file_info_t * p_file_info, struct opj_event_mgr* p_manager ); diff --git a/libopenjpeg/jp2.c b/libopenjpeg/jp2.c index 14e8c585..efbf8d10 100644 --- a/libopenjpeg/jp2.c +++ b/libopenjpeg/jp2.c @@ -2389,8 +2389,7 @@ static opj_bool jp2_read_boxhdr_char( */ opj_bool jp2_read_header( struct opj_stream_private *p_stream, opj_jp2_v2_t *jp2, - opj_image_header_t ** p_image_header, - struct opj_codestream_info** p_cstr_info, + opj_file_info_t * p_file_info, struct opj_event_mgr * p_manager ) { @@ -2417,8 +2416,7 @@ opj_bool jp2_read_header( struct opj_stream_private *p_stream, return j2k_read_header( p_stream, jp2->j2k, - p_image_header, - p_cstr_info, + p_file_info, p_manager); } diff --git a/libopenjpeg/jp2.h b/libopenjpeg/jp2.h index b0a60086..0203fd12 100644 --- a/libopenjpeg/jp2.h +++ b/libopenjpeg/jp2.h @@ -334,8 +334,7 @@ opj_bool jp2_end_decompress(opj_jp2_v2_t *jp2, struct opj_stream_private *cio, s */ opj_bool jp2_read_header( struct opj_stream_private *p_stream, opj_jp2_v2_t *jp2, - opj_image_header_t ** p_image_header, - struct opj_codestream_info** p_cstr_info, + opj_file_info_t * p_file_info, struct opj_event_mgr * p_manager ); diff --git a/libopenjpeg/openjpeg.c b/libopenjpeg/openjpeg.c index 707a2066..5b99d4d1 100644 --- a/libopenjpeg/openjpeg.c +++ b/libopenjpeg/openjpeg.c @@ -33,32 +33,44 @@ typedef struct opj_decompression { - opj_bool (* opj_read_header) ( - struct opj_stream_private * cio, - void * p_codec, - opj_image_header_t ** image_header, - opj_codestream_info_t ** cstr_info, - struct opj_event_mgr * p_manager); - opj_image_t* (* opj_decode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager); - opj_bool (*opj_read_tile_header)( - void * p_codec, - OPJ_UINT32 * p_tile_index, - OPJ_UINT32* p_data_size, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_INT32 * p_tile_x1, - OPJ_INT32 * p_tile_y1, - OPJ_UINT32 * p_nb_comps, - opj_bool * p_should_go_on, - struct opj_stream_private *p_cio, - struct opj_event_mgr * p_manager); - opj_bool (*opj_decode_tile_data)(void * p_codec,OPJ_UINT32 p_tile_index,OPJ_BYTE * p_data,OPJ_UINT32 p_data_size,struct opj_stream_private *p_cio,struct opj_event_mgr * p_manager); - opj_bool (* opj_end_decompress) (void *p_codec,struct opj_stream_private *cio,struct opj_event_mgr * p_manager); + opj_bool (* opj_read_header) ( struct opj_stream_private * cio, + void * p_codec, + opj_file_info_t * file_info, + struct opj_event_mgr * p_manager); + + opj_image_t* (* opj_decode) ( void * p_codec, + struct opj_stream_private *p_cio, + struct opj_event_mgr * p_manager); + + opj_bool (*opj_read_tile_header)( void * p_codec, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32* p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + opj_bool * p_should_go_on, + struct opj_stream_private *p_cio, + struct opj_event_mgr * p_manager); + + opj_bool (*opj_decode_tile_data)( void * p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private *p_cio, + struct opj_event_mgr * p_manager); + + opj_bool (* opj_end_decompress) ( void *p_codec, + struct opj_stream_private *cio, + struct opj_event_mgr * p_manager); + void (* opj_destroy) (void * p_codec); + void (*opj_setup_decoder) (void * p_codec, opj_dparameters_t * p_param); - opj_bool (*opj_set_decode_area) (void * p_codec,OPJ_INT32 p_start_x,OPJ_INT32 p_end_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_y,struct opj_event_mgr * p_manager); - + opj_bool (*opj_set_decode_area) ( void * p_codec, + OPJ_INT32 p_start_x, OPJ_INT32 p_end_x, + OPJ_INT32 p_start_y, OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager); }opj_decompression_t; typedef struct opj_compression @@ -74,10 +86,10 @@ typedef struct opj_compression typedef struct opj_codec_private { - union - { /* code-blocks informations */ - opj_decompression_t m_decompression; - opj_compression_t m_compression; + /* code-blocks informations */ + union { + opj_decompression_t m_decompression; + opj_compression_t m_compression; } m_codec_data; void * m_codec; opj_event_mgr_t* m_event_mgr; @@ -118,21 +130,19 @@ OPJ_UINT32 opj_write_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p OPJ_SIZE_T opj_skip_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data) { - if - (fseek(p_user_data,p_nb_bytes,SEEK_CUR)) - { + if (fseek(p_user_data,p_nb_bytes,SEEK_CUR)) { return -1; } + return p_nb_bytes; } opj_bool opj_seek_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data) { - if - (fseek(p_user_data,p_nb_bytes,SEEK_SET)) - { + if (fseek(p_user_data,p_nb_bytes,SEEK_SET)) { return EXIT_FAILURE; } + return EXIT_SUCCESS; } @@ -214,30 +224,39 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT p_format) switch (p_format) { case CODEC_J2K: - l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))j2k_decode; // TODO MSD - l_info->m_codec_data.m_decompression.opj_end_decompress = (opj_bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *))j2k_end_decompress; - l_info->m_codec_data.m_decompression.opj_read_header = (opj_bool (*) ( - struct opj_stream_private *, - void *, - opj_image_header_t **, - opj_codestream_info_t**, - struct opj_event_mgr * )) j2k_read_header; + l_info->m_codec_data.m_decompression.opj_decode = + (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))j2k_decode; // TODO MSD + + l_info->m_codec_data.m_decompression.opj_end_decompress = + (opj_bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr *))j2k_end_decompress; + + l_info->m_codec_data.m_decompression.opj_read_header = + (opj_bool (*) ( struct opj_stream_private *, + void *, + opj_file_info_t *, + struct opj_event_mgr * )) j2k_read_header; + l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))j2k_destroy; - l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) j2k_setup_decoder_v2; - l_info->m_codec_data.m_decompression.opj_read_tile_header = (opj_bool (*) ( - void *, - OPJ_UINT32*, - OPJ_UINT32*, - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_UINT32 * , - opj_bool *, - struct opj_stream_private *, - struct opj_event_mgr * )) j2k_read_tile_header; - l_info->m_codec_data.m_decompression.opj_decode_tile_data = (opj_bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) j2k_decode_tile; - l_info->m_codec_data.m_decompression.opj_set_decode_area = (opj_bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) j2k_set_decode_area; + + l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * , opj_dparameters_t * )) j2k_setup_decoder_v2; + + l_info->m_codec_data.m_decompression.opj_read_tile_header = + (opj_bool (*) ( void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32*, OPJ_INT32*, + OPJ_INT32*, OPJ_INT32*, + OPJ_UINT32*, + opj_bool*, + struct opj_stream_private *, + struct opj_event_mgr * )) j2k_read_tile_header; + + l_info->m_codec_data.m_decompression.opj_decode_tile_data = + (opj_bool (*) (void *, OPJ_UINT32, OPJ_BYTE*, OPJ_UINT32, struct opj_stream_private *, struct opj_event_mgr *)) j2k_decode_tile; + + l_info->m_codec_data.m_decompression.opj_set_decode_area = + (opj_bool (*) (void *, OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, struct opj_event_mgr *)) j2k_set_decode_area; + l_info->m_codec = j2k_create_decompress_v2(); if (! l_info->m_codec) { @@ -250,16 +269,16 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT p_format) case CODEC_JP2: /* get a JP2 decoder handle */ l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))opj_jp2_decode; // TODO MSD + l_info->m_codec_data.m_decompression.opj_end_decompress = (opj_bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *)) jp2_end_decompress; + l_info->m_codec_data.m_decompression.opj_read_header = (opj_bool (*) ( struct opj_stream_private *, void *, - opj_image_header_t **, - opj_codestream_info_t**, + opj_file_info_t *, struct opj_event_mgr * )) jp2_read_header; - l_info->m_codec_data.m_decompression.opj_read_tile_header = ( - opj_bool (*) ( + l_info->m_codec_data.m_decompression.opj_read_tile_header = ( opj_bool (*) ( void *, OPJ_UINT32*, OPJ_UINT32*, @@ -275,7 +294,9 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT p_format) l_info->m_codec_data.m_decompression.opj_decode_tile_data = (opj_bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) opj_jp2_decode_tile; l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))jp2_destroy; + l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) jp2_setup_decoder_v2; + l_info->m_codec_data.m_decompression.opj_set_decode_area = (opj_bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) jp2_set_decode_area; l_info->m_codec = jp2_create(OPJ_TRUE); @@ -473,7 +494,7 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *paramete parameters->cod_format = -1; parameters->tcp_rates[0] = 0; parameters->tcp_numlayers = 0; - parameters->cp_disto_alloc = 0; + parameters->cp_disto_alloc = 0; parameters->cp_fixed_alloc = 0; parameters->cp_fixed_quality = 0; parameters->jpip_on = OPJ_FALSE; @@ -602,6 +623,8 @@ void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) { } } + + #ifdef OLD_WAY_MS opj_bool OPJ_CALLCONV opj_read_header ( opj_codec_t *p_codec, @@ -640,10 +663,13 @@ opj_bool OPJ_CALLCONV opj_read_header ( opj_bool OPJ_CALLCONV opj_read_header ( opj_stream_t *p_cio, opj_codec_t *p_codec, - opj_image_header_t **p_image_header, - opj_codestream_info_t **p_cstr_info ) + opj_file_info_t* p_file_info, + OPJ_INT32 file_info_flag) { + /* Initialize the output structure */ + opj_initialise_file_info(p_file_info, file_info_flag, CODEC_J2K); + if (p_codec && p_cio) { opj_codec_private_t* l_info = (opj_codec_private_t*) p_codec; opj_stream_private_t* l_cio = (opj_stream_private_t*) p_cio; @@ -655,8 +681,7 @@ opj_bool OPJ_CALLCONV opj_read_header ( opj_stream_t *p_cio, return l_info->m_codec_data.m_decompression.opj_read_header( l_cio, l_info->m_codec, - p_image_header, - p_cstr_info, + p_file_info, l_info->m_event_mgr); } return OPJ_FALSE; @@ -682,3 +707,37 @@ void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_info) opj_free(l_info); } } + +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_codec the jpeg2000 codec. + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * + * @return true if the area could be set. + */ +opj_bool OPJ_CALLCONV opj_set_decode_area( opj_codec_t *p_codec, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y + ) +{ + if (p_codec) { + opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; + if (! l_info->is_decompressor) { + return OPJ_FALSE; + } + + return l_info->m_codec_data.m_decompression.opj_set_decode_area( + l_info->m_codec, + p_start_x, + p_start_y, + p_end_x, + p_end_y, + &(l_info->m_event_mgr)); + + } + return OPJ_FALSE; +} diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h index a94f3a47..94fbdfa5 100644 --- a/libopenjpeg/openjpeg.h +++ b/libopenjpeg/openjpeg.h @@ -105,6 +105,15 @@ typedef float OPJ_FLOAT32; #define JPWL_MAXIMUM_EPB_ROOM 65450 /**< Expect this maximum number of bytes for composition of EPBs */ /* <> */ if(p_cstr_info) { - opj_tile_info_t *info_TL = &p_cstr_info->tile[p_tile_no]; + opj_tile_info_v2_t *info_TL = &p_cstr_info->tile[p_tile_no]; opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno]; if (!p_cstr_info->packno) { info_PK->start_pos = info_TL->end_header + 1; diff --git a/libopenjpeg/t2.h b/libopenjpeg/t2.h index b130746f..55cac98f 100644 --- a/libopenjpeg/t2.h +++ b/libopenjpeg/t2.h @@ -104,7 +104,12 @@ Decode the packets of a tile from a source buffer @param tileno number that identifies the tile for which to decode the packets @param tile tile for which to decode the packets */ -opj_bool t2_decode_packets_v2(opj_t2_v2_t *t2, OPJ_UINT32 tileno,struct opj_tcd_tile *tile, OPJ_BYTE *src, OPJ_UINT32 * p_data_read, OPJ_UINT32 len, struct opj_codestream_info *cstr_info); +opj_bool t2_decode_packets_v2( opj_t2_v2_t *t2, + OPJ_UINT32 tileno, + struct opj_tcd_tile *tile, + OPJ_BYTE *src, OPJ_UINT32 * p_data_read, + OPJ_UINT32 len, + struct opj_codestream_info_v2 *cstr_info); /** * Creates a Tier 2 handle diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index 1eeba002..9d8dc782 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -107,7 +107,7 @@ opj_bool tcd_t2_decode ( OPJ_BYTE * p_src_data, OPJ_UINT32 * p_data_read, OPJ_UINT32 p_max_src_size, - opj_codestream_info_t *p_cstr_info + opj_codestream_info_v2_t *p_cstr_info ); opj_bool tcd_t1_decode ( @@ -2046,7 +2046,7 @@ opj_bool tcd_decode_tile_v2( OPJ_BYTE *p_src, OPJ_UINT32 p_max_length, OPJ_UINT32 p_tile_no, - opj_codestream_info_t *p_cstr_info) + opj_codestream_info_v2_t *p_cstr_info) { OPJ_UINT32 l_data_read; p_tcd->tcd_tileno = p_tile_no; @@ -2077,7 +2077,7 @@ opj_bool tcd_decode_tile_v2( // FIXME _ProfStart(PGROUP_T2); l_data_read = 0; if - (! tcd_t2_decode(p_tcd,p_src,&l_data_read,p_max_length,p_cstr_info)) + (! tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_info)) { return OPJ_FALSE; } @@ -2396,7 +2396,7 @@ opj_bool tcd_t2_decode ( OPJ_BYTE * p_src_data, OPJ_UINT32 * p_data_read, OPJ_UINT32 p_max_src_size, - opj_codestream_info_t *p_cstr_info + opj_codestream_info_v2_t *p_cstr_info ) { opj_t2_v2_t * l_t2; diff --git a/libopenjpeg/tcd.h b/libopenjpeg/tcd.h index 09c184ac..c3c416c6 100644 --- a/libopenjpeg/tcd.h +++ b/libopenjpeg/tcd.h @@ -436,7 +436,11 @@ Decode a tile from a buffer into a raw image @param len Length of source buffer @param tileno Number that identifies one of the tiles to be decoded */ -opj_bool tcd_decode_tile_v2(opj_tcd_v2_t *tcd, OPJ_BYTE *src, OPJ_UINT32 len, OPJ_UINT32 tileno, struct opj_codestream_info *cstr_info); +opj_bool tcd_decode_tile_v2(opj_tcd_v2_t *tcd, + OPJ_BYTE *src, + OPJ_UINT32 len, + OPJ_UINT32 tileno, + struct opj_codestream_info_v2 *cstr_info); /**