From 7e2b6bebff12eab8bdc17fc9af017e8c11652f4f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 19 Sep 2017 16:52:07 +0200 Subject: Add capability to decode only a subset of all components of an image. This adds a opj_set_decoded_components(opj_codec_t *p_codec, OPJ_UINT32 numcomps, const OPJ_UINT32* comps_indices) function, and equivalent "opj_decompress -c compno[,compno]*" option. When specified, neither the MCT transform nor JP2 channel transformations will be applied. Tests added for various combinations of whole image vs tiled-based decoding, full or reduced resolution, use of decode area or not. --- src/bin/jp2/opj_decompress.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'src/bin') diff --git a/src/bin/jp2/opj_decompress.c b/src/bin/jp2/opj_decompress.c index 479d8382..6c28277a 100644 --- a/src/bin/jp2/opj_decompress.c +++ b/src/bin/jp2/opj_decompress.c @@ -152,6 +152,10 @@ typedef struct opj_decompress_params { int num_threads; /* Quiet */ int quiet; + /** number of components to decode */ + OPJ_UINT32 numcomps; + /** indices of components to decode */ + OPJ_UINT32* comps_indices; } opj_decompress_parameters; /* -------------------------------------------------------------------------- */ @@ -227,6 +231,10 @@ static void decode_help_display(void) " If 'C' is specified (default), values are clipped.\n" " If 'S' is specified, values are scaled.\n" " A 0 value can be specified (meaning original bit depth).\n"); + fprintf(stdout, " -c first_comp_index[,second_comp_index][,...]\n" + " OPTIONAL\n" + " To limit the number of components to decoded.\n" + " Component indices are numbered starting at 0.\n"); fprintf(stdout, " -force-rgb\n" " Force output image colorspace to RGB\n" " -upsample\n" @@ -560,7 +568,7 @@ int parse_cmdline_decoder(int argc, char **argv, {"quiet", NO_ARG, NULL, 1}, }; - const char optlist[] = "i:o:r:l:x:d:t:p:" + const char optlist[] = "i:o:r:l:x:d:t:p:c:" /* UniPG>> */ #ifdef USE_JPWL @@ -770,6 +778,25 @@ int parse_cmdline_decoder(int argc, char **argv, return 1; } } + break; + + /* ----------------------------------------------------- */ + case 'c': { /* Componenets */ + const char* iter = opj_optarg; + while (1) { + parameters->numcomps ++; + parameters->comps_indices = (OPJ_UINT32*) realloc( + parameters->comps_indices, + parameters->numcomps * sizeof(OPJ_UINT32)); + parameters->comps_indices[parameters->numcomps - 1] = + (OPJ_UINT32) atoi(iter); + iter = strchr(iter, ','); + if (iter == NULL) { + break; + } + iter ++; + } + } break; /* ----------------------------------------------------- */ @@ -1015,6 +1042,9 @@ static void destroy_parameters(opj_decompress_parameters* parameters) free(parameters->precision); parameters->precision = NULL; } + + free(parameters->comps_indices); + parameters->comps_indices = NULL; } } @@ -1455,6 +1485,20 @@ int main(int argc, char **argv) goto fin; } + if (parameters.numcomps) { + if (! opj_set_decoded_components(l_codec, + parameters.numcomps, + parameters.comps_indices)) { + fprintf(stderr, + "ERROR -> opj_decompress: failed to set the component indices!\n"); + opj_destroy_codec(l_codec); + opj_stream_destroy(l_stream); + opj_image_destroy(image); + failed = 1; + goto fin; + } + } + if (getenv("USE_OPJ_SET_DECODED_RESOLUTION_FACTOR") != NULL) { /* For debugging/testing purposes, and also an illustration on how to */ /* use the alternative API opj_set_decoded_resolution_factor() instead */ -- cgit v1.2.3 From e17bbde9066600528ab523adee69d9c9c33ba157 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Tue, 19 Sep 2017 17:48:07 +0200 Subject: opj_set_decoded_components(): add a provision for a apply_color_transforms parameter in case we support it in the future --- src/bin/jp2/opj_decompress.c | 3 ++- src/lib/openjp2/openjpeg.c | 11 ++++++++++- src/lib/openjp2/openjpeg.h | 16 ++++++++++++---- 3 files changed, 24 insertions(+), 6 deletions(-) (limited to 'src/bin') diff --git a/src/bin/jp2/opj_decompress.c b/src/bin/jp2/opj_decompress.c index 6c28277a..a963b86a 100644 --- a/src/bin/jp2/opj_decompress.c +++ b/src/bin/jp2/opj_decompress.c @@ -1488,7 +1488,8 @@ int main(int argc, char **argv) if (parameters.numcomps) { if (! opj_set_decoded_components(l_codec, parameters.numcomps, - parameters.comps_indices)) { + parameters.comps_indices, + OPJ_FALSE)) { fprintf(stderr, "ERROR -> opj_decompress: failed to set the component indices!\n"); opj_destroy_codec(l_codec); diff --git a/src/lib/openjp2/openjpeg.c b/src/lib/openjp2/openjpeg.c index 5ba205e1..7b123034 100644 --- a/src/lib/openjp2/openjpeg.c +++ b/src/lib/openjp2/openjpeg.c @@ -441,12 +441,21 @@ OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, OPJ_BOOL OPJ_CALLCONV opj_set_decoded_components(opj_codec_t *p_codec, OPJ_UINT32 numcomps, - const OPJ_UINT32* comps_indices) + const OPJ_UINT32* comps_indices, + OPJ_BOOL apply_color_transforms) { if (p_codec) { opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_set_decoded_components function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + if (apply_color_transforms) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "apply_color_transforms = OPJ_TRUE is not supported.\n"); return OPJ_FALSE; } diff --git a/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h index 2888e4d1..f36286eb 100644 --- a/src/lib/openjp2/openjpeg.h +++ b/src/lib/openjp2/openjpeg.h @@ -1341,9 +1341,12 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, * * This function should be called after opj_read_header(). * - * Normally all the components are decoded. This call enables to restrict - * the set of decoded components to the specified indices. - * Note that neither the MCT transform nor JP2 channel transformatios will be applied. + * This function enables to restrict the set of decoded components to the + * specified indices. + * Note that the current implementation (apply_color_transforms == OPJ_FALSE) + * is such that neither the multi-component transform at codestream level, + * nor JP2 channel transformations will be applied. + * Consequently the indices are relative to the codestream. * * Note: opj_decode_tile_data() should not be used together with opj_set_decoded_components(). * @@ -1352,12 +1355,17 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, * @param comps_indices Array of numcomps values representing the indices * of the components to decode (relative to the * codestream, starting at 0) + * @param apply_color_transforms Whether multi-component transform at codestream level + * or JP2 channel transformations should be applied. + * Currently this parameter should be set to OPJ_FALSE. + * Setting it to OPJ_TRUE will result in an error. * * @return OPJ_TRUE in case of success. */ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decoded_components(opj_codec_t *p_codec, OPJ_UINT32 numcomps, - const OPJ_UINT32* comps_indices); + const OPJ_UINT32* comps_indices, + OPJ_BOOL apply_color_transforms); /** * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. -- cgit v1.2.3