X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fbin%2Fjp2%2Fopj_decompress.c;h=ab7ff04adf624845348fa700ef888c1375e61e6e;hb=319fc971fef8a1e1c1c543506c26805873e3f258;hp=c6e5cff8d22fe4c60bff42ee8bc562cfc99af829;hpb=237ddd72f15fffe26e446604b2019604d9ae5211;p=openjpeg.git diff --git a/src/bin/jp2/opj_decompress.c b/src/bin/jp2/opj_decompress.c index c6e5cff8..ab7ff04a 100644 --- a/src/bin/jp2/opj_decompress.c +++ b/src/bin/jp2/opj_decompress.c @@ -75,6 +75,7 @@ #include "color.h" #include "format_defs.h" +#include "opj_string.h" typedef struct dircnt{ /** Buffer for holding images read from Directory*/ @@ -121,6 +122,8 @@ typedef struct opj_decompress_params int decod_format; /** output file format 0: PGX, 1: PxM, 2: BMP */ int cod_format; + /** index file name */ + char indexfilename[OPJ_PATH_LEN]; /** Decoding area left boundary */ OPJ_UINT32 DA_x0; @@ -145,6 +148,8 @@ typedef struct opj_decompress_params int force_rgb; /* upsample components according to their dx/dy values */ int upsample; + /* split output components to different files */ + int split_pnm; }opj_decompress_parameters; /* -------------------------------------------------------------------------- */ @@ -155,7 +160,7 @@ int get_file_format(const char *filename); char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_decompress_parameters *parameters); static int infile_format(const char *fname); -int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *parameters,img_fol_t *img_fol, char *indexfilename); +int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *parameters,img_fol_t *img_fol); int parse_DA_values( char* inArg, unsigned int *DA_x0, unsigned int *DA_y0, unsigned int *DA_x1, unsigned int *DA_y1); static opj_image_t* convert_gray_to_rgb(opj_image_t* original); @@ -173,12 +178,12 @@ static void decode_help_display(void) { " Image file Directory path \n" " -OutFor \n" " REQUIRED only if -ImgDir is used\n" - " Output format for decompressed images.\n" - " -i \n" + " Output format for decompressed images.\n"); + fprintf(stdout," -i \n" " REQUIRED only if an Input image directory is not specified\n" " Currently accepts J2K-files, JP2-files and JPT-files. The file type\n" - " is identified based on its suffix.\n" - " -o \n" + " is identified based on its suffix.\n"); + fprintf(stdout," -o \n" " REQUIRED\n" " Currently accepts formats specified above (see OutFor option)\n" " Binary data is written to the file (not ascii). If a PGX\n" @@ -186,8 +191,8 @@ static void decode_help_display(void) { " components: an indice starting from 0 will then be appended to the\n" " output filename, just before the \"pgx\" extension. If a PGM filename\n" " is given and there are more than one component, only the first component\n" - " will be written to the file.\n" - " -r \n" + " will be written to the file.\n"); + fprintf(stdout," -r \n" " Set the number of highest resolution levels to be discarded. The\n" " image resolution is effectively divided by 2 to the power of the\n" " number of discarded levels. The reduce factor is limited by the\n" @@ -195,8 +200,8 @@ static void decode_help_display(void) { " -l \n" " Set the maximum number of quality layers to decode. If there are\n" " less quality layers than the specified number, all the quality layers\n" - " are decoded.\n" - " -x \n" + " are decoded.\n"); + fprintf(stdout," -x \n" " Create an index file *.Idx (-x index_name.Idx) \n" " -d \n" " OPTIONAL\n" @@ -205,19 +210,21 @@ static void decode_help_display(void) { " -t \n" " OPTIONAL\n" " Set the tile number of the decoded tile. Follow the JPEG2000 convention from left-up to bottom-up\n" - " By default all tiles are decoded.\n" - " -p [C|S][,[C|S][,...]]\n" + " By default all tiles are decoded.\n"); + fprintf(stdout," -p [C|S][,[C|S][,...]]\n" " OPTIONAL\n" - " Force the precision (bit depth) of components.\n" - " 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" + " 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" " If there are less values than components, the last value is used for remaining components.\n" " 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" - " -force-rgb\n" + " A 0 value can be specified (meaning original bit depth).\n"); + fprintf(stdout," -force-rgb\n" " Force output image colorspace to RGB\n" " -upsample\n" " Downsampled components will be upsampled to image size\n" + " -split-pnm\n" + " Split output components to different files when writing to PNM\n" "\n"); /* UniPG>> */ #ifdef USE_JPWL @@ -248,7 +255,7 @@ static OPJ_BOOL parse_precision(const char* option, opj_decompress_parameters* p for(;;) { - OPJ_UINT32 prec; + int prec; char mode; char comma; int count; @@ -266,7 +273,7 @@ static OPJ_BOOL parse_precision(const char* option, opj_decompress_parameters* p count = 3; } if (count == 3) { - if (prec > 32U) { + if ((prec < 1) || (prec > 32)) { fprintf(stderr,"Invalid precision %d in precision option %s\n", prec, option); l_result = OPJ_FALSE; break; @@ -284,7 +291,7 @@ static OPJ_BOOL parse_precision(const char* option, opj_decompress_parameters* p if (parameters->precision == NULL) { /* first one */ - parameters->precision = malloc(sizeof(opj_precision)); + 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; @@ -300,7 +307,7 @@ static OPJ_BOOL parse_precision(const char* option, opj_decompress_parameters* p break; } - l_new = realloc(parameters->precision, l_new_size * sizeof(opj_precision)); + 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; @@ -309,7 +316,7 @@ static OPJ_BOOL parse_precision(const char* option, opj_decompress_parameters* p parameters->precision = l_new; } - parameters->precision[parameters->nb_precision].prec = prec; + parameters->precision[parameters->nb_precision].prec = (OPJ_UINT32)prec; switch (mode) { case 'C': parameters->precision[parameters->nb_precision].mode = OPJ_PREC_MODE_CLIP; @@ -357,6 +364,7 @@ int get_num_images(char *imgdirpath){ continue; num_images++; } + closedir(dir); return num_images; } @@ -383,6 +391,7 @@ int load_images(dircnt_t *dirptr, char *imgdirpath){ strcpy(dirptr->filename[i],content->d_name); i++; } + closedir(dir); return 0; } @@ -391,7 +400,7 @@ int get_file_format(const char *filename) { unsigned int i; static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "rawl", "tga", "png", "j2k", "jp2", "jpt", "j2c", "jpc" }; static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT, J2K_CFMT }; - char * ext = strrchr(filename, '.'); + const char * ext = strrchr(filename, '.'); if (ext == NULL) return -1; ext++; @@ -423,7 +432,9 @@ char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_decompre parameters->decod_format = infile_format(infilename); if (parameters->decod_format == -1) return 1; - strncpy(parameters->infile, infilename, sizeof(infilename)); + if (opj_strcpy_s(parameters->infile, sizeof(parameters->infile), infilename) != 0) { + return 1; + } /*Set output file*/ strcpy(temp_ofname,strtok(image_filename,".")); @@ -433,7 +444,9 @@ char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_decompre } if(img_fol->set_out_format==1){ sprintf(outfilename,"%s/%s.%s",img_fol->imgdirpath,temp_ofname,img_fol->out_format); - strncpy(parameters->outfile, outfilename, sizeof(outfilename)); + if (opj_strcpy_s(parameters->outfile, sizeof(parameters->outfile), outfilename) != 0) { + return 1; + } } return 0; } @@ -499,14 +512,15 @@ static int infile_format(const char *fname) * Parse the command line */ /* -------------------------------------------------------------------------- */ -int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *parameters,img_fol_t *img_fol, char *indexfilename) { +int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *parameters,img_fol_t *img_fol) { /* parse the command line */ int totlen, c; opj_option_t long_option[]={ - {"ImgDir", REQ_ARG, NULL ,'y'}, - {"OutFor", REQ_ARG, NULL ,'O'}, - {"force-rgb", NO_ARG, &(parameters->force_rgb), 1}, - {"upsample", NO_ARG, &(parameters->upsample), 1} + {"ImgDir", REQ_ARG, NULL,'y'}, + {"OutFor", REQ_ARG, NULL,'O'}, + {"force-rgb", NO_ARG, NULL, 1}, + {"upsample", NO_ARG, NULL, 1}, + {"split-pnm", NO_ARG, NULL, 1} }; const char optlist[] = "i:o:r:l:x:d:t:p:" @@ -517,6 +531,10 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para #endif /* USE_JPWL */ /* <force_rgb); + long_option[3].flag = &(parameters->upsample); + long_option[4].flag = &(parameters->split_pnm); totlen=sizeof(long_option); opj_reset_options_reading(); img_fol->set_out_format = 0; @@ -550,7 +568,10 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para infile); return 1; } - strncpy(parameters->infile, infile, sizeof(parameters->infile)-1); + if (opj_strcpy_s(parameters->infile, sizeof(parameters->infile), infile) != 0) { + fprintf(stderr, "[ERROR] Path is too long\n"); + return 1; + } } break; @@ -578,10 +599,13 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para case PNG_DFMT: break; default: - fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga]!! \n", outfile); + fprintf(stderr, "Unknown output format image %s [only *.png, *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga]!!\n", outfile); return 1; } - strncpy(parameters->outfile, outfile, sizeof(parameters->outfile)-1); + if (opj_strcpy_s(parameters->outfile, sizeof(parameters->outfile), outfile) != 0) { + fprintf(stderr, "[ERROR] Path is too long\n"); + return 1; + } } break; @@ -620,7 +644,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para img_fol->out_format = "png"; break; default: - fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga]!! \n", outformat); + fprintf(stderr, "Unknown output format image %s [only *.png, *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif, *.raw or *.tga]!!\n", outformat); return 1; break; } @@ -656,6 +680,9 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para case 'y': /* Image Directory path */ { img_fol->imgdirpath = (char*)malloc(strlen(opj_optarg) + 1); + if(img_fol->imgdirpath == NULL){ + return 1; + } strcpy(img_fol->imgdirpath,opj_optarg); img_fol->set_imgdir=1; } @@ -665,11 +692,14 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para case 'd': /* Input decode ROI */ { - int size_optarg = (int)strlen(opj_optarg) + 1; - char *ROI_values = (char*) malloc((size_t)size_optarg); + size_t size_optarg = (size_t)strlen(opj_optarg) + 1U; + char *ROI_values = (char*) malloc(size_optarg); + if (ROI_values == NULL) { + fprintf(stderr, "[ERROR] Couldn't allocate memory\n"); + return 1; + } ROI_values[0] = '\0'; - strncpy(ROI_values, opj_optarg, strlen(opj_optarg)); - ROI_values[strlen(opj_optarg)] = '\0'; + memcpy(ROI_values, opj_optarg, size_optarg); /*printf("ROI_values = %s [%d / %d]\n", ROI_values, strlen(ROI_values), size_optarg ); */ parse_DA_values( ROI_values, ¶meters->DA_x0, ¶meters->DA_y0, ¶meters->DA_x1, ¶meters->DA_y1); @@ -690,8 +720,10 @@ int parse_cmdline_decoder(int argc, char **argv, opj_decompress_parameters *para case 'x': /* Creation of index file */ { - char *index = opj_optarg; - strncpy(indexfilename, index, OPJ_PATH_LEN); + if (opj_strcpy_s(parameters->indexfilename, sizeof(parameters->indexfilename), opj_optarg) != 0) { + fprintf(stderr, "[ERROR] Path is too long\n"); + return 1; + } } break; @@ -1079,7 +1111,7 @@ static opj_image_t* upsample_image_components(opj_image_t* original) l_dst += l_new_cmp->w; } - if(l_new_cmp->h > (l_org_cmp->dy - 1U)) { /* check substraction overflow for really small images */ + if(l_new_cmp->h > (l_org_cmp->dy - 1U)) { /* check subtraction overflow for really small images */ for (; y < l_new_cmp->h - (l_org_cmp->dy - 1U); y += l_org_cmp->dy) { OPJ_UINT32 x, dy; OPJ_UINT32 xorg; @@ -1088,7 +1120,7 @@ static opj_image_t* upsample_image_components(opj_image_t* original) for (x = 0U; x < xoff; ++x) { l_dst[x] = 0; } - if (l_new_cmp->w > (l_org_cmp->dx - 1U)) { /* check substraction overflow for really small images */ + if (l_new_cmp->w > (l_org_cmp->dx - 1U)) { /* check subtraction overflow for really small images */ for (; x < l_new_cmp->w - (l_org_cmp->dx - 1U); x += l_org_cmp->dx, ++xorg) { OPJ_UINT32 dx; for (dx = 0U; dx < l_org_cmp->dx; ++dx) { @@ -1116,7 +1148,7 @@ static opj_image_t* upsample_image_components(opj_image_t* original) for (x = 0U; x < xoff; ++x) { l_dst[x] = 0; } - if (l_new_cmp->w > (l_org_cmp->dx - 1U)) { /* check substraction overflow for really small images */ + if (l_new_cmp->w > (l_org_cmp->dx - 1U)) { /* check subtraction overflow for really small images */ for (; x < l_new_cmp->w - (l_org_cmp->dx - 1U); x += l_org_cmp->dx, ++xorg) { OPJ_UINT32 dx; for (dx = 0U; dx < l_org_cmp->dx; ++dx) { @@ -1156,8 +1188,6 @@ int main(int argc, char **argv) opj_codec_t* l_codec = NULL; /* Handle to a decompressor */ opj_codestream_index_t* cstr_index = NULL; - char indexfilename[OPJ_PATH_LEN]; /* index file name */ - OPJ_INT32 num_images, imageno; img_fol_t img_fol; dircnt_t *dirptr = NULL; @@ -1168,16 +1198,12 @@ int main(int argc, char **argv) /* set decoding parameters to default values */ set_default_parameters(¶meters); - /* FIXME Initialize indexfilename and img_fol */ - *indexfilename = 0; - /* Initialize img_fol */ memset(&img_fol,0,sizeof(img_fol_t)); /* parse input and get user encoding parameters */ - if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol, indexfilename) == 1) { - destroy_parameters(¶meters); - return EXIT_FAILURE; + if(parse_cmdline_decoder(argc, argv, ¶meters,&img_fol) == 1) { + failed = 1; goto fin; } /* Initialize reading of directory */ @@ -1186,26 +1212,30 @@ int main(int argc, char **argv) num_images=get_num_images(img_fol.imgdirpath); dirptr=(dircnt_t*)malloc(sizeof(dircnt_t)); - if(dirptr){ - dirptr->filename_buf = (char*)malloc((size_t)num_images*OPJ_PATH_LEN*sizeof(char)); /* Stores at max 10 image file names*/ - dirptr->filename = (char**) malloc((size_t)num_images*sizeof(char*)); + if(!dirptr){ + destroy_parameters(¶meters); + return EXIT_FAILURE; + } + dirptr->filename_buf = (char*)malloc((size_t)num_images*OPJ_PATH_LEN*sizeof(char)); /* Stores at max 10 image file names*/ + if(!dirptr->filename_buf){ + failed = 1; goto fin; + } + + dirptr->filename = (char**) malloc((size_t)num_images*sizeof(char*)); - if(!dirptr->filename_buf){ - destroy_parameters(¶meters); - return EXIT_FAILURE; - } - for(it_image=0;it_imagefilename[it_image] = dirptr->filename_buf + it_image*OPJ_PATH_LEN; - } + if(!dirptr->filename){ + failed = 1; goto fin; + } + for(it_image=0;it_imagefilename[it_image] = dirptr->filename_buf + it_image*OPJ_PATH_LEN; } + if(load_images(dirptr,img_fol.imgdirpath)==1){ - destroy_parameters(¶meters); - return EXIT_FAILURE; + failed = 1; goto fin; } if (num_images==0){ fprintf(stdout,"Folder is empty\n"); - destroy_parameters(¶meters); - return EXIT_FAILURE; + failed = 1; goto fin; } }else{ num_images=1; @@ -1230,8 +1260,7 @@ int main(int argc, char **argv) l_stream = opj_stream_create_default_file_stream(parameters.infile,1); if (!l_stream){ fprintf(stderr, "ERROR -> failed to create the stream from the file %s\n", parameters.infile); - destroy_parameters(¶meters); - return EXIT_FAILURE; + failed = 1; goto fin; } /* decode the JPEG2000 stream */ @@ -1273,21 +1302,19 @@ int main(int argc, char **argv) /* Setup the decoder decoding parameters using user parameters */ if ( !opj_setup_decoder(l_codec, &(parameters.core)) ){ fprintf(stderr, "ERROR -> opj_decompress: failed to setup the decoder\n"); - destroy_parameters(¶meters); opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); - return EXIT_FAILURE; + failed = 1; goto fin; } /* Read the main header of the codestream and if necessary the JP2 boxes*/ if(! opj_read_header(l_stream, l_codec, &image)){ fprintf(stderr, "ERROR -> opj_decompress: failed to read the header\n"); - destroy_parameters(¶meters); opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); - return EXIT_FAILURE; + failed = 1; goto fin; } if (!parameters.nb_tile_to_decode) { @@ -1295,21 +1322,19 @@ int main(int argc, char **argv) if (!opj_set_decode_area(l_codec, image, (OPJ_INT32)parameters.DA_x0, (OPJ_INT32)parameters.DA_y0, (OPJ_INT32)parameters.DA_x1, (OPJ_INT32)parameters.DA_y1)){ fprintf(stderr, "ERROR -> opj_decompress: failed to set the decoded area\n"); - destroy_parameters(¶meters); opj_stream_destroy(l_stream); opj_destroy_codec(l_codec); opj_image_destroy(image); - return EXIT_FAILURE; + failed = 1; goto fin; } /* Get the decoded image */ if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec, l_stream))) { fprintf(stderr,"ERROR -> opj_decompress: failed to decode image!\n"); - destroy_parameters(¶meters); opj_destroy_codec(l_codec); opj_stream_destroy(l_stream); opj_image_destroy(image); - return EXIT_FAILURE; + failed = 1; goto fin; } } else { @@ -1320,16 +1345,15 @@ int main(int argc, char **argv) opj_destroy_codec(l_codec); opj_stream_destroy(l_stream); opj_image_destroy(image); - return EXIT_FAILURE; + failed = 1; goto fin; }*/ if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) { fprintf(stderr, "ERROR -> opj_decompress: failed to decode tile!\n"); - destroy_parameters(¶meters); opj_destroy_codec(l_codec); opj_stream_destroy(l_stream); opj_image_destroy(image); - return EXIT_FAILURE; + failed = 1; goto fin; } fprintf(stdout, "tile %d is decoded!\n\n", parameters.tile_index); } @@ -1340,10 +1364,6 @@ int main(int argc, char **argv) /* Close the byte stream */ opj_stream_destroy(l_stream); - if(image->color_space == OPJ_CLRSPC_SYCC){ - color_sycc_to_rgb(image); /* FIXME */ - } - if( image->color_space != OPJ_CLRSPC_SYCC && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy && image->comps[1].dx != 1 ) @@ -1351,9 +1371,22 @@ int main(int argc, char **argv) else if (image->numcomps <= 2) image->color_space = OPJ_CLRSPC_GRAY; + if(image->color_space == OPJ_CLRSPC_SYCC){ + color_sycc_to_rgb(image); + } + else if((image->color_space == OPJ_CLRSPC_CMYK) && (parameters.cod_format != TIF_DFMT)){ + color_cmyk_to_rgb(image); + } + else if(image->color_space == OPJ_CLRSPC_EYCC){ + color_esycc_to_rgb(image); + } + if(image->icc_profile_buf) { #if defined(OPJ_HAVE_LIBLCMS1) || defined(OPJ_HAVE_LIBLCMS2) - color_apply_icc_profile(image); /* FIXME */ + if(image->icc_profile_len) + color_apply_icc_profile(image); + else + color_cielab_to_rgb(image); #endif free(image->icc_profile_buf); image->icc_profile_buf = NULL; image->icc_profile_len = 0; @@ -1399,9 +1432,8 @@ int main(int argc, char **argv) image = upsample_image_components(image); if (image == NULL) { fprintf(stderr, "ERROR -> opj_decompress: failed to upsample image components!\n"); - destroy_parameters(¶meters); opj_destroy_codec(l_codec); - return EXIT_FAILURE; + failed = 1; goto fin; } } @@ -1423,9 +1455,8 @@ int main(int argc, char **argv) } if (image == NULL) { fprintf(stderr, "ERROR -> opj_decompress: failed to convert to RGB image!\n"); - destroy_parameters(¶meters); opj_destroy_codec(l_codec); - return EXIT_FAILURE; + failed = 1; goto fin; } } @@ -1433,7 +1464,7 @@ int main(int argc, char **argv) /* ------------------- */ switch (parameters.cod_format) { case PXM_DFMT: /* PNM PGM PPM */ - if (imagetopnm(image, parameters.outfile)) { + if (imagetopnm(image, parameters.outfile, parameters.split_pnm)) { fprintf(stderr,"[ERROR] Outfile %s not generated\n",parameters.outfile); failed = 1; } @@ -1532,12 +1563,19 @@ int main(int argc, char **argv) /* destroy the codestream index */ opj_destroy_cstr_index(&cstr_index); - if(failed) remove(parameters.outfile); + if(failed) (void)remove(parameters.outfile); /* ignore return value */ } +fin: destroy_parameters(¶meters); - if (numDecompressedImages) - fprintf(stdout, "decode time: %d ms \n", (int)( (tCumulative * 1000) / numDecompressedImages)); - //getch(); + if(failed && img_fol.imgdirpath) free(img_fol.imgdirpath); + if(dirptr){ + if(dirptr->filename) free(dirptr->filename); + if(dirptr->filename_buf) free(dirptr->filename_buf); + free(dirptr); + } + if (numDecompressedImages) { + fprintf(stdout, "decode time: %d ms\n", (int)( (tCumulative * 1000.0) / (OPJ_FLOAT64)numDecompressedImages)); + } return failed ? EXIT_FAILURE : EXIT_SUCCESS; } -/*end main*/ +/*end main()*/