From f1d69068c7d677a3e9c8c0963904cae80ce22ca0 Mon Sep 17 00:00:00 2001 From: Antonin Descampe Date: Wed, 26 Mar 2014 14:26:49 +0000 Subject: [PATCH] [trunk] add ability in opj_compress to input subsampled images through '-F' (aka raw option). Let the user input raw images with 444, 422, 420 (etc) subsampling. To be used in conjunction with '-mct 0' option to compress subsampled YCC images. --- src/bin/jp2/convert.c | 30 +++++++++---- src/bin/jp2/convert.h | 22 +++++++--- src/bin/jp2/opj_compress.c | 90 ++++++++++++++++++++++++++++++-------- 3 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/bin/jp2/convert.c b/src/bin/jp2/convert.c index d3e9773c..0033b523 100644 --- a/src/bin/jp2/convert.c +++ b/src/bin/jp2/convert.c @@ -2953,9 +2953,11 @@ static opj_image_t* rawtoimage_common(const char *filename, opj_cparameters_t *p { fprintf(stderr,"\nError: invalid raw image parameters\n"); fprintf(stderr,"Please use the Format option -F:\n"); - fprintf(stderr,"-F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); - fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); - fprintf(stderr,"Aborting\n"); + fprintf(stderr,"-F ,,,,{s,u}@x:...:x\n"); + fprintf(stderr,"If subsampling is omitted, 1x1 is assumed for all components\n"); + fprintf(stderr,"Example: -i image.raw -o image.j2k -F 512,512,3,8,u@1x1:2x2:2x2\n"); + fprintf(stderr," for raw 512x512 image with 4:2:0 subsampling\n"); + fprintf(stderr,"Aborting.\n"); return NULL; } @@ -2966,7 +2968,17 @@ static opj_image_t* rawtoimage_common(const char *filename, opj_cparameters_t *p return NULL; } numcomps = raw_cp->rawComp; - color_space = OPJ_CLRSPC_SRGB; + + /* FIXME ADE at this point, tcp_mct has not been properly set in calling function */ + if (numcomps == 0) { + color_space = OPJ_CLRSPC_GRAY; + } else if ((numcomps >= 3) && (parameters->tcp_mct == 0)) { + color_space = OPJ_CLRSPC_SYCC; + } else if ((numcomps >= 3) && (parameters->tcp_mct != 2)) { + color_space = OPJ_CLRSPC_SRGB; + } else { + color_space = OPJ_CLRSPC_UNKNOWN; + } w = raw_cp->rawWidth; h = raw_cp->rawHeight; cmptparm = (opj_image_cmptparm_t*) malloc((size_t)numcomps * sizeof(opj_image_cmptparm_t)); @@ -2977,8 +2989,8 @@ static opj_image_t* rawtoimage_common(const char *filename, opj_cparameters_t *p cmptparm[i].prec = (OPJ_UINT32)raw_cp->rawBitDepth; cmptparm[i].bpp = (OPJ_UINT32)raw_cp->rawBitDepth; cmptparm[i].sgnd = (OPJ_UINT32)raw_cp->rawSigned; - cmptparm[i].dx = (OPJ_UINT32)subsampling_dx; - cmptparm[i].dy = (OPJ_UINT32)subsampling_dy; + cmptparm[i].dx = (OPJ_UINT32)subsampling_dx * raw_cp->rawComps[i].dx; + cmptparm[i].dy = (OPJ_UINT32)subsampling_dy * raw_cp->rawComps[i].dy; cmptparm[i].w = (OPJ_UINT32)w; cmptparm[i].h = (OPJ_UINT32)h; } @@ -2999,7 +3011,8 @@ static opj_image_t* rawtoimage_common(const char *filename, opj_cparameters_t *p { unsigned char value = 0; for(compno = 0; compno < numcomps; compno++) { - for (i = 0; i < w * h; i++) { + int nloop = (w*h)/(raw_cp->rawComps[compno].dx*raw_cp->rawComps[compno].dx); + for (i = 0; i < nloop; i++) { if (!fread(&value, 1, 1, f)) { fprintf(stderr,"Error reading raw file. End of file probably reached.\n"); return NULL; @@ -3012,7 +3025,8 @@ static opj_image_t* rawtoimage_common(const char *filename, opj_cparameters_t *p { unsigned short value; for(compno = 0; compno < numcomps; compno++) { - for (i = 0; i < w * h; i++) { + int nloop = (w*h)/(raw_cp->rawComps[compno].dx*raw_cp->rawComps[compno].dx); + for (i = 0; i < nloop; i++) { unsigned char temp1; unsigned char temp2; if (!fread(&temp1, 1, 1, f)) { diff --git a/src/bin/jp2/convert.h b/src/bin/jp2/convert.h index 11bc31ee..360d9293 100644 --- a/src/bin/jp2/convert.h +++ b/src/bin/jp2/convert.h @@ -31,6 +31,16 @@ #ifndef __J2K_CONVERT_H #define __J2K_CONVERT_H +/**@name RAW component encoding parameters */ +/*@{*/ +typedef struct raw_comp_cparameters { + /** subsampling in X direction */ + int dx; + /** subsampling in Y direction */ + int dy; + /*@}*/ +} raw_comp_cparameters_t; + /**@name RAW image encoding parameters */ /*@{*/ typedef struct raw_cparameters { @@ -38,12 +48,14 @@ typedef struct raw_cparameters { int rawWidth; /** height of the raw image */ int rawHeight; - /** components of the raw image */ + /** number of components of the raw image */ int rawComp; - /** bit depth of the raw image */ - int rawBitDepth; - /** signed/unsigned raw image */ - OPJ_BOOL rawSigned; + /** bit depth of the raw image */ + int rawBitDepth; + /** signed/unsigned raw image */ + OPJ_BOOL rawSigned; + /** raw components parameters */ + raw_comp_cparameters_t *rawComps; /*@}*/ } raw_cparameters_t; diff --git a/src/bin/jp2/opj_compress.c b/src/bin/jp2/opj_compress.c index f3a20d0d..8bd8b4d3 100644 --- a/src/bin/jp2/opj_compress.c +++ b/src/bin/jp2/opj_compress.c @@ -209,7 +209,7 @@ static void encode_help_display(void) { fprintf(stdout," -F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); fprintf(stdout," Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); fprintf(stdout,"\n"); - fprintf(stdout,"-mct {0,1,2} : explicitely specifies if an Multiple Component Transform has to be used.\n"); + fprintf(stdout,"-mct {0,1,2} : explicitely specifies if a Multiple Component Transform has to be used.\n"); fprintf(stdout," 0: no MCT ; 1: RGB->YCC conversion ; 2: custom MCT.\n"); fprintf(stdout," If custom MCT, \"-m\" option has to be used (see hereunder).\n"); fprintf(stdout," By default, RGB->YCC conversion is used if there are 3 components or more,\n"); @@ -569,33 +569,84 @@ static int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *param case 'F': /* Raw image format parameters */ { + OPJ_BOOL wrong = OPJ_FALSE; + char *substr1; + char *substr2; + char *sep; char signo; - char *s = opj_optarg; - if (sscanf(s, "%d,%d,%d,%d,%c", &raw_cp->rawWidth, &raw_cp->rawHeight, &raw_cp->rawComp, &raw_cp->rawBitDepth, &signo) == 5) { + int width,height,bitdepth,ncomp; + int len; + OPJ_BOOL raw_signed; + substr2 = strchr(opj_optarg,'@'); + if (substr2 == NULL) { + len = (int) strlen(opj_optarg); + } else { + len = substr2 - opj_optarg; + substr2++; /* skip '@' character */ + } + substr1 = (char*) malloc((len+1)*sizeof(char)); + memcpy(substr1,opj_optarg,len); + substr1[len] = '\0'; + if (sscanf(substr1, "%d,%d,%d,%d,%[su]", &width, &height, &ncomp, &bitdepth, &signo) == 5) { if (signo == 's') { - raw_cp->rawSigned = OPJ_TRUE; - fprintf(stdout,"\nRaw file parameters: %d,%d,%d,%d Signed\n", raw_cp->rawWidth, raw_cp->rawHeight, raw_cp->rawComp, raw_cp->rawBitDepth); + raw_signed = OPJ_TRUE; + } else if (signo == 'u') { + raw_signed = OPJ_FALSE; + } else { + wrong = OPJ_TRUE; } - else if (signo == 'u') { - raw_cp->rawSigned = OPJ_FALSE; - fprintf(stdout,"\nRaw file parameters: %d,%d,%d,%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,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); - fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); - fprintf(stderr,"Aborting\n"); + } else { + wrong = OPJ_TRUE; + } + if (!wrong) { + int i; + int lastdx = 1; + int lastdy = 1; + raw_cp->rawWidth = width; + raw_cp->rawHeight = height; + raw_cp->rawComp = ncomp; + raw_cp->rawBitDepth = bitdepth; + raw_cp->rawSigned = raw_signed; + raw_cp->rawComps = (raw_comp_cparameters_t*) malloc(ncomp*sizeof(raw_comp_cparameters_t)); + for (i = 0; i < ncomp && !wrong; i++) { + if (substr2 == NULL) { + raw_cp->rawComps[i].dx = lastdx; + raw_cp->rawComps[i].dy = lastdy; + } else { + int dx,dy; + sep = strchr(substr2,':'); + if (sep == NULL) { + if (sscanf(substr2, "%dx%d", &dx, &dy) == 2) { + lastdx = dx; + lastdy = dy; + raw_cp->rawComps[i].dx = dx; + raw_cp->rawComps[i].dy = dy; + substr2 = NULL; + } else { + wrong = OPJ_TRUE; + } + } else { + if (sscanf(substr2, "%dx%d:%s", &dx, &dy, substr2) == 3) { + raw_cp->rawComps[i].dx = dx; + raw_cp->rawComps[i].dy = dy; + } else { + wrong = OPJ_TRUE; + } + } + } } } - else { + if (wrong) { fprintf(stderr,"\nError: invalid raw image parameters\n"); fprintf(stderr,"Please use the Format option -F:\n"); - fprintf(stderr,"-F rawWidth,rawHeight,rawComp,rawBitDepth,s/u (Signed/Unsigned)\n"); - fprintf(stderr,"Example: -i lena.raw -o lena.j2k -F 512,512,3,8,u\n"); - fprintf(stderr,"Aborting\n"); + fprintf(stderr,"-F ,,,,{s,u}@x:...:x\n"); + fprintf(stderr,"If subsampling is omitted, 1x1 is assumed for all components\n"); + fprintf(stderr,"Example: -i image.raw -o image.j2k -F 512,512,3,8,u@1x1:2x2:2x2\n"); + fprintf(stderr," for raw 512x512 image with 4:2:0 subsampling\n"); + fprintf(stderr,"Aborting.\n"); return 1; } + if (substr1 != NULL) free(substr1); } break; @@ -1749,6 +1800,7 @@ int main(int argc, char **argv) { /* free user parameters structure */ if(parameters.cp_comment) free(parameters.cp_comment); if(parameters.cp_matrice) free(parameters.cp_matrice); + if(raw_cp.rawComps) free(raw_cp.rawComps); return 0; }