From 7ad3e2a870a02a6d5effce55d8d90705ac27e3ff Mon Sep 17 00:00:00 2001 From: mayeut Date: Sun, 18 Oct 2015 16:07:40 +0200 Subject: [PATCH] Add "-p", "-force-rgb" and "-upsample" options to j2k_to_image Fix #606 --- applications/codec/convert.c | 103 ++++++ applications/codec/convert.h | 4 + applications/codec/j2k_to_image.c | 545 ++++++++++++++++++++++++++++-- 3 files changed, 628 insertions(+), 24 deletions(-) diff --git a/applications/codec/convert.c b/applications/codec/convert.c index f1ac4791..bb5c52bf 100644 --- a/applications/codec/convert.c +++ b/applications/codec/convert.c @@ -48,6 +48,23 @@ #include "openjpeg.h" #include "convert.h" +#ifdef HAVE_STDINT_H +#include +#else +#if defined(_WIN32) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#error unsupported platform +#endif +#endif + /* * Get logarithm of an integer and round downwards. * @@ -61,6 +78,92 @@ static int int_floorlog2(int a) { return l; } +/* Component precision scaling */ +void clip_component(opj_image_comp_t* component, int precision) +{ + size_t i, len; + unsigned int umax = (unsigned int)((int)-1); + + len = (size_t)component->w * (size_t)component->h; + if (precision < 32) { + umax = (1U << precision) - 1U; + } + + if (component->sgnd) { + int* l_data = component->data; + int max = (int)(umax / 2U); + int min = -max - 1; + for (i = 0U; i < len; ++i) { + if (l_data[i] > max) { + l_data[i] = max; + } else if (l_data[i] < min) { + l_data[i] = min; + } + } + } else { + unsigned int* l_data = (unsigned int*)component->data; + for (i = 0U; i < len; ++i) { + if (l_data[i] > umax) { + l_data[i] = umax; + } + } + } + component->prec = precision; +} + +/* Component precision scaling */ +static void scale_component_up(opj_image_comp_t* component, int precision) +{ + size_t i, len; + + len = (size_t)component->w * (size_t)component->h; + if (component->sgnd) { + int64_t newMax = (int64_t)(1U << (precision - 1)); + int64_t oldMax = (int64_t)(1U << (component->prec - 1)); + int* l_data = component->data; + for (i = 0; i < len; ++i) { + l_data[i] = (int)(((int64_t)l_data[i] * newMax) / oldMax); + } + } else { + uint64_t newMax = (uint64_t)((1U << precision) - 1U); + uint64_t oldMax = (uint64_t)((1U << component->prec) - 1U); + unsigned int* l_data = (unsigned int*)component->data; + for (i = 0; i < len; ++i) { + l_data[i] = (unsigned int)(((uint64_t)l_data[i] * newMax) / oldMax); + } + } + component->prec = precision; + component->bpp = precision; +} +void scale_component(opj_image_comp_t* component, int precision) +{ + int shift; + size_t i, len; + + if (component->prec == precision) { + return; + } + if (component->prec < precision) { + scale_component_up(component, precision); + return; + } + shift = (int)(component->prec - precision); + len = (size_t)component->w * (size_t)component->h; + if (component->sgnd) { + int* l_data = component->data; + for (i = 0U; i < len; ++i) { + l_data[i] >>= shift; + } + } else { + unsigned int* l_data = (unsigned int*)component->data; + for (i = 0U; i < len; ++i) { + l_data[i] >>= shift; + } + } + component->bpp = precision; + component->prec = precision; +} + /* -->> -->> -->> -->> TGA IMAGE FORMAT diff --git a/applications/codec/convert.h b/applications/codec/convert.h index d2f82fcf..0fb2ee6f 100644 --- a/applications/codec/convert.h +++ b/applications/codec/convert.h @@ -47,6 +47,10 @@ typedef struct raw_cparameters { /*@}*/ } raw_cparameters_t; +/* Component precision scaling */ +void clip_component(opj_image_comp_t* component, int precision); +void scale_component(opj_image_comp_t* component, int precision); + /* TGA conversion */ opj_image_t* tgatoimage(const char *filename, opj_cparameters_t *parameters); int imagetotga(opj_image_t * image, const char *outfile); diff --git a/applications/codec/j2k_to_image.c b/applications/codec/j2k_to_image.c index 43dc7c35..4fba5007 100644 --- a/applications/codec/j2k_to_image.c +++ b/applications/codec/j2k_to_image.c @@ -85,6 +85,40 @@ typedef struct img_folder{ }img_fol_t; +typedef enum opj_prec_mode +{ + OPJ_PREC_MODE_CLIP, + OPJ_PREC_MODE_SCALE +} opj_precision_mode; + +typedef struct opj_prec +{ + int prec; + opj_precision_mode mode; +}opj_precision; + +typedef struct opj_decompress_params +{ + /** core library parameters */ + opj_dparameters_t core; + + /** input file name */ + char infile[OPJ_PATH_LEN]; + /** output file name */ + char outfile[OPJ_PATH_LEN]; + /** input file format 0: J2K, 1: JP2, 2: JPT */ + int decod_format; + /** output file format 0: PGX, 1: PxM, 2: BMP */ + int cod_format; + + opj_precision* precision; + int nb_precision; + /* force output colorspace to RGB */ + int force_rgb; + /* upsample components according to their dx/dy values */ + int upsample; +}opj_decompress_parameters; + static void decode_help_display(void) { fprintf(stdout,"HELP for j2k_to_image\n----\n\n"); fprintf(stdout,"- the -h option displays this help information on screen\n\n"); @@ -128,6 +162,18 @@ static void decode_help_display(void) { fprintf(stdout," are decoded.\n"); fprintf(stdout," -x \n"); fprintf(stdout," Create an index file *.Idx (-x index_name.Idx) \n"); + fprintf(stdout," -p [C|S][,[C|S][,...]]\n"); + fprintf(stdout," OPTIONAL\n"); + fprintf(stdout," Force the precision (bit depth) of components.\n"); + fprintf(stdout," There shall be at least 1 value. Theres no limit on the number of values (comma separated, last values ignored if too much values).\n"); + fprintf(stdout," If there are less values than components, the last value is used for remaining components.\n"); + fprintf(stdout," If 'C' is specified (default), values are clipped.\n"); + fprintf(stdout," If 'S' is specified, values are scaled.\n"); + fprintf(stdout," A 0 value can be specified (meaning original bit depth).\n"); + fprintf(stdout," -force-rgb\n"); + fprintf(stdout," Force output image colorspace to RGB\n"); + fprintf(stdout," -upsample\n"); + fprintf(stdout," Downsampled components will be upsampled to image size\n"); fprintf(stdout,"\n"); /* UniPG>> */ #ifdef USE_JPWL @@ -144,6 +190,111 @@ static void decode_help_display(void) { /* -------------------------------------------------------------------------- */ +static opj_bool parse_precision(const char* option, opj_decompress_parameters* parameters) +{ + const char* l_remaining = option; + opj_bool l_result = OPJ_TRUE; + + /* reset */ + if (parameters->precision) { + free(parameters->precision); + parameters->precision = NULL; + } + parameters->nb_precision = 0U; + + for(;;) + { + int prec; + char mode; + char comma; + int count; + + count = sscanf(l_remaining, "%d%c%c", &prec, &mode, &comma); + if (count == 1) { + mode = 'C'; + count++; + } + if ((count == 2) || (mode==',')) { + if (mode==',') { + mode = 'C'; + } + comma=','; + count = 3; + } + if (count == 3) { + if ((prec < 1) || (prec > 32)) { + fprintf(stderr,"Invalid precision %d in precision option %s\n", prec, option); + l_result = OPJ_FALSE; + break; + } + if ((mode != 'C') && (mode != 'S')) { + fprintf(stderr,"Invalid precision mode %c in precision option %s\n", mode, option); + l_result = OPJ_FALSE; + break; + } + if (comma != ',') { + fprintf(stderr,"Invalid character %c in precision option %s\n", comma, option); + l_result = OPJ_FALSE; + break; + } + + if (parameters->precision == NULL) { + /* first one */ + parameters->precision = (opj_precision *)malloc(sizeof(opj_precision)); + if (parameters->precision == NULL) { + fprintf(stderr,"Could not allocate memory for precision option\n"); + l_result = OPJ_FALSE; + break; + } + } else { + int l_new_size = parameters->nb_precision + 1U; + opj_precision* l_new; + + if (l_new_size == 0U) { + fprintf(stderr,"Could not allocate memory for precision option\n"); + l_result = OPJ_FALSE; + break; + } + + l_new = (opj_precision *)realloc(parameters->precision, l_new_size * sizeof(opj_precision)); + if (l_new == NULL) { + fprintf(stderr,"Could not allocate memory for precision option\n"); + l_result = OPJ_FALSE; + break; + } + parameters->precision = l_new; + } + + parameters->precision[parameters->nb_precision].prec = prec; + switch (mode) { + case 'C': + parameters->precision[parameters->nb_precision].mode = OPJ_PREC_MODE_CLIP; + break; + case 'S': + parameters->precision[parameters->nb_precision].mode = OPJ_PREC_MODE_SCALE; + break; + default: + break; + } + parameters->nb_precision++; + + l_remaining = strchr(l_remaining, ','); + if (l_remaining == NULL) { + break; + } + l_remaining += 1; + } else { + fprintf(stderr,"Could not parse precision option %s\n", option); + l_result = OPJ_FALSE; + break; + } + } + + return l_result; +} + +/* -------------------------------------------------------------------------- */ + static int get_num_images(char *imgdirpath){ DIR *dir; struct dirent* content; @@ -211,7 +362,7 @@ static int get_file_format(char *filename) { return -1; } -static char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_dparameters_t *parameters){ +static char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_decompress_parameters *parameters){ char image_filename[OPJ_PATH_LEN], infilename[OPJ_PATH_LEN],outfilename[OPJ_PATH_LEN],temp_ofname[OPJ_PATH_LEN]; char *temp_p, temp1[OPJ_PATH_LEN]=""; @@ -237,18 +388,20 @@ static char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_d } /* -------------------------------------------------------------------------- */ -static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,img_fol_t *img_fol, char *indexfilename) { +static int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *parameters,img_fol_t *img_fol, char *indexfilename) { /* parse the command line */ int totlen, c; opj_option_t long_option[]={ {"ImgDir",REQ_ARG, NULL ,'y'}, - {"OutFor",REQ_ARG, NULL ,'O'}, + {"OutFor",REQ_ARG, NULL ,'O'}, + {"force-rgb", NO_ARG, NULL, 1}, + {"upsample", NO_ARG, NULL, 1}, #ifdef USE_SYSTEM_GETOPT - {0,0,0,0} /* GNU getopt_long requirement */ + {0,0,0,0} /* GNU getopt_long requirement */ #endif }; - const char optlist[] = "i:o:r:l:x:" + const char optlist[] = "i:o:r:l:x:p:" /* UniPG>> */ #ifdef USE_JPWL @@ -256,7 +409,10 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param #endif /* USE_JPWL */ /* <force_rgb); + long_option[3].flag = &(parameters->upsample); + totlen=sizeof(long_option); img_fol->set_out_format = 0; do { #ifdef USE_SYSTEM_GETOPT @@ -267,6 +423,8 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param if (c == -1) break; switch (c) { + case 0: /* long opt with flag */ + break; case 'i': /* input file */ { char *infile = opj_optarg; @@ -353,7 +511,7 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param case 'r': /* reduce option */ { - sscanf(opj_optarg, "%d", ¶meters->cp_reduce); + sscanf(opj_optarg, "%d", ¶meters->core.cp_reduce); } break; @@ -362,7 +520,7 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param case 'l': /* layering option */ { - sscanf(opj_optarg, "%d", ¶meters->cp_layer); + sscanf(opj_optarg, "%d", ¶meters->core.cp_layer); } break; @@ -389,6 +547,15 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param } break; /* ----------------------------------------------------- */ + case 'p': /* Force precision */ + { + if (!parse_precision(opj_optarg, parameters)) + { + return 1; + } + } + break; + /* ----------------------------------------------------- */ /* UniPG>> */ #ifdef USE_JPWL @@ -496,6 +663,32 @@ static int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *param /* -------------------------------------------------------------------------- */ +static void set_default_parameters(opj_decompress_parameters* parameters) +{ + if (parameters) { + memset(parameters, 0, sizeof(opj_decompress_parameters)); + + /* default decoding parameters (command line specific) */ + parameters->decod_format = -1; + parameters->cod_format = -1; + + /* default decoding parameters (core) */ + opj_set_default_decoder_parameters(&(parameters->core)); + } +} + +static void destroy_parameters(opj_decompress_parameters* parameters) +{ + if (parameters) { + if (parameters->precision) { + free(parameters->precision); + parameters->precision = NULL; + } + } +} + +/* -------------------------------------------------------------------------- */ + /** sample error callback expecting a FILE* client object */ @@ -520,8 +713,233 @@ static void info_callback(const char *msg, void *client_data) { /* -------------------------------------------------------------------------- */ +static opj_image_t* convert_gray_to_rgb(opj_image_t* original) +{ + int compno; + opj_image_t* l_new_image = NULL; + opj_image_cmptparm_t* l_new_components = NULL; + + l_new_components = (opj_image_cmptparm_t*)malloc((original->numcomps + 2U) * sizeof(opj_image_cmptparm_t)); + if (l_new_components == NULL) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for RGB image!\n"); + opj_image_destroy(original); + return NULL; + } + + l_new_components[0].bpp = l_new_components[1].bpp = l_new_components[2].bpp = original->comps[0].bpp; + l_new_components[0].dx = l_new_components[1].dx = l_new_components[2].dx = original->comps[0].dx; + l_new_components[0].dy = l_new_components[1].dy = l_new_components[2].dy = original->comps[0].dy; + l_new_components[0].h = l_new_components[1].h = l_new_components[2].h = original->comps[0].h; + l_new_components[0].w = l_new_components[1].w = l_new_components[2].w = original->comps[0].w; + l_new_components[0].prec = l_new_components[1].prec = l_new_components[2].prec = original->comps[0].prec; + l_new_components[0].sgnd = l_new_components[1].sgnd = l_new_components[2].sgnd = original->comps[0].sgnd; + l_new_components[0].x0 = l_new_components[1].x0 = l_new_components[2].x0 = original->comps[0].x0; + l_new_components[0].y0 = l_new_components[1].y0 = l_new_components[2].y0 = original->comps[0].y0; + + for(compno = 1; compno < original->numcomps; ++compno) { + l_new_components[compno+2].bpp = original->comps[compno].bpp; + l_new_components[compno+2].dx = original->comps[compno].dx; + l_new_components[compno+2].dy = original->comps[compno].dy; + l_new_components[compno+2].h = original->comps[compno].h; + l_new_components[compno+2].w = original->comps[compno].w; + l_new_components[compno+2].prec = original->comps[compno].prec; + l_new_components[compno+2].sgnd = original->comps[compno].sgnd; + l_new_components[compno+2].x0 = original->comps[compno].x0; + l_new_components[compno+2].y0 = original->comps[compno].y0; + } + + l_new_image = opj_image_create(original->numcomps + 2, l_new_components, CLRSPC_SRGB); + free(l_new_components); + if (l_new_image == NULL) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for RGB image!\n"); + opj_image_destroy(original); + return NULL; + } + + l_new_image->x0 = original->x0; + l_new_image->x1 = original->x1; + l_new_image->y0 = original->y0; + l_new_image->y1 = original->y1; + + l_new_image->comps[0].factor = l_new_image->comps[1].factor = l_new_image->comps[2].factor = original->comps[0].factor; + l_new_image->comps[0].resno_decoded = l_new_image->comps[1].resno_decoded = l_new_image->comps[2].resno_decoded = original->comps[0].resno_decoded; + + memcpy(l_new_image->comps[0].data, original->comps[0].data, original->comps[0].w * original->comps[0].h * sizeof(int)); + memcpy(l_new_image->comps[1].data, original->comps[0].data, original->comps[0].w * original->comps[0].h * sizeof(int)); + memcpy(l_new_image->comps[2].data, original->comps[0].data, original->comps[0].w * original->comps[0].h * sizeof(int)); + + for(compno = 1; compno < original->numcomps; ++compno) { + l_new_image->comps[compno+2].factor = original->comps[compno].factor; + l_new_image->comps[compno+2].resno_decoded = original->comps[compno].resno_decoded; + memcpy(l_new_image->comps[compno+2].data, original->comps[compno].data, original->comps[compno].w * original->comps[compno].h * sizeof(int)); + } + opj_image_destroy(original); + return l_new_image; +} + +/* -------------------------------------------------------------------------- */ + +static opj_image_t* upsample_image_components(opj_image_t* original) +{ + opj_image_t* l_new_image = NULL; + opj_image_cmptparm_t* l_new_components = NULL; + opj_bool l_upsample_need = OPJ_FALSE; + int compno; + + for (compno = 0; compno < original->numcomps; ++compno) { + if (original->comps[compno].factor > 0) { + fprintf(stderr, "ERROR -> j2k_to_image: -upsample not supported with reduction\n"); + opj_image_destroy(original); + return NULL; + } + if ((original->comps[compno].dx > 1) || (original->comps[compno].dy > 1)) { + l_upsample_need = OPJ_TRUE; + break; + } + } + if (!l_upsample_need) { + return original; + } + /* Upsample is needed */ + l_new_components = (opj_image_cmptparm_t*)malloc(original->numcomps * sizeof(opj_image_cmptparm_t)); + if (l_new_components == NULL) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for upsampled components!\n"); + opj_image_destroy(original); + return NULL; + } + + for (compno = 0; compno < original->numcomps; ++compno) { + opj_image_cmptparm_t* l_new_cmp = &(l_new_components[compno]); + opj_image_comp_t* l_org_cmp = &(original->comps[compno]); + + l_new_cmp->bpp = l_org_cmp->bpp; + l_new_cmp->prec = l_org_cmp->prec; + l_new_cmp->sgnd = l_org_cmp->sgnd; + l_new_cmp->x0 = original->x0; + l_new_cmp->y0 = original->y0; + l_new_cmp->dx = 1; + l_new_cmp->dy = 1; + l_new_cmp->w = l_org_cmp->w; /* should be original->x1 - original->x0 for dx==1 */ + l_new_cmp->h = l_org_cmp->h; /* should be original->y1 - original->y0 for dy==0 */ + + if (l_org_cmp->dx > 1) { + l_new_cmp->w = original->x1 - original->x0; + } + + if (l_org_cmp->dy > 1) { + l_new_cmp->h = original->y1 - original->y0; + } + } + + l_new_image = opj_image_create(original->numcomps, l_new_components, original->color_space); + free(l_new_components); + if (l_new_image == NULL) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to allocate memory for upsampled components!\n"); + opj_image_destroy(original); + return NULL; + } + + l_new_image->x0 = original->x0; + l_new_image->x1 = original->x1; + l_new_image->y0 = original->y0; + l_new_image->y1 = original->y1; + + for (compno = 0; compno < original->numcomps; ++compno) { + opj_image_comp_t* l_new_cmp = &(l_new_image->comps[compno]); + opj_image_comp_t* l_org_cmp = &(original->comps[compno]); + + l_new_cmp->factor = l_org_cmp->factor; + l_new_cmp->resno_decoded = l_org_cmp->resno_decoded; + + if ((l_org_cmp->dx > 1) || (l_org_cmp->dy > 1)) { + const int* l_src = l_org_cmp->data; + int* l_dst = l_new_cmp->data; + int y; + int xoff, yoff; + + /* need to take into account dx & dy */ + xoff = l_org_cmp->dx * l_org_cmp->x0 - original->x0; + yoff = l_org_cmp->dy * l_org_cmp->y0 - original->y0; + if ((xoff >= l_org_cmp->dx) || (yoff >= l_org_cmp->dy)) { + fprintf(stderr, "ERROR -> j2k_to_image: Invalid image/component parameters found when upsampling\n"); + opj_image_destroy(original); + opj_image_destroy(l_new_image); + return NULL; + } + + for (y = 0; y < yoff; ++y) { + memset(l_dst, 0, l_new_cmp->w * sizeof(int)); + l_dst += l_new_cmp->w; + } + + if(l_new_cmp->h > (l_org_cmp->dy - 1)) { /* check subtraction overflow for really small images */ + for (; y < l_new_cmp->h - (l_org_cmp->dy - 1); y += l_org_cmp->dy) { + int x, dy; + int xorg; + + xorg = 0; + for (x = 0; x < xoff; ++x) { + l_dst[x] = 0; + } + if (l_new_cmp->w > (l_org_cmp->dx - 1)) { /* check subtraction overflow for really small images */ + for (; x < l_new_cmp->w - (l_org_cmp->dx - 1); x += l_org_cmp->dx, ++xorg) { + int dx; + for (dx = 0; dx < l_org_cmp->dx; ++dx) { + l_dst[x + dx] = l_src[xorg]; + } + } + } + for (; x < l_new_cmp->w; ++x) { + l_dst[x] = l_src[xorg]; + } + l_dst += l_new_cmp->w; + + for (dy = 1; dy < l_org_cmp->dy; ++dy) { + memcpy(l_dst, l_dst - l_new_cmp->w, l_new_cmp->w * sizeof(int)); + l_dst += l_new_cmp->w; + } + l_src += l_org_cmp->w; + } + } + if (y < l_new_cmp->h) { + int x; + int xorg; + + xorg = 0; + for (x = 0; x < xoff; ++x) { + l_dst[x] = 0; + } + if (l_new_cmp->w > (l_org_cmp->dx - 1)) { /* check subtraction overflow for really small images */ + for (; x < l_new_cmp->w - (l_org_cmp->dx - 1); x += l_org_cmp->dx, ++xorg) { + int dx; + for (dx = 0; dx < l_org_cmp->dx; ++dx) { + l_dst[x + dx] = l_src[xorg]; + } + } + } + for (; x < l_new_cmp->w; ++x) { + l_dst[x] = l_src[xorg]; + } + l_dst += l_new_cmp->w; + ++y; + for (; y < l_new_cmp->h; ++y) { + memcpy(l_dst, l_dst - l_new_cmp->w, l_new_cmp->w * sizeof(int)); + l_dst += l_new_cmp->w; + } + } + } + else { + memcpy(l_new_cmp->data, l_org_cmp->data, l_org_cmp->w * l_org_cmp->h * sizeof(int)); + } + } + opj_image_destroy(original); + return l_new_image; +} + +/* -------------------------------------------------------------------------- */ + int main(int argc, char **argv) { - opj_dparameters_t parameters; /* decompression parameters */ + opj_decompress_parameters parameters; /* decompression parameters */ img_fol_t img_fol; opj_event_mgr_t event_mgr; /* event manager */ opj_image_t *image = NULL; @@ -543,7 +961,7 @@ int main(int argc, char **argv) { event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ - opj_set_default_decoder_parameters(¶meters); + set_default_parameters(¶meters); /* Initialize indexfilename and img_fol */ *indexfilename = 0; @@ -551,6 +969,7 @@ int main(int argc, char **argv) { /* parse input and get user encoding parameters */ if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol, indexfilename) == 1) { + destroy_parameters(¶meters); return 1; } @@ -564,6 +983,7 @@ int main(int argc, char **argv) { dirptr->filename = (char**) malloc(num_images*sizeof(char*)); if(!dirptr->filename_buf){ + destroy_parameters(¶meters); return 1; } for(i=0;i failed to open %s for reading\n", parameters.infile); + destroy_parameters(¶meters); return 1; } fseek(fsrc, 0, SEEK_END); @@ -609,6 +1032,7 @@ int main(int argc, char **argv) { free(src); fclose(fsrc); fprintf(stderr, "\nERROR: fread return a number of element different from the expected.\n"); + destroy_parameters(¶meters); return 1; } fclose(fsrc); @@ -628,7 +1052,7 @@ int main(int argc, char **argv) { opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ - opj_setup_decoder(dinfo, ¶meters); + opj_setup_decoder(dinfo, ¶meters.core); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); @@ -643,6 +1067,7 @@ int main(int argc, char **argv) { opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); + destroy_parameters(¶meters); return 1; } @@ -671,7 +1096,7 @@ int main(int argc, char **argv) { opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using the current image and user parameters */ - opj_setup_decoder(dinfo, ¶meters); + opj_setup_decoder(dinfo, ¶meters.core); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); @@ -686,6 +1111,7 @@ int main(int argc, char **argv) { opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); + destroy_parameters(¶meters); return 1; } @@ -714,7 +1140,7 @@ int main(int argc, char **argv) { opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); /* setup the decoder decoding parameters using user parameters */ - opj_setup_decoder(dinfo, ¶meters); + opj_setup_decoder(dinfo, ¶meters.core); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); @@ -729,6 +1155,7 @@ int main(int argc, char **argv) { opj_destroy_decompress(dinfo); opj_cio_close(cio); free(src); + destroy_parameters(¶meters); return 1; } @@ -755,20 +1182,89 @@ int main(int argc, char **argv) { free(src); src = NULL; - if(image->color_space == CLRSPC_SYCC) - { - color_sycc_to_rgb(image); - } + if(image->color_space == CLRSPC_SYCC) + { + color_sycc_to_rgb(image); + } - if(image->icc_profile_buf) - { + if(image->icc_profile_buf) + { #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - color_apply_icc_profile(image); + color_apply_icc_profile(image); #endif - - free(image->icc_profile_buf); - image->icc_profile_buf = NULL; image->icc_profile_len = 0; - } + free(image->icc_profile_buf); + image->icc_profile_buf = NULL; image->icc_profile_len = 0; + } + + /* Force output precision */ + /* ---------------------- */ + if (parameters.precision != NULL) + { + int compno; + for (compno = 0; compno < image->numcomps; ++compno) + { + int precno = compno; + int prec; + + if (precno >= parameters.nb_precision) { + precno = parameters.nb_precision - 1U; + } + + prec = parameters.precision[precno].prec; + if (prec == 0) { + prec = image->comps[compno].prec; + } + + switch (parameters.precision[precno].mode) { + case OPJ_PREC_MODE_CLIP: + clip_component(&(image->comps[compno]), prec); + break; + case OPJ_PREC_MODE_SCALE: + scale_component(&(image->comps[compno]), prec); + break; + default: + break; + } + + } + } + + /* Upsample components */ + /* ------------------- */ + if (parameters.upsample) + { + image = upsample_image_components(image); + if (image == NULL) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to upsample image components!\n"); + destroy_parameters(¶meters); + opj_destroy_decompress(dinfo); + return EXIT_FAILURE; + } + } + + /* Force RGB output */ + /* ---------------- */ + if (parameters.force_rgb) + { + switch (image->color_space) { + case CLRSPC_SRGB: + break; + case CLRSPC_GRAY: + image = convert_gray_to_rgb(image); + break; + default: + fprintf(stderr, "ERROR -> j2k_to_image: don't know how to convert image to RGB colorspace!\n"); + opj_image_destroy(image); + image = NULL; + break; + } + if (image == NULL) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to convert to RGB image!\n"); + destroy_parameters(¶meters); + opj_destroy_decompress(dinfo); + return EXIT_FAILURE; + } + } /* create output image */ /* ------------------- */ @@ -854,6 +1350,7 @@ int main(int argc, char **argv) { opj_image_destroy(image); } + destroy_parameters(¶meters); return 0; } /*end main*/