예제 #1
0
/* -------------------------------------------------------------------------- */
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(&parameters);

	/* 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, &parameters,&img_fol, indexfilename) == 1) {
		destroy_parameters(&parameters);
		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(&parameters);
				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(&parameters);
			return EXIT_FAILURE;
		}
		if (num_images==0){
			fprintf(stdout,"Folder is empty\n");
			destroy_parameters(&parameters);
			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, &parameters)) {
				fprintf(stderr,"skipping file...\n");
				destroy_parameters(&parameters);
				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(&parameters);
			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(&parameters);
				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(&parameters);
			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(&parameters);
			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(&parameters);
				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(&parameters);
				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(&parameters);
				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(&parameters);
				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(&parameters);
				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(&parameters);
	if (numDecompressedImages) {
		fprintf(stdout, "decode time: %d ms\n", (int)( (tCumulative * 1000.0) / (OPJ_FLOAT64)numDecompressedImages));
	}
	return failed ? EXIT_FAILURE : EXIT_SUCCESS;
}
예제 #2
0
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() */