From b7ce19709df0b304c1c8b0116b617208992b3a32 Mon Sep 17 00:00:00 2001 From: Francois-Olivier Devaux Date: Tue, 17 Jul 2007 16:19:41 +0000 Subject: [PATCH] Added support for RAW images. This module has been developped by the University of Perugia team. Thanks to them ! --- ChangeLog | 3 + codec/convert.c | 190 ++++++++++++++++++++++++++++++++++++++++++- codec/convert.h | 20 +++++ codec/image_to_j2k.c | 86 ++++++++++++++++---- codec/j2k_to_image.c | 40 ++++++--- 5 files changed, 308 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f3f4670..ca281130 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,9 @@ What's New for OpenJPEG ! : changed + : added +July 17, 2007 ++ [FOD] Added support for RAW images. This module has been developped by the University of Perugia team. Thanks to them ! [image_to_j2k.c j2k_to_image.c convert.c convert.h] + July 13, 2007 ! [FOD] Modified the memory allocation for codestreams containing multiple tiles. The memory is now allocated for each tile indenpendently, leading to an important decrease of the virtual memory needed. [j2k.c tcd.h tcd.c] ! [FOD] Modified old comments about the ability to decode mega-images and comments about the disk size necessary to do this. [image_to_j2k.c and frames_to_mj2.c] diff --git a/codec/convert.c b/codec/convert.c index 4aafaae8..7ab674b9 100644 --- a/codec/convert.c +++ b/codec/convert.c @@ -34,6 +34,7 @@ #include #include "openjpeg.h" #include "../libs/libtiff/tiffio.h" +#include "convert.h" /* * Get logarithm of an integer and round downwards. @@ -1236,7 +1237,7 @@ int imagetotif(opj_image_t * image, const char *outfile) { return 0; } -opj_image_t* tiftoimage(char *filename, opj_cparameters_t *parameters) +opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters) { int subsampling_dx = parameters->subsampling_dx; int subsampling_dy = parameters->subsampling_dy; @@ -1436,3 +1437,190 @@ opj_image_t* tiftoimage(char *filename, opj_cparameters_t *parameters) } return image; } + +/* -->> -->> -->> -->> + + RAW IMAGE FORMAT + + <<-- <<-- <<-- <<-- */ + +opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp) { + int subsampling_dx = parameters->subsampling_dx; + int subsampling_dy = parameters->subsampling_dy; + + FILE *f = NULL; + int i, compno, numcomps, w, h; + OPJ_COLOR_SPACE color_space; + opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */ + opj_image_t * image = NULL; + unsigned short ch; + + if((raw_cp->rawWidth * raw_cp->rawHeight * raw_cp->rawComp * raw_cp->rawBitDepth) == 0) + { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth x rawHeight x rawComp x rawBitDepth+s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512x512x3x8xu\n"); + fprintf(stderr,"Aborting\n"); + return NULL; + } + + f = fopen(filename, "rb"); + if (!f) { + fprintf(stderr, "Failed to open %s for reading !!\n", filename); + fprintf(stderr,"Aborting\n"); + return NULL; + } + numcomps = raw_cp->rawComp; + color_space = CLRSPC_SRGB; + w = raw_cp->rawWidth; + h = raw_cp->rawHeight; + + + /* initialize image components */ + memset(&cmptparm[0], 0, numcomps * sizeof(opj_image_cmptparm_t)); + for(i = 0; i < numcomps; i++) { + cmptparm[i].prec = raw_cp->rawBitDepth; + cmptparm[i].bpp = raw_cp->rawBitDepth; + cmptparm[i].sgnd = raw_cp->rawSigned; + cmptparm[i].dx = subsampling_dx; + cmptparm[i].dy = subsampling_dy; + cmptparm[i].w = w; + cmptparm[i].h = h; + } + /* create the image */ + image = opj_image_create(numcomps, &cmptparm[0], color_space); + if(!image) { + fclose(f); + return NULL; + } + + /* set image offset and reference grid */ + image->x0 = parameters->image_offset_x0; + image->y0 = parameters->image_offset_y0; + image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1; + image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1; + + if(raw_cp->rawBitDepth <= 8) + { + unsigned char value = 0; + for(compno = 0; compno < numcomps; compno++) { + for (i = 0; i < w * h; i++) { + if (!fread(&value, 1, 1, f)) { + fprintf(stderr,"Error reading raw file. End of file probably reached.\n"); + return NULL; + } + image->comps[compno].data[i] = raw_cp->rawSigned?(char)value:value; + } + } + } + else + { + unsigned short value = 0; + for(compno = 0; compno < numcomps; compno++) { + for (i = 0; i < w * h; i++) { + if (!fread(&value, 2, 1, f)) { + fprintf(stderr,"Error reading raw file. End of file probably reached.\n"); + return NULL; + } + image->comps[compno].data[i] = raw_cp->rawSigned?(short)value:value; + } + } + } + + if (fread(&ch, 1, 1, f)) { + fprintf(stderr,"Warning. End of raw file not reached... processing anyway\n"); + } + + fclose(f); + + return image; +} + +int imagetoraw(opj_image_t * image, const char *outfile) +{ + FILE *rawFile = NULL; + int compno, pixelsToWrite, offset, cont; + + if((image->numcomps * image->x1 * image->y1) == 0) + { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + return 1; + } + + rawFile = fopen(outfile, "wb"); + if (!rawFile) { + fprintf(stderr, "Failed to open %s for writing !!\n", outfile); + return 1; + } + + fprintf(stdout,"Raw image characteristics: %d components\n", image->numcomps); + + for(compno = 0; compno < image->numcomps; compno++) + { + fprintf(stdout,"Component %d characteristics: %dx%dx%d %s\n", compno, image->comps[compno].w, + image->comps[compno].h, image->comps[compno].prec, image->comps[compno].sgnd==1 ? "signed": "unsigned"); + + pixelsToWrite = image->comps[compno].w * image->comps[compno].h; + offset = 0; + + if(image->comps[compno].prec <= 8) + { + if(image->comps[compno].sgnd == 1) + { + signed char curr; + int mask = (1 << image->comps[compno].prec) - 1; + for(cont = 0; cont < pixelsToWrite; cont++) + { + curr = (signed char) (image->comps[compno].data[cont] & mask); + fwrite(&curr, sizeof(signed char), 1, rawFile); + } + } + else if(image->comps[compno].sgnd == 0) + { + unsigned char curr; + int mask = (1 << image->comps[compno].prec) - 1; + for(cont = 0; cont < pixelsToWrite; cont++) + { + curr = (unsigned char) (image->comps[compno].data[cont] & mask); + fwrite(&curr, sizeof(unsigned char), 1, rawFile); + } + } + } + else if(image->comps[compno].prec <= 16) + { + if(image->comps[compno].sgnd == 1) + { + signed short int curr; + int mask = (1 << image->comps[compno].prec) - 1; + for(cont = 0; cont < pixelsToWrite; cont++) + { + curr = (signed short int) (image->comps[compno].data[cont] & mask); + fwrite(&curr, sizeof(signed short int), 1, rawFile); + } + } + else if(image->comps[compno].sgnd == 0) + { + unsigned short int curr; + int mask = (1 << image->comps[compno].prec) - 1; + for(cont = 0; cont < pixelsToWrite; cont++) + { + curr = (unsigned short int) (image->comps[compno].data[cont] & mask); + fwrite(&curr, sizeof(unsigned short int), 1, rawFile); + } + } + } + else if (image->comps[compno].prec <= 32) + { + + + } + else + { + fprintf(stderr,"\nError: invalid precision\n"); + return 1; + } + } + fclose(rawFile); + return 0; +} diff --git a/codec/convert.h b/codec/convert.h index 68aed4b3..b2bc16de 100644 --- a/codec/convert.h +++ b/codec/convert.h @@ -31,6 +31,22 @@ #ifndef __J2K_CONVERT_H #define __J2K_CONVERT_H +/**@name RAW image encoding parameters */ +/*@{*/ +typedef struct raw_cparameters { + /** width of the raw image */ + int rawWidth; + /** height of the raw image */ + int rawHeight; + /** components of the raw image */ + int rawComp; + /** bit depth of the raw image */ + int rawBitDepth; + /** signed/unsigned raw image */ + bool rawSigned; + /*@}*/ +} raw_cparameters_t; + opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters); int imagetobmp(opj_image_t *image, const char *outfile); @@ -52,5 +68,9 @@ opj_image_t* pnmtoimage(const char *filename, opj_cparameters_t *parameters); int imagetopnm(opj_image_t *image, const char *outfile); +int imagetoraw(opj_image_t * image, const char *outfile); + +opj_image_t* rawtoimage(const char *filename, opj_cparameters_t *parameters, raw_cparameters_t *raw_cp); + #endif /* __J2K_CONVERT_H */ diff --git a/codec/image_to_j2k.c b/codec/image_to_j2k.c index 73708e30..e3899593 100644 --- a/codec/image_to_j2k.c +++ b/codec/image_to_j2k.c @@ -54,6 +54,7 @@ #define BMP_DFMT 12 #define YUV_DFMT 13 #define TIF_DFMT 14 +#define RAW_DFMT 15 /* ----------------------------------------------------------------------- */ #define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/ @@ -77,7 +78,6 @@ typedef struct img_folder{ char set_imgdir; /** Enable Cod Format for output*/ char set_out_format; - }img_fol_t; void encode_help_display() { @@ -136,7 +136,7 @@ void encode_help_display() { fprintf(stdout," Need to specify only format without filename \n"); fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP format\n"); fprintf(stdout,"\n"); - fprintf(stdout,"-i : source file (-i source.pnm also *.pgm, *.ppm) \n"); + fprintf(stdout,"-i : source file (-i source.pnm also *.pgm, *.ppm, *.bmp, *.tif, *.raw) \n"); fprintf(stdout," When using this option -o must be used\n"); fprintf(stdout,"\n"); fprintf(stdout,"-o : destination file (-o dest.j2k or .jp2) \n"); @@ -278,9 +278,7 @@ void encode_help_display() { fprintf(stdout,"Image_height Image_width\n"); fprintf(stdout,"progression order\n"); fprintf(stdout,"Tiles_size_X Tiles_size_Y\n"); -/* UniPG>> */ fprintf(stdout,"Tiles_nb_X Tiles_nb_Y\n"); -/* <> */ - const char optlist[] = "i:o:hr:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:" + const char optlist[] = "i:o:hr:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:" #ifdef USE_JPWL "W:" #endif /* USE_JPWL */ @@ -568,10 +566,10 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,i totlen=sizeof(long_option); img_fol->set_out_format=0; + raw_cp->rawWidth = 0; while (1) { int c = getopt_long(argc, argv, optlist,long_option,totlen); -/* <outfile, outfile, sizeof(parameters->outfile)-1); @@ -628,7 +627,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,i img_fol->out_format = optarg; break; default: - fprintf(stderr, "Unknown output format image [only j2k, jp2]!! \n"); + fprintf(stderr, "Unknown output format image [only j2k, j2c, jp2]!! \n"); return 1; } } @@ -656,6 +655,41 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,i /* ----------------------------------------------------- */ + + case 'F': /* Raw image format parameters */ + { + char signo; + char *s = optarg; + if (sscanf(s, "%dx%dx%dx%dx%c", &raw_cp->rawWidth, &raw_cp->rawHeight, &raw_cp->rawComp, &raw_cp->rawBitDepth, &signo) == 5) { + if (signo == 's') { + raw_cp->rawSigned = true; + fprintf(stdout,"\nRaw file parameters: %dx%dx%dx%d Signed\n", raw_cp->rawWidth, raw_cp->rawHeight, raw_cp->rawComp, raw_cp->rawBitDepth); + } + else if (signo == 'u') { + raw_cp->rawSigned = false; + fprintf(stdout,"\nRaw file parameters: %dx%dx%dx%d Unsigned\n", raw_cp->rawWidth, raw_cp->rawHeight, raw_cp->rawComp, raw_cp->rawBitDepth); + } + else { + fprintf(stderr,"\nError: invalid raw image parameters: Unknown sign of raw file\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth x rawHeight x rawComp x rawBitDepth+s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512x512x3x8xu\n"); + fprintf(stderr,"Aborting\n"); + } + } + else { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth x rawHeight x rawComp x rawBitDepth+s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512x512x3x8xu\n"); + fprintf(stderr,"Aborting\n"); + return 1; + } + } + break; + + /* ----------------------------------------------------- */ + case 'q': /* add fixed_quality */ { char *s = optarg; @@ -1348,6 +1382,15 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,i } } + if (parameters->decod_format == RAW_DFMT && raw_cp->rawWidth == 0) { + fprintf(stderr,"\nError: invalid raw image parameters\n"); + fprintf(stderr,"Please use the Format option -F:\n"); + fprintf(stderr,"-F rawWidth x rawHeight x rawComp x rawBitDepth+s/u (Signed/Unsigned)\n"); + fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512x512x3x8xu\n"); + fprintf(stderr,"Aborting\n"); + return 1; + } + if ((parameters->cp_disto_alloc || parameters->cp_fixed_alloc || parameters->cp_fixed_quality) && (!(parameters->cp_disto_alloc ^ parameters->cp_fixed_alloc ^ parameters->cp_fixed_quality))) { fprintf(stderr, "Error: options -r -q and -f cannot be used together !!\n"); @@ -1414,6 +1457,7 @@ int main(int argc, char **argv) { int i,num_images; int imageno; dircnt_t *dirptr; + raw_cparameters_t raw_cp; /* configure the event callbacks (not required) @@ -1428,14 +1472,13 @@ int main(int argc, char **argv) { opj_set_default_encoder_parameters(¶meters); /* parse input and get user encoding parameters */ - if(parse_cmdline_encoder(argc, argv, ¶meters,&img_fol) == 1) { + if(parse_cmdline_encoder(argc, argv, ¶meters,&img_fol, &raw_cp) == 1) { return 0; } if (parameters.cp_cinema){ cinema_parameters(¶meters); - } - + } /* Create comment for codestream */ if(parameters.cp_comment == NULL) { @@ -1504,7 +1547,8 @@ int main(int argc, char **argv) { break; case TIF_DFMT: break; - + case RAW_DFMT: + break; default: fprintf(stderr,"skipping file...\n"); continue; @@ -1545,6 +1589,14 @@ int main(int argc, char **argv) { return 1; } break; + + case RAW_DFMT: + image = rawtoimage(parameters.infile, ¶meters, &raw_cp); + if (!image) { + fprintf(stderr, "Unable to load raw file\n"); + return 1; + } + break; } /* Decide if MCT should be used */ parameters.tcp_mct = image->numcomps == 3 ? 1 : 0; diff --git a/codec/j2k_to_image.c b/codec/j2k_to_image.c index 1cf9dbcc..977b1d03 100644 --- a/codec/j2k_to_image.c +++ b/codec/j2k_to_image.c @@ -54,6 +54,7 @@ #define BMP_DFMT 12 #define YUV_DFMT 13 #define TIF_DFMT 14 +#define RAW_DFMT 15 /* ----------------------------------------------------------------------- */ @@ -95,15 +96,15 @@ void decode_help_display() { fprintf(stdout," -OutFor \n"); fprintf(stdout," REQUIRED only if -ImgDir is used\n"); fprintf(stdout," Need to specify only format without filename \n"); - fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP format\n"); + fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP, TIF and RAW formats\n"); fprintf(stdout," -i \n"); fprintf(stdout," REQUIRED only if an Input image directory not specified\n"); fprintf(stdout," Currently accepts J2K-files, JP2-files and JPT-files. The file type\n"); fprintf(stdout," is identified based on its suffix.\n"); fprintf(stdout," -o \n"); fprintf(stdout," REQUIRED\n"); - fprintf(stdout," Currently accepts PGM-files, PPM-files, PNM-files, PGX-files and\n"); - fprintf(stdout," BMP-files. Binary data is written to the file (not ascii). If a PGX\n"); + fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP, TIF and RAW files\n"); + fprintf(stdout," Binary data is written to the file (not ascii). If a PGX\n"); fprintf(stdout," filename is given, there will be as many output files as there are\n"); fprintf(stdout," components: an indice starting from 0 will then be appended to the\n"); fprintf(stdout," output filename, just before the \"pgx\" extension. If a PGM filename\n"); @@ -181,8 +182,8 @@ int load_images(dircnt_t *dirptr, char *imgdirpath){ int get_file_format(char *filename) { unsigned int i; - static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "j2k", "jp2", "jpt", "j2c" }; - static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT }; + static const char *extension[] = {"pgx", "pnm", "pgm", "ppm", "bmp","tif", "raw", "j2k", "jp2", "jpt", "j2c" }; + static const int format[] = { PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, RAW_DFMT, J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT }; char * ext = strrchr(filename, '.'); if (ext == NULL) return -1; @@ -229,14 +230,14 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i {"OutFor",REQ_ARG, NULL ,'O'}, }; -/* UniPG>> */ const char optlist[] = "i:o:r:l:h" +/* UniPG>> */ #ifdef USE_JPWL "W:" #endif /* USE_JPWL */ - ; /* <set_out_format = 0; while (1) { @@ -274,9 +275,10 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i case PXM_DFMT: case BMP_DFMT: case TIF_DFMT: + case RAW_DFMT: break; default: - fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx or *.bmp]!! \n", outfile); + fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif or *.raw]!! \n", outfile); return 1; } strncpy(parameters->outfile, outfile, sizeof(parameters->outfile)-1); @@ -305,8 +307,11 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i case TIF_DFMT: img_fol->out_format = "tif"; break; + case RAW_DFMT: + img_fol->out_format = "raw"; + break; default: - fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx or *.bmp]!! \n"); + fprintf(stderr, "Unknown output format image %s [only *.pnm, *.pgm, *.ppm, *.pgx, *.bmp, *.tif or *.raw]!! \n"); return 1; break; } @@ -434,7 +439,7 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i } if(img_fol->set_out_format == 0){ fprintf(stderr, "Error: When -ImgDir is used, -OutFor must be used !!\n"); - fprintf(stderr, "Only one format allowed! Valid format PGM, PPM, PNM, PGX,BMP!!\n"); + fprintf(stderr, "Only one format allowed! Valid format PGM, PPM, PNM, PGX, BMP, TIF, RAW!!\n"); return 1; } if(!((parameters->outfile[0] == 0))){ @@ -443,9 +448,9 @@ int parse_cmdline_decoder(int argc, char **argv, opj_dparameters_t *parameters,i } }else{ if((parameters->infile[0] == 0) || (parameters->outfile[0] == 0)) { - fprintf(stderr, "Error: One of option; -i or -ImgDir must be specified\n"); - fprintf(stderr, "Error: When using -i; -o must be used\n"); - fprintf(stderr, "usage: image_to_j2k -i *.j2k/jp2 -o *.pgm/ppm/pnm/pgx/bmp(+ options)\n"); + fprintf(stderr, "Error: One of the options -i or -ImgDir must be specified\n"); + fprintf(stderr, "Error: When using -i, -o must be used\n"); + fprintf(stderr, "usage: image_to_j2k -i *.j2k/jp2/j2c -o *.pgm/ppm/pnm/pgx/bmp/tif/raw(+ options)\n"); return 1; } } @@ -708,6 +713,15 @@ int main(int argc, char **argv) { fprintf(stdout,"Generated Outfile %s\n",parameters.outfile); } break; + + case RAW_DFMT: /* RAW */ + if(imagetoraw(image, parameters.outfile)){ + fprintf(stdout,"Error generating raw file. Outfile %s not generated\n",parameters.outfile); + } + else { + fprintf(stdout,"Successfully generated Outfile %s\n",parameters.outfile); + } + break; } /* free remaining structures */