/* -------------------------------------------------------------------------- */ int main(int argc, char **argv) { opj_decompress_parameters parameters; /* decompression parameters */ opj_image_t* image = NULL; opj_stream_t *l_stream = NULL; /* Stream */ 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; int failed = 0; OPJ_FLOAT64 t, tCumulative = 0; OPJ_UINT32 numDecompressedImages = 0; /* 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; } /* Initialize reading of directory */ if(img_fol.set_imgdir==1){ int it_image; 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->filename_buf){ destroy_parameters(¶meters); return EXIT_FAILURE; } for(it_image=0;it_image<num_images;it_image++){ dirptr->filename[it_image] = dirptr->filename_buf + it_image*OPJ_PATH_LEN; } } if(load_images(dirptr,img_fol.imgdirpath)==1){ destroy_parameters(¶meters); return EXIT_FAILURE; } if (num_images==0){ fprintf(stdout,"Folder is empty\n"); destroy_parameters(¶meters); return EXIT_FAILURE; } }else{ num_images=1; } /*Decoding image one by one*/ for(imageno = 0; imageno < num_images ; imageno++) { fprintf(stderr,"\n"); if(img_fol.set_imgdir==1){ if (get_next_file(imageno, dirptr,&img_fol, ¶meters)) { fprintf(stderr,"skipping file...\n"); destroy_parameters(¶meters); continue; } } /* read the input file and put it in memory */ /* ---------------------------------------- */ 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; } /* decode the JPEG2000 stream */ /* ---------------------- */ switch(parameters.decod_format) { case J2K_CFMT: /* JPEG-2000 codestream */ { /* Get a decoder handle */ l_codec = opj_create_decompress(OPJ_CODEC_J2K); break; } case JP2_CFMT: /* JPEG 2000 compressed image data */ { /* Get a decoder handle */ l_codec = opj_create_decompress(OPJ_CODEC_JP2); break; } case JPT_CFMT: /* JPEG 2000, JPIP */ { /* Get a decoder handle */ l_codec = opj_create_decompress(OPJ_CODEC_JPT); break; } default: fprintf(stderr, "skipping file..\n"); destroy_parameters(¶meters); opj_stream_destroy(l_stream); continue; } /* catch events using our callbacks and give a local context */ opj_set_info_handler(l_codec, info_callback,00); opj_set_warning_handler(l_codec, warning_callback,00); opj_set_error_handler(l_codec, error_callback,00); t = opj_clock(); /* 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; } /* 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; } if (!parameters.nb_tile_to_decode) { /* Optional if you want decode the entire image */ 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; } /* 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; } } else { /* It is just here to illustrate how to use the resolution after set parameters */ /*if (!opj_set_decoded_resolution_factor(l_codec, 5)) { fprintf(stderr, "ERROR -> opj_decompress: failed to set the resolution factor tile!\n"); opj_destroy_codec(l_codec); opj_stream_destroy(l_stream); opj_image_destroy(image); return EXIT_FAILURE; }*/ 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; } fprintf(stdout, "tile %d is decoded!\n\n", parameters.tile_index); } tCumulative += opj_clock() - t; numDecompressedImages++; /* Close the byte stream */ opj_stream_destroy(l_stream); if( image->color_space != OPJ_CLRSPC_SYCC && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy && image->comps[1].dx != 1 ) image->color_space = OPJ_CLRSPC_SYCC; 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) 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; } /* Force output precision */ /* ---------------------- */ if (parameters.precision != NULL) { OPJ_UINT32 compno; for (compno = 0; compno < image->numcomps; ++compno) { OPJ_UINT32 precno = compno; OPJ_UINT32 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 -> opj_decompress: failed to upsample image components!\n"); destroy_parameters(¶meters); opj_destroy_codec(l_codec); return EXIT_FAILURE; } } /* Force RGB output */ /* ---------------- */ if (parameters.force_rgb) { switch (image->color_space) { case OPJ_CLRSPC_SRGB: break; case OPJ_CLRSPC_GRAY: image = convert_gray_to_rgb(image); break; default: fprintf(stderr, "ERROR -> opj_decompress: don't know how to convert image to RGB colorspace!\n"); opj_image_destroy(image); image = NULL; break; } 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; } } /* create output image */ /* ------------------- */ switch (parameters.cod_format) { case PXM_DFMT: /* PNM PGM PPM */ if (imagetopnm(image, parameters.outfile, parameters.split_pnm)) { fprintf(stderr,"[ERROR] Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; case PGX_DFMT: /* PGX */ if(imagetopgx(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; case BMP_DFMT: /* BMP */ if(imagetobmp(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; #ifdef OPJ_HAVE_LIBTIFF case TIF_DFMT: /* TIFF */ if(imagetotif(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; #endif /* OPJ_HAVE_LIBTIFF */ case RAW_DFMT: /* RAW */ if(imagetoraw(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Error generating raw file. Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; case RAWL_DFMT: /* RAWL */ if(imagetorawl(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Error generating rawl file. Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; case TGA_DFMT: /* TGA */ if(imagetotga(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Error generating tga file. Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; #ifdef OPJ_HAVE_LIBPNG case PNG_DFMT: /* PNG */ if(imagetopng(image, parameters.outfile)){ fprintf(stderr,"[ERROR] Error generating png file. Outfile %s not generated\n",parameters.outfile); failed = 1; } else { fprintf(stdout,"[INFO] Generated Outfile %s\n",parameters.outfile); } break; #endif /* OPJ_HAVE_LIBPNG */ /* Can happen if output file is TIFF or PNG * and OPJ_HAVE_LIBTIF or OPJ_HAVE_LIBPNG is undefined */ default: fprintf(stderr,"[ERROR] Outfile %s not generated\n",parameters.outfile); failed = 1; } /* free remaining structures */ if (l_codec) { opj_destroy_codec(l_codec); } /* free image data structure */ opj_image_destroy(image); /* destroy the codestream index */ opj_destroy_cstr_index(&cstr_index); if(failed) remove(parameters.outfile); } destroy_parameters(¶meters); if (numDecompressedImages) { fprintf(stdout, "decode time: %d ms\n", (int)( (tCumulative * 1000.0) / (OPJ_FLOAT64)numDecompressedImages)); } return failed ? EXIT_FAILURE : EXIT_SUCCESS; }
int imagetopng(opj_image_t * image, const char *write_idf) { FILE * volatile writer = NULL; png_structp png = NULL; png_infop info = NULL; png_bytep volatile row_buf = NULL; int nr_comp, color_type; volatile int prec; png_color_8 sig_bit; int32_t const* planes[4]; int i; int32_t* volatile buffer32s = NULL; volatile int fails = 1; memset(&sig_bit, 0, sizeof(sig_bit)); prec = (int)image->comps[0].prec; planes[0] = image->comps[0].data; nr_comp = (int)image->numcomps; if (nr_comp > 4) { nr_comp = 4; } for (i = 1; i < nr_comp; ++i) { if (image->comps[0].dx != image->comps[i].dx) { break; } if (image->comps[0].dy != image->comps[i].dy) { break; } if (image->comps[0].prec != image->comps[i].prec) { break; } if (image->comps[0].sgnd != image->comps[i].sgnd) { break; } planes[i] = image->comps[i].data; } if (i != nr_comp) { fprintf(stderr,"imagetopng: All components shall have the same subsampling, same bit depth, same sign.\n"); fprintf(stderr,"\tAborting\n"); return 1; } for (i = 0; i < nr_comp; ++i) { clip_component(&(image->comps[i]), image->comps[0].prec); } if(prec > 8 && prec < 16) { for (i = 0; i < nr_comp; ++i) { scale_component(&(image->comps[i]), 16); } prec = 16; } else if(prec < 8 && nr_comp > 1) { /* GRAY_ALPHA, RGB, RGB_ALPHA */ for (i = 0; i < nr_comp; ++i) { scale_component(&(image->comps[i]), 8); } prec = 8; } else if((prec > 1) && (prec < 8) && ((prec == 6) || ((prec & 1)==1))) { /* GRAY with non native precision */ if ((prec == 5) || (prec == 6)) { prec = 8; } else { prec++; } for (i = 0; i < nr_comp; ++i) { scale_component(&(image->comps[i]), (uint32_t)prec); } } if(prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16) { fprintf(stderr,"imagetopng: can not create %s\n\twrong bit_depth %d\n", write_idf, prec); return fails; } writer = fopen(write_idf, "wb"); if(writer == NULL) return fails; /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); /*png_voidp user_error_ptr, user_error_fn, user_warning_fn); */ if(png == NULL) goto fin; /* Allocate/initialize the image information data. REQUIRED */ info = png_create_info_struct(png); if(info == NULL) goto fin; /* Set error handling. REQUIRED if you are not supplying your own * error handling functions in the png_create_write_struct() call. */ if(setjmp(png_jmpbuf(png))) goto fin; /* I/O initialization functions is REQUIRED */ png_init_io(png, writer); /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. * REQUIRED * * ERRORS: * * color_type == PNG_COLOR_TYPE_PALETTE && bit_depth > 8 * color_type == PNG_COLOR_TYPE_RGB && bit_depth < 8 * color_type == PNG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8 * color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8 * */ png_set_compression_level(png, Z_BEST_COMPRESSION); if(nr_comp >= 3) { /* RGB(A) */ color_type = PNG_COLOR_TYPE_RGB; sig_bit.red = sig_bit.green = sig_bit.blue = (png_byte)prec; } else { /* GRAY(A) */ color_type = PNG_COLOR_TYPE_GRAY; sig_bit.gray = (png_byte)prec; } if((nr_comp & 1) == 0) { /* ALPHA */ color_type |= PNG_COLOR_MASK_ALPHA; sig_bit.alpha = (png_byte)prec; } png_set_IHDR(png, info, image->comps[0].w, image->comps[0].h, prec, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_sBIT(png, info, &sig_bit); /* png_set_gamma(png, 2.2, 1./2.2); */ /* png_set_sRGB(png, info, PNG_sRGB_INTENT_PERCEPTUAL); */ png_write_info(png, info); /* setup conversion */ { size_t rowStride; png_size_t png_row_size; png_row_size = png_get_rowbytes(png, info); rowStride = ((size_t)image->comps[0].w * (size_t)nr_comp * (size_t)prec + 7U) / 8U; if (rowStride != (size_t)png_row_size) { fprintf(stderr, "Invalid PNG row size\n"); goto fin; } row_buf = (png_bytep)malloc(png_row_size); if (row_buf == NULL) { fprintf(stderr, "Can't allocate memory for PNG row\n"); goto fin; } buffer32s = (int32_t*)malloc((size_t)image->comps[0].w * (size_t)nr_comp * sizeof(int32_t)); if (buffer32s == NULL) { fprintf(stderr, "Can't allocate memory for interleaved 32s row\n"); goto fin; } } /* convert */ { size_t width= image->comps[0].w; uint32_t y; convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp]; convert_32sXXx_C1R cvt32sToPack = NULL; int32_t adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0; png_bytep row_buf_cpy = row_buf; int32_t* buffer32s_cpy = buffer32s; switch (prec) { case 1: case 2: case 4: case 8: cvt32sToPack = convert_32sXXu_C1R_LUT[prec]; break; case 16: cvt32sToPack = convert_32s16u_C1R; break; default: /* never here */ return 1; break; } for(y = 0; y < image->comps[0].h; ++y) { cvtPxToCx(planes, buffer32s_cpy, width, adjust); cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (size_t)nr_comp); png_write_row(png, row_buf_cpy); planes[0] += width; planes[1] += width; planes[2] += width; planes[3] += width; } } png_write_end(png, info); fails = 0; fin: if(png) { png_destroy_write_struct(&png, &info); } if(row_buf) { free(row_buf); } if(buffer32s) { free(buffer32s); } fclose(writer); if(fails) (void)remove(write_idf); /* ignore return value */ return fails; }/* imagetopng() */