diff --git a/ChangeLog b/ChangeLog index 5ec873e2..3c55378f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,13 @@ What's New for OpenJPEG ! : changed + : added +March 7, 2007 ++ [Parvatha] Added option for Digital cinema profile compliant codestream. This can be chosen by "-cinema2K" or "-cinema4K" for a 2K and 4K compliance respectively. The feature for tileparts has not been implemented in this version. Modification in image_to_j2k.c ++ [Parvatha] Added the Digital Cinema profiles (CINEMA2K and CINEMA4K) to the list of profiles recognized in the codestream SIZ marker segment. Modification in openjpeg.h,j2k.c ++ [Parvatha] Added feature for constant quality within bitrate defined in Digital cinema standards. Modification in tcd.c +! [Parvatha] Modified the method of generation of buffer length. Modification in cio.c + + March 1, 2007 * [FOD] Modified codec projects (*.dsp) and makefile to include the tiff library (modified codec/image_to_j2k.dsp codec/j2k_to_image.dsp and codec/makefile) + [GB] Zoom capability and decoder settings dialog in OPJViewer; modified JPWL library .dsp project in order to create a library with embedded JPWL functions diff --git a/codec/image_to_j2k.c b/codec/image_to_j2k.c index 28208c5c..014ae1d9 100644 --- a/codec/image_to_j2k.c +++ b/codec/image_to_j2k.c @@ -55,6 +55,8 @@ #define TIF_DFMT 14 /* ----------------------------------------------------------------------- */ +#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/ +#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/ typedef struct dircnt{ /** Buffer for holding images read from Directory*/ @@ -125,8 +127,10 @@ void encode_help_display() { fprintf(stdout,"------------\n"); fprintf(stdout,"\n"); fprintf(stdout,"Required Parameters (except with -h):\n"); + fprintf(stdout,"One of the two options -ImgDir or -i must be used\n"); fprintf(stdout,"\n"); fprintf(stdout,"-ImgDir : Image file Directory path (example ../Images) \n"); + fprintf(stdout," When using this option -OutFor must be used\n"); fprintf(stdout,"\n"); fprintf(stdout,"-OutFor \n"); fprintf(stdout," REQUIRED only if -ImgDir is used\n"); @@ -134,6 +138,7 @@ void encode_help_display() { 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," When using this option -o must be used\n"); fprintf(stdout,"\n"); fprintf(stdout,"-o : destination file (-o dest.j2k or .jp2) \n"); fprintf(stdout,"\n"); @@ -141,6 +146,12 @@ void encode_help_display() { fprintf(stdout,"\n"); fprintf(stdout,"-h : display the help information \n "); fprintf(stdout,"\n"); + fprintf(stdout,"-cinema2k : Digital Cinema 2K profile compliant codestream for 2K resolution.(-cinema2k 24 or 48) \n"); + fprintf(stdout," Need to specify the frames per second for a 2K resolution. Only 24 or 48 fps is allowed\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"-cinema4k : Digital Cinema 4K profile compliant codestream for 4K resolution \n"); + fprintf(stdout," Frames per second not required. Default value is 24fps\n"); + fprintf(stdout,"\n"); fprintf(stdout,"-r : different compression ratios for successive layers (-r 20,10,5)\n "); fprintf(stdout," - The rate specified for each quality level is the desired \n"); fprintf(stdout," compression factor.\n"); @@ -403,16 +414,92 @@ char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_cparamet } +void cinema_setup_encoder(opj_cparameters_t *parameters,opj_image_t *image){ + int i; + float temp_rate; + + parameters->tile_size_on = false; + parameters->cp_tdx=1; + parameters->cp_tdy=1; + /*Tile and Image shall be at (0,0)*/ + parameters->cp_tx0=0; parameters->cp_ty0=0; + + /*Codeblock size= 32*32*/ + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + + /*The progression order shall be CPRL*/ + strncpy(parameters->cp_prog,"CPRL",4); + parameters->prog_order = give_progression(parameters->cp_prog); + /*Tile parts not implemented*/ + + /* No ROI */ + parameters->roi_compno = -1; + + parameters->subsampling_dx = 1; parameters->subsampling_dy = 1; + + switch (parameters->cp_cinema){ + case CINEMA2K_24: + case CINEMA4K_24: + if (image->comps[0].w == 2048 || image->comps[0].h == 1080){ + parameters->numresolution = 6; + parameters->cp_rsiz = CINEMA2K; + }else{ + fprintf(stdout,"One of the image coordinates are not 2K\n"); + } + + for(i=0;itcp_numlayers;i++){ + temp_rate = 0 ; + if (parameters->tcp_rates[i]== 0){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (parameters->tcp_rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > CINEMA_24_CS ){ + parameters->tcp_rates[i]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy); + } + } + } + break; + + case CINEMA2K_48: + if (image->comps[0].w == 4096 || image->comps[0].h == 2160){ + parameters->numresolution = 7; + parameters->cp_rsiz= CINEMA4K; + }else{ + fprintf(stdout,"One of the image coordinates are not 4K\n"); + } + for(i=0;itcp_numlayers;i++){ + if (parameters->tcp_rates[i]== 0){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + }else{ + parameters->tcp_rates[i]=((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (parameters->tcp_rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (parameters->tcp_rates[i] > CINEMA_48_CS ){ + parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/ + (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy); + } + } + } + break; + +} + + parameters->cp_disto_alloc = 1; +} /* ------------------------------------------------------------------------------------ */ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,img_fol_t *img_fol) { int i, j,totlen; option_t long_option[]={ - {"DCI",NO_ARG, NULL ,'z'}, - {"ImgDir",REQ_ARG, NULL ,'y'}, - {"fps",REQ_ARG, NULL ,'w'}, + {"cinema2k",REQ_ARG, NULL ,'w'}, + {"cinema4k",NO_ARG, NULL ,'y'}, + {"ImgDir",REQ_ARG, NULL ,'z'}, {"TP",REQ_ARG, NULL ,'v'}, {"SOP",NO_ARG, NULL ,'S'}, {"EPH",NO_ARG, NULL ,'E'}, @@ -803,17 +890,45 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,i break; /* ------------------------------------------------------ */ - - case 'y': /* Image Directory path */ - { - img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1); - strcpy(img_fol->imgdirpath,optarg); - img_fol->set_imgdir=1; - } - break; - + + case 'z': /* Image Directory path */ + { + img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1); + strcpy(img_fol->imgdirpath,optarg); + img_fol->set_imgdir=1; + } + break; /* ------------------------------------------------------ */ + + case 'w': /* Digital Cinema 2K profile compliance*/ + { + int fps=0; + sscanf(optarg,"%d",&fps); + if(fps == 24){ + parameters->cp_cinema = CINEMA2K_24; + }else if(fps == 48 ){ + parameters->cp_cinema = CINEMA2K_48; + }else { + fprintf(stderr,"Incorrect value!! must be 24 or 48\n"); + return 1; + } + fprintf(stdout,"CINEMA 2K compliant codestream\n"); + + } + break; + + /* ------------------------------------------------------ */ + + case 'y': /* Digital Cinema 4K profile compliance*/ + { + parameters->cp_cinema = CINEMA4K_24; + fprintf(stdout,"CINEMA 4K compliant codestream\n"); + } + break; + + /* ------------------------------------------------------ */ + /* UniPG>> */ #ifdef USE_JPWL /* ------------------------------------------------------ */ @@ -1379,6 +1494,10 @@ int main(int argc, char **argv) { /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + if(parameters.cp_cinema){ + cinema_setup_encoder(¶meters,image); + } + /* setup the encoder parameters using the current image and user parameters */ opj_setup_encoder(cinfo, ¶meters, image); diff --git a/libopenjpeg/cio.c b/libopenjpeg/cio.c index eadf71b2..6082e9be 100644 --- a/libopenjpeg/cio.c +++ b/libopenjpeg/cio.c @@ -58,7 +58,7 @@ opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer opj_free(cio); return NULL; } - cio->length = cp->tdx * cp->tdy * cp->tw * cp->th * 4; + cio->length = (int) (1.3 * cp->img_size); cio->buffer = (unsigned char *)opj_malloc(cio->length); if(!cio->buffer) { opj_free(cio); diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index db291ff2..fb9aeaff 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -324,7 +324,7 @@ static void j2k_write_siz(opj_j2k_t *j2k) { cio_write(cio, J2K_MS_SIZ, 2); /* SIZ */ lenp = cio_tell(cio); cio_skip(cio, 2); - cio_write(cio, 0, 2); /* Rsiz (capabilities) */ + cio_write(cio, cp->rsiz, 2); /* Rsiz (capabilities) */ cio_write(cio, image->x1, 4); /* Xsiz */ cio_write(cio, image->y1, 4); /* Ysiz */ cio_write(cio, image->x0, 4); /* X0siz */ @@ -1780,7 +1780,8 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ /* copy user encoding parameters */ - + cp->cinema = parameters->cp_cinema; + cp->rsiz = parameters->cp_rsiz; cp->disto_alloc = parameters->cp_disto_alloc; cp->fixed_alloc = parameters->cp_fixed_alloc; cp->fixed_quality = parameters->cp_fixed_quality; @@ -1826,6 +1827,11 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ cp->tdy = image->y1 - cp->ty0; } + cp->img_size = 0; + for(i=0;inumcomps ;i++){ + cp->img_size += (image->comps[i].w *image->comps[i].h * image->comps[i].prec); + } + /* UniPG>> */ #ifdef USE_JPWL /* @@ -1940,42 +1946,60 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_ } else { tccp->roishift = 0; } - if (parameters->csty & J2K_CCP_CSTY_PRT) { - int p = 0; - for (j = tccp->numresolutions - 1; j >= 0; j--) { - if (p < parameters->res_spec) { - if (parameters->prcw_init[p] < 1) { - tccp->prcw[j] = 1; - } else { - tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]); - } - if (parameters->prch_init[p] < 1) { - tccp->prch[j] = 1; - } else { - tccp->prch[j] = int_floorlog2(parameters->prch_init[p]); - } - } else { - int res_spec = parameters->res_spec; - int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); - int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); - if (size_prcw < 1) { - tccp->prcw[j] = 1; - } else { - tccp->prcw[j] = int_floorlog2(size_prcw); - } - if (size_prch < 1) { - tccp->prch[j] = 1; - } else { - tccp->prch[j] = int_floorlog2(size_prch); - } - } - p++; - /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */ + + if(parameters->cp_cinema) + { + //Precinct size for lowest frequency subband=128 + tccp->prcw[0] = 7; + tccp->prch[0] = 7; + //Precinct size at all other resolutions = 256 + for (j = 1; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 8; + tccp->prch[j] = 8; } - } else { - for (j = 0; j < tccp->numresolutions; j++) { - tccp->prcw[j] = 15; - tccp->prch[j] = 15; + }else{ + if (parameters->csty & J2K_CCP_CSTY_PRT) { + int p = 0; + for (j = tccp->numresolutions - 1; j >= 0; j--) { + if (p < parameters->res_spec) { + + if (parameters->prcw_init[p] < 1) { + tccp->prcw[j] = 1; + } else { + tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]); + } + + if (parameters->prch_init[p] < 1) { + tccp->prch[j] = 1; + }else { + tccp->prch[j] = int_floorlog2(parameters->prch_init[p]); + } + + } else { + int res_spec = parameters->res_spec; + int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); + int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); + + if (size_prcw < 1) { + tccp->prcw[j] = 1; + } else { + tccp->prcw[j] = int_floorlog2(size_prcw); + } + + if (size_prch < 1) { + tccp->prch[j] = 1; + } else { + tccp->prch[j] = int_floorlog2(size_prch); + } + } + p++; + /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */ + } //end for + } else { + for (j = 0; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 15; + tccp->prch[j] = 15; + } } } diff --git a/libopenjpeg/j2k.h b/libopenjpeg/j2k.h index 9738bf85..5f8e0824 100644 --- a/libopenjpeg/j2k.h +++ b/libopenjpeg/j2k.h @@ -187,6 +187,12 @@ typedef struct opj_tcp { Coding parameters */ typedef struct opj_cp { + /** Digital cinema profile*/ + OPJ_CINEMA_MODE cinema; + /** Size of the image in bits*/ + int img_size; + /** Rsiz*/ + OPJ_RSIZ_CAPABILITIES rsiz; /** allocation by rate/distortion */ int disto_alloc; /** allocation by fixed layer */ diff --git a/libopenjpeg/openjpeg.c b/libopenjpeg/openjpeg.c index b522939e..3db8a5f7 100644 --- a/libopenjpeg/openjpeg.c +++ b/libopenjpeg/openjpeg.c @@ -222,7 +222,9 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *paramete if(parameters) { memset(parameters, 0, sizeof(opj_cparameters_t)); /* default coding parameters */ + parameters->cp_cinema = OFF; parameters->numresolution = 6; + parameters->cp_rsiz = STD_RSIZ; parameters->cblockw_init = 64; parameters->cblockh_init = 64; parameters->prog_order = LRCP; diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h index ceb5df2c..d5543b92 100644 --- a/libopenjpeg/openjpeg.h +++ b/libopenjpeg/openjpeg.h @@ -113,6 +113,19 @@ braindamage below. ========================================================== */ +typedef enum RSIZ_CAPABILITIES { + STD_RSIZ = 0, + CINEMA2K = 3, /** Profile name for a 2K image*/ + CINEMA4K = 4 /** Profile name for a 4K image*/ +} OPJ_RSIZ_CAPABILITIES; + +typedef enum CINEMA_MODE { + OFF = 0, + CINEMA2K_24 = 1, + CINEMA2K_48 = 2, + CINEMA4K_24 = 3 +}OPJ_CINEMA_MODE; + /** Progression order */ typedef enum PROG_ORDER { PROG_UNKNOWN = -1, /**< place-holder */ @@ -204,6 +217,12 @@ typedef struct opj_poc { Compression parameters */ typedef struct opj_cparameters { + /** Digital Cinema compliance 0-not compliant, 1-compliant*/ + OPJ_CINEMA_MODE cp_cinema; + /** Progression order*/ + char cp_prog[4]; + /** Profile name*/ + OPJ_RSIZ_CAPABILITIES cp_rsiz; /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ bool tile_size_on; /** XTOsiz */ diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c index 73c3ef5e..89658ce7 100644 --- a/libopenjpeg/tcd.c +++ b/libopenjpeg/tcd.c @@ -1040,13 +1040,29 @@ bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_image_in tcd_makelayer(tcd, layno, thresh, 0); if (cp->fixed_quality) { /* fixed_quality */ - distoachieved = (layno == 0) ? - tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); - if (distoachieved < distotarget) { - hi = thresh; - continue; + if(cp->cinema){ + l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, image_info); + if (l == -999) { + lo = thresh; + continue; + }else{ + distoachieved = layno == 0 ? + tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; + if (distoachieved < distotarget) { + hi=thresh; continue; + }else{ + lo=thresh; + } + } + }else{ + distoachieved = (layno == 0) ? + tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + if (distoachieved < distotarget) { + hi = thresh; + continue; + } + lo = thresh; } - lo = thresh; } else { l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, image_info); /* TODO: what to do with l ??? seek / tell ??? */