]> granicus.if.org Git - openjpeg/commitdiff
[trunk] modify image_to_j2k and the lib to support functionalities given by the v2...
authorMickael Savinaud <savmickael@users.noreply.github.com>
Thu, 15 Mar 2012 10:23:20 +0000 (10:23 +0000)
committerMickael Savinaud <savmickael@users.noreply.github.com>
Thu, 15 Mar 2012 10:23:20 +0000 (10:23 +0000)
20 files changed:
applications/codec/image_to_j2k.c
libopenjpeg/dwt.c
libopenjpeg/dwt.h
libopenjpeg/int.h
libopenjpeg/j2k.c
libopenjpeg/j2k.h
libopenjpeg/jp2.c
libopenjpeg/jp2.h
libopenjpeg/mct.c
libopenjpeg/mct.h
libopenjpeg/openjpeg.c
libopenjpeg/openjpeg.h
libopenjpeg/pi.c
libopenjpeg/pi.h
libopenjpeg/t1.c
libopenjpeg/t1.h
libopenjpeg/t2.c
libopenjpeg/t2.h
libopenjpeg/tcd.c
libopenjpeg/tcd.h

index cbdc1e6009d5725be28aad6aac0b601b797fdc35..7d2bba0d9682b1df2c1af41d4299a752004b854d 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
  * Copyright (c) 2005, Herve Drolon, FreeImage Team
  * Copyright (c) 2006-2007, Parvatha Elangovan
+ * Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -211,6 +212,8 @@ 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,"-m           : use array-based MCT, values are coma separated, line by line\n");
+       fprintf(stdout,"                           no specific separators between lines, no space allowed between values\n");
        fprintf(stdout,"-jpip        : write jpip codestream index box in JP2 output file\n");
        fprintf(stdout,"               NOTICE: currently supports only RPCL order\n");
        fprintf(stdout,"\n");
@@ -1054,6 +1057,73 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,
                        }
                        break;
 
+                               /* ------------------------------------------------------ */
+                       case 'm':                       /* mct input file */
+                       {
+                               char *lFilename = opj_optarg;
+                               char *lMatrix;
+                               char *lCurrentPtr ;
+                               float *lCurrentDoublePtr;
+                               float *lSpace;
+                               int *l_int_ptr;
+                               int lNbComp = 0, lTotalComp, lMctComp, i, lStrLen;
+
+                               /* Open file */
+                               FILE * lFile = fopen(lFilename,"r");
+                               if (lFile == NULL) {
+                                       return 1;
+                               }
+
+                               /* Set size of file and read its content*/
+                               fseek(lFile,0,SEEK_END);
+                               lStrLen = ftell(lFile);
+                               fseek(lFile,0,SEEK_SET);
+                               lMatrix = (char *) malloc(lStrLen + 1);
+                               fread(lMatrix, lStrLen, 1, lFile);
+                               fclose(lFile);
+
+                               lMatrix[lStrLen] = 0;
+                               lCurrentPtr = lMatrix;
+
+                               /* replace ',' by 0 */
+                               while (*lCurrentPtr != 0 ) {
+                                       if (*lCurrentPtr == ' ') {
+                                               *lCurrentPtr = 0;
+                                               ++lNbComp;
+                                       }
+                                       ++lCurrentPtr;
+                               }
+                               ++lNbComp;
+                               lCurrentPtr = lMatrix;
+
+                               lNbComp = (int) (sqrt(4*lNbComp + 1)/2. - 0.5);
+                               lMctComp = lNbComp * lNbComp;
+                               lTotalComp = lMctComp + lNbComp;
+                               lSpace = (float *) malloc(lTotalComp * sizeof(float));
+                               lCurrentDoublePtr = lSpace;
+                               for (i=0;i<lMctComp;++i) {
+                                       lStrLen = strlen(lCurrentPtr) + 1;
+                                       *lCurrentDoublePtr++ = (float) atof(lCurrentPtr);
+                                       lCurrentPtr += lStrLen;
+                               }
+
+                               l_int_ptr = (int*) lCurrentDoublePtr;
+                               for (i=0;i<lNbComp;++i) {
+                                       lStrLen = strlen(lCurrentPtr) + 1;
+                                       *l_int_ptr++ = atoi(lCurrentPtr);
+                                       lCurrentPtr += lStrLen;
+                               }
+
+                               /* TODO should not be here ! */
+                               opj_set_MCT(parameters, lSpace, (int *)(lSpace + lMctComp), lNbComp);
+
+                               /* Free memory*/
+                               free(lSpace);
+                               free(lMatrix);
+                       }
+                       break;
+
+
                                /* ------------------------------------------------------ */
 
 /* UniPG>> */
@@ -1486,20 +1556,30 @@ void info_callback(const char *msg, void *client_data) {
 }
 
 /* -------------------------------------------------------------------------- */
-
+/**
+ * IMAGE_TO_J2K MAIN
+ */
+/* -------------------------------------------------------------------------- */
 int main(int argc, char **argv) {
-       opj_bool bSuccess;
+       FILE *f = NULL;
+
        opj_cparameters_t parameters;   /* compression parameters */
-       img_fol_t img_fol;
        opj_event_mgr_t event_mgr;              /* event manager */
+
+       opj_stream_t *cio = 00;
+       opj_codec_t* cinfo = 00;
        opj_image_t *image = NULL;
-       int i,num_images;
-       int imageno;
-       dircnt_t *dirptr = NULL;
        raw_cparameters_t raw_cp;
        opj_codestream_info_t cstr_info;                /* Codestream information structure */
+
        char indexfilename[OPJ_PATH_LEN];       /* index file name */
 
+       int i, num_images, imageno;
+       img_fol_t img_fol;
+       dircnt_t *dirptr = NULL;
+
+       opj_bool bSuccess;
+
        /*
        configure the event callbacks (not required)
        setting of each callback is optionnal
@@ -1580,6 +1660,7 @@ int main(int argc, char **argv) {
                                continue;
                        }
                }
+
                switch(parameters.decod_format) {
                        case PGX_DFMT:
                                break;
@@ -1600,213 +1681,151 @@ int main(int argc, char **argv) {
                                continue;
                }
 
-                       /* decode the source image */
-                       /* ----------------------- */
+               /* decode the source image */
+               /* ----------------------- */
 
-                       switch (parameters.decod_format) {
-                               case PGX_DFMT:
-                                       image = pgxtoimage(parameters.infile, &parameters);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load pgx file\n");
-                                               return 1;
-                                       }
-                                       break;
+               switch (parameters.decod_format) {
+                       case PGX_DFMT:
+                               image = pgxtoimage(parameters.infile, &parameters);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load pgx file\n");
+                                       return 1;
+                               }
+                               break;
 
-                               case PXM_DFMT:
-                                       image = pnmtoimage(parameters.infile, &parameters);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load pnm file\n");
-                                               return 1;
-                                       }
-                                       break;
+                       case PXM_DFMT:
+                               image = pnmtoimage(parameters.infile, &parameters);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load pnm file\n");
+                                       return 1;
+                               }
+                               break;
 
-                               case BMP_DFMT:
-                                       image = bmptoimage(parameters.infile, &parameters);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load bmp file\n");
-                                               return 1;
-                                       }
-                                       break;
-#ifdef HAVE_LIBTIFF
-                               case TIF_DFMT:
-                                       image = tiftoimage(parameters.infile, &parameters);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load tiff file\n");
-                                               return 1;
-                                       }
+                       case BMP_DFMT:
+                               image = bmptoimage(parameters.infile, &parameters);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load bmp file\n");
+                                       return 1;
+                               }
                                break;
+
+#ifdef HAVE_LIBTIFF
+                       case TIF_DFMT:
+                               image = tiftoimage(parameters.infile, &parameters);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load tiff file\n");
+                                       return 1;
+                               }
+                       break;
 #endif /* HAVE_LIBTIFF */
-                               case RAW_DFMT:
-                                       image = rawtoimage(parameters.infile, &parameters, &raw_cp);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load raw file\n");
-                                               return 1;
-                                       }
-                               break;
 
-                               case TGA_DFMT:
-                                       image = tgatoimage(parameters.infile, &parameters);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load tga file\n");
-                                               return 1;
-                                       }
-                               break;
+                       case RAW_DFMT:
+                               image = rawtoimage(parameters.infile, &parameters, &raw_cp);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load raw file\n");
+                                       return 1;
+                               }
+                       break;
+
+                       case TGA_DFMT:
+                               image = tgatoimage(parameters.infile, &parameters);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load tga file\n");
+                                       return 1;
+                               }
+                       break;
+
 #ifdef HAVE_LIBPNG
-                               case PNG_DFMT:
-                                       image = pngtoimage(parameters.infile, &parameters);
-                                       if (!image) {
-                                               fprintf(stderr, "Unable to load png file\n");
-                                               return 1;
-                                       }
-                                       break;
+                       case PNG_DFMT:
+                               image = pngtoimage(parameters.infile, &parameters);
+                               if (!image) {
+                                       fprintf(stderr, "Unable to load png file\n");
+                                       return 1;
+                               }
+                               break;
 #endif /* HAVE_LIBPNG */
                }
+
 /* Can happen if input file is TIFF or PNG 
  * and HAVE_LIBTIF or HAVE_LIBPNG is undefined
 */
-                       if( !image)
-                  {
+               if( !image) {
                        fprintf(stderr, "Unable to load file: got no image\n");
                        return 1;
-                  }
-                       /* Decide if MCT should be used */
-                       parameters.tcp_mct = image->numcomps == 3 ? 1 : 0;
+               }
 
-                       if(parameters.cp_cinema){
-                               cinema_setup_encoder(&parameters,image,&img_fol);
-                       }
+               /* Decide if MCT should be used */
+               parameters.tcp_mct = image->numcomps == 3 ? 1 : 0;
 
-                       /* encode the destination image */
-                       /* ---------------------------- */
+               if(parameters.cp_cinema){
+                       cinema_setup_encoder(&parameters,image,&img_fol);
+               }
 
-                       if (parameters.cod_format == J2K_CFMT) {        /* J2K format output */
-                               int codestream_length;
-        size_t res;
-                               opj_cio_t *cio = NULL;
-                               FILE *f = NULL;
+               /* encode the destination image */
+               /* ---------------------------- */
 
-                               /* get a J2K compressor handle */
-                               opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
+               switch(parameters.decod_format) {
+                       case J2K_CFMT:  /* JPEG-2000 codestream */
+                       {
+                               /* Get a decoder handle */
+                               cinfo = opj_create_compress_v2(CODEC_J2K);
+                               break;
+                       }
+                       case JP2_CFMT:  /* JPEG 2000 compressed image data */
+                       {
+                               /* Get a decoder handle */
+                               cinfo = opj_create_compress_v2(CODEC_JP2);
+                               break;
+                       }
+                       default:
+                               fprintf(stderr, "skipping file..\n");
+                               opj_stream_destroy(cio);
+                               continue;
+               }
 
-                               /* catch events using our callbacks and give a local context */
-                               opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+               opj_setup_encoder_v2(cinfo, &parameters, image);
 
-                               /* setup the encoder parameters using the current image and user parameters */
-                               opj_setup_encoder(cinfo, &parameters, image);
+               /* Open the output file*/
+               f = fopen(parameters.outfile, "wb");
+               if (! f) {
+                       fprintf(stderr, "Not enable to create output file!\n");
+                       opj_stream_destroy(cio);
+                       return 1;
+               }
 
-                               /* open a byte stream for writing */
-                               /* allocate memory for all tiles */
-                               cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
+               /* open a byte stream for writing and allocate memory for all tiles */
+               cio = opj_stream_create_default_file_stream(f,OPJ_FALSE);
+               if (! cio){
+                       return 1;
+               }
 
-                               /* encode the image */
-                               if (*indexfilename)                                     /* If need to extract codestream information*/
-                                 bSuccess = opj_encode_with_info(cinfo, cio, image, &cstr_info);
-                               else
-                                       bSuccess = opj_encode(cinfo, cio, image, NULL);
-                               if (!bSuccess) {
-                                       opj_cio_close(cio);
-                                       fprintf(stderr, "failed to encode image\n");
-                                       return 1;
-                               }
-                               codestream_length = cio_tell(cio);
+               /* encode the image */
+               bSuccess = opj_start_compress(cinfo,image,cio);
+               bSuccess = bSuccess && opj_encode_v2(cinfo, cio);
+               bSuccess = bSuccess && opj_end_compress(cinfo, cio);
 
-                               /* write the buffer to disk */
-                               f = fopen(parameters.outfile, "wb");
-                               if (!f) {
-                                       fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
-                                       return 1;
-                               }
-                               res = fwrite(cio->buffer, 1, codestream_length, f);
-        if( res < (size_t)codestream_length ) { /* FIXME */
-                                       fprintf(stderr, "failed to write %d (%s)\n", codestream_length, parameters.outfile);
-                                       return 1;
-         }
-                               fclose(f);
-
-                               fprintf(stderr,"Generated outfile %s\n",parameters.outfile);
-                               /* close and free the byte stream */
-                               opj_cio_close(cio);
-
-                               /* Write the index to disk */
-                               if (*indexfilename) {
-                                       bSuccess = write_index_file(&cstr_info, indexfilename);
-                                       if (bSuccess) {
-                                               fprintf(stderr, "Failed to output index file into [%s]\n", indexfilename);
-                                       }
-                               }
+               if (!bSuccess)  {
+                       opj_stream_destroy(cio);
+                       fclose(f);
+                       fprintf(stderr, "failed to encode image\n");
+                       return 1;
+               }
 
-                               /* free remaining compression structures */
-                               opj_destroy_compress(cinfo);
-                               if (*indexfilename)
-                                       opj_destroy_cstr_info(&cstr_info);
-                       } else {                        /* JP2 format output */
-                               int codestream_length;
-        size_t res;
-                               opj_cio_t *cio = NULL;
-                               FILE *f = NULL;
-                               opj_cinfo_t *cinfo = NULL;
-
-                               /* get a JP2 compressor handle */                               
-                               cinfo = opj_create_compress(CODEC_JP2);
-
-                               /* catch events using our callbacks and give a local context */
-                               opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
-
-                               /* setup the encoder parameters using the current image and using user parameters */
-                               opj_setup_encoder(cinfo, &parameters, image);
-
-                               /* open a byte stream for writing */
-                               /* allocate memory for all tiles */
-                               cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
-
-                               /* encode the image */
-                               if (*indexfilename || parameters.jpip_on) /* If need to extract codestream information*/
-                                 bSuccess = opj_encode_with_info(cinfo, cio, image, &cstr_info);
-                               else
-                                       bSuccess = opj_encode(cinfo, cio, image, NULL);
-                               if (!bSuccess) {
-                                       opj_cio_close(cio);
-                                       fprintf(stderr, "failed to encode image\n");
-                                       return 1;
-                               }
-                               codestream_length = cio_tell(cio);
+               fprintf(stderr,"Generated outfile %s\n",parameters.outfile);
+               /* close and free the byte stream */
+               opj_stream_destroy(cio);
+               fclose(f);
 
-                               /* write the buffer to disk */
-                               f = fopen(parameters.outfile, "wb");
-                               if (!f) {
-                                       fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
-                                       return 1;
-                               }
-                               res = fwrite(cio->buffer, 1, codestream_length, f);
-        if( res < (size_t)codestream_length ) { /* FIXME */
-                                       fprintf(stderr, "failed to write %d (%s)\n", codestream_length, parameters.outfile);
-                                       return 1;
-         }
-                               fclose(f);
-                               fprintf(stderr,"Generated outfile %s\n",parameters.outfile);
-                               /* close and free the byte stream */
-                               opj_cio_close(cio);
-
-                               /* Write the index to disk */
-                               if (*indexfilename) {
-                                       bSuccess = write_index_file(&cstr_info, indexfilename);
-                                       if (bSuccess) {
-                                               fprintf(stderr, "Failed to output index file\n");
-                                       }
-                               }
+               /* free remaining compression structures */
+               opj_destroy_codec(cinfo);
 
-                               /* free remaining compression structures */
-                               opj_destroy_compress(cinfo);
-                               if (*indexfilename)
-                                       opj_destroy_cstr_info(&cstr_info);
-                       }
+               /* free image data */
+               opj_image_destroy(image);
 
-                       /* free image data */
-                       opj_image_destroy(image);
        }
 
        /* free user parameters structure */
-  if(parameters.cp_comment) free(parameters.cp_comment);
+       if(parameters.cp_comment) free(parameters.cp_comment);
        if(parameters.cp_matrice) free(parameters.cp_matrice);
 
        return 0;
index 1b4ad48b7d4e4b23f63f7962cb6cae94e93f04ed..13a3001b31aa7fc2c3d6b640cb0d8e54b8d69de5 100644 (file)
@@ -128,6 +128,12 @@ Inverse wavelet transform in 2-D.
 */
 static opj_bool dwt_decode_tile_v2(opj_tcd_tilecomp_v2_t* tilec, OPJ_UINT32 i, DWT1DFN fn);
 
+static opj_bool dwt_encode_procedure(  opj_tcd_tilecomp_v2_t * tilec,
+                                                                               void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) );
+
+static OPJ_UINT32 dwt_max_resolution_v2(opj_tcd_resolution_v2_t* restrict r, OPJ_UINT32 i);
+
+
 /*@}*/
 
 /*@}*/
@@ -383,6 +389,95 @@ void dwt_encode(opj_tcd_tilecomp_t * tilec) {
        }
 }
 
+/* <summary>                            */
+/* Forward 5-3 wavelet transform in 2-D. */
+/* </summary>                           */
+INLINE opj_bool dwt_encode_procedure(opj_tcd_tilecomp_v2_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) )
+{
+       OPJ_INT32 i, j, k;
+       OPJ_INT32 *a = 00;
+       OPJ_INT32 *aj = 00;
+       OPJ_INT32 *bj = 00;
+       OPJ_INT32 w, l;
+
+       OPJ_INT32 rw;                   /* width of the resolution level computed   */
+       OPJ_INT32 rh;                   /* height of the resolution level computed  */
+       OPJ_INT32 l_data_size;
+
+       opj_tcd_resolution_v2_t * l_cur_res = 0;
+       opj_tcd_resolution_v2_t * l_last_res = 0;
+
+       w = tilec->x1-tilec->x0;
+       l = tilec->numresolutions-1;
+       a = tilec->data;
+
+       l_cur_res = tilec->resolutions + l;
+       l_last_res = l_cur_res - 1;
+
+       rw = l_cur_res->x1 - l_cur_res->x0;
+       rh = l_cur_res->y1 - l_cur_res->y0;
+
+       l_data_size = dwt_max_resolution_v2( tilec->resolutions,tilec->numresolutions) * sizeof(OPJ_INT32);
+       bj = (OPJ_INT32*)opj_malloc(l_data_size);
+       if (! bj) {
+               return OPJ_FALSE;
+       }
+       i = l;
+
+       while (i--) {
+               OPJ_INT32 rw1;          /* width of the resolution level once lower than computed one                                       */
+               OPJ_INT32 rh1;          /* height of the resolution level once lower than computed one                                      */
+               OPJ_INT32 cas_col;      /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+               OPJ_INT32 cas_row;      /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering   */
+               OPJ_INT32 dn, sn;
+
+               rw  = l_cur_res->x1 - l_cur_res->x0;
+               rh  = l_cur_res->y1 - l_cur_res->y0;
+               rw1 = l_last_res->x1 - l_last_res->x0;
+               rh1 = l_last_res->y1 - l_last_res->y0;
+
+               cas_row = l_cur_res->x0 & 1;
+               cas_col = l_cur_res->y0 & 1;
+
+               sn = rh1;
+               dn = rh - rh1;
+               for (j = 0; j < rw; ++j) {
+                       aj = a + j;
+                       for (k = 0; k < rh; ++k) {
+                               bj[k] = aj[k*w];
+                       }
+
+                       (*p_function) (bj, dn, sn, cas_col);
+
+                       dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+               }
+
+               sn = rw1;
+               dn = rw - rw1;
+
+               for (j = 0; j < rh; j++) {
+                       aj = a + j * w;
+                       for (k = 0; k < rw; k++)  bj[k] = aj[k];
+                       (*p_function) (bj, dn, sn, cas_row);
+                       dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+               }
+
+               l_cur_res = l_last_res;
+
+               --l_last_res;
+       }
+
+       opj_free(bj);
+       return OPJ_TRUE;
+}
+
+/* Forward 5-3 wavelet transform in 2-D. */
+/* </summary>                           */
+opj_bool dwt_encode_v2(opj_tcd_tilecomp_v2_t * tilec)
+{
+       return dwt_encode_procedure(tilec,dwt_encode_1);
+}
+
 #ifdef OPJ_V1
 /* <summary>                            */
 /* Inverse 5-3 wavelet transform in 2-D. */
@@ -492,6 +587,13 @@ void dwt_encode_real(opj_tcd_tilecomp_t * tilec) {
        }
 }
 
+/* <summary>                             */
+/* Forward 9-7 wavelet transform in 2-D. */
+/* </summary>                            */
+opj_bool dwt_encode_real_v2(opj_tcd_tilecomp_v2_t * tilec)
+{
+       return dwt_encode_procedure(tilec,dwt_encode_1_real);
+}
 
 /* <summary>                          */
 /* Get gain of 9-7 wavelet transform. */
index a43882dc6d763639094aede32f3d2de16c210ad6..3b8333919a86ddde3b893aa7b8c03912288b3f82 100644 (file)
@@ -52,6 +52,13 @@ Forward 5-3 wavelet tranform in 2-D.
 Apply a reversible DWT transform to a component of an image.
 @param tilec Tile component information (current tile)
 */
+opj_bool dwt_encode_v2(struct opj_tcd_tilecomp_v2 * tilec);
+
+/**
+Forward 5-3 wavelet tranform in 2-D.
+Apply a reversible DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+*/
 void dwt_encode(opj_tcd_tilecomp_t * tilec);
 /**
 Inverse 5-3 wavelet tranform in 2-D.
@@ -87,6 +94,7 @@ Apply an irreversible DWT transform to a component of an image.
 @param tilec Tile component information (current tile)
 */
 void dwt_encode_real(opj_tcd_tilecomp_t * tilec);
+opj_bool dwt_encode_real_v2(opj_tcd_tilecomp_v2_t * tilec);
 /**
 KEEP TRUNK VERSION + return type of v2 because rev557
 Inverse 9-7 wavelet transform in 2-D. 
index a39772b02266d40659339762443d039af5099bd9..57fec99d21ea794b5813668e22cd7d50ade0c338 100644 (file)
@@ -104,6 +104,15 @@ Divide an integer and round upwards
 static INLINE int int_ceildiv(int a, int b) {
        return (a + b - 1) / b;
 }
+
+/**
+Divide an integer and round upwards
+@return Returns a divided by b
+*/
+static INLINE OPJ_UINT32  uint_ceildiv(OPJ_UINT32  a, OPJ_UINT32  b) {
+       return (a + b - 1) / b;
+}
+
 /**
 Divide an integer by a power of 2 and round upwards
 @return Returns a divided by 2^b
index 2194e6d53f09d5d560305b88dbf4c26ff1bf33ed..0d7f62bcbb4fa0ab42cefb3fbe58bbe548149722 100644 (file)
@@ -54,6 +54,19 @@ opj_bool j2k_read_header_procedure(
                                                                struct opj_stream_private *p_stream,
                                                                struct opj_event_mgr * p_manager);
 
+/**
+ * The default encoding validation procedure without any extension.
+ *
+ * @param      p_j2k                   the jpeg2000 codec to validate.
+ * @param      p_stream                                the input stream to validate.
+ * @param      p_manager               the user event manager.
+ *
+ * @return true if the parameters are correct.
+ */
+opj_bool j2k_encoding_validation (     opj_j2k_v2_t * p_j2k,
+                                                                       opj_stream_private_t *p_stream,
+                                                                       opj_event_mgr_t * p_manager );
+
 /**
  * The default decoding validation procedure without any extension.
  *
@@ -69,20 +82,60 @@ opj_bool j2k_decoding_validation (
                                                                opj_event_mgr_t * p_manager
                                                        );
 
+/**
+ * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
+ * are valid. Developpers wanting to extend the library can add their own validation procedures.
+ */
+static void j2k_setup_encoding_validation (opj_j2k_v2_t *p_j2k);
+
 /**
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
  */
 static void j2k_setup_decoding_validation (opj_j2k_v2_t *p_j2k);
 
+/**
+ * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
+ * are valid. Developpers wanting to extend the library can add their own validation procedures.
+ */
+static void j2k_setup_end_compress (opj_j2k_v2_t *p_j2k);
+
+/**
+ * The mct encoding validation procedure.
+ *
+ * @param      p_j2k                   the jpeg2000 codec to validate.
+ * @param      p_stream                                the input stream to validate.
+ * @param      p_manager               the user event manager.
+ *
+ * @return true if the parameters are correct.
+ */
+opj_bool j2k_mct_validation (  opj_j2k_v2_t * p_j2k,
+                                                               opj_stream_private_t *p_stream,
+                                                               opj_event_mgr_t * p_manager );
+
 /**
  * Builds the tcd decoder to use to decode tile.
  */
-opj_bool j2k_build_decoder (
-                                               opj_j2k_v2_t * p_j2k,
-                                               opj_stream_private_t *p_stream,
-                                               opj_event_mgr_t * p_manager
-                                               );
+opj_bool j2k_build_decoder (opj_j2k_v2_t * p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       opj_event_mgr_t * p_manager );
+/**
+ * Builds the tcd encoder to use to encode tile.
+ */
+opj_bool j2k_build_encoder (opj_j2k_v2_t * p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       opj_event_mgr_t * p_manager );
+
+/**
+ * Creates a tile-coder decoder.
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_create_tcd(        opj_j2k_v2_t *p_j2k,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager );
 
 /**
  * Excutes the given procedures on the given codec.
@@ -101,6 +154,17 @@ static opj_bool j2k_exec (
                                        opj_event_mgr_t * p_manager
                                  );
 
+/**
+ * Updates the rates of the tcp.
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_update_rates(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
  * Copies the decoding tile parameters onto all the tile parameters.
  * Creates also the tile decoder.
@@ -109,6 +173,13 @@ opj_bool j2k_copy_default_tcp_and_create_tcd (     opj_j2k_v2_t * p_j2k,
                                                                                                opj_stream_private_t *p_stream,
                                                                                                opj_event_mgr_t * p_manager );
 
+/**
+ * Destroys the memory associated with the decoding of headers.
+ */
+opj_bool j2k_destroy_header_memory (opj_j2k_v2_t * p_j2k,
+                                                                       opj_stream_private_t *p_stream,
+                                                                       opj_event_mgr_t * p_manager );
+
 /**
  * Reads the lookup table containing all the marker, status and action, and returns the handler associated
  * with the marker value.
@@ -140,6 +211,35 @@ static void j2k_tcp_data_destroy (opj_tcp_v2_t *p_tcp);
 static void j2k_cp_destroy (opj_cp_v2_t *p_cp);
 
 
+/**
+ * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
+ *
+ * @param      p_comp_no       the component number to output.
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+ *
+*/
+static opj_bool j2k_write_SPCod_SPCoc( opj_j2k_v2_t *p_j2k,
+                                                                               OPJ_UINT32 p_tile_no,
+                                                                               OPJ_UINT32 p_comp_no,
+                                                                               OPJ_BYTE * p_data,
+                                                                               OPJ_UINT32 * p_header_size,
+                                                                               struct opj_event_mgr * p_manager );
+
+/**
+ * Gets the size taken by writing a SPCod or SPCoc for the given tile and component.
+ *
+ * @param      p_tile_no               the tile index.
+ * @param      p_comp_no               the component being outputted.
+ * @param      p_j2k                   the J2K codec.
+ *
+ * @return     the number of bytes taken by the SPCod element.
+ */
+static OPJ_UINT32 j2k_get_SPCod_SPCoc_size (opj_j2k_v2_t *p_j2k,
+                                                                                       OPJ_UINT32 p_tile_no,
+                                                                                       OPJ_UINT32 p_comp_no );
+
 /**
  * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
  * @param      p_header_data   the data contained in the COM box.
@@ -155,6 +255,43 @@ static opj_bool j2k_read_SPCod_SPCoc(
                                                        struct opj_event_mgr * p_manager
                                                        );
 
+/**
+ * Gets the size taken by writing SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
+ *
+ * @param      p_tile_no               the tile index.
+ * @param      p_comp_no               the component being outputted.
+ * @param      p_j2k                   the J2K codec.
+ *
+ * @return     the number of bytes taken by the SPCod element.
+ */
+static OPJ_UINT32 j2k_get_SQcd_SQcc_size (     opj_j2k_v2_t *p_j2k,
+                                                                               OPJ_UINT32 p_tile_no,
+                                                                               OPJ_UINT32 p_comp_no );
+
+/**
+ * Writes a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
+ *
+ * @param      p_tile_no               the tile to output.
+ * @param      p_comp_no               the component number to output.
+ * @param      p_data                  the data buffer.
+ * @param      p_header_size   pointer to the size of the data buffer, it is changed by the function.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+ *
+*/
+static opj_bool j2k_write_SQcd_SQcc(opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_UINT32 p_tile_no,
+                                                                       OPJ_UINT32 p_comp_no,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_header_size,
+                                                                       struct opj_event_mgr * p_manager
+                                                                       );
+
+/**
+ * Updates the Tile Length Marker.
+ */
+static void j2k_update_tlm ( opj_j2k_v2_t * p_j2k, OPJ_UINT32 p_tile_part_size);
+
 /**
  * Reads a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
  *
@@ -195,12 +332,56 @@ static void j2k_copy_tile_quantization_parameters(
 /**
  * Reads the tiles.
  */
-opj_bool j2k_decode_tiles (            opj_j2k_v2_t *p_j2k,
-                                                               opj_stream_private_t *p_stream,
-                                                               opj_event_mgr_t * p_manager);
+opj_bool j2k_decode_tiles (    opj_j2k_v2_t *p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       opj_event_mgr_t * p_manager);
+
+
+static opj_bool j2k_pre_write_tile ( opj_j2k_v2_t * p_j2k,
+                                                                        OPJ_UINT32 p_tile_index,
+                                                                        opj_stream_private_t *p_stream,
+                                                                        opj_event_mgr_t * p_manager );
 
 static opj_bool j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_image_t* p_output_image);
 
+static void j2k_get_tile_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data);
+
+static opj_bool j2k_post_write_tile (opj_j2k_v2_t * p_j2k,
+                                                                        OPJ_BYTE * p_data,
+                                                                        OPJ_UINT32 p_data_size,
+                                                                        opj_stream_private_t *p_stream,
+                                                                        opj_event_mgr_t * p_manager );
+
+/**
+ * Sets up the procedures to do on writing header.
+ * Developers wanting to extend the library can add their own writing procedures.
+ */
+void j2k_setup_header_writting (opj_j2k_v2_t *p_j2k);
+
+static opj_bool j2k_write_first_tile_part(     opj_j2k_v2_t *p_j2k,
+                                                                                       OPJ_BYTE * p_data,
+                                                                                       OPJ_UINT32 * p_data_written,
+                                                                                       OPJ_UINT32 p_total_data_size,
+                                                                                       opj_stream_private_t *p_stream,
+                                                                                       struct opj_event_mgr * p_manager );
+
+static opj_bool j2k_write_all_tile_parts(      opj_j2k_v2_t *p_j2k,
+                                                                                       OPJ_BYTE * p_data,
+                                                                                       OPJ_UINT32 * p_data_written,
+                                                                                       OPJ_UINT32 p_total_data_size,
+                                                                                       opj_stream_private_t *p_stream,
+                                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Gets the offset of the header.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_get_end_header(    opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
 
 /*
  * -----------------------------------------------------------------------
@@ -213,6 +394,18 @@ Write the SOC marker (Start Of Codestream)
 @param j2k J2K handle
 */
 static void j2k_write_soc(opj_j2k_t *j2k);
+
+/**
+ * Writes the SOC marker (Start Of Codestream)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+static opj_bool j2k_write_soc_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
 Read the SOC marker (Start of Codestream)
 @param j2k J2K handle
@@ -237,6 +430,18 @@ Write the SIZ marker (image and tile size)
 @param j2k J2K handle
 */
 static void j2k_write_siz(opj_j2k_t *j2k);
+
+/**
+ * Writes the SIZ marker (image and tile size)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+static opj_bool j2k_write_siz_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
 Read the SIZ marker (image and tile size)
 @param j2k J2K handle
@@ -297,6 +502,18 @@ Write the COD marker (coding style default)
 @param j2k J2K handle
 */
 static void j2k_write_cod(opj_j2k_t *j2k);
+
+/**
+ * Writes the COD marker (Coding style default)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+static opj_bool j2k_write_cod_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
 Read the COD marker (coding style default)
 @param j2k J2K handle
@@ -323,6 +540,41 @@ Write the COC marker (coding style component)
 @param compno Number of the component concerned by the information written
 */
 static void j2k_write_coc(opj_j2k_t *j2k, int compno);
+
+/**
+ * Writes the COC marker (Coding style component)
+ *
+ * @param      p_comp_number   the index of the component to output.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_coc_v2( opj_j2k_v2_t *p_j2k,
+                                                       OPJ_UINT32 p_comp_number,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager
+                                                 );
+/**
+ * Writes the COC marker (Coding style component)
+ *
+ * @param      p_comp_no               the index of the component to output.
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static void j2k_write_coc_in_memory(opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_UINT32 p_comp_no,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Gets the maximum size taken by a coc.
+ *
+ * @param      p_j2k   the jpeg2000 codec to use.
+ */
+static OPJ_UINT32 j2k_get_max_coc_size(opj_j2k_v2_t *p_j2k);
+
 /**
 Read the COC marker (coding style component)
 @param j2k J2K handle
@@ -361,6 +613,19 @@ Write the QCD marker (quantization default)
 @param j2k J2K handle
 */
 static void j2k_write_qcd(opj_j2k_t *j2k);
+
+/**
+ * Writes the QCD marker (quantization default)
+ *
+ * @param      p_comp_number   the index of the component to output.
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_qcd_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
 Read the QCD marker (quantization default)
 @param j2k J2K handle
@@ -387,6 +652,39 @@ Write the QCC marker (quantization component)
 @param compno Number of the component concerned by the information written
 */
 static void j2k_write_qcc(opj_j2k_t *j2k, int compno);
+
+/**
+ * Writes the QCC marker (quantization component)
+ *
+ * @param      p_comp_no       the index of the component to output.
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_qcc_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_UINT32 p_comp_no,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Writes the QCC marker (quantization component)
+ *
+ * @param      p_comp_no       the index of the component to output.
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static void j2k_write_qcc_in_memory(opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_UINT32 p_comp_no,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Gets the maximum size taken by a qcc.
+ */
+static OPJ_UINT32 j2k_get_max_qcc_size (opj_j2k_v2_t *p_j2k);
+
 /**
 Read the QCC marker (quantization component)
 @param j2k J2K handle
@@ -410,6 +708,36 @@ Write the POC marker (progression order change)
 @param j2k J2K handle
 */
 static void j2k_write_poc(opj_j2k_t *j2k);
+
+/**
+ * Writes the POC marker (Progression Order Change)
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+ */
+static void j2k_write_poc_in_memory(opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Gets the maximum size taken by the writting of a POC.
+ */
+static OPJ_UINT32 j2k_get_max_poc_size(opj_j2k_v2_t *p_j2k);
+
+/**
+ * Gets the maximum size taken by the toc headers of all the tile parts of any given tile.
+ */
+static OPJ_UINT32 j2k_get_max_toc_size (opj_j2k_v2_t *p_j2k);
+
+/**
+ * Gets the maximum size taken by the headers of the SOT.
+ *
+ * @param      p_j2k   the jpeg2000 codec to use.
+ */
+static OPJ_UINT32 j2k_get_specific_header_sizes(opj_j2k_v2_t *p_j2k);
+
 /**
 Read the POC marker (progression order change)
 @param j2k J2K handle
@@ -429,6 +757,7 @@ static opj_bool j2k_read_poc_v2 (
                                                OPJ_UINT32 p_header_size,
                                                struct opj_event_mgr * p_manager
                                        );
+
 /**
 Read the CRG marker (component registration)
 @param j2k J2K handle
@@ -467,6 +796,18 @@ static opj_bool j2k_read_tlm_v2 (
                                                OPJ_UINT32 p_header_size,
                                                struct opj_event_mgr * p_manager
                                        );
+
+/**
+ * Writes the updated tlm.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_updated_tlm( opj_j2k_v2_t *p_j2k,
+                                                                               struct opj_stream_private *p_stream,
+                                                                               struct opj_event_mgr * p_manager );
+
 /**
 Read the PLM marker (packet length, main header)
 @param j2k J2K handle
@@ -568,6 +909,19 @@ Read the SOT marker (start of tile-part)
 */
 static void j2k_read_sot(opj_j2k_t *j2k);
 
+/**
+ * Writes the SOT marker (Start of tile-part)
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_sot_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       const struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
  * Reads a PPT marker (Packed packet headers, tile-part header)
  *
@@ -588,6 +942,22 @@ Write the SOD marker (start of data)
 @param tile_coder Pointer to a TCD handle
 */
 static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder);
+
+/**
+ * Writes the SOD marker (Start of data)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_sod_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_tcd_v2 * p_tile_coder,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       OPJ_UINT32 p_total_data_size,
+                                                                       const struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
 Read the SOD marker (start of data)
 @param j2k J2K handle
@@ -608,6 +978,18 @@ static opj_bool j2k_read_sod_v2 (
                                                struct opj_event_mgr * p_manager
                                        );
 
+/**
+ * Updates the Tile Length Marker.
+ */
+void j2k_update_tlm (opj_j2k_v2_t * p_j2k, OPJ_UINT32 p_tile_part_size )
+{
+       opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_j2k->m_current_tile_number,1);                                    /* PSOT */
+       ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current;
+
+       opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_tile_part_size,4);                                        /* PSOT */
+       p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 4;
+}
+
 /**
 Write the RGN marker (region-of-interest)
 @param j2k J2K handle
@@ -615,6 +997,22 @@ Write the RGN marker (region-of-interest)
 @param tileno Number of the tile concerned by the information written
 */
 static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno);
+
+/**
+ * Writes the RGN marker (Region Of Interest)
+ *
+ * @param      p_tile_no               the tile to output
+ * @param      p_comp_no               the component to output
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_rgn_v2(      opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_UINT32 p_tile_no,
+                                                                       OPJ_UINT32 p_comp_no,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
 Read the RGN marker (region-of-interest)
 @param j2k J2K handle
@@ -661,6 +1059,30 @@ static opj_bool j2k_read_eoc_v2 (
                                                struct opj_event_mgr * p_manager
                                        ) ;
 
+
+
+/**
+ * Writes the CBD-MCT-MCC-MCO markers (Multi components transform)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+static opj_bool j2k_write_mct_data_group(      opj_j2k_v2_t *p_j2k,
+                                                                                       struct opj_stream_private *p_stream,
+                                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Inits the Info
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_init_info( opj_j2k_v2_t *p_j2k,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager );
+
 /**
 Read an unknown marker
 @param j2k J2K handle
@@ -702,6 +1124,18 @@ static opj_bool j2k_read_unk_v2 ( opj_j2k_v2_t *p_j2k,
                                                                        OPJ_UINT32 *output_marker,
                                                                        struct opj_event_mgr * p_manager );
 
+/**
+ * Writes the MCT marker (Multiple Component Transform)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_mct_record(  opj_j2k_v2_t *p_j2k,
+                                                                               opj_mct_data_t * p_mct_record,
+                                                                               struct opj_stream_private *p_stream,
+                                                                               struct opj_event_mgr * p_manager );
+
 /**
  * Reads a MCT marker (Multiple Component Transform)
  *
@@ -715,6 +1149,19 @@ static opj_bool j2k_read_mct (    opj_j2k_v2_t *p_j2k,
                                                                OPJ_UINT32 p_header_size,
                                                                struct opj_event_mgr * p_manager );
 
+/**
+ * Writes the MCC marker (Multiple Component Collection)
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_mcc_record(  opj_j2k_v2_t *p_j2k,
+                                                                               struct opj_simple_mcc_decorrelation_data * p_mcc_record,
+                                                                               struct opj_stream_private *p_stream,
+                                                                               struct opj_event_mgr * p_manager );
+
+
 /**
  * Reads a MCC marker (Multiple Component Collection)
  *
@@ -724,9 +1171,20 @@ static opj_bool j2k_read_mct (    opj_j2k_v2_t *p_j2k,
  * @param      p_manager               the user event manager.
 */
 static opj_bool j2k_read_mcc ( opj_j2k_v2_t *p_j2k,
-                                                       OPJ_BYTE * p_header_data,
-                                                       OPJ_UINT32 p_header_size,
-                                                       struct opj_event_mgr * p_manager );
+                                                               OPJ_BYTE * p_header_data,
+                                                               OPJ_UINT32 p_header_size,
+                                                               struct opj_event_mgr * p_manager );
+
+/**
+ * Writes the MCO marker (Multiple component transformation ordering)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_mco( opj_j2k_v2_t *p_j2k,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager );
 
 /**
  * Reads a MCO marker (Multiple Component Transform Ordering)
@@ -758,6 +1216,29 @@ static void  j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_da
 static void  j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
 static void  j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
 
+
+/**
+ * Ends the encoding, i.e. frees memory.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_end_encoding(      opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Writes the CBD marker (Component bit depth definition)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_cbd( opj_j2k_v2_t *p_j2k,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager );
+
 /**
  * Reads a CBD marker (Component bit depth definition)
  * @param      p_header_data   the data contained in the CBD box.
@@ -770,6 +1251,67 @@ static opj_bool j2k_read_cbd (    opj_j2k_v2_t *p_j2k,
                                                        OPJ_UINT32 p_header_size,
                                                        struct opj_event_mgr * p_manager);
 
+/**
+ * Writes the image components.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_image_components(    opj_j2k_v2_t *p_j2k,
+                                                                                       struct opj_stream_private *p_stream,
+                                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Writes regions of interests.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_regions(     opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Writes EPC ????
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+static opj_bool j2k_write_epc(         opj_j2k_v2_t *p_j2k,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager );
+
+/**
+ * Gets the number of tile parts used for the given change of progression (if any) and the given tile.
+ *
+ * @param              cp                      the coding parameters.
+ * @param              pino            the offset of the given poc (i.e. its position in the coding parameter).
+ * @param              tileno          the given tile.
+ *
+ * @return             the number of tile parts.
+ */
+static OPJ_UINT32 j2k_get_num_tp_v2( opj_cp_v2_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno);
+
+/**
+ * Calculates the total number of tile parts needed by the encoder to
+ * encode such an image. If not enough memory is available, then the function return false.
+ *
+ * @param      p_nb_tiles      pointer that will hold the number of tile parts.
+ * @param      cp                      the coding parameters for the image.
+ * @param      image           the image to encode.
+ * @param      p_j2k                   the p_j2k encoder.
+ * @param      p_manager       the user event manager.
+ *
+ * @return true if the function was successful, false else.
+ */
+static opj_bool j2k_calculate_tp_v2(opj_j2k_v2_t *p_j2k,
+                                                                       opj_cp_v2_t *cp,
+                                                                       OPJ_UINT32 * p_nb_tiles,
+                                                                       opj_image_t *image,
+                                                                       opj_event_mgr_t * p_manager);
 
 static void j2k_dump_MH_info(opj_j2k_v2_t* p_j2k, FILE* out_stream);
 
@@ -1158,6 +1700,73 @@ static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){
        return tpnum;
 }
 
+/**
+ * Gets the number of tile parts used for the given change of progression (if any) and the given tile.
+ *
+ * @param              cp                      the coding parameters.
+ * @param              pino            the offset of the given poc (i.e. its position in the coding parameter).
+ * @param              tileno          the given tile.
+ *
+ * @return             the number of tile parts.
+ */
+OPJ_UINT32 j2k_get_num_tp_v2(opj_cp_v2_t *cp, OPJ_UINT32 pino, OPJ_UINT32 tileno)
+{
+       const OPJ_CHAR *prog = 00;
+       OPJ_UINT32 i;
+       OPJ_UINT32 tpnum = 1;
+       opj_tcp_v2_t *tcp = 00;
+       opj_poc_t * l_current_poc = 00;
+
+       /*  preconditions */
+       assert(tileno < (cp->tw * cp->th));
+       assert(pino < (cp->tcps[tileno].numpocs + 1));
+
+       /* get the given tile coding parameter */
+       tcp = &cp->tcps[tileno];
+       assert(tcp != 00);
+
+       l_current_poc = &(tcp->pocs[pino]);
+       assert(l_current_poc != 0);
+
+       /* get the progression order as a character string */
+       prog = j2k_convert_progression_order(tcp->prg);
+       assert(strlen(prog) > 0);
+
+       if (cp->m_specific_param.m_enc.m_tp_on == 1) {
+               for (i=0;i<4;++i) {
+                       switch (prog[i])
+                       {
+                               /* component wise */
+                               case 'C':
+                                       tpnum *= l_current_poc->compE;
+                                       break;
+                               /* resolution wise */
+                               case 'R':
+                                       tpnum *= l_current_poc->resE;
+                                       break;
+                               // precinct wise
+                               case 'P':
+                                       tpnum *= l_current_poc->prcE;
+                                       break;
+                               /* layer wise */
+                               case 'L':
+                                       tpnum *= l_current_poc->layE;
+                                       break;
+                       }
+                       /* whould we split here ? */
+                       if ( cp->m_specific_param.m_enc.m_tp_flag == prog[i] ) {
+                               cp->m_specific_param.m_enc.m_tp_pos=i;
+                               break;
+                       }
+               }
+       }
+       else {
+               tpnum=1;
+       }
+
+       return tpnum;
+}
+
 /**    mem allocation for TLM marker*/
 int j2k_calculate_tp(opj_cp_t *cp,int img_numcomp,opj_image_t *image,opj_j2k_t *j2k ){
        int pino,tileno,totnum_tp=0;
@@ -1188,6 +1797,95 @@ int j2k_calculate_tp(opj_cp_t *cp,int img_numcomp,opj_image_t *image,opj_j2k_t *
        return totnum_tp;
 }
 
+/**
+ * Calculates the total number of tile parts needed by the encoder to
+ * encode such an image. If not enough memory is available, then the function return false.
+ *
+ * @param      p_nb_tiles      pointer that will hold the number of tile parts.
+ * @param      cp                      the coding parameters for the image.
+ * @param      image           the image to encode.
+ * @param      p_j2k                   the p_j2k encoder.
+ * @param      p_manager       the user event manager.
+ *
+ * @return true if the function was successful, false else.
+ */
+opj_bool j2k_calculate_tp_v2( opj_j2k_v2_t *p_j2k,
+                                                         opj_cp_v2_t *cp,
+                                                         OPJ_UINT32 * p_nb_tiles,
+                                                         opj_image_t *image,
+                                                         opj_event_mgr_t * p_manager)
+{
+       OPJ_UINT32 pino,tileno;
+       OPJ_UINT32 l_nb_tiles;
+       opj_tcp_v2_t *tcp;
+
+       /* preconditions */
+       assert(p_nb_tiles != 00);
+       assert(cp != 00);
+       assert(image != 00);
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+
+       l_nb_tiles = cp->tw * cp->th;
+       * p_nb_tiles = 0;
+       tcp = cp->tcps;
+
+       /* INDEX >> */
+       /* TODO mergeV2: check this part which use cstr_info */
+       /*if (p_j2k->cstr_info) {
+               opj_tile_info_t * l_info_tile_ptr = p_j2k->cstr_info->tile;
+
+               for (tileno = 0; tileno < l_nb_tiles; ++tileno) {
+                       OPJ_UINT32 cur_totnum_tp = 0;
+
+                       pi_update_encoding_parameters(image,cp,tileno);
+
+                       for (pino = 0; pino <= tcp->numpocs; ++pino)
+                       {
+                               OPJ_UINT32 tp_num = j2k_get_num_tp_v2(cp,pino,tileno);
+
+                               *p_nb_tiles = *p_nb_tiles + tp_num;
+
+                               cur_totnum_tp += tp_num;
+                       }
+
+                       tcp->m_nb_tile_parts = cur_totnum_tp;
+
+                       l_info_tile_ptr->tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t));
+                       if (l_info_tile_ptr->tp == 00) {
+                               return OPJ_FALSE;
+                       }
+
+                       memset(l_info_tile_ptr->tp,0,cur_totnum_tp * sizeof(opj_tp_info_t));
+
+                       l_info_tile_ptr->num_tps = cur_totnum_tp;
+
+                       ++l_info_tile_ptr;
+                       ++tcp;
+               }
+       }
+       else */{
+               for (tileno = 0; tileno < l_nb_tiles; ++tileno) {
+                       OPJ_UINT32 cur_totnum_tp = 0;
+
+                       pi_update_encoding_parameters(image,cp,tileno);
+
+                       for (pino = 0; pino <= tcp->numpocs; ++pino) {
+                               OPJ_UINT32 tp_num = j2k_get_num_tp_v2(cp,pino,tileno);
+
+                               *p_nb_tiles = *p_nb_tiles + tp_num;
+
+                               cur_totnum_tp += tp_num;
+                       }
+                       tcp->m_nb_tile_parts = cur_totnum_tp;
+
+                       ++tcp;
+               }
+       }
+
+       return OPJ_TRUE;
+}
+
 static void j2k_write_soc(opj_j2k_t *j2k) {
        opj_cio_t *cio = j2k->cio;
        cio_write(cio, J2K_MS_SOC, 2);
@@ -1204,6 +1902,44 @@ static void j2k_write_soc(opj_j2k_t *j2k) {
 /* <<UniPG */
 }
 
+/**
+ * Writes the SOC marker (Start Of Codestream)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+opj_bool j2k_write_soc_v2(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       /* 2 bytes will be written */
+       OPJ_BYTE * l_start_stream = 00;
+
+       /* preconditions */
+       assert(p_stream != 00);
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+
+       l_start_stream = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       /* write SOC identifier */
+       opj_write_bytes(l_start_stream,J2K_MS_SOC,2);
+
+       if (opj_stream_write_data(p_stream,l_start_stream,2,p_manager) != 2) {
+               return OPJ_FALSE;
+       }
+
+/* UniPG>> */
+#ifdef USE_JPWL
+       /* update markers struct */
+       j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2);
+#endif /* USE_JPWL */
+/* <<UniPG */
+
+       return OPJ_TRUE;
+}
+
 static void j2k_read_soc(opj_j2k_t *j2k) {     
        j2k->state = J2K_STATE_MHSIZ;
        /* Index */
@@ -1290,6 +2026,107 @@ static void j2k_write_siz(opj_j2k_t *j2k) {
          j2k_add_mhmarker(j2k->cstr_info, J2K_MS_SIZ, lenp, len);
 }
 
+/**
+ * Writes the SIZ marker (image and tile size)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+opj_bool j2k_write_siz_v2(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 i;
+       OPJ_UINT32 l_size_len;
+       OPJ_BYTE * l_current_ptr;
+       opj_image_t * l_image = 00;
+       opj_cp_v2_t *cp = 00;
+       opj_image_comp_t * l_img_comp = 00;
+
+       /* preconditions */
+       assert(p_stream != 00);
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+
+       l_image = p_j2k->m_private_image;
+       cp = &(p_j2k->m_cp);
+       l_size_len = 40 + 3 * l_image->numcomps;
+       l_img_comp = l_image->comps;
+
+       if (l_size_len > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_size_len);
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_size_len;
+       }
+
+       l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       /* write SOC identifier */
+       opj_write_bytes(l_current_ptr,J2K_MS_SIZ,2);    /* SIZ */
+       l_current_ptr+=2;
+
+       opj_write_bytes(l_current_ptr,l_size_len-2,2); /* L_SIZ */
+       l_current_ptr+=2;
+
+       opj_write_bytes(l_current_ptr, cp->rsiz, 2);    /* Rsiz (capabilities) */
+       l_current_ptr+=2;
+
+       opj_write_bytes(l_current_ptr, l_image->x1, 4); /* Xsiz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, l_image->y1, 4); /* Ysiz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, l_image->x0, 4); /* X0siz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, l_image->y0, 4); /* Y0siz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, cp->tdx, 4);             /* XTsiz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, cp->tdy, 4);             /* YTsiz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, cp->tx0, 4);             /* XT0siz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, cp->ty0, 4);             /* YT0siz */
+       l_current_ptr+=4;
+
+       opj_write_bytes(l_current_ptr, l_image->numcomps, 2);   /* Csiz */
+       l_current_ptr+=2;
+
+       for (i = 0; i < l_image->numcomps; ++i) {
+               // TODO here with MCT ?
+               opj_write_bytes(l_current_ptr, l_img_comp->prec - 1 + (l_img_comp->sgnd << 7), 1);      /* Ssiz_i */
+               ++l_current_ptr;
+
+               opj_write_bytes(l_current_ptr, l_img_comp->dx, 1);      /* XRsiz_i */
+               ++l_current_ptr;
+
+               opj_write_bytes(l_current_ptr, l_img_comp->dy, 1);      /* YRsiz_i */
+               ++l_current_ptr;
+
+               ++l_img_comp;
+       }
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_size_len,p_manager) != l_size_len) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
 static void j2k_read_siz(opj_j2k_t *j2k) {
        int len, i;
        
@@ -1971,6 +2808,84 @@ static void j2k_write_cod(opj_j2k_t *j2k) {
 
 }
 
+/**
+ * Writes the COD marker (Coding style default)
+ *
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+*/
+opj_bool j2k_write_cod_v2(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       OPJ_UINT32 l_code_size,l_remaining_size;
+       OPJ_BYTE * l_current_data = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number];
+       l_code_size = 9 + j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,0);
+       l_remaining_size = l_code_size;
+
+       if (l_code_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_code_size);
+
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_code_size;
+       }
+
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_COD,2);           /* COD */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_code_size-2,2);        /* L_COD */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_tcp->csty,1);          /* Scod */
+       ++l_current_data;
+
+       opj_write_bytes(l_current_data,l_tcp->prg,1);           /* SGcod (A) */
+       ++l_current_data;
+
+       opj_write_bytes(l_current_data,l_tcp->numlayers,2);     /* SGcod (B) */
+       l_current_data+=2;
+
+       opj_write_bytes(l_current_data,l_tcp->mct,1);           /* SGcod (C) */
+       ++l_current_data;
+
+       l_remaining_size -= 9;
+
+       if (! j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting COD marker\n");
+               return OPJ_FALSE;
+       }
+
+       if (l_remaining_size != 0) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting COD marker\n");
+               return OPJ_FALSE;
+       }
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_code_size,p_manager) != l_code_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
 static void j2k_read_cod(opj_j2k_t *j2k) {
        int len, i, pos;
        
@@ -2117,7 +3032,131 @@ static void j2k_write_coc(opj_j2k_t *j2k, int compno) {
        cio_seek(cio, lenp + len);
 }
 
-static void j2k_read_coc(opj_j2k_t *j2k) {
+/**
+ * Writes the COC marker (Coding style component)
+ *
+ * @param      p_comp_no               the index of the component to output.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_coc_v2(     opj_j2k_v2_t *p_j2k,
+                                                       OPJ_UINT32 p_comp_no,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 l_coc_size,l_remaining_size;
+       OPJ_UINT32 l_comp_room;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_comp_room = (p_j2k->m_private_image->numcomps <= 256) ? 1 : 2;
+
+       l_coc_size = 5 + l_comp_room + j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no);
+
+       if (l_coc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_coc_size);
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size;
+       }
+
+       j2k_write_coc_in_memory(p_j2k,p_comp_no,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_remaining_size,p_manager);
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_coc_size,p_manager) != l_coc_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Writes the COC marker (Coding style component)
+ *
+ * @param      p_comp_no               the index of the component to output.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+void j2k_write_coc_in_memory(  opj_j2k_v2_t *p_j2k,
+                                                               OPJ_UINT32 p_comp_no,
+                                                               OPJ_BYTE * p_data,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               struct opj_event_mgr * p_manager )
+{
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       OPJ_UINT32 l_coc_size,l_remaining_size;
+       OPJ_BYTE * l_current_data = 00;
+       opj_image_t *l_image = 00;
+       OPJ_UINT32 l_comp_room;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number];
+       l_image = p_j2k->m_private_image;
+       l_comp_room = (l_image->numcomps <= 256) ? 1 : 2;
+
+       l_coc_size = 5 + l_comp_room + j2k_get_SPCod_SPCoc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no);
+       l_remaining_size = l_coc_size;
+
+       l_current_data = p_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_COC,2);                           /* COC */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_coc_size-2,2);                         /* L_COC */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,p_comp_no, l_comp_room);         /* Ccoc */
+       l_current_data+=l_comp_room;
+
+       opj_write_bytes(l_current_data, l_tcp->tccps[p_comp_no].csty, 1);               /* Scoc */
+       ++l_current_data;
+
+       l_remaining_size -= (5 + l_comp_room);
+       j2k_write_SPCod_SPCoc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager);
+       * p_data_written = l_coc_size;
+}
+
+/**
+ * Gets the maximum size taken by a coc.
+ *
+ * @param      p_j2k   the jpeg2000 codec to use.
+ */
+OPJ_UINT32 j2k_get_max_coc_size(opj_j2k_v2_t *p_j2k)
+{
+       OPJ_UINT32 i,j;
+       OPJ_UINT32 l_nb_comp;
+       OPJ_UINT32 l_nb_tiles;
+       OPJ_UINT32 l_max = 0;
+
+       /* preconditions */
+
+       l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ;
+       l_nb_comp = p_j2k->m_private_image->numcomps;
+
+       for (i=0;i<l_nb_tiles;++i) {
+               for (j=0;j<l_nb_comp;++j) {
+                       l_max = uint_max(l_max,j2k_get_SPCod_SPCoc_size(p_j2k,i,j));
+               }
+       }
+
+       return 6 + l_max;
+}
+
+static void j2k_read_coc(opj_j2k_t *j2k) {
        int len, compno;
 
        opj_cp_t *cp = j2k->cp;
@@ -2309,6 +3348,74 @@ static void j2k_write_qcd(opj_j2k_t *j2k) {
          j2k_add_mhmarker(j2k->cstr_info, J2K_MS_QCD, lenp, len);
 }
 
+/**
+ * Writes the QCD marker (quantization default)
+ *
+ * @param      p_comp_number   the index of the component to output.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_qcd_v2(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       OPJ_UINT32 l_qcd_size,l_remaining_size;
+       OPJ_BYTE * l_current_data = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number];
+       l_qcd_size = 4 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,0);
+       l_remaining_size = l_qcd_size;
+
+       if (l_qcd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_qcd_size);
+
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcd_size;
+       }
+
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_QCD,2);           /* QCD */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_qcd_size-2,2);         /* L_QCD */
+       l_current_data += 2;
+
+       l_remaining_size -= 4;
+
+       if (! j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,0,l_current_data,&l_remaining_size,p_manager)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting QCD marker\n");
+               return OPJ_FALSE;
+       }
+
+       if (l_remaining_size != 0) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting QCD marker\n");
+               return OPJ_FALSE;
+       }
+
+       if (opj_stream_write_data(p_stream, p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcd_size,p_manager) != l_qcd_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+
 static void j2k_read_qcd(opj_j2k_t *j2k) {
        int len, i, pos;
 
@@ -2374,6 +3481,114 @@ static void j2k_write_qcc(opj_j2k_t *j2k, int compno) {
        cio_seek(cio, lenp + len);
 }
 
+/**
+ * Writes the QCC marker (quantization component)
+ *
+ * @param      p_comp_no       the index of the component to output.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_qcc_v2(     opj_j2k_v2_t *p_j2k,
+                                                       OPJ_UINT32 p_comp_no,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 l_qcc_size,l_remaining_size;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_qcc_size = 6 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no);
+       l_remaining_size = l_qcc_size;
+
+       if (l_qcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_qcc_size);
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size;
+       }
+
+       j2k_write_qcc_in_memory(p_j2k,p_comp_no,p_j2k->m_specific_param.m_encoder.m_header_tile_data,&l_remaining_size,p_manager);
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcc_size,p_manager) != l_qcc_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Writes the QCC marker (quantization component)
+ *
+ * @param      p_comp_no       the index of the component to output.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+void j2k_write_qcc_in_memory(  opj_j2k_v2_t *p_j2k,
+                                                               OPJ_UINT32 p_comp_no,
+                                                               OPJ_BYTE * p_data,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 l_qcc_size,l_remaining_size;
+       OPJ_BYTE * l_current_data = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+
+       l_qcc_size = 6 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no);
+       l_remaining_size = l_qcc_size;
+
+       l_current_data = p_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_QCC,2);           /* QCC */
+       l_current_data += 2;
+
+       if (p_j2k->m_private_image->numcomps <= 256) {
+               --l_qcc_size;
+
+               opj_write_bytes(l_current_data,l_qcc_size-2,2);         /* L_QCC */
+               l_current_data += 2;
+
+               opj_write_bytes(l_current_data, p_comp_no, 1);  /* Cqcc */
+               ++l_current_data;
+
+               /* in the case only one byte is sufficient the last byte allocated is useless -> still do -6 for available */
+               l_remaining_size -= 6;
+       }
+       else {
+               opj_write_bytes(l_current_data,l_qcc_size-2,2);         /* L_QCC */
+               l_current_data += 2;
+
+               opj_write_bytes(l_current_data, p_comp_no, 2);  /* Cqcc */
+               l_current_data+=2;
+
+               l_remaining_size -= 6;
+       }
+
+       j2k_write_SQcd_SQcc(p_j2k,p_j2k->m_current_tile_number,p_comp_no,l_current_data,&l_remaining_size,p_manager);
+
+       *p_data_written = l_qcc_size;
+}
+
+/**
+ * Gets the maximum size taken by a qcc.
+ */
+OPJ_UINT32 j2k_get_max_qcc_size (opj_j2k_v2_t *p_j2k)
+{
+       return j2k_get_max_coc_size(p_j2k);
+}
+
 static void j2k_read_qcc(opj_j2k_t *j2k) {
        int len, compno;
        int numcomp = j2k->image->numcomps;
@@ -2519,100 +3734,256 @@ static void j2k_write_poc(opj_j2k_t *j2k) {
        }
 }
 
-static void j2k_read_poc(opj_j2k_t *j2k) {
-       int len, numpchgs, i, old_poc;
-
-       int numcomps = j2k->image->numcomps;
-       
-       opj_cp_t *cp = j2k->cp;
-       opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
-       opj_cio_t *cio = j2k->cio;
-       
-       old_poc = tcp->POC ? tcp->numpocs + 1 : 0;
-       tcp->POC = 1;
-       len = cio_read(cio, 2);         /* Lpoc */
-       numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2));
-       
-       for (i = old_poc; i < numpchgs + old_poc; i++) {
-               opj_poc_t *poc;
-               poc = &tcp->pocs[i];
-               poc->resno0 = cio_read(cio, 1); /* RSpoc_i */
-               poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2);  /* CSpoc_i */
-               poc->layno1 = cio_read(cio, 2);    /* LYEpoc_i */
-               poc->resno1 = cio_read(cio, 1);    /* REpoc_i */
-               poc->compno1 = int_min(
-                       cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps);       /* CEpoc_i */
-               poc->prg = (OPJ_PROG_ORDER)cio_read(cio, 1);    /* Ppoc_i */
-       }
-       
-       tcp->numpocs = numpchgs + old_poc - 1;
-}
-
 /**
- * Reads a POC marker (Progression Order Change)
+ * Writes the POC marker (Progression Order Change)
  *
- * @param      p_header_data   the data contained in the POC box.
- * @param      p_j2k                   the jpeg2000 codec.
- * @param      p_header_size   the size of the data contained in the POC marker.
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
  * @param      p_manager               the user event manager.
 */
-opj_bool j2k_read_poc_v2 (
-                                               opj_j2k_v2_t *p_j2k,
-                                               OPJ_BYTE * p_header_data,
-                                               OPJ_UINT32 p_header_size,
-                                               struct opj_event_mgr * p_manager)
+void j2k_write_poc_in_memory(  opj_j2k_v2_t *p_j2k,
+                                                               OPJ_BYTE * p_data,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               struct opj_event_mgr * p_manager )
 {
-       OPJ_UINT32 i, l_nb_comp, l_tmp;
-       opj_image_t * l_image = 00;
-       OPJ_UINT32 l_old_poc_nb, l_current_poc_nb, l_current_poc_remaining;
-       OPJ_UINT32 l_chunk_size, l_comp_room;
-
-       opj_cp_v2_t *l_cp = 00;
+       OPJ_UINT32 i;
+       OPJ_BYTE * l_current_data = 00;
+       OPJ_UINT32 l_nb_comp;
+       OPJ_UINT32 l_nb_poc;
+       OPJ_UINT32 l_poc_size;
+       opj_image_t *l_image = 00;
        opj_tcp_v2_t *l_tcp = 00;
+       opj_tccp_t *l_tccp = 00;
        opj_poc_t *l_current_poc = 00;
+       OPJ_UINT32 l_poc_room;
 
        /* preconditions */
-       assert(p_header_data != 00);
        assert(p_j2k != 00);
        assert(p_manager != 00);
 
+       l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number];
+       l_tccp = &l_tcp->tccps[0];
        l_image = p_j2k->m_private_image;
        l_nb_comp = l_image->numcomps;
+       l_nb_poc = 1 + l_tcp->numpocs;
+
        if (l_nb_comp <= 256) {
-               l_comp_room = 1;
+               l_poc_room = 1;
        }
        else {
-               l_comp_room = 2;
+               l_poc_room = 2;
        }
-       l_chunk_size = 5 + 2 * l_comp_room;
-       l_current_poc_nb = p_header_size / l_chunk_size;
-       l_current_poc_remaining = p_header_size % l_chunk_size;
 
-       if ((l_current_poc_nb <= 0) || (l_current_poc_remaining != 0)) {
-               opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading POC marker\n");
-               return OPJ_FALSE;
-       }
+       l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc;
 
-       l_cp = &(p_j2k->m_cp);
-       l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ?
-                               &l_cp->tcps[p_j2k->m_current_tile_number] :
-                               p_j2k->m_specific_param.m_decoder.m_default_tcp;
-       l_old_poc_nb = l_tcp->POC ? l_tcp->numpocs + 1 : 0;
-       l_current_poc_nb += l_old_poc_nb;
+       l_current_data = p_data;
 
-       assert(l_current_poc_nb < 32);
+       opj_write_bytes(l_current_data,J2K_MS_POC,2);                                   /* POC  */
+       l_current_data += 2;
 
-       /* now poc is in use.*/
-       l_tcp->POC = 1;
+       opj_write_bytes(l_current_data,l_poc_size-2,2);                                 /* Lpoc */
+       l_current_data += 2;
 
-       l_current_poc = &l_tcp->pocs[l_old_poc_nb];
-       for     (i = l_old_poc_nb; i < l_current_poc_nb; ++i) {
-               opj_read_bytes(p_header_data,&(l_current_poc->resno0),1);                               /* RSpoc_i */
-               ++p_header_data;
-               opj_read_bytes(p_header_data,&(l_current_poc->compno0),l_comp_room);    /* CSpoc_i */
-               p_header_data+=l_comp_room;
-               opj_read_bytes(p_header_data,&(l_current_poc->layno1),2);                               /* LYEpoc_i */
-               p_header_data+=2;
+       l_current_poc =  l_tcp->pocs;
+       for (i = 0; i < l_nb_poc; ++i) {
+               opj_write_bytes(l_current_data,l_current_poc->resno0,1);                                /* RSpoc_i */
+               ++l_current_data;
+
+               opj_write_bytes(l_current_data,l_current_poc->compno0,l_poc_room);              /* CSpoc_i */
+               l_current_data+=l_poc_room;
+
+               opj_write_bytes(l_current_data,l_current_poc->layno1,2);                                /* LYEpoc_i */
+               l_current_data+=2;
+
+               opj_write_bytes(l_current_data,l_current_poc->resno1,1);                                /* REpoc_i */
+               ++l_current_data;
+
+               opj_write_bytes(l_current_data,l_current_poc->compno1,l_poc_room);              /* CEpoc_i */
+               l_current_data+=l_poc_room;
+
+               opj_write_bytes(l_current_data,l_current_poc->prg,1);                                   /* Ppoc_i */
+               ++l_current_data;
+
+               /* change the value of the max layer according to the actual number of layers in the file, components and resolutions*/
+               l_current_poc->layno1 = int_min(l_current_poc->layno1, l_tcp->numlayers);
+               l_current_poc->resno1 = int_min(l_current_poc->resno1, l_tccp->numresolutions);
+               l_current_poc->compno1 = int_min(l_current_poc->compno1, l_nb_comp);
+
+               ++l_current_poc;
+       }
+
+       *p_data_written = l_poc_size;
+}
+
+/**
+ * Gets the maximum size taken by the writing of a POC.
+ */
+OPJ_UINT32 j2k_get_max_poc_size(opj_j2k_v2_t *p_j2k)
+{
+       opj_tcp_v2_t * l_tcp = 00;
+       OPJ_UINT32 l_nb_tiles = 0;
+       OPJ_UINT32 l_max_poc = 0;
+       OPJ_UINT32 i;
+
+       l_tcp = p_j2k->m_cp.tcps;
+       l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
+
+       for (i=0;i<l_nb_tiles;++i) {
+               l_max_poc = uint_max(l_max_poc,l_tcp->numpocs);
+               ++l_tcp;
+       }
+
+       ++l_max_poc;
+
+       return 4 + 9 * l_max_poc;
+}
+
+/**
+ * Gets the maximum size taken by the toc headers of all the tile parts of any given tile.
+ */
+OPJ_UINT32 j2k_get_max_toc_size (opj_j2k_v2_t *p_j2k)
+{
+       OPJ_UINT32 i;
+       OPJ_UINT32 l_nb_tiles;
+       OPJ_UINT32 l_max = 0;
+       opj_tcp_v2_t * l_tcp = 00;
+
+       l_tcp = p_j2k->m_cp.tcps;
+       l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ;
+
+       for (i=0;i<l_nb_tiles;++i) {
+               l_max = uint_max(l_max,l_tcp->m_nb_tile_parts);
+
+               ++l_tcp;
+       }
+
+       return 12 * l_max;
+}
+
+
+/**
+ * Gets the maximum size taken by the headers of the SOT.
+ *
+ * @param      p_j2k   the jpeg2000 codec to use.
+ */
+OPJ_UINT32 j2k_get_specific_header_sizes(opj_j2k_v2_t *p_j2k)
+{
+       OPJ_UINT32 l_nb_bytes = 0;
+       OPJ_UINT32 l_nb_comps;
+       OPJ_UINT32 l_coc_bytes,l_qcc_bytes;
+
+       l_nb_comps = p_j2k->m_private_image->numcomps - 1;
+       l_nb_bytes += j2k_get_max_toc_size(p_j2k);
+
+       if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == 0) {
+               l_coc_bytes = j2k_get_max_coc_size(p_j2k);
+               l_nb_bytes += l_nb_comps * l_coc_bytes;
+
+               l_qcc_bytes = j2k_get_max_qcc_size(p_j2k);
+               l_nb_bytes += l_nb_comps * l_qcc_bytes;
+       }
+
+       l_nb_bytes += j2k_get_max_poc_size(p_j2k);
+
+       /*** DEVELOPER CORNER, Add room for your headers ***/
+
+       return l_nb_bytes;
+}
+
+static void j2k_read_poc(opj_j2k_t *j2k) {
+       int len, numpchgs, i, old_poc;
+
+       int numcomps = j2k->image->numcomps;
+       
+       opj_cp_t *cp = j2k->cp;
+       opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+       opj_cio_t *cio = j2k->cio;
+       
+       old_poc = tcp->POC ? tcp->numpocs + 1 : 0;
+       tcp->POC = 1;
+       len = cio_read(cio, 2);         /* Lpoc */
+       numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2));
+       
+       for (i = old_poc; i < numpchgs + old_poc; i++) {
+               opj_poc_t *poc;
+               poc = &tcp->pocs[i];
+               poc->resno0 = cio_read(cio, 1); /* RSpoc_i */
+               poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2);  /* CSpoc_i */
+               poc->layno1 = cio_read(cio, 2);    /* LYEpoc_i */
+               poc->resno1 = cio_read(cio, 1);    /* REpoc_i */
+               poc->compno1 = int_min(
+                       cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps);       /* CEpoc_i */
+               poc->prg = (OPJ_PROG_ORDER)cio_read(cio, 1);    /* Ppoc_i */
+       }
+       
+       tcp->numpocs = numpchgs + old_poc - 1;
+}
+
+/**
+ * Reads a POC marker (Progression Order Change)
+ *
+ * @param      p_header_data   the data contained in the POC box.
+ * @param      p_j2k                   the jpeg2000 codec.
+ * @param      p_header_size   the size of the data contained in the POC marker.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_read_poc_v2 (
+                                               opj_j2k_v2_t *p_j2k,
+                                               OPJ_BYTE * p_header_data,
+                                               OPJ_UINT32 p_header_size,
+                                               struct opj_event_mgr * p_manager)
+{
+       OPJ_UINT32 i, l_nb_comp, l_tmp;
+       opj_image_t * l_image = 00;
+       OPJ_UINT32 l_old_poc_nb, l_current_poc_nb, l_current_poc_remaining;
+       OPJ_UINT32 l_chunk_size, l_comp_room;
+
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_poc_t *l_current_poc = 00;
+
+       /* preconditions */
+       assert(p_header_data != 00);
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+
+       l_image = p_j2k->m_private_image;
+       l_nb_comp = l_image->numcomps;
+       if (l_nb_comp <= 256) {
+               l_comp_room = 1;
+       }
+       else {
+               l_comp_room = 2;
+       }
+       l_chunk_size = 5 + 2 * l_comp_room;
+       l_current_poc_nb = p_header_size / l_chunk_size;
+       l_current_poc_remaining = p_header_size % l_chunk_size;
+
+       if ((l_current_poc_nb <= 0) || (l_current_poc_remaining != 0)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading POC marker\n");
+               return OPJ_FALSE;
+       }
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ?
+                               &l_cp->tcps[p_j2k->m_current_tile_number] :
+                               p_j2k->m_specific_param.m_decoder.m_default_tcp;
+       l_old_poc_nb = l_tcp->POC ? l_tcp->numpocs + 1 : 0;
+       l_current_poc_nb += l_old_poc_nb;
+
+       assert(l_current_poc_nb < 32);
+
+       /* now poc is in use.*/
+       l_tcp->POC = 1;
+
+       l_current_poc = &l_tcp->pocs[l_old_poc_nb];
+       for     (i = l_old_poc_nb; i < l_current_poc_nb; ++i) {
+               opj_read_bytes(p_header_data,&(l_current_poc->resno0),1);                               /* RSpoc_i */
+               ++p_header_data;
+               opj_read_bytes(p_header_data,&(l_current_poc->compno0),l_comp_room);    /* CSpoc_i */
+               p_header_data+=l_comp_room;
+               opj_read_bytes(p_header_data,&(l_current_poc->layno1),2);                               /* LYEpoc_i */
+               p_header_data+=2;
                opj_read_bytes(p_header_data,&(l_current_poc->resno1),1);                               /* REpoc_i */
                ++p_header_data;
                opj_read_bytes(p_header_data,&(l_current_poc->compno1),l_comp_room);    /* CEpoc_i */
@@ -3422,6 +4793,54 @@ static void j2k_write_sot(opj_j2k_t *j2k) {
        }
 }
 
+/**
+ * Writes the SOT marker (Start of tile-part)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_sot_v2(     opj_j2k_v2_t *p_j2k,
+                                                       OPJ_BYTE * p_data,
+                                                       OPJ_UINT32 * p_data_written,
+                                                       const struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       opj_write_bytes(p_data,J2K_MS_SOT,2);                                   /* SOT */
+       p_data += 2;
+
+       opj_write_bytes(p_data,10,2);                                                   /* Lsot */
+       p_data += 2;
+
+       opj_write_bytes(p_data, p_j2k->m_current_tile_number,2);                        /* Isot */
+       p_data += 2;
+
+       /* Psot  */
+       p_data += 4;
+
+       opj_write_bytes(p_data, p_j2k->m_specific_param.m_encoder.m_current_tile_part_number,1);                        /* TPsot */
+       ++p_data;
+
+       opj_write_bytes(p_data, p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts,1);                      /* TNsot */
+       ++p_data;
+
+       /* UniPG>> */
+#ifdef USE_JPWL
+       /* update markers struct */
+       j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2);
+#endif /* USE_JPWL */
+
+       * p_data_written = 12;
+
+       return OPJ_TRUE;
+}
+
+
 static void j2k_read_sot(opj_j2k_t *j2k) {
        int len, tileno, totlen, partno, numparts, i;
        opj_tcp_t *tcp = NULL;
@@ -3860,6 +5279,95 @@ static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder) {
        cio_seek(cio, j2k->sot_start + totlen);
 }
 
+/**
+ * Writes the SOD marker (Start of data)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_sod_v2(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_tcd_v2 * p_tile_coder,
+                                                       OPJ_BYTE * p_data,
+                                                       OPJ_UINT32 * p_data_written,
+                                                       OPJ_UINT32 p_total_data_size,
+                                                       const struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_codestream_info_t *l_cstr_info = 00;
+       opj_cp_v2_t *l_cp = 00;
+
+       OPJ_UINT32 l_size_tile;
+       OPJ_UINT32 l_remaining_data;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       opj_write_bytes(p_data,J2K_MS_SOD,2);                                   /* SOD */
+       p_data += 2;
+
+       /* make room for the EOF marker */
+       l_remaining_data =  p_total_data_size - 4;
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number];
+
+
+       /* update tile coder */
+       p_tile_coder->tp_num = p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number ;
+       p_tile_coder->cur_tp_num = p_j2k->m_specific_param.m_encoder.m_current_tile_part_number;
+
+       l_size_tile = l_cp->th * l_cp->tw;
+
+       /* INDEX >> */
+       /* TODO mergeV2: check this part which use cstr_info */
+       /*l_cstr_info = p_j2k->cstr_info;
+       if (l_cstr_info) {
+               if (!p_j2k->m_specific_param.m_encoder.m_current_tile_part_number ) {
+                       //TODO cstr_info->tile[p_j2k->m_current_tile_number].end_header = p_stream_tell(p_stream) + p_j2k->pos_correction - 1;
+                       l_cstr_info->tile[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number;
+               }
+               else {*/
+                       /*
+                       TODO
+                       if
+                               (cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno - 1].end_pos < p_stream_tell(p_stream))
+                       {
+                               cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno].start_pos = p_stream_tell(p_stream);
+                       }*/
+               /*}*/
+               /* UniPG>> */
+#ifdef USE_JPWL
+               /* update markers struct */
+               j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2);
+#endif /* USE_JPWL */
+               /* <<UniPG */
+       /*}*/
+       /* << INDEX */
+
+       if (p_j2k->m_specific_param.m_encoder.m_current_tile_part_number == 0) {
+               p_tile_coder->tcd_image->tiles->packno = 0;
+               if (l_cstr_info) {
+                       l_cstr_info->packno = 0;
+               }
+       }
+
+       *p_data_written = 0;
+
+       if (! tcd_encode_tile_v2(p_tile_coder, p_j2k->m_current_tile_number, p_data, p_data_written, l_remaining_data , l_cstr_info)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Cannot encode tile\n");
+               return OPJ_FALSE;
+       }
+
+       *p_data_written += 2;
+
+       return OPJ_TRUE;
+}
+
+
 static void j2k_read_sod(opj_j2k_t *j2k) {
        int len, truncate = 0, i;
        unsigned char *data = NULL, *data_ptr = NULL;
@@ -4005,17 +5513,85 @@ static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno) {
        cio_write(cio, tcp->tccps[compno].roishift, 1);         /* SPrgn */
 }
 
-static void j2k_read_rgn(opj_j2k_t *j2k) {
-       int len, compno, roisty;
-
-       opj_cp_t *cp = j2k->cp;
-       opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
-       opj_cio_t *cio = j2k->cio;
-       int numcomps = j2k->image->numcomps;
+/**
+ * Writes the RGN marker (Region Of Interest)
+ *
+ * @param      p_tile_no               the tile to output
+ * @param      p_comp_no               the component to output
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_rgn_v2(     opj_j2k_v2_t *p_j2k,
+                                                       OPJ_UINT32 p_tile_no,
+                                                       OPJ_UINT32 p_comp_no,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_BYTE * l_current_data = 00;
+       OPJ_UINT32 l_nb_comp;
+       OPJ_UINT32 l_rgn_size;
+       opj_image_t *l_image = 00;
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tccp_t *l_tccp = 00;
+       OPJ_UINT32 l_comp_room;
 
-       len = cio_read(cio, 2);                                                                         /* Lrgn */
-       compno = cio_read(cio, numcomps <= 256 ? 1 : 2);                        /* Crgn */
-       roisty = cio_read(cio, 1);                                                                      /* Srgn */
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp = &l_tcp->tccps[p_comp_no];
+
+       l_nb_comp = l_image->numcomps;
+
+       if (l_nb_comp <= 256) {
+               l_comp_room = 1;
+       }
+       else {
+               l_comp_room = 2;
+       }
+
+       l_rgn_size = 6 + l_comp_room;
+
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_RGN,2);                                   /* RGN  */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_rgn_size-2,2);                                 /* Lrgn */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,p_comp_no,l_comp_room);                  /* Crgn */
+       l_current_data+=l_comp_room;
+
+       opj_write_bytes(l_current_data, 0,1);                                                   /* Srgn */
+       ++l_current_data;
+
+       opj_write_bytes(l_current_data, l_tccp->roishift,1);                    /* SPrgn */
+       ++l_current_data;
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_rgn_size,p_manager) != l_rgn_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+static void j2k_read_rgn(opj_j2k_t *j2k) {
+       int len, compno, roisty;
+
+       opj_cp_t *cp = j2k->cp;
+       opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+       opj_cio_t *cio = j2k->cio;
+       int numcomps = j2k->image->numcomps;
+
+       len = cio_read(cio, 2);                                                                         /* Lrgn */
+       compno = cio_read(cio, numcomps <= 256 ? 1 : 2);                        /* Crgn */
+       roisty = cio_read(cio, 1);                                                                      /* Srgn */
 
 #ifdef USE_JPWL
        if (j2k->cp->correct) {
@@ -4120,6 +5696,186 @@ opj_bool j2k_read_rgn_v2 (
 
 }
 
+OPJ_FLOAT32 get_tp_stride (opj_tcp_v2_t * p_tcp)
+{
+       return (OPJ_FLOAT32) ((p_tcp->m_nb_tile_parts - 1) * 14);
+}
+
+OPJ_FLOAT32 get_default_stride (opj_tcp_v2_t * p_tcp)
+{
+       return 0;
+}
+
+/**
+ * Updates the rates of the tcp.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_update_rates(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       opj_cp_v2_t * l_cp = 00;
+       opj_image_t * l_image = 00;
+       opj_tcp_v2_t * l_tcp = 00;
+       opj_image_comp_t * l_img_comp = 00;
+
+       OPJ_UINT32 i,j,k;
+       OPJ_INT32 l_x0,l_y0,l_x1,l_y1;
+       OPJ_FLOAT32 * l_rates = 0;
+       OPJ_FLOAT32 l_sot_remove;
+       OPJ_UINT32 l_bits_empty, l_size_pixel;
+       OPJ_UINT32 l_tile_size = 0;
+       OPJ_UINT32 l_last_res;
+       OPJ_FLOAT32 (* l_tp_stride_func)(opj_tcp_v2_t *) = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+
+       l_cp = &(p_j2k->m_cp);
+       l_image = p_j2k->m_private_image;
+       l_tcp = l_cp->tcps;
+
+       l_bits_empty = 8 * l_image->comps->dx * l_image->comps->dy;
+       l_size_pixel = l_image->numcomps * l_image->comps->prec;
+       l_sot_remove = ((OPJ_FLOAT32) opj_stream_tell(p_stream)) / (l_cp->th * l_cp->tw);
+
+       if (l_cp->m_specific_param.m_enc.m_tp_on) {
+               l_tp_stride_func = get_tp_stride;
+       }
+       else {
+               l_tp_stride_func = get_default_stride;
+       }
+
+       for (i=0;i<l_cp->th;++i) {
+               for (j=0;j<l_cp->tw;++j) {
+                       OPJ_FLOAT32 l_offset = ((*l_tp_stride_func)(l_tcp)) / l_tcp->numlayers;
+
+                       /* 4 borders of the tile rescale on the image if necessary */
+                       l_x0 = int_max(l_cp->tx0 + j * l_cp->tdx, l_image->x0);
+                       l_y0 = int_max(l_cp->ty0 + i * l_cp->tdy, l_image->y0);
+                       l_x1 = int_min(l_cp->tx0 + (j + 1) * l_cp->tdx, l_image->x1);
+                       l_y1 = int_min(l_cp->ty0 + (i + 1) * l_cp->tdy, l_image->y1);
+
+                       l_rates = l_tcp->rates;
+
+                       /* Modification of the RATE >> */
+                       if (*l_rates) {
+                               *l_rates =              (( (float) (l_size_pixel * (l_x1 - l_x0) * (l_y1 - l_y0)))
+                                                               /
+                                                               ((*l_rates) * l_bits_empty)
+                                                               )
+                                                               -
+                                                               l_offset;
+                       }
+
+                       ++l_rates;
+
+                       for (k = 1; k < l_tcp->numlayers; ++k) {
+                               if (*l_rates) {
+                                       *l_rates =              (( (OPJ_FLOAT32) (l_size_pixel * (l_x1 - l_x0) * (l_y1 - l_y0)))
+                                                                       /
+                                                                               ((*l_rates) * l_bits_empty)
+                                                                       )
+                                                                       -
+                                                                       l_offset;
+                               }
+
+                               ++l_rates;
+                       }
+
+                       ++l_tcp;
+
+               }
+       }
+
+       l_tcp = l_cp->tcps;
+
+       for (i=0;i<l_cp->th;++i) {
+               for     (j=0;j<l_cp->tw;++j) {
+                       l_rates = l_tcp->rates;
+
+                       if (*l_rates) {
+                               *l_rates -= l_sot_remove;
+
+                               if (*l_rates < 30) {
+                                       *l_rates = 30;
+                               }
+                       }
+
+                       ++l_rates;
+
+                       l_last_res = l_tcp->numlayers - 1;
+
+                       for (k = 1; k < l_last_res; ++k) {
+
+                               if (*l_rates) {
+                                       *l_rates -= l_sot_remove;
+
+                                       if (*l_rates < *(l_rates - 1) + 10) {
+                                               *l_rates  = (*(l_rates - 1)) + 20;
+                                       }
+                               }
+
+                               ++l_rates;
+                       }
+
+                       if (*l_rates) {
+                               *l_rates -= (l_sot_remove + 2.f);
+
+                               if (*l_rates < *(l_rates - 1) + 10) {
+                                       *l_rates  = (*(l_rates - 1)) + 20;
+                               }
+                       }
+
+                       ++l_tcp;
+               }
+       }
+
+       l_img_comp = l_image->comps;
+       l_tile_size = 0;
+
+       for (i=0;i<l_image->numcomps;++i) {
+               l_tile_size += (        uint_ceildiv(l_cp->tdx,l_img_comp->dx)
+                                                       *
+                                                       uint_ceildiv(l_cp->tdy,l_img_comp->dy)
+                                                       *
+                                                       l_img_comp->prec
+                                               );
+
+               ++l_img_comp;
+       }
+
+       l_tile_size = (OPJ_UINT32) (l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */
+
+       l_tile_size += j2k_get_specific_header_sizes(p_j2k);
+
+       p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = l_tile_size;
+       p_j2k->m_specific_param.m_encoder.m_encoded_tile_data =
+                       (OPJ_BYTE *) opj_malloc(p_j2k->m_specific_param.m_encoder.m_encoded_tile_size);
+       if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data == 00) {
+               return OPJ_FALSE;
+       }
+
+       if (l_cp->m_specific_param.m_enc.m_cinema) {
+               p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer =
+                               (OPJ_BYTE *) opj_malloc(5*p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
+               if (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current =
+                               p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer;
+       }
+
+       return OPJ_TRUE;
+}
+
 static void j2k_read_eoc(opj_j2k_t *j2k) {
        int i, tileno;
        opj_bool success;
@@ -4214,108 +5970,293 @@ opj_bool j2k_read_eoc_v2 (    opj_j2k_v2_t *p_j2k,
        return OPJ_TRUE;
 }
 
-typedef struct opj_dec_mstabent {
-       /** marker value */
-       int id;
-       /** value of the state when the marker can appear */
-       int states;
-       /** action linked to the marker */
-       void (*handler) (opj_j2k_t *j2k);
-} opj_dec_mstabent_t;
+/**
+ * Gets the offset of the header.
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_get_end_header(opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
 
-opj_dec_mstabent_t j2k_dec_mstab[] = {
-  {J2K_MS_SOC, J2K_STATE_MHSOC, j2k_read_soc},
-  {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, j2k_read_sot},
-  {J2K_MS_SOD, J2K_STATE_TPH, j2k_read_sod},
-  {J2K_MS_EOC, J2K_STATE_TPHSOT, j2k_read_eoc},
-  {J2K_MS_SIZ, J2K_STATE_MHSIZ, j2k_read_siz},
-  {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_cod},
-  {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_coc},
-  {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_rgn},
-  {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcd},
-  {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcc},
-  {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_poc},
-  {J2K_MS_TLM, J2K_STATE_MH, j2k_read_tlm},
-  {J2K_MS_PLM, J2K_STATE_MH, j2k_read_plm},
-  {J2K_MS_PLT, J2K_STATE_TPH, j2k_read_plt},
-  {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm},
-  {J2K_MS_PPT, J2K_STATE_TPH, j2k_read_ppt},
-  {J2K_MS_SOP, 0, 0},
-  {J2K_MS_CRG, J2K_STATE_MH, j2k_read_crg},
-  {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com},
+       p_j2k->cstr_index->main_head_end = opj_stream_tell(p_stream);
 
-#ifdef USE_JPWL
-  {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc},
-  {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb},
-  {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd},
-  {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red},
-#endif /* USE_JPWL */
-#ifdef USE_JPSEC
-  {J2K_MS_SEC, J2K_STATE_MH, j2k_read_sec},
-  {J2K_MS_INSEC, 0, j2k_read_insec},
-#endif /* USE_JPSEC */
+       return OPJ_TRUE;
+}
 
-  {0, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_unk}
-};
+/**
+ * Writes the MCT marker (Multiple Component Transform)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_mct_data_group(     opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 i;
+       opj_simple_mcc_decorrelation_data_t * l_mcc_record;
+       opj_mct_data_t * l_mct_record;
+       opj_tcp_v2_t * l_tcp;
 
-static void j2k_read_unk(opj_j2k_t *j2k) {
-       opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown marker\n");
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_stream != 00);
+       assert(p_manager != 00);
 
-#ifdef USE_JPWL
-       if (j2k->cp->correct) {
-               int m = 0, id, i;
-               int min_id = 0, min_dist = 17, cur_dist = 0, tmp_id;
-               cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
-               id = cio_read(j2k->cio, 2);
-               opj_event_msg(j2k->cinfo, EVT_ERROR,
-                       "JPWL: really don't know this marker %x\n",
-                       id);
-               if (!JPWL_ASSUME) {
-                       opj_event_msg(j2k->cinfo, EVT_ERROR,
-                               "- possible synch loss due to uncorrectable codestream errors => giving up\n");
-                       return;
-               }
-               /* OK, activate this at your own risk!!! */
-               /* we look for the marker at the minimum hamming distance from this */
-               while (j2k_dec_mstab[m].id) {
-                       
-                       /* 1's where they differ */
-                       tmp_id = j2k_dec_mstab[m].id ^ id;
+       if (! j2k_write_cbd(p_j2k,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
 
-                       /* compute the hamming distance between our id and the current */
-                       cur_dist = 0;
-                       for (i = 0; i < 16; i++) {
-                               if ((tmp_id >> i) & 0x0001) {
-                                       cur_dist++;
-                               }
-                       }
+       l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]);
+       l_mct_record = l_tcp->m_mct_records;
 
-                       /* if current distance is smaller, set the minimum */
-                       if (cur_dist < min_dist) {
-                               min_dist = cur_dist;
-                               min_id = j2k_dec_mstab[m].id;
-                       }
-                       
-                       /* jump to the next marker */
-                       m++;
+       for (i=0;i<l_tcp->m_nb_mct_records;++i) {
+
+               if (! j2k_write_mct_record(p_j2k,l_mct_record,p_stream,p_manager)) {
+                       return OPJ_FALSE;
                }
 
-               /* do we substitute the marker? */
-               if (min_dist < JPWL_MAXIMUM_HAMMING) {
-                       opj_event_msg(j2k->cinfo, EVT_ERROR,
-                               "- marker %x is at distance %d from the read %x\n",
-                               min_id, min_dist, id);
-                       opj_event_msg(j2k->cinfo, EVT_ERROR,
-                               "- trying to substitute in place and crossing fingers!\n");
-                       cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
-                       cio_write(j2k->cio, min_id, 2);
+               ++l_mct_record;
+       }
 
-                       /* rewind */
-                       cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+       l_mcc_record = l_tcp->m_mcc_records;
+
+       for     (i=0;i<l_tcp->m_nb_mcc_records;++i) {
 
+               if (! j2k_write_mcc_record(p_j2k,l_mcc_record,p_stream,p_manager)) {
+                       return OPJ_FALSE;
                }
 
-       };
+               ++l_mcc_record;
+       }
+
+       if (! j2k_write_mco(p_j2k,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Writes the image components.
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_image_components(opj_j2k_v2_t *p_j2k,
+                                                                       struct opj_stream_private *p_stream,
+                                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 compno;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno)
+       {
+               if (! j2k_write_coc_v2(p_j2k,compno,p_stream, p_manager)) {
+                       return OPJ_FALSE;
+               }
+
+               if (! j2k_write_qcc_v2(p_j2k,compno,p_stream, p_manager)) {
+                       return OPJ_FALSE;
+               }
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Writes regions of interests.
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_regions(    opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 compno;
+       const opj_tccp_t *l_tccp = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_tccp = p_j2k->m_cp.tcps->tccps;
+
+       for     (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno)  {
+               if (l_tccp->roishift) {
+
+                       if (! j2k_write_rgn_v2(p_j2k,0,compno,p_stream,p_manager)) {
+                               return OPJ_FALSE;
+                       }
+               }
+
+               ++l_tccp;
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Writes EPC ????
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_epc(        opj_j2k_v2_t *p_j2k,
+                                               struct opj_stream_private *p_stream,
+                                               struct opj_event_mgr * p_manager )
+{
+       opj_codestream_index_t * l_cstr_index = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_cstr_index = p_j2k->cstr_index;
+       if (l_cstr_index) {
+               l_cstr_index->codestream_size = opj_stream_tell(p_stream);
+               /* UniPG>> */
+               /* The following adjustment is done to adjust the codestream size */
+               /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */
+               /* the first bunch of bytes is not in the codestream              */
+               l_cstr_index->codestream_size -= l_cstr_index->main_head_start;
+               /* <<UniPG */
+       }
+
+#ifdef USE_JPWL
+       /* preparation of JPWL marker segments */
+       if(cp->epc_on) {
+
+               /* encode according to JPWL */
+               jpwl_encode(p_j2k, p_stream, image);
+
+       }
+#endif /* USE_JPWL */
+
+       return OPJ_TRUE;
+}
+
+typedef struct opj_dec_mstabent {
+       /** marker value */
+       int id;
+       /** value of the state when the marker can appear */
+       int states;
+       /** action linked to the marker */
+       void (*handler) (opj_j2k_t *j2k);
+} opj_dec_mstabent_t;
+
+opj_dec_mstabent_t j2k_dec_mstab[] = {
+  {J2K_MS_SOC, J2K_STATE_MHSOC, j2k_read_soc},
+  {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, j2k_read_sot},
+  {J2K_MS_SOD, J2K_STATE_TPH, j2k_read_sod},
+  {J2K_MS_EOC, J2K_STATE_TPHSOT, j2k_read_eoc},
+  {J2K_MS_SIZ, J2K_STATE_MHSIZ, j2k_read_siz},
+  {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_cod},
+  {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_coc},
+  {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_rgn},
+  {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcd},
+  {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcc},
+  {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_poc},
+  {J2K_MS_TLM, J2K_STATE_MH, j2k_read_tlm},
+  {J2K_MS_PLM, J2K_STATE_MH, j2k_read_plm},
+  {J2K_MS_PLT, J2K_STATE_TPH, j2k_read_plt},
+  {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm},
+  {J2K_MS_PPT, J2K_STATE_TPH, j2k_read_ppt},
+  {J2K_MS_SOP, 0, 0},
+  {J2K_MS_CRG, J2K_STATE_MH, j2k_read_crg},
+  {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com},
+
+#ifdef USE_JPWL
+  {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc},
+  {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb},
+  {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd},
+  {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red},
+#endif /* USE_JPWL */
+#ifdef USE_JPSEC
+  {J2K_MS_SEC, J2K_STATE_MH, j2k_read_sec},
+  {J2K_MS_INSEC, 0, j2k_read_insec},
+#endif /* USE_JPSEC */
+
+  {0, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_unk}
+};
+
+static void j2k_read_unk(opj_j2k_t *j2k) {
+       opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown marker\n");
+
+#ifdef USE_JPWL
+       if (j2k->cp->correct) {
+               int m = 0, id, i;
+               int min_id = 0, min_dist = 17, cur_dist = 0, tmp_id;
+               cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+               id = cio_read(j2k->cio, 2);
+               opj_event_msg(j2k->cinfo, EVT_ERROR,
+                       "JPWL: really don't know this marker %x\n",
+                       id);
+               if (!JPWL_ASSUME) {
+                       opj_event_msg(j2k->cinfo, EVT_ERROR,
+                               "- possible synch loss due to uncorrectable codestream errors => giving up\n");
+                       return;
+               }
+               /* OK, activate this at your own risk!!! */
+               /* we look for the marker at the minimum hamming distance from this */
+               while (j2k_dec_mstab[m].id) {
+                       
+                       /* 1's where they differ */
+                       tmp_id = j2k_dec_mstab[m].id ^ id;
+
+                       /* compute the hamming distance between our id and the current */
+                       cur_dist = 0;
+                       for (i = 0; i < 16; i++) {
+                               if ((tmp_id >> i) & 0x0001) {
+                                       cur_dist++;
+                               }
+                       }
+
+                       /* if current distance is smaller, set the minimum */
+                       if (cur_dist < min_dist) {
+                               min_dist = cur_dist;
+                               min_id = j2k_dec_mstab[m].id;
+                       }
+                       
+                       /* jump to the next marker */
+                       m++;
+               }
+
+               /* do we substitute the marker? */
+               if (min_dist < JPWL_MAXIMUM_HAMMING) {
+                       opj_event_msg(j2k->cinfo, EVT_ERROR,
+                               "- marker %x is at distance %d from the read %x\n",
+                               min_id, min_dist, id);
+                       opj_event_msg(j2k->cinfo, EVT_ERROR,
+                               "- trying to substitute in place and crossing fingers!\n");
+                       cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+                       cio_write(j2k->cio, min_id, 2);
+
+                       /* rewind */
+                       cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+
+               }
+
+       };
 #endif /* USE_JPWL */
 
 }
@@ -4399,6 +6340,70 @@ static opj_dec_mstabent_t *j2k_dec_mstab_lookup(int id) {
        return e;
 }
 
+/**
+ * Writes the MCT marker (Multiple Component Transform)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_mct_record( opj_j2k_v2_t *p_j2k,
+                                                               opj_mct_data_t * p_mct_record,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 l_mct_size;
+       OPJ_BYTE * l_current_data = 00;
+       OPJ_UINT32 l_tmp;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_mct_size = 10 + p_mct_record->m_data_size;
+
+       if (l_mct_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_mct_size);
+
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mct_size;
+       }
+
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_MCT,2);                                   /* MCT */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_mct_size-2,2);                                 /* Lmct */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,0,2);                                                    /* Zmct */
+       l_current_data += 2;
+
+       /* only one marker atm */
+       l_tmp = (p_mct_record->m_index & 0xff) | (p_mct_record->m_array_type << 8) | (p_mct_record->m_element_type << 10);
+
+       opj_write_bytes(l_current_data,l_tmp,2);
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,0,2);                                                    /* Ymct */
+       l_current_data+=2;
+
+       memcpy(l_current_data,p_mct_record->m_data,p_mct_record->m_data_size);
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mct_size,p_manager) != l_mct_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
 
 /**
  * Reads a MCT marker (Multiple Component Transform)
@@ -4509,28 +6514,137 @@ opj_bool j2k_read_mct (        opj_j2k_v2_t *p_j2k,
 }
 
 /**
- * Reads a MCC marker (Multiple Component Collection)
+ * Writes the MCC marker (Multiple Component Collection)
  *
- * @param      p_header_data   the data contained in the MCC box.
- * @param      p_j2k                   the jpeg2000 codec.
- * @param      p_header_size   the size of the data contained in the MCC marker.
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
  * @param      p_manager               the user event manager.
 */
-opj_bool j2k_read_mcc (        opj_j2k_v2_t *p_j2k,
-                                       OPJ_BYTE * p_header_data,
-                                       OPJ_UINT32 p_header_size,
-                                       struct opj_event_mgr * p_manager )
+opj_bool j2k_write_mcc_record( opj_j2k_v2_t *p_j2k,
+                                                               struct opj_simple_mcc_decorrelation_data * p_mcc_record,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager )
 {
-       OPJ_UINT32 i,j;
-       OPJ_UINT32 l_tmp;
-       OPJ_UINT32 l_indix;
-       opj_tcp_v2_t * l_tcp;
-       opj_simple_mcc_decorrelation_data_t * l_mcc_record;
-       opj_mct_data_t * l_mct_data;
-       OPJ_UINT32 l_nb_collections;
-       OPJ_UINT32 l_nb_comps;
-       OPJ_UINT32 l_nb_bytes_by_comp;
-
+       OPJ_UINT32 i;
+       OPJ_UINT32 l_mcc_size;
+       OPJ_BYTE * l_current_data = 00;
+       OPJ_UINT32 l_nb_bytes_for_comp;
+       OPJ_UINT32 l_mask;
+       OPJ_UINT32 l_tmcc;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       if (p_mcc_record->m_nb_comps > 255 ) {
+        l_nb_bytes_for_comp = 2;
+               l_mask = 0x8000;
+       }
+       else {
+               l_nb_bytes_for_comp = 1;
+               l_mask = 0;
+       }
+
+       l_mcc_size = p_mcc_record->m_nb_comps * 2 * l_nb_bytes_for_comp + 19;
+       if (l_mcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size)
+       {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_mcc_size);
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mcc_size;
+       }
+
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_MCC,2);                                   /* MCC */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_mcc_size-2,2);                                 /* Lmcc */
+       l_current_data += 2;
+
+       /* first marker */
+       opj_write_bytes(l_current_data,0,2);                                    /* Zmcc */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,p_mcc_record->m_index,1);                                        /* Imcc -> no need for other values, take the first */
+       ++l_current_data;
+
+       /* only one marker atm */
+       opj_write_bytes(l_current_data,0,2);                                    /* Ymcc */
+       l_current_data+=2;
+
+       opj_write_bytes(l_current_data,1,2);                                    /* Qmcc -> number of collections -> 1 */
+       l_current_data+=2;
+
+       opj_write_bytes(l_current_data,0x1,1);                                  /* Xmcci type of component transformation -> array based decorrelation */
+       ++l_current_data;
+
+       opj_write_bytes(l_current_data,p_mcc_record->m_nb_comps | l_mask,2);    /* Nmcci number of input components involved and size for each component offset = 8 bits */
+       l_current_data+=2;
+
+       for (i=0;i<p_mcc_record->m_nb_comps;++i) {
+               opj_write_bytes(l_current_data,i,l_nb_bytes_for_comp);                          /* Cmccij Component offset*/
+               l_current_data+=l_nb_bytes_for_comp;
+       }
+
+       opj_write_bytes(l_current_data,p_mcc_record->m_nb_comps|l_mask,2);      /* Mmcci number of output components involved and size for each component offset = 8 bits */
+       l_current_data+=2;
+
+       for (i=0;i<p_mcc_record->m_nb_comps;++i)
+       {
+               opj_write_bytes(l_current_data,i,l_nb_bytes_for_comp);                          /* Wmccij Component offset*/
+               l_current_data+=l_nb_bytes_for_comp;
+       }
+
+       l_tmcc = ((!p_mcc_record->m_is_irreversible)&1)<<16;
+
+       if (p_mcc_record->m_decorrelation_array) {
+               l_tmcc |= p_mcc_record->m_decorrelation_array->m_index;
+       }
+
+       if (p_mcc_record->m_offset_array) {
+               l_tmcc |= ((p_mcc_record->m_offset_array->m_index)<<8);
+       }
+
+       opj_write_bytes(l_current_data,l_tmcc,3);       /* Tmcci : use MCT defined as number 1 and irreversible array based. */
+       l_current_data+=3;
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mcc_size,p_manager) != l_mcc_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Reads a MCC marker (Multiple Component Collection)
+ *
+ * @param      p_header_data   the data contained in the MCC box.
+ * @param      p_j2k                   the jpeg2000 codec.
+ * @param      p_header_size   the size of the data contained in the MCC marker.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_read_mcc (        opj_j2k_v2_t *p_j2k,
+                                       OPJ_BYTE * p_header_data,
+                                       OPJ_UINT32 p_header_size,
+                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 i,j;
+       OPJ_UINT32 l_tmp;
+       OPJ_UINT32 l_indix;
+       opj_tcp_v2_t * l_tcp;
+       opj_simple_mcc_decorrelation_data_t * l_mcc_record;
+       opj_mct_data_t * l_mct_data;
+       OPJ_UINT32 l_nb_collections;
+       OPJ_UINT32 l_nb_comps;
+       OPJ_UINT32 l_nb_bytes_by_comp;
+
 
        /* preconditions */
        assert(p_header_data != 00);
@@ -4726,6 +6840,72 @@ opj_bool j2k_read_mcc (  opj_j2k_v2_t *p_j2k,
        return OPJ_TRUE;
 }
 
+
+/**
+ * Writes the MCO marker (Multiple component transformation ordering)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_mco(        opj_j2k_v2_t *p_j2k,
+                                               struct opj_stream_private *p_stream,
+                                               struct opj_event_mgr * p_manager
+                                 )
+{
+       OPJ_BYTE * l_current_data = 00;
+       OPJ_UINT32 l_mco_size;
+       opj_tcp_v2_t * l_tcp = 00;
+       opj_simple_mcc_decorrelation_data_t * l_mcc_record;
+       OPJ_UINT32 i;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_tcp =&(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]);
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       l_mco_size = 5 + l_tcp->m_nb_mcc_records;
+       if (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_mco_size);
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data)
+               {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size;
+       }
+
+       opj_write_bytes(l_current_data,J2K_MS_MCO,2);                   /* MCO */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_mco_size-2,2);                                 /* Lmco */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_tcp->m_nb_mcc_records,1);                                      /* Nmco : only one tranform stage*/
+       ++l_current_data;
+
+       l_mcc_record = l_tcp->m_mcc_records;
+       for     (i=0;i<l_tcp->m_nb_mcc_records;++i) {
+               opj_write_bytes(l_current_data,l_mcc_record->m_index,1);                                        /* Imco -> use the mcc indicated by 1*/
+               ++l_current_data;
+
+               ++l_mcc_record;
+       }
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_mco_size,p_manager) != l_mco_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
 /**
  * Reads a MCO marker (Multiple Component Transform Ordering)
  *
@@ -4881,6 +7061,71 @@ opj_bool j2k_add_mct(opj_tcp_v2_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_i
        return OPJ_TRUE;
 }
 
+/**
+ * Writes the CBD marker (Component bit depth definition)
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_cbd( opj_j2k_v2_t *p_j2k,
+                                               struct opj_stream_private *p_stream,
+                                               struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 i;
+       OPJ_UINT32 l_cbd_size;
+       OPJ_BYTE * l_current_data = 00;
+       opj_image_t *l_image = 00;
+       opj_image_comp_t * l_comp = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_image = p_j2k->m_private_image;
+       l_cbd_size = 6 + p_j2k->m_private_image->numcomps;
+
+       if (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data
+                       = (OPJ_BYTE*)opj_realloc(
+                               p_j2k->m_specific_param.m_encoder.m_header_tile_data,
+                               l_cbd_size);
+
+               if (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+                       return OPJ_FALSE;
+               }
+
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_cbd_size;
+       }
+
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
+
+       opj_write_bytes(l_current_data,J2K_MS_CBD,2);                                   /* CBD */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_cbd_size-2,2);                                 /* L_CBD */
+       l_current_data += 2;
+
+       opj_write_bytes(l_current_data,l_image->numcomps, 2);           /* Ncbd */
+       l_current_data+=2;
+
+       l_comp = l_image->comps;
+
+       for (i=0;i<l_image->numcomps;++i) {
+               opj_write_bytes(l_current_data, (l_comp->sgnd << 7) | (l_comp->prec - 1), 1);           /* Component bit depth */
+               ++l_current_data;
+
+               ++l_comp;
+       }
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_cbd_size,p_manager) != l_cbd_size) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
 /**
  * Reads a CBD marker (Component bit depth definition)
  * @param      p_header_data   the data contained in the CBD box.
@@ -5957,20 +8202,117 @@ void j2k_setup_decoding_validation (opj_j2k_v2_t *p_j2k)
 
 }
 
+
+/**
+ * The mct encoding validation procedure.
+ *
+ * @param      p_j2k                   the jpeg2000 codec to validate.
+ * @param      p_stream                                the input stream to validate.
+ * @param      p_manager               the user event manager.
+ *
+ * @return true if the parameters are correct.
+ */
+opj_bool j2k_mct_validation (  opj_j2k_v2_t * p_j2k,
+                                                               opj_stream_private_t *p_stream,
+                                                               opj_event_mgr_t * p_manager )
+{
+       opj_bool l_is_valid = OPJ_TRUE;
+       OPJ_UINT32 i,j;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_stream != 00);
+       assert(p_manager != 00);
+
+       if ((p_j2k->m_cp.rsiz & 0x8200) == 0x8200) {
+               OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
+               opj_tcp_v2_t * l_tcp = p_j2k->m_cp.tcps;
+
+               for (i=0;i<l_nb_tiles;++i) {
+                       if (l_tcp->mct == 2) {
+                               opj_tccp_t * l_tccp = l_tcp->tccps;
+                               l_is_valid &= (l_tcp->m_mct_coding_matrix != 00);
+
+                               for (j=0;j<p_j2k->m_private_image->numcomps;++j) {
+                                       l_is_valid &= ! (l_tccp->qmfbid & 1);
+                                       ++l_tccp;
+                               }
+                       }
+                       ++l_tcp;
+               }
+       }
+
+       return l_is_valid;
+}
+
 /**
  * Builds the cp decoder parameters to use to decode tile.
  */
-opj_bool j2k_build_decoder (
-                                               opj_j2k_v2_t * p_j2k,
-                                               opj_stream_private_t *p_stream,
-                                               opj_event_mgr_t * p_manager
-                                               )
+opj_bool j2k_build_decoder (opj_j2k_v2_t * p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       opj_event_mgr_t * p_manager )
+{
+       /* add here initialization of cp
+          copy paste of setup_decoder */
+       return OPJ_TRUE;
+}
+
+/**
+ * Builds the cp encoder parameters to use to encode tile.
+ */
+opj_bool j2k_build_encoder (opj_j2k_v2_t * p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       opj_event_mgr_t * p_manager )
 {
        /* add here initialization of cp
-       // copy paste of setup_decoder*/
+          copy paste of setup_encoder */
        return OPJ_TRUE;
 }
 
+/**
+ * The default encoding validation procedure without any extension.
+ *
+ * @param      p_j2k                   the jpeg2000 codec to validate.
+ * @param      p_stream                                the input stream to validate.
+ * @param      p_manager               the user event manager.
+ *
+ * @return true if the parameters are correct.
+ */
+opj_bool j2k_encoding_validation (     opj_j2k_v2_t * p_j2k,
+                                                                       opj_stream_private_t *p_stream,
+                                                                       opj_event_mgr_t * p_manager )
+{
+       opj_bool l_is_valid = OPJ_TRUE;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_stream != 00);
+       assert(p_manager != 00);
+
+       /* STATE checking */
+       /* make sure the state is at 0 */
+       l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NONE);
+
+       /* POINTER validation */
+       /* make sure a p_j2k codec is present */
+       l_is_valid &= (p_j2k->m_procedure_list != 00);
+       /* make sure a validation list is present */
+       l_is_valid &= (p_j2k->m_validation_list != 00);
+
+       if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
+               return OPJ_FALSE;
+       }
+
+       if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
+               return OPJ_FALSE;
+       }
+
+       /* PARAMETER VALIDATION */
+       return l_is_valid;
+}
+
 /**
  * The default decoding validation procedure without any extension.
  *
@@ -7359,30 +9701,142 @@ opj_codestream_index_t* j2k_create_cstr_index(void)
        return cstr_index;
 }
 
+
 /**
- * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
- * @param      p_header_data   the data contained in the COM box.
- * @param      p_j2k                   the jpeg2000 codec.
- * @param      p_header_size   the size of the data contained in the COM marker.
- * @param      p_manager               the user event manager.
-*/
-opj_bool j2k_read_SPCod_SPCoc(
-                                                   opj_j2k_v2_t *p_j2k,
-                                                       OPJ_UINT32 compno,
-                                                       OPJ_BYTE * p_header_data,
-                                                       OPJ_UINT32 * p_header_size,
-                                                       struct opj_event_mgr * p_manager
-                                                       )
+ * Gets the size taken by writing a SPCod or SPCoc for the given tile and component.
+ *
+ * @param      p_tile_no               the tile index.
+ * @param      p_comp_no               the component being outputted.
+ * @param      p_j2k                   the J2K codec.
+ *
+ * @return     the number of bytes taken by the SPCod element.
+ */
+OPJ_UINT32 j2k_get_SPCod_SPCoc_size (  opj_j2k_v2_t *p_j2k,
+                                                                               OPJ_UINT32 p_tile_no,
+                                                                               OPJ_UINT32 p_comp_no )
 {
-       OPJ_UINT32 i, l_tmp;
-       opj_cp_v2_t *l_cp = NULL;
-       opj_tcp_v2_t *l_tcp = NULL;
-       opj_tccp_t *l_tccp = NULL;
-       OPJ_BYTE * l_current_ptr = NULL;
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tccp_t *l_tccp = 00;
 
        /* preconditions */
        assert(p_j2k != 00);
-       assert(p_manager != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp = &l_tcp->tccps[p_comp_no];
+
+       /* preconditions again */
+       assert(p_tile_no < (l_cp->tw * l_cp->th));
+       assert(p_comp_no < p_j2k->m_private_image->numcomps);
+
+       if (l_tccp->csty & J2K_CCP_CSTY_PRT) {
+               return 5 + l_tccp->numresolutions;
+       }
+       else {
+               return 5;
+       }
+}
+
+/**
+ * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
+ *
+ * @param      p_comp_no       the component number to output.
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager       the user event manager.
+ *
+*/
+opj_bool j2k_write_SPCod_SPCoc(        opj_j2k_v2_t *p_j2k,
+                                                               OPJ_UINT32 p_tile_no,
+                                                               OPJ_UINT32 p_comp_no,
+                                                               OPJ_BYTE * p_data,
+                                                               OPJ_UINT32 * p_header_size,
+                                                               struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 i;
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tccp_t *l_tccp = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_header_size != 00);
+       assert(p_manager != 00);
+       assert(p_data != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp = &l_tcp->tccps[p_comp_no];
+
+       /* preconditions again */
+       assert(p_tile_no < (l_cp->tw * l_cp->th));
+       assert(p_comp_no <(p_j2k->m_private_image->numcomps));
+
+       if (*p_header_size < 5) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n");
+               return OPJ_FALSE;
+       }
+
+       opj_write_bytes(p_data,l_tccp->numresolutions - 1, 1);  /* SPcoc (D) */
+       ++p_data;
+
+       opj_write_bytes(p_data,l_tccp->cblkw - 2, 1);                   /* SPcoc (E) */
+       ++p_data;
+
+       opj_write_bytes(p_data,l_tccp->cblkh - 2, 1);                   /* SPcoc (F) */
+       ++p_data;
+
+       opj_write_bytes(p_data,l_tccp->cblksty, 1);                             /* SPcoc (G) */
+       ++p_data;
+
+       opj_write_bytes(p_data,l_tccp->qmfbid, 1);                              /* SPcoc (H) */
+       ++p_data;
+
+       *p_header_size = *p_header_size - 5;
+
+       if (l_tccp->csty & J2K_CCP_CSTY_PRT) {
+
+               if (*p_header_size < l_tccp->numresolutions) {
+                       opj_event_msg_v2(p_manager, EVT_ERROR, "Error writting SPCod SPCoc element\n");
+                       return OPJ_FALSE;
+               }
+
+               for (i = 0; i < l_tccp->numresolutions; ++i) {
+                       opj_write_bytes(p_data,l_tccp->prcw[i] + (l_tccp->prch[i] << 4), 1);    /* SPcoc (I_i) */
+                       ++p_data;
+               }
+
+               *p_header_size = *p_header_size - l_tccp->numresolutions;
+       }
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile.
+ * @param      p_header_data   the data contained in the COM box.
+ * @param      p_j2k                   the jpeg2000 codec.
+ * @param      p_header_size   the size of the data contained in the COM marker.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_read_SPCod_SPCoc(
+                                                   opj_j2k_v2_t *p_j2k,
+                                                       OPJ_UINT32 compno,
+                                                       OPJ_BYTE * p_header_data,
+                                                       OPJ_UINT32 * p_header_size,
+                                                       struct opj_event_mgr * p_manager
+                                                       )
+{
+       OPJ_UINT32 i, l_tmp;
+       opj_cp_v2_t *l_cp = NULL;
+       opj_tcp_v2_t *l_tcp = NULL;
+       opj_tccp_t *l_tccp = NULL;
+       OPJ_BYTE * l_current_ptr = NULL;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
        assert(p_header_data != 00);
 
        l_cp = &(p_j2k->m_cp);
@@ -7513,6 +9967,130 @@ void j2k_copy_tile_component_parameters( opj_j2k_v2_t *p_j2k )
        }
 }
 
+/**
+ * Gets the size taken by writing SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC.
+ *
+ * @param      p_tile_no               the tile index.
+ * @param      p_comp_no               the component being outputted.
+ * @param      p_j2k                   the J2K codec.
+ *
+ * @return     the number of bytes taken by the SPCod element.
+ */
+OPJ_UINT32 j2k_get_SQcd_SQcc_size (    opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_UINT32 p_tile_no,
+                                                                       OPJ_UINT32 p_comp_no )
+{
+       OPJ_UINT32 l_num_bands;
+
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tccp_t *l_tccp = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp = &l_tcp->tccps[p_comp_no];
+
+       /* preconditions again */
+       assert(p_tile_no < l_cp->tw * l_cp->th);
+       assert(p_comp_no < p_j2k->m_private_image->numcomps);
+
+       l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (l_tccp->numresolutions * 3 - 2);
+
+       if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT)  {
+               return 1 + l_num_bands;
+       }
+       else {
+               return 1 + 2*l_num_bands;
+       }
+}
+
+/**
+ * Writes a SQcd or SQcc element, i.e. the quantization values of a band.
+ *
+ * @param      p_tile_no               the tile to output.
+ * @param      p_comp_no               the component number to output.
+ * @param      p_data                  the data buffer.
+ * @param      p_header_size   pointer to the size of the data buffer, it is changed by the function.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+ *
+*/
+opj_bool j2k_write_SQcd_SQcc(  opj_j2k_v2_t *p_j2k,
+                                                               OPJ_UINT32 p_tile_no,
+                                                               OPJ_UINT32 p_comp_no,
+                                                               OPJ_BYTE * p_data,
+                                                               OPJ_UINT32 * p_header_size,
+                                                               struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 l_header_size;
+       OPJ_UINT32 l_band_no, l_num_bands;
+       OPJ_UINT32 l_expn,l_mant;
+
+       opj_cp_v2_t *l_cp = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tccp_t *l_tccp = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_header_size != 00);
+       assert(p_manager != 00);
+       assert(p_data != 00);
+
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = &l_cp->tcps[p_tile_no];
+       l_tccp = &l_tcp->tccps[p_comp_no];
+
+       /* preconditions again */
+       assert(p_tile_no < l_cp->tw * l_cp->th);
+       assert(p_comp_no <p_j2k->m_private_image->numcomps);
+
+       l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : (l_tccp->numresolutions * 3 - 2);
+
+       if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT)  {
+               l_header_size = 1 + l_num_bands;
+
+               if (*p_header_size < l_header_size) {
+                       opj_event_msg_v2(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n");
+                       return OPJ_FALSE;
+               }
+
+               opj_write_bytes(p_data,l_tccp->qntsty + (l_tccp->numgbits << 5), 1);    /* Sqcx */
+               ++p_data;
+
+               for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) {
+                       l_expn = l_tccp->stepsizes[l_band_no].expn;
+                       opj_write_bytes(p_data, l_expn << 3, 1);        /* SPqcx_i */
+                       ++p_data;
+               }
+       }
+       else {
+               l_header_size = 1 + 2*l_num_bands;
+
+               if (*p_header_size < l_header_size) {
+                       opj_event_msg_v2(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n");
+                       return OPJ_FALSE;
+               }
+
+               opj_write_bytes(p_data,l_tccp->qntsty + (l_tccp->numgbits << 5), 1);    /* Sqcx */
+               ++p_data;
+
+               for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) {
+                       l_expn = l_tccp->stepsizes[l_band_no].expn;
+                       l_mant = l_tccp->stepsizes[l_band_no].mant;
+
+                       opj_write_bytes(p_data, (l_expn << 11) + l_mant, 2);    /* SPqcx_i */
+                       p_data += 2;
+               }
+       }
+
+       *p_header_size = *p_header_size - l_header_size;
+
+       return OPJ_TRUE;
+}
+
 /**
  * Reads a SQcd or SQcc element, i.e. the quantization values of a band.
  *
@@ -8517,3 +11095,794 @@ opj_bool j2k_set_decoded_resolution_factor(opj_j2k_v2_t *p_j2k, OPJ_UINT32 res_f
 
        return OPJ_FALSE;
 }
+
+
+/**
+ * Encodes all the tiles in a row.
+ */
+opj_bool j2k_encode_v2(        opj_j2k_v2_t * p_j2k,
+                                               opj_stream_private_t *p_stream,
+                                               opj_event_mgr_t * p_manager )
+{
+       OPJ_UINT32 i;
+       OPJ_UINT32 l_nb_tiles;
+       OPJ_UINT32 l_max_tile_size, l_current_tile_size;
+       OPJ_BYTE * l_current_data;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_stream != 00);
+       assert(p_manager != 00);
+
+       l_current_data = (OPJ_BYTE*)opj_malloc(1000);
+       if (! l_current_data) {
+               return OPJ_FALSE;
+       }
+       l_max_tile_size = 1000;
+
+       l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
+       for (i=0;i<l_nb_tiles;++i) {
+               if (! j2k_pre_write_tile(p_j2k,i,p_stream,p_manager)) {
+                       opj_free(l_current_data);
+                       return OPJ_FALSE;
+               }
+
+               l_current_tile_size = tcd_get_encoded_tile_size(p_j2k->m_tcd);
+               if (l_current_tile_size > l_max_tile_size) {
+                       l_current_data = (OPJ_BYTE*)opj_realloc(l_current_data,l_current_tile_size);
+                       if (! l_current_data) {
+                               return OPJ_FALSE;
+                       }
+                       l_max_tile_size = l_current_tile_size;
+               }
+
+               j2k_get_tile_data(p_j2k->m_tcd,l_current_data);
+
+               if (! j2k_post_write_tile (p_j2k,l_current_data,l_current_tile_size,p_stream,p_manager)) {
+                       return OPJ_FALSE;
+               }
+       }
+
+       opj_free(l_current_data);
+       return OPJ_TRUE;
+}
+
+/**
+ * Ends the compression procedures and possibility add data to be read after the
+ * codestream.
+ */
+opj_bool j2k_end_compress(     opj_j2k_v2_t *p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       struct opj_event_mgr * p_manager)
+{
+       /* customization of the encoding */
+       j2k_setup_end_compress(p_j2k);
+
+       if (! j2k_exec (p_j2k, p_j2k->m_procedure_list, p_stream, p_manager))
+       {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+
+/**
+ * Starts a compression scheme, i.e. validates the codec parameters, writes the header.
+ *
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      p_stream        the stream object.
+ * @param      p_manager       the user event manager.
+ *
+ * @return true if the codec is valid.
+ */
+opj_bool j2k_start_compress(opj_j2k_v2_t *p_j2k,
+                                                       opj_stream_private_t *p_stream,
+                                                       opj_image_t * p_image,
+                                                       opj_event_mgr_t * p_manager)
+{
+       // preconditions
+       assert(p_j2k != 00);
+       assert(p_stream != 00);
+       assert(p_manager != 00);
+
+       p_j2k->m_private_image = p_image;
+
+       /* customization of the validation */
+       j2k_setup_encoding_validation (p_j2k);
+
+       /* validation of the parameters codec */
+       if (! j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       /* customization of the encoding */
+       j2k_setup_header_writting(p_j2k);
+
+       /* write header */
+       if (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+/*
+ *
+ */
+opj_bool j2k_pre_write_tile (  opj_j2k_v2_t * p_j2k,
+                                                               OPJ_UINT32 p_tile_index,
+                                                               opj_stream_private_t *p_stream,
+                                                               opj_event_mgr_t * p_manager )
+{
+       if (p_tile_index != p_j2k->m_current_tile_number) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "The given tile index does not match." );
+               return OPJ_FALSE;
+       }
+
+       opj_event_msg_v2(p_manager, EVT_INFO, "tile number %d / %d\n", p_j2k->m_current_tile_number + 1, p_j2k->m_cp.tw * p_j2k->m_cp.th);
+
+       p_j2k->m_specific_param.m_encoder.m_current_tile_part_number = 0;
+       p_j2k->m_tcd->cur_totnum_tp = p_j2k->m_cp.tcps[p_tile_index].m_nb_tile_parts;
+       p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0;
+
+       /* initialisation before tile encoding  */
+       if (! tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+/*
+ *
+ */
+void j2k_get_tile_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data)
+{
+       OPJ_UINT32 i,j,k = 0;
+       OPJ_UINT32 l_width,l_height,l_stride, l_offset_x,l_offset_y, l_image_width;
+       opj_image_comp_t * l_img_comp = 00;
+       opj_tcd_tilecomp_v2_t * l_tilec = 00;
+       opj_image_t * l_image = 00;
+       OPJ_UINT32 l_size_comp, l_remaining;
+       OPJ_INT32 * l_src_ptr;
+       l_tilec = p_tcd->tcd_image->tiles->comps;
+       l_image = p_tcd->image;
+       l_img_comp = l_image->comps;
+
+       for (i=0;i<p_tcd->image->numcomps;++i) {
+               l_size_comp = l_img_comp->prec >> 3; /* (/8) */
+               l_remaining = l_img_comp->prec & 7;  /* (%8) */
+               if (l_remaining) {
+                       ++l_size_comp;
+               }
+
+               if (l_size_comp == 3) {
+                       l_size_comp = 4;
+               }
+
+               l_width = (l_tilec->x1 - l_tilec->x0);
+               l_height = (l_tilec->y1 - l_tilec->y0);
+               l_offset_x = int_ceildiv(l_image->x0, l_img_comp->dx);
+               l_offset_y = int_ceildiv(l_image->y0, l_img_comp->dy);
+               l_image_width = int_ceildiv(l_image->x1 - l_image->x0, l_img_comp->dx);
+               l_stride = l_image_width - l_width;
+               l_src_ptr = l_img_comp->data + (l_tilec->x0 - l_offset_x) + (l_tilec->y0 - l_offset_y) * l_image_width;
+
+               switch (l_size_comp) {
+                       case 1:
+                               {
+                                       OPJ_CHAR * l_dest_ptr = (OPJ_CHAR*) p_data;
+                                       if (l_img_comp->sgnd) {
+                                               for     (j=0;j<l_height;++j) {
+                                                       for (k=0;k<l_width;++k) {
+                                                               *(l_dest_ptr) = (OPJ_CHAR) (*l_src_ptr);
+                                                               ++l_dest_ptr;
+                                                               ++l_src_ptr;
+                                                       }
+                                                       l_src_ptr += l_stride;
+                                               }
+                                       }
+                                       else {
+                                               for (j=0;j<l_height;++j) {
+                                                       for (k=0;k<l_width;++k) {
+                                                               *(l_dest_ptr) = (*l_src_ptr)&0xff;
+                                                               ++l_dest_ptr;
+                                                               ++l_src_ptr;
+                                                       }
+                                                       l_src_ptr += l_stride;
+                                               }
+                                       }
+
+                                       p_data = (OPJ_BYTE*) l_dest_ptr;
+                               }
+                               break;
+                       case 2:
+                               {
+                                       OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_data;
+                                       if (l_img_comp->sgnd) {
+                                               for (j=0;j<l_height;++j) {
+                                                       for (k=0;k<l_width;++k) {
+                                                               *(l_dest_ptr++) = (OPJ_INT16) (*(l_src_ptr++));
+                                                       }
+                                                       l_src_ptr += l_stride;
+                                               }
+                                       }
+                                       else {
+                                               for (j=0;j<l_height;++j) {
+                                                       for (k=0;k<l_width;++k) {
+                                                               *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff;
+                                                       }
+                                                       l_src_ptr += l_stride;
+                                               }
+                                       }
+
+                                       p_data = (OPJ_BYTE*) l_dest_ptr;
+                               }
+                               break;
+                       case 4:
+                               {
+                                       OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_data;
+                                       for (j=0;j<l_height;++j) {
+                                               for (k=0;k<l_width;++k) {
+                                                       *(l_dest_ptr++) = *(l_src_ptr++);
+                                               }
+                                               l_src_ptr += l_stride;
+                                       }
+
+                                       p_data = (OPJ_BYTE*) l_dest_ptr;
+                               }
+                               break;
+               }
+
+               ++l_img_comp;
+               ++l_tilec;
+       }
+}
+
+
+/**
+ * Write a tile.
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      p_stream        the stream to write data to.
+ * @param      p_manager       the user event manager.
+ */
+opj_bool j2k_post_write_tile ( opj_j2k_v2_t * p_j2k,
+                                                               OPJ_BYTE * p_data,
+                                                               OPJ_UINT32 p_data_size,
+                                                               opj_stream_private_t *p_stream,
+                                                               opj_event_mgr_t * p_manager )
+{
+       opj_tcd_v2_t * l_tcd = 00;
+       opj_cp_v2_t * l_cp = 00;
+       opj_tcp_v2_t * l_tcp = 00;
+       OPJ_UINT32 l_nb_bytes_written;
+       OPJ_BYTE * l_current_data = 00;
+       OPJ_UINT32 l_tile_size = 0;
+       OPJ_UINT32 l_available_data;
+
+       /* preconditions */
+       assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data);
+
+       l_tcd = p_j2k->m_tcd;
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = l_cp->tcps + p_j2k->m_current_tile_number;
+
+       l_tile_size = p_j2k->m_specific_param.m_encoder.m_encoded_tile_size;
+       l_available_data = l_tile_size;
+       l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data;
+
+       if (! tcd_copy_tile_data(l_tcd,p_data,p_data_size)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Size mismtach between tile data and sent data." );
+               return OPJ_FALSE;
+       }
+
+       l_nb_bytes_written = 0;
+       if (! j2k_write_first_tile_part(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+       l_current_data += l_nb_bytes_written;
+       l_available_data -= l_nb_bytes_written;
+
+       l_nb_bytes_written = 0;
+       if (! j2k_write_all_tile_parts(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       l_available_data -= l_nb_bytes_written;
+       l_nb_bytes_written = l_tile_size - l_available_data;
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_encoded_tile_data,l_nb_bytes_written,p_manager) != l_nb_bytes_written) {
+               return OPJ_FALSE;
+       }
+
+       ++p_j2k->m_current_tile_number;
+
+       return OPJ_TRUE;
+}
+
+
+/**
+ * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
+ * are valid. Developers wanting to extend the library can add their own validation procedures.
+ */
+void j2k_setup_end_compress (opj_j2k_v2_t *p_j2k)
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+
+       /* DEVELOPER CORNER, insert your custom procedures */
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_eoc );
+
+       if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) {
+               opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_updated_tlm);
+       }
+
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_epc );
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_end_encoding );
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_destroy_header_memory);
+}
+
+/**
+ * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
+ * are valid. Developers wanting to extend the library can add their own validation procedures.
+ */
+void j2k_setup_encoding_validation (opj_j2k_v2_t *p_j2k)
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+
+       opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_build_encoder);
+       opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_encoding_validation);
+
+       /* DEVELOPER CORNER, add your custom validation procedure */
+       opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_mct_validation);
+}
+
+
+/**
+ * Sets up the procedures to do on writing header.
+ * Developers wanting to extend the library can add their own writing procedures.
+ */
+void j2k_setup_header_writting (opj_j2k_v2_t *p_j2k)
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_init_info );
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_soc_v2 );
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_siz_v2 );
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_cod_v2 );
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_qcd_v2 );
+
+
+       if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) {
+               opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_image_components );
+               opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_tlm );
+
+               if (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == CINEMA4K_24) {
+                       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_poc );
+               }
+       }
+
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_regions);
+
+       if (p_j2k->m_cp.comment != 00)  {
+               opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_com);
+       }
+
+       /* DEVELOPER CORNER, insert your custom procedures */
+       if (p_j2k->m_cp.rsiz & MCT) {
+               opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_mct_data_group );
+       }
+       /* End of Developer Corner */
+
+       if (p_j2k->cstr_index) {
+               opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_get_end_header );
+       }
+
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_create_tcd);
+       opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_update_rates);
+}
+
+
+opj_bool j2k_write_first_tile_part (opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       OPJ_UINT32 p_total_data_size,
+                                                                       opj_stream_private_t *p_stream,
+                                                                       struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 compno;
+       OPJ_UINT32 l_nb_bytes_written = 0;
+       OPJ_UINT32 l_current_nb_bytes_written;
+       OPJ_BYTE * l_begin_data = 00;
+
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tcd_v2_t * l_tcd = 00;
+       opj_cp_v2_t * l_cp = 00;
+
+       l_tcd = p_j2k->m_tcd;
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = l_cp->tcps + p_j2k->m_current_tile_number;
+
+       l_tcd->cur_pino = 0;
+
+       /*Get number of tile parts*/
+       p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0;
+
+       /* INDEX >> */
+       /* << INDEX */
+
+       l_current_nb_bytes_written = 0;
+       l_begin_data = p_data;
+       if (! j2k_write_sot_v2(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager))
+       {
+               return OPJ_FALSE;
+       }
+
+       l_nb_bytes_written += l_current_nb_bytes_written;
+       p_data += l_current_nb_bytes_written;
+       p_total_data_size -= l_current_nb_bytes_written;
+
+       if (l_cp->m_specific_param.m_enc.m_cinema == 0) {
+               for (compno = 1; compno < p_j2k->m_private_image->numcomps; compno++) {
+                       l_current_nb_bytes_written = 0;
+                       j2k_write_coc_in_memory(p_j2k,compno,p_data,&l_current_nb_bytes_written,p_manager);
+                       l_nb_bytes_written += l_current_nb_bytes_written;
+                       p_data += l_current_nb_bytes_written;
+                       p_total_data_size -= l_current_nb_bytes_written;
+
+                       l_current_nb_bytes_written = 0;
+                       j2k_write_qcc_in_memory(p_j2k,compno,p_data,&l_current_nb_bytes_written,p_manager);
+                       l_nb_bytes_written += l_current_nb_bytes_written;
+                       p_data += l_current_nb_bytes_written;
+                       p_total_data_size -= l_current_nb_bytes_written;
+               }
+
+               if (l_cp->tcps[p_j2k->m_current_tile_number].numpocs) {
+                       l_current_nb_bytes_written = 0;
+                       j2k_write_poc_in_memory(p_j2k,p_data,&l_current_nb_bytes_written,p_manager);
+                       l_nb_bytes_written += l_current_nb_bytes_written;
+                       p_data += l_current_nb_bytes_written;
+                       p_total_data_size -= l_current_nb_bytes_written;
+               }
+       }
+
+       l_current_nb_bytes_written = 0;
+       if (! j2k_write_sod_v2(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       l_nb_bytes_written += l_current_nb_bytes_written;
+       * p_data_written = l_nb_bytes_written;
+
+       /* Writing Psot in SOT marker */
+       opj_write_bytes(l_begin_data + 6,l_nb_bytes_written,4);                                 /* PSOT */
+
+       if (l_cp->m_specific_param.m_enc.m_cinema){
+               j2k_update_tlm(p_j2k,l_nb_bytes_written);
+       }
+
+       return OPJ_TRUE;
+}
+
+opj_bool j2k_write_all_tile_parts(     opj_j2k_v2_t *p_j2k,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 * p_data_written,
+                                                                       OPJ_UINT32 p_total_data_size,
+                                                                       opj_stream_private_t *p_stream,
+                                                                       struct opj_event_mgr * p_manager
+                                                               )
+{
+       OPJ_UINT32 tilepartno=0;
+       OPJ_UINT32 l_nb_bytes_written = 0;
+       OPJ_UINT32 l_current_nb_bytes_written;
+       OPJ_UINT32 l_part_tile_size;
+       OPJ_UINT32 tot_num_tp;
+       OPJ_UINT32 pino;
+
+       OPJ_BYTE * l_begin_data;
+       opj_tcp_v2_t *l_tcp = 00;
+       opj_tcd_v2_t * l_tcd = 00;
+       opj_cp_v2_t * l_cp = 00;
+
+
+       l_tcd = p_j2k->m_tcd;
+       l_cp = &(p_j2k->m_cp);
+       l_tcp = l_cp->tcps + p_j2k->m_current_tile_number;
+
+       /*Get number of tile parts*/
+       tot_num_tp = j2k_get_num_tp_v2(l_cp,0,p_j2k->m_current_tile_number);
+
+       for (tilepartno = 1; tilepartno < tot_num_tp ; ++tilepartno) {
+               p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno;
+               l_current_nb_bytes_written = 0;
+               l_part_tile_size = 0;
+               l_begin_data = p_data;
+
+               if (! j2k_write_sot_v2(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) {
+                       return OPJ_FALSE;
+               }
+
+               l_nb_bytes_written += l_current_nb_bytes_written;
+               p_data += l_current_nb_bytes_written;
+               p_total_data_size -= l_current_nb_bytes_written;
+               l_part_tile_size += l_nb_bytes_written;
+
+               l_current_nb_bytes_written = 0;
+               if (! j2k_write_sod_v2(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) {
+                       return OPJ_FALSE;
+               }
+
+               p_data += l_current_nb_bytes_written;
+               l_nb_bytes_written += l_current_nb_bytes_written;
+               p_total_data_size -= l_current_nb_bytes_written;
+               l_part_tile_size += l_nb_bytes_written;
+
+               /* Writing Psot in SOT marker */
+               opj_write_bytes(l_begin_data + 6,l_part_tile_size,4);                                   /* PSOT */
+
+               if (l_cp->m_specific_param.m_enc.m_cinema) {
+                       j2k_update_tlm(p_j2k,l_part_tile_size);
+               }
+
+               ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number;
+       }
+
+       for (pino = 1; pino <= l_tcp->numpocs; ++pino) {
+               l_tcd->cur_pino = pino;
+
+               /*Get number of tile parts*/
+               tot_num_tp = j2k_get_num_tp_v2(l_cp,pino,p_j2k->m_current_tile_number);
+               for (tilepartno = 0; tilepartno < tot_num_tp ; ++tilepartno) {
+                       p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno;
+                       l_current_nb_bytes_written = 0;
+                       l_part_tile_size = 0;
+                       l_begin_data = p_data;
+
+                       if (! j2k_write_sot_v2(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) {
+                               return OPJ_FALSE;
+                       }
+
+                       l_nb_bytes_written += l_current_nb_bytes_written;
+                       p_data += l_current_nb_bytes_written;
+                       p_total_data_size -= l_current_nb_bytes_written;
+                       l_part_tile_size += l_current_nb_bytes_written;
+
+                       l_current_nb_bytes_written = 0;
+
+                       if (! j2k_write_sod_v2(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) {
+                               return OPJ_FALSE;
+                       }
+
+                       l_nb_bytes_written += l_current_nb_bytes_written;
+                       p_data += l_current_nb_bytes_written;
+                       p_total_data_size -= l_current_nb_bytes_written;
+                       l_part_tile_size += l_current_nb_bytes_written;
+
+                       /* Writing Psot in SOT marker */
+                       opj_write_bytes(l_begin_data + 6,l_part_tile_size,4);                                   /* PSOT */
+
+                       if (l_cp->m_specific_param.m_enc.m_cinema) {
+                               j2k_update_tlm(p_j2k,l_part_tile_size);
+                       }
+
+                       ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number;
+               }
+       }
+
+       *p_data_written = l_nb_bytes_written;
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Writes the updated tlm.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_write_updated_tlm( opj_j2k_v2_t *p_j2k,
+                                                               struct opj_stream_private *p_stream,
+                                                               struct opj_event_mgr * p_manager )
+{
+       OPJ_UINT32 l_tlm_size;
+       OPJ_SIZE_T l_tlm_position, l_current_position;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       l_tlm_size = 5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts;
+       l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start;
+       l_current_position = opj_stream_tell(p_stream);
+
+       if (! opj_stream_seek(p_stream,l_tlm_position,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       if (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer,l_tlm_size,p_manager) != l_tlm_size) {
+               return OPJ_FALSE;
+       }
+
+       if (! opj_stream_seek(p_stream,l_current_position,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+
+/**
+ * Ends the encoding, i.e. frees memory.
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_end_encoding(     opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       tcd_destroy_v2(p_j2k->m_tcd);
+       p_j2k->m_tcd = 00;
+
+       if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) {
+               opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer);
+               p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 0;
+               p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 0;
+       }
+
+       if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) {
+               opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data);
+               p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 0;
+       }
+
+       p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = 0;
+
+       return OPJ_TRUE;
+}
+
+/**
+ * Destroys the memory associated with the decoding of headers.
+ */
+opj_bool j2k_destroy_header_memory (opj_j2k_v2_t * p_j2k,
+                                                                       opj_stream_private_t *p_stream,
+                                                                       opj_event_mgr_t * p_manager )
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_stream != 00);
+       assert(p_manager != 00);
+
+       if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) {
+               opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data);
+               p_j2k->m_specific_param.m_encoder.m_header_tile_data = 0;
+       }
+
+       p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0;
+
+       return OPJ_TRUE;
+}
+
+
+/**
+ * Inits the Info
+ *
+ * @param      p_stream                                the stream to write data to.
+ * @param      p_j2k                           J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_init_info(        opj_j2k_v2_t *p_j2k,
+                                               struct opj_stream_private *p_stream,
+                                               struct opj_event_mgr * p_manager )
+{
+       opj_codestream_info_t * l_cstr_info = 00;
+
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       /* TODO mergeV2: check this part which use cstr_info */
+       /*l_cstr_info = p_j2k->cstr_info;
+
+       if (l_cstr_info)  {
+               OPJ_UINT32 compno;
+               l_cstr_info->tile = (opj_tile_info_t *) opj_malloc(p_j2k->m_cp.tw * p_j2k->m_cp.th * sizeof(opj_tile_info_t));
+
+               l_cstr_info->image_w = p_j2k->m_image->x1 - p_j2k->m_image->x0;
+               l_cstr_info->image_h = p_j2k->m_image->y1 - p_j2k->m_image->y0;
+
+               l_cstr_info->prog = (&p_j2k->m_cp.tcps[0])->prg;
+
+               l_cstr_info->tw = p_j2k->m_cp.tw;
+               l_cstr_info->th = p_j2k->m_cp.th;
+
+               l_cstr_info->tile_x = p_j2k->m_cp.tdx;*/        /* new version parser */
+               /*l_cstr_info->tile_y = p_j2k->m_cp.tdy;*/      /* new version parser */
+               /*l_cstr_info->tile_Ox = p_j2k->m_cp.tx0;*/     /* new version parser */
+               /*l_cstr_info->tile_Oy = p_j2k->m_cp.ty0;*/     /* new version parser */
+
+               /*l_cstr_info->numcomps = p_j2k->m_image->numcomps;
+
+               l_cstr_info->numlayers = (&p_j2k->m_cp.tcps[0])->numlayers;
+
+               l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(p_j2k->m_image->numcomps * sizeof(OPJ_INT32));
+
+               for (compno=0; compno < p_j2k->m_image->numcomps; compno++) {
+                       l_cstr_info->numdecompos[compno] = (&p_j2k->m_cp.tcps[0])->tccps->numresolutions - 1;
+               }
+
+               l_cstr_info->D_max = 0.0;       */      /* ADD Marcela */
+
+               /*l_cstr_info->main_head_start = opj_stream_tell(p_stream);*/ /* position of SOC */
+
+               /*l_cstr_info->maxmarknum = 100;
+               l_cstr_info->marker = (opj_marker_info_t *) opj_malloc(l_cstr_info->maxmarknum * sizeof(opj_marker_info_t));
+               l_cstr_info->marknum = 0;
+       }*/
+
+       return j2k_calculate_tp_v2(p_j2k,&(p_j2k->m_cp),&p_j2k->m_specific_param.m_encoder.m_total_tile_parts,p_j2k->m_private_image,p_manager);
+}
+
+/**
+ * Creates a tile-coder decoder.
+ *
+ * @param      p_stream                the stream to write data to.
+ * @param      p_j2k                   J2K codec.
+ * @param      p_manager               the user event manager.
+*/
+opj_bool j2k_create_tcd(opj_j2k_v2_t *p_j2k,
+                                               struct opj_stream_private *p_stream,
+                                               struct opj_event_mgr * p_manager )
+{
+       /* preconditions */
+       assert(p_j2k != 00);
+       assert(p_manager != 00);
+       assert(p_stream != 00);
+
+       p_j2k->m_tcd = tcd_create_v2(OPJ_FALSE);
+
+       if (! p_j2k->m_tcd) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n");
+               return OPJ_FALSE;
+       }
+
+       if (! tcd_init_v2(p_j2k->m_tcd,p_j2k->m_private_image,&p_j2k->m_cp)) {
+               tcd_destroy_v2(p_j2k->m_tcd);
+               p_j2k->m_tcd = 00;
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
+
+/**
+ * Writes a tile.
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_manager       the user event manager.
+ */
+opj_bool j2k_write_tile (opj_j2k_v2_t * p_j2k,
+                                                OPJ_UINT32 p_tile_index,
+                                                OPJ_BYTE * p_data,
+                                                OPJ_UINT32 p_data_size,
+                                                opj_stream_private_t *p_stream,
+                                                opj_event_mgr_t * p_manager )
+{
+       if (! j2k_pre_write_tile(p_j2k,p_tile_index,p_stream,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       return j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager);
+}
index ae2f36f6ca321d6ce93f1ab59684bd68f3c17170..b31be140630d509cb9f3bf40ca83be45af0a1985 100644 (file)
@@ -107,6 +107,7 @@ The functions in J2K.C have for goal to read/write the several parts of the code
  * These values may be combined with a | operator.
  * */
 typedef enum J2K_STATUS {
+       J2K_STATE_NONE  =  0x0000, /**< a SOC marker is expected */
        J2K_STATE_MHSOC  = 0x0001, /**< a SOC marker is expected */
        J2K_STATE_MHSIZ  = 0x0002, /**< a SIZ marker is expected */
        J2K_STATE_MH     = 0x0004, /**< the decoding process is in the main header */
@@ -1024,4 +1025,47 @@ opj_bool j2k_get_tile(   opj_j2k_v2_t *p_j2k,
 opj_bool j2k_set_decoded_resolution_factor(opj_j2k_v2_t *p_j2k, OPJ_UINT32 res_factor, opj_event_mgr_t * p_manager);
 
 
+/**
+ * Writes a tile.
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_manager       the user event manager.
+ */
+opj_bool j2k_write_tile (      opj_j2k_v2_t * p_j2k,
+                                                       OPJ_UINT32 p_tile_index,
+                                                       OPJ_BYTE * p_data,
+                                                       OPJ_UINT32 p_data_size,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Encodes an image into a JPEG-2000 codestream
+ */
+opj_bool j2k_encode_v2(        opj_j2k_v2_t * p_j2k,
+                                               opj_stream_private_t *cio,
+                                               struct opj_event_mgr * p_manager );
+
+/**
+ * Starts a compression scheme, i.e. validates the codec parameters, writes the header.
+ *
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      cio                     the stream object.
+ * @param      p_manager       the user event manager.
+ *
+ * @return true if the codec is valid.
+ */
+opj_bool j2k_start_compress(opj_j2k_v2_t *p_j2k,
+                                                       struct opj_stream_private *cio,
+                                                       struct opj_image * p_image,
+                                                       struct opj_event_mgr * p_manager );
+
+/**
+ * Ends the compression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool j2k_end_compress(     opj_j2k_v2_t *p_j2k,
+                                                       opj_stream_private_t *cio,
+                                                       struct opj_event_mgr * p_manager);
+
+
 #endif /* __J2K_H */
index 841bc455b46aa1e37c22cca904174130b2a56c98..b0a2dcb39a3f0dd6079b843f4a81ef4222dd81df 100644 (file)
@@ -132,6 +132,19 @@ static opj_bool jp2_read_ftyp_v2(
                                                        struct opj_event_mgr * p_manager
                                                );
 
+/**
+ * Skips the Jpeg2000 Codestream Header box - JP2C Header box.
+ *
+ * @param      cio                     the stream to write data to.
+ * @param      jp2                     the jpeg2000 file codec.
+ * @param      p_manager       user event manager.
+ *
+ * @return true if writting was successful.
+*/
+opj_bool jp2_skip_jp2c(        opj_jp2_v2_t *jp2,
+                                               struct opj_stream_private *cio,
+                                               struct opj_event_mgr * p_manager );
+
 /**
  * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box).
  *
@@ -286,6 +299,13 @@ static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int le
 
 /*@}*/
 
+/**
+ * Sets up the procedures to do on writting header after the codestream.
+ * Developpers wanting to extend the library can add their own writting procedures.
+ */
+static void jp2_setup_end_header_writting (opj_jp2_v2_t *jp2);
+
+
 /**
  * Sets up the procedures to do on reading header after the codestream.
  * Developpers wanting to extend the library can add their own writting procedures.
@@ -350,6 +370,31 @@ static opj_bool jp2_read_boxhdr_v2(
  */
 static const opj_jp2_header_handler_t * jp2_find_handler (int p_id );
 
+/**
+ * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
+ * are valid. Developpers wanting to extend the library can add their own validation procedures.
+ */
+static void jp2_setup_encoding_validation (opj_jp2_v2_t *jp2);
+
+
+/**
+ * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures.
+ */
+static void jp2_setup_header_writting (opj_jp2_v2_t *jp2);
+
+/**
+ * The default validation procedure without any extension.
+ *
+ * @param      jp2                             the jpeg2000 codec to validate.
+ * @param      cio                             the input stream to validate.
+ * @param      p_manager               the user event manager.
+ *
+ * @return true if the parameters are correct.
+ */
+opj_bool jp2_default_validation (      opj_jp2_v2_t * jp2,
+                                                                       struct opj_stream_private *cio,
+                                                                       struct opj_event_mgr * p_manager );
+
 /**
  * Finds the image execution function related to the given box id.
  *
@@ -1980,9 +2025,47 @@ opj_bool jp2_end_decompress(opj_jp2_v2_t *jp2, opj_stream_private_t *cio, opj_ev
        return j2k_end_decompress(jp2->j2k, cio, p_manager);
 }
 
+/**
+ * Ends the compression procedures and possibility add data to be read after the
+ * codestream.
+ */
+opj_bool jp2_end_compress(     opj_jp2_v2_t *jp2,
+                                                       opj_stream_private_t *cio,
+                                                       opj_event_mgr_t * p_manager)
+{
+       /* preconditions */
+       assert(jp2 != 00);
+       assert(cio != 00);
+       assert(p_manager != 00);
+
+       /* customization of the end encoding */
+       jp2_setup_end_header_writting(jp2);
+
+       if (! j2k_end_compress(jp2->j2k,cio,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       /* write header */
+       return jp2_exec(jp2,jp2->m_procedure_list,cio,p_manager);
+}
+
+
+/**
+ * Sets up the procedures to do on writing header after the codestream.
+ * Developers wanting to extend the library can add their own writing procedures.
+ */
+void jp2_setup_end_header_writting (opj_jp2_v2_t *jp2)
+{
+       /* preconditions */
+       assert(jp2 != 00);
+
+       opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_jp2c );
+       /* DEVELOPER CORNER, add your custom procedures */
+}
+
 /**
  * Sets up the procedures to do on reading header after the codestream.
- * Developpers wanting to extend the library can add their own writting procedures.
+ * Developers wanting to extend the library can add their own writing procedures.
  */
 void jp2_setup_end_header_reading (opj_jp2_v2_t *jp2)
 {
@@ -1992,6 +2075,68 @@ void jp2_setup_end_header_reading (opj_jp2_v2_t *jp2)
        /* DEVELOPER CORNER, add your custom procedures */
 }
 
+/**
+ * The default validation procedure without any extension.
+ *
+ * @param      jp2                             the jpeg2000 codec to validate.
+ * @param      cio                             the input stream to validate.
+ * @param      p_manager               the user event manager.
+ *
+ * @return true if the parameters are correct.
+ */
+opj_bool jp2_default_validation (      opj_jp2_v2_t * jp2,
+                                                                       opj_stream_private_t *cio,
+                                                                       opj_event_mgr_t * p_manager )
+{
+       opj_bool l_is_valid = OPJ_TRUE;
+       unsigned int i;
+
+       /* preconditions */
+       assert(jp2 != 00);
+       assert(cio != 00);
+       assert(p_manager != 00);
+
+       /* JPEG2000 codec validation */
+       /*TODO*/
+
+       /* STATE checking */
+       /* make sure the state is at 0 */
+       l_is_valid &= (jp2->jp2_state == JP2_STATE_NONE);
+
+       /* make sure not reading a jp2h ???? WEIRD */
+       l_is_valid &= (jp2->jp2_img_state == JP2_IMG_STATE_NONE);
+
+       /* POINTER validation */
+       /* make sure a j2k codec is present */
+       l_is_valid &= (jp2->j2k != 00);
+
+       /* make sure a procedure list is present */
+       l_is_valid &= (jp2->m_procedure_list != 00);
+
+       /* make sure a validation list is present */
+       l_is_valid &= (jp2->m_validation_list != 00);
+
+       /* PARAMETER VALIDATION */
+       /* number of components */
+       l_is_valid &= (jp2->numcl > 0);
+       /* width */
+       l_is_valid &= (jp2->h > 0);
+       /* height */
+       l_is_valid &= (jp2->w > 0);
+       /* precision */
+       for (i = 0; i < jp2->numcomps; ++i)     {
+               l_is_valid &= (jp2->comps[i].bpcc > 0);
+       }
+
+       /* METH */
+       l_is_valid &= ((jp2->meth > 0) && (jp2->meth < 3));
+
+       /* stream validation */
+       /* back and forth is needed */
+       l_is_valid &= opj_stream_has_seek(cio);
+
+       return l_is_valid;
+}
 
 /**
  * Reads a jpeg2000 file header structure.
@@ -2126,6 +2271,42 @@ opj_bool jp2_exec (
        return l_result;
 }
 
+/**
+ * Starts a compression scheme, i.e. validates the codec parameters, writes the header.
+ *
+ * @param      jp2             the jpeg2000 file codec.
+ * @param      cio             the stream object.
+ *
+ * @return true if the codec is valid.
+ */
+opj_bool jp2_start_compress(opj_jp2_v2_t *jp2,
+                                                       struct opj_stream_private *cio,
+                                                       opj_image_t * p_image,
+                                                       struct opj_event_mgr * p_manager)
+{
+       /* preconditions */
+       assert(jp2 != 00);
+       assert(cio != 00);
+       assert(p_manager != 00);
+
+       /* customization of the validation */
+       jp2_setup_encoding_validation (jp2);
+
+       /* validation of the parameters codec */
+       if (! jp2_exec(jp2,jp2->m_validation_list,cio,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       /* customization of the encoding */
+       jp2_setup_header_writting(jp2);
+
+       /* write header */
+       if (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) {
+               return OPJ_FALSE;
+       }
+
+       return j2k_start_compress(jp2->j2k,cio,p_image,p_manager);
+}
 
 /**
  * Finds the execution function related to the given box id.
@@ -2288,6 +2469,32 @@ opj_bool jp2_read_ftyp_v2(
        return OPJ_TRUE;
 }
 
+/**
+ * Skips the Jpeg2000 Codestream Header box - JP2C Header box.
+ *
+ * @param      cio                     the stream to write data to.
+ * @param      jp2                     the jpeg2000 file codec.
+ * @param      p_manager       user event manager.
+ *
+ * @return true if writting was successful.
+*/
+opj_bool jp2_skip_jp2c(        opj_jp2_v2_t *jp2,
+                                               struct opj_stream_private *cio,
+                                               struct opj_event_mgr * p_manager )
+{
+       /* preconditions */
+       assert(jp2 != 00);
+       assert(cio != 00);
+       assert(p_manager != 00);
+
+       jp2->j2k_codestream_offset = opj_stream_tell(cio);
+
+       if (opj_stream_skip(cio,8,p_manager) != 8) {
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
 
 /**
  * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box).
@@ -2479,6 +2686,19 @@ opj_bool jp2_read_header(        struct opj_stream_private *p_stream,
                                                        p_manager);
 }
 
+/**
+ * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters
+ * are valid. Developers wanting to extend the library can add their own validation procedures.
+ */
+void jp2_setup_encoding_validation (opj_jp2_v2_t *jp2)
+{
+       /* preconditions */
+       assert(jp2 != 00);
+
+       opj_procedure_list_add_procedure(jp2->m_validation_list, (void*)jp2_default_validation);
+       /* DEVELOPER CORNER, add your custom validation procedure */
+}
+
 /**
  * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
  * are valid. Developpers wanting to extend the library can add their own validation procedures.
@@ -2490,6 +2710,24 @@ void jp2_setup_decoding_validation (opj_jp2_v2_t *jp2)
        /* DEVELOPER CORNER, add your custom validation procedure */
 }
 
+/**
+ * Sets up the procedures to do on writting header.
+ * Developers wanting to extend the library can add their own writing procedures.
+ */
+void jp2_setup_header_writting (opj_jp2_v2_t *jp2)
+{
+       /* preconditions */
+       assert(jp2 != 00);
+
+       opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_jp );
+       opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_ftyp );
+       opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_jp2h );
+       opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_skip_jp2c );
+
+       /* DEVELOPER CORNER, insert your custom procedures */
+
+}
+
 /**
  * Sets up the procedures to do on reading header.
  * Developpers wanting to extend the library can add their own writting procedures.
@@ -2531,6 +2769,22 @@ opj_bool jp2_read_tile_header(   opj_jp2_v2_t * p_jp2,
                                                                p_manager);
 }
 
+/**
+ * Writes a tile.
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_manager       the user event manager.
+ */
+opj_bool jp2_write_tile (      opj_jp2_v2_t *p_jp2,
+                                                       OPJ_UINT32 p_tile_index,
+                                                       OPJ_BYTE * p_data,
+                                                       OPJ_UINT32 p_data_size,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager )
+{
+       return j2k_write_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager);
+}
+
 /**
  * Decode tile data.
  * @param      p_j2k           the jpeg2000 codec.
index d00b8d67c0118df4c1f9f8c5881165b4d89920d5..299215e08f9c2a3676a7e6f9db0f2bc14bb97925 100644 (file)
@@ -330,6 +330,28 @@ Encode an image into a JPEG-2000 file stream
 opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
 
 
+/**
+ * Starts a compression scheme, i.e. validates the codec parameters, writes the header.
+ *
+ * @param      jp2             the jpeg2000 file codec.
+ * @param      cio             the stream object.
+ *
+ * @return true if the codec is valid.
+ */
+opj_bool jp2_start_compress(opj_jp2_v2_t *jp2,
+                                                       struct opj_stream_private *cio,
+                                                       struct opj_image * p_image,
+                                                       struct opj_event_mgr * p_manager);
+
+
+/**
+ * Ends the compression procedures and possibiliy add data to be read after the
+ * codestream.
+ */
+opj_bool jp2_end_compress(     opj_jp2_v2_t *jp2,
+                                                       struct opj_stream_private *cio,
+                                                       struct opj_event_mgr * p_manager);
+
 /* ----------------------------------------------------------------------- */
 
 /**
@@ -373,6 +395,21 @@ opj_bool jp2_read_tile_header (
                                         struct opj_event_mgr * p_manager
                                        );
 
+
+
+/**
+ * Writes a tile.
+ * @param      p_j2k           the jpeg2000 codec.
+ * @param      p_stream                        the stream to write data to.
+ * @param      p_manager       the user event manager.
+ */
+opj_bool jp2_write_tile (      opj_jp2_v2_t *p_jp2,
+                                                       OPJ_UINT32 p_tile_index,
+                                                       OPJ_BYTE * p_data,
+                                                       OPJ_UINT32 p_data_size,
+                                                       struct opj_stream_private *p_stream,
+                                                       struct opj_event_mgr * p_manager );
+
 /**
  * Decode tile data.
  * @param      p_j2k           the jpeg2000 codec.
index c29218a43aa0e6e5f1be296ac179ea441d45ac2b..2cf581be2cdfc2b4a3fe61225035d0246c1279d1 100644 (file)
@@ -45,6 +45,16 @@ static const double mct_norms[3] = { 1.732, .8292, .8292 };
 /* </summary> */
 static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 };
 
+const OPJ_FLOAT64 * get_mct_norms ()
+{
+       return mct_norms;
+}
+
+const OPJ_FLOAT64 * get_mct_norms_real ()
+{
+       return mct_norms_real;
+}
+
 /* <summary> */
 /* Foward reversible MCT. */
 /* </summary> */
@@ -190,6 +200,62 @@ double mct_getnorm_real(int compno) {
 }
 
 
+opj_bool mct_encode_custom(
+                                          // MCT data
+                                          OPJ_BYTE * pCodingdata,
+                                          // size of components
+                                          OPJ_UINT32 n,
+                                          // components
+                                          OPJ_BYTE ** pData,
+                                          // nb of components (i.e. size of pData)
+                                          OPJ_UINT32 pNbComp,
+                                          // tells if the data is signed
+                                          OPJ_UINT32 isSigned)
+{
+       OPJ_FLOAT32 * lMct = (OPJ_FLOAT32 *) pCodingdata;
+       OPJ_UINT32 i;
+       OPJ_UINT32 j;
+       OPJ_UINT32 k;
+       OPJ_UINT32 lNbMatCoeff = pNbComp * pNbComp;
+       OPJ_INT32 * lCurrentData = 00;
+       OPJ_INT32 * lCurrentMatrix = 00;
+       OPJ_INT32 ** lData = (OPJ_INT32 **) pData;
+       OPJ_UINT32 lMultiplicator = 1 << 13;
+       OPJ_INT32 * lMctPtr;
+
+       lCurrentData = (OPJ_INT32 *) opj_malloc((pNbComp + lNbMatCoeff) * sizeof(OPJ_INT32));
+       if (! lCurrentData) {
+               return OPJ_FALSE;
+       }
+
+       lCurrentMatrix = lCurrentData + pNbComp;
+
+       for (i =0;i<lNbMatCoeff;++i) {
+               lCurrentMatrix[i] = (OPJ_INT32) (*(lMct++) * lMultiplicator);
+       }
+
+       for (i = 0; i < n; ++i)  {
+               lMctPtr = lCurrentMatrix;
+               for (j=0;j<pNbComp;++j) {
+                       lCurrentData[j] = (*(lData[j]));
+               }
+
+               for (j=0;j<pNbComp;++j) {
+                       *(lData[j]) = 0;
+                       for (k=0;k<pNbComp;++k) {
+                               *(lData[j]) += fix_mul(*lMctPtr, lCurrentData[k]);
+                               ++lMctPtr;
+                       }
+
+                       ++lData[j];
+               }
+       }
+
+       opj_free(lCurrentData);
+
+       return OPJ_TRUE;
+}
+
 opj_bool mct_decode_custom(
                                           /* MCT data */
                                           OPJ_BYTE * pDecodingData,
index 45de5e5b6ace81d22e57ae0ed1338615263c58d9..c701280a35681efff6399fd4d2e8d9cf4198e888 100644 (file)
@@ -91,6 +91,19 @@ Get norm of the basis function used for the irreversible multi-component transfo
 */
 double mct_getnorm_real(int compno);
 
+
+opj_bool mct_encode_custom(
+                                          // MCT data
+                                          OPJ_BYTE * p_coding_data,
+                                          // size of components
+                                          OPJ_UINT32 n,
+                                          // components
+                                          OPJ_BYTE ** p_data,
+                                          // nb of components (i.e. size of p_data)
+                                          OPJ_UINT32 p_nb_comp,
+                                          // tells if the data is signed
+                                          OPJ_UINT32 is_signed);
+
 opj_bool mct_decode_custom(
                                           /* MCT data */
                                           OPJ_BYTE * pDecodingData,
@@ -102,6 +115,9 @@ opj_bool mct_decode_custom(
                                           OPJ_UINT32 pNbComp,
                                           /* tells if the data is signed */
                                           OPJ_UINT32 isSigned);
+
+const OPJ_FLOAT64 * get_mct_norms ();
+const OPJ_FLOAT64 * get_mct_norms_real ();
 /* ----------------------------------------------------------------------- */
 /*@}*/
 
index 1adc126d51c6fedee39cb4e10b8530a6f77a4aa1..90ea2c6b7678719cbe917396b35c5ae983f945bc 100644 (file)
@@ -96,12 +96,32 @@ typedef struct opj_decompression
  */
 typedef struct opj_compression
 {
-       opj_bool (* opj_start_compress) (void *p_codec,struct opj_stream_private *cio,struct opj_image * p_image,       struct opj_event_mgr * p_manager);
-       opj_bool (* opj_encode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager);
-       opj_bool (* opj_write_tile) (void * p_codec,OPJ_UINT32 p_tile_index,OPJ_BYTE * p_data,OPJ_UINT32 p_data_size,struct opj_stream_private * p_cio,struct opj_event_mgr * p_manager);
-       opj_bool (* opj_end_compress) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager);
+       opj_bool (* opj_start_compress) (       void *p_codec,
+                                                                               struct opj_stream_private *cio,
+                                                                               struct opj_image * p_image,
+                                                                               struct opj_event_mgr * p_manager);
+
+       opj_bool (* opj_encode) (       void * p_codec,
+                                                               struct opj_stream_private *p_cio,
+                                                               struct opj_event_mgr * p_manager);
+
+       opj_bool (* opj_write_tile) (   void * p_codec,
+                                                                       OPJ_UINT32 p_tile_index,
+                                                                       OPJ_BYTE * p_data,
+                                                                       OPJ_UINT32 p_data_size,
+                                                                       struct opj_stream_private * p_cio,
+                                                                       struct opj_event_mgr * p_manager);
+
+       opj_bool (* opj_end_compress) ( void * p_codec,
+                                                                       struct opj_stream_private *p_cio,
+                                                                       struct opj_event_mgr * p_manager);
+
        void (* opj_destroy) (void * p_codec);
-       void (*opj_setup_encoder) (void * p_codec,opj_cparameters_t * p_param,struct opj_image * p_image, struct opj_event_mgr * p_manager);
+
+       void (*opj_setup_encoder) (     void * p_codec,
+                                                               opj_cparameters_t * p_param,
+                                                               struct opj_image * p_image,
+                                                               struct opj_event_mgr * p_manager);
 
 }opj_compression_t;
 
@@ -529,6 +549,105 @@ opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) {
        return cinfo;
 }
 
+
+opj_codec_t* OPJ_CALLCONV opj_create_compress_v2(OPJ_CODEC_FORMAT p_format)
+{
+       opj_codec_private_t *l_info = 00;
+
+       l_info = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t));
+       if (!l_info) {
+               return 00;
+       }
+
+       memset(l_info, 0, sizeof(opj_codec_private_t));
+       l_info->is_decompressor = 0;
+
+       switch(p_format) {
+               case CODEC_J2K:
+                       l_info->m_codec_data.m_compression.opj_encode = (opj_bool (*) ( void *,
+                                                                                                                                                       struct opj_stream_private *,
+                                                                                                                                                       struct opj_event_mgr * )) j2k_encode_v2;
+
+                       l_info->m_codec_data.m_compression.opj_end_compress = (opj_bool (*) (   void *,
+                                                                                                                                                                       struct opj_stream_private *,
+                                                                                                                                                                       struct opj_event_mgr *)) j2k_end_compress;
+
+                       l_info->m_codec_data.m_compression.opj_start_compress = (opj_bool (*) ( void *,
+                                                                                                                                                                       struct opj_stream_private *,
+                                                                                                                                                                       struct opj_image * ,
+                                                                                                                                                                       struct opj_event_mgr *)) j2k_start_compress;
+
+                       l_info->m_codec_data.m_compression.opj_write_tile = (opj_bool (*) (     void *,
+                                                                                                                                                               OPJ_UINT32,
+                                                                                                                                                               OPJ_BYTE*,
+                                                                                                                                                               OPJ_UINT32,
+                                                                                                                                                               struct opj_stream_private *,
+                                                                                                                                                               struct opj_event_mgr *) ) j2k_write_tile;
+
+                       l_info->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) j2k_destroy;
+
+                       l_info->m_codec_data.m_compression.opj_setup_encoder = (void (*) (      void *,
+                                                                                                                                                               opj_cparameters_t *,
+                                                                                                                                                               struct opj_image *,
+                                                                                                                                                               struct opj_event_mgr * )) j2k_setup_encoder;
+
+                       l_info->m_codec = j2k_create_compress_v2();
+                       if (! l_info->m_codec) {
+                               opj_free(l_info);
+                               return 00;
+                       }
+
+                       break;
+
+               case CODEC_JP2:
+                       /* get a JP2 decoder handle */
+                       l_info->m_codec_data.m_compression.opj_encode = (opj_bool (*) ( void *,
+                                                                                                                                                       struct opj_stream_private *,
+                                                                                                                                                       struct opj_event_mgr * )) opj_jp2_encode;
+
+                       l_info->m_codec_data.m_compression.opj_end_compress = (opj_bool (*) (   void *,
+                                                                                                                                                                       struct opj_stream_private *,
+                                                                                                                                                                       struct opj_event_mgr *)) jp2_end_compress;
+
+                       l_info->m_codec_data.m_compression.opj_start_compress = (opj_bool (*) ( void *,
+                                                                                                                                                                       struct opj_stream_private *,
+                                                                                                                                                                       struct opj_image * ,
+                                                                                                                                                                       struct opj_event_mgr *))  jp2_start_compress;
+
+                       l_info->m_codec_data.m_compression.opj_write_tile = (opj_bool (*) (     void *,
+                                                                                                                                                               OPJ_UINT32,
+                                                                                                                                                               OPJ_BYTE*,
+                                                                                                                                                               OPJ_UINT32,
+                                                                                                                                                               struct opj_stream_private *,
+                                                                                                                                                               struct opj_event_mgr *)) jp2_write_tile;
+
+                       l_info->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) jp2_destroy;
+
+                       l_info->m_codec_data.m_compression.opj_setup_encoder = (void (*) (      void *,
+                                                                                                                                                               opj_cparameters_t *,
+                                                                                                                                                               struct opj_image *,
+                                                                                                                                                               struct opj_event_mgr * )) jp2_setup_encoder;
+
+                       l_info->m_codec = jp2_create(OPJ_FALSE);
+                       if (! l_info->m_codec) {
+                               opj_free(l_info);
+                               return 00;
+                       }
+
+                       break;
+
+               case CODEC_UNKNOWN:
+               case CODEC_JPT:
+               default:
+                       opj_free(l_info);
+                       return 00;
+       }
+
+       /*set_default_event_handler(&(l_info->m_event_mgr));*/
+       return (opj_codec_t*) l_info;
+}
+
+
 void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo) {
        if(cinfo) {
                /* destroy the codec */
@@ -658,6 +777,66 @@ void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *param
        }
 }
 
+opj_bool OPJ_CALLCONV opj_setup_encoder_v2(opj_codec_t *p_info, opj_cparameters_t *parameters, opj_image_t *image)
+{
+       if (p_info && parameters && image) {
+               opj_codec_private_t * l_codec = ((opj_codec_private_t *) p_info);
+
+               if (! l_codec->is_decompressor) {
+                       l_codec->m_codec_data.m_compression.opj_setup_encoder(l_codec->m_codec,parameters,image,l_codec->m_event_mgr);
+                       return OPJ_TRUE;
+               }
+       }
+
+       return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_start_compress (     opj_codec_t *p_codec,
+                                                                                       opj_image_t * p_image,
+                                                                                       opj_stream_t *p_cio)
+{
+       if (p_codec && p_cio) {
+               opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+               opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio;
+
+               if (! l_codec->is_decompressor) {
+                       return l_codec->m_codec_data.m_compression.opj_start_compress(l_codec->m_codec,l_cio,p_image,l_codec->m_event_mgr);
+               }
+       }
+
+       return OPJ_FALSE;
+}
+
+opj_bool OPJ_CALLCONV opj_encode_v2(opj_codec_t *p_info, opj_stream_t *cio)
+{
+       if (p_info && cio) {
+               opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info;
+               opj_stream_private_t * l_cio = (opj_stream_private_t *) cio;
+
+               if (! l_codec->is_decompressor) {
+                       l_codec->m_codec_data.m_compression.opj_encode(l_codec->m_codec,l_cio,l_codec->m_event_mgr);
+                       return OPJ_TRUE;
+               }
+       }
+
+       return OPJ_FALSE;
+
+}
+
+opj_bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,opj_stream_t *p_cio)
+{
+       if (p_codec && p_cio) {
+               opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
+               opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio;
+
+               if (! l_codec->is_decompressor) {
+                       return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec,l_cio,l_codec->m_event_mgr);
+               }
+       }
+       return OPJ_FALSE;
+
+}
+
 opj_bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) {
        if (index != NULL)
                opj_event_msg((opj_common_ptr)cinfo, EVT_WARNING, "Set index to NULL when calling the opj_encode function.\n"
@@ -1034,3 +1213,31 @@ opj_bool OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, OP
 
        return OPJ_TRUE;
 }
+
+
+opj_bool OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters,OPJ_FLOAT32 * pEncodingMatrix,OPJ_INT32 * p_dc_shift,OPJ_UINT32 pNbComp)
+{
+       OPJ_UINT32 l_matrix_size = pNbComp * pNbComp * sizeof(OPJ_FLOAT32);
+       OPJ_UINT32 l_dc_shift_size = pNbComp * sizeof(OPJ_INT32);
+       OPJ_UINT32 l_mct_total_size = l_matrix_size + l_dc_shift_size;
+
+       /* add MCT capability */
+       int rsiz = (int)parameters->cp_rsiz | (int)MCT;
+       parameters->cp_rsiz = (OPJ_RSIZ_CAPABILITIES)rsiz;
+       parameters->irreversible = 1;
+
+       /* use array based MCT */
+       parameters->tcp_mct = 2;
+       parameters->mct_data = opj_malloc(l_mct_total_size);
+       if (! parameters->mct_data) {
+               return OPJ_FALSE;
+       }
+
+       memcpy(parameters->mct_data,pEncodingMatrix,l_matrix_size);
+       memcpy(((OPJ_BYTE *) parameters->mct_data) +  l_matrix_size,p_dc_shift,l_dc_shift_size);
+
+       return OPJ_TRUE;
+}
+
+
+
index b5772263bbfc76055cff01240f4da584e2b74602..909dbf47392500275e6a82e77a19607c1e214344 100644 (file)
@@ -173,7 +173,8 @@ typedef OPJ_INT64 OPJ_OFF_T;
 typedef enum RSIZ_CAPABILITIES {
        STD_RSIZ = 0,           /** Standard JPEG2000 profile*/
        CINEMA2K = 3,           /** Profile name for a 2K image*/
-       CINEMA4K = 4            /** Profile name for a 4K image*/
+       CINEMA4K = 4,           /** Profile name for a 4K image*/
+       MCT = 0x8100
 } OPJ_RSIZ_CAPABILITIES;
 
 /** 
@@ -425,6 +426,9 @@ typedef struct opj_cparameters {
        char tcp_mct;
        /** Enable JPIP indexing*/
        opj_bool jpip_on;
+       /** Naive implementation of MCT restricted to a single reversible array based encoding without offset concerning all the components. */
+       void * mct_data;
+
 } opj_cparameters_t;
 
 #define OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG     0x0001
@@ -1399,6 +1403,15 @@ Creates a J2K/JP2 compression structure
 @return Returns a handle to a compressor if successful, returns NULL otherwise
 */
 OPJ_API opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format);
+
+/**
+Creates a J2K/JP2 compression structure
+@param format Coder to select
+@return Returns a handle to a compressor if successful, returns NULL otherwise
+*/
+OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_compress_v2(OPJ_CODEC_FORMAT format);
+
+
 /**
 Destroy a compressor handle
 @param cinfo compressor handle to destroy
@@ -1433,6 +1446,32 @@ Setup the encoder parameters using the current image and using user parameters.
 @param image Input filled image
 */
 OPJ_API void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image);
+
+/**
+Setup the encoder parameters using the current image and using user parameters.
+@param cinfo Compressor handle
+@param parameters Compression parameters
+@param image Input filled image
+*/
+OPJ_API opj_bool OPJ_CALLCONV opj_setup_encoder_v2(opj_codec_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image);
+
+
+opj_bool OPJ_CALLCONV opj_start_compress (     opj_codec_t *p_codec,
+                                                                                       opj_image_t * p_image,
+                                                                                       opj_stream_t *p_cio);
+
+opj_bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,opj_stream_t *p_cio);
+
+/**
+Encode an image into a JPEG-2000 codestream
+@param cinfo compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param index Depreacted -> Set to NULL. To extract index, used opj_encode_wci()
+@return Returns true if successful, returns false otherwise
+*/
+OPJ_API opj_bool OPJ_CALLCONV opj_encode_v2(opj_codec_t *cinfo, opj_stream_t * cio);
+
 /**
 Encode an image into a JPEG-2000 codestream
 3@param cinfo compressor handle
@@ -1537,6 +1576,26 @@ OPJ_API opj_jp2_metadata_t* OPJ_CALLCONV opj_get_jp2_metadata(opj_codec_t *p_cod
 OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec);
 
 
+/*
+==========================================================
+   new functions
+==========================================================
+*/
+
+/**
+ * Sets the MCT matrix to use.
+ *
+ * @param      parameters              the parameters to change.
+ * @param      pEncodingMatrix the encoding matrix.
+ * @param      p_dc_shift              the dc shift coefficients to use.
+ * @param      pNbComp                 the number of components of the image.
+ *
+ * @return     true if the parameters could be set.
+ */
+OPJ_API opj_bool OPJ_CALLCONV opj_set_MCT( opj_cparameters_t *parameters,
+                                                  OPJ_FLOAT32 * pEncodingMatrix,
+                                                  OPJ_INT32 * p_dc_shift,
+                                                  OPJ_UINT32 pNbComp);
 
 
 
index 2d3354f293b24d973b01d2a38956a7b98e61bfa2..06250321217a7c901d642c18aabd9f2dee564144 100644 (file)
@@ -69,7 +69,83 @@ Get next packet in component-precinct-resolution-layer order.
 */
 static opj_bool pi_next_cprl(opj_pi_iterator_t * pi);
 
+/**
+ * Updates the coding parameters if the encoding is used with Progression order changes and final (or cinema parameters are used).
+ *
+ * @param      p_cp            the coding parameters to modify
+ * @param      p_tileno        the tile index being concerned.
+ * @param      p_tx0           X0 parameter for the tile
+ * @param      p_tx1           X1 parameter for the tile
+ * @param      p_ty0           Y0 parameter for the tile
+ * @param      p_ty1           Y1 parameter for the tile
+ * @param      p_max_prec      the maximum precision for all the bands of the tile
+ * @param      p_max_res       the maximum number of resolutions for all the poc inside the tile.
+ * @param      dx_min          the minimum dx of all the components of all the resolutions for the tile.
+ * @param      dy_min          the minimum dy of all the components of all the resolutions for the tile.
+ */
+void pi_update_encode_poc_and_final (opj_cp_v2_t *p_cp,
+                                                                        OPJ_UINT32 p_tileno,
+                                                                        OPJ_INT32 p_tx0,
+                                                                        OPJ_INT32 p_tx1,
+                                                                        OPJ_INT32 p_ty0,
+                                                                        OPJ_INT32 p_ty1,
+                                                                        OPJ_UINT32 p_max_prec,
+                                                                        OPJ_UINT32 p_max_res,
+                                     OPJ_UINT32 p_dx_min,
+                                                                        OPJ_UINT32 p_dy_min);
+
+/**
+ * Updates the coding parameters if the encoding is not used with Progression order changes and final (and cinema parameters are used).
+ *
+ * @param      p_cp            the coding parameters to modify
+ * @param      p_tileno        the tile index being concerned.
+ * @param      p_tx0           X0 parameter for the tile
+ * @param      p_tx1           X1 parameter for the tile
+ * @param      p_ty0           Y0 parameter for the tile
+ * @param      p_ty1           Y1 parameter for the tile
+ * @param      p_max_prec      the maximum precision for all the bands of the tile
+ * @param      p_max_res       the maximum number of resolutions for all the poc inside the tile.
+ * @param      dx_min          the minimum dx of all the components of all the resolutions for the tile.
+ * @param      dy_min          the minimum dy of all the components of all the resolutions for the tile.
+ */
+void pi_update_encode_not_poc ( opj_cp_v2_t *p_cp,
+                                                               OPJ_UINT32 p_num_comps,
+                                                               OPJ_UINT32 p_tileno,
+                                                               OPJ_INT32 p_tx0,
+                                                               OPJ_INT32 p_tx1,
+                                                               OPJ_INT32 p_ty0,
+                                                               OPJ_INT32 p_ty1,
+                                                               OPJ_UINT32 p_max_prec,
+                                                               OPJ_UINT32 p_max_res,
+                                OPJ_UINT32 p_dx_min,
+                                                               OPJ_UINT32 p_dy_min);
 
+/**
+ * Gets the encoding parameters needed to update the coding parameters and all the pocs.
+ *
+ * @param      p_image                 the image being encoded.
+ * @param      p_cp                    the coding parameters.
+ * @param      tileno                  the tile index of the tile being encoded.
+ * @param      p_tx0                   pointer that will hold the X0 parameter for the tile
+ * @param      p_tx1                   pointer that will hold the X1 parameter for the tile
+ * @param      p_ty0                   pointer that will hold the Y0 parameter for the tile
+ * @param      p_ty1                   pointer that will hold the Y1 parameter for the tile
+ * @param      p_max_prec              pointer that will hold the the maximum precision for all the bands of the tile
+ * @param      p_max_res               pointer that will hold the the maximum number of resolutions for all the poc inside the tile.
+ * @param      dx_min                  pointer that will hold the the minimum dx of all the components of all the resolutions for the tile.
+ * @param      dy_min                  pointer that will hold the the minimum dy of all the components of all the resolutions for the tile.
+ */
+void get_encoding_parameters(  const opj_image_t *p_image,
+                                                               const opj_cp_v2_t *p_cp,
+                                                               OPJ_UINT32  tileno,
+                                                               OPJ_INT32  * p_tx0,
+                                                               OPJ_INT32 * p_tx1,
+                                                               OPJ_INT32 * p_ty0,
+                                                               OPJ_INT32 * p_ty1,
+                                                               OPJ_UINT32 * p_dx_min,
+                                                               OPJ_UINT32 * p_dy_min,
+                                                               OPJ_UINT32 * p_max_prec,
+                                                               OPJ_UINT32 * p_max_res );
 
 /**
  * Gets the encoding parameters needed to update the coding parameters and all the pocs.
@@ -123,6 +199,12 @@ void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ
 void pi_update_decode_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ_UINT32 p_max_precision,OPJ_UINT32 p_max_res);
 
 
+OPJ_INT32 pi_check_next_level( OPJ_INT32 pos,
+                                                               opj_cp_v2_t *cp,
+                                                               OPJ_UINT32 tileno,
+                                                               OPJ_UINT32 pino,
+                                                               const OPJ_CHAR *prog);
+
 /*@}*/
 
 /*@}*/
@@ -938,6 +1020,202 @@ opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int ti
                        return pi;
        }
 
+/**
+ * Creates a packet iterator for encoding.
+ *
+ * @param      p_image         the image being encoded.
+ * @param      p_cp            the coding parameters.
+ * @param      p_tile_no       index of the tile being encoded.
+ * @param      p_t2_mode       the type of pass for generating the packet iterator
+ * @return     a list of packet iterator that points to the first packet of the tile (not true).
+*/
+opj_pi_iterator_t *pi_initialise_encode_v2(
+                                                                               const opj_image_t *p_image,
+                                                                               opj_cp_v2_t *p_cp,
+                                                                               OPJ_UINT32 p_tile_no,
+                                                                               J2K_T2_MODE p_t2_mode
+                                                                               )
+{
+       // loop
+       OPJ_UINT32 pino;
+       OPJ_UINT32 compno, resno;
+
+       // to store w, h, dx and dy fro all components and resolutions
+       OPJ_UINT32 * l_tmp_data;
+       OPJ_UINT32 ** l_tmp_ptr;
+
+       // encoding prameters to set
+       OPJ_UINT32 l_max_res;
+       OPJ_UINT32 l_max_prec;
+       OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1;
+       OPJ_UINT32 l_dx_min,l_dy_min;
+       OPJ_UINT32 l_bound;
+       OPJ_UINT32 l_step_p , l_step_c , l_step_r , l_step_l ;
+       OPJ_UINT32 l_data_stride;
+
+       // pointers
+       opj_pi_iterator_t *l_pi = 00;
+       opj_tcp_v2_t *l_tcp = 00;
+       const opj_tccp_t *l_tccp = 00;
+       opj_pi_comp_t *l_current_comp = 00;
+       opj_image_comp_t * l_img_comp = 00;
+       opj_pi_iterator_t * l_current_pi = 00;
+       OPJ_UINT32 * l_encoding_value_ptr = 00;
+
+       // preconditions in debug
+       assert(p_cp != 00);
+       assert(p_image != 00);
+       assert(p_tile_no < p_cp->tw * p_cp->th);
+
+       // initializations
+       l_tcp = &p_cp->tcps[p_tile_no];
+       l_bound = l_tcp->numpocs+1;
+
+       l_data_stride = 4 * J2K_MAXRLVLS;
+       l_tmp_data = (OPJ_UINT32*)opj_malloc(
+               l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32));
+       if (! l_tmp_data) {
+               return 00;
+       }
+
+       l_tmp_ptr = (OPJ_UINT32**)opj_malloc(
+               p_image->numcomps * sizeof(OPJ_UINT32 *));
+       if (! l_tmp_ptr) {
+               opj_free(l_tmp_data);
+               return 00;
+       }
+
+       // memory allocation for pi
+       l_pi = pi_create(p_image,p_cp,p_tile_no);
+       if (!l_pi) {
+               opj_free(l_tmp_data);
+               opj_free(l_tmp_ptr);
+               return 00;
+       }
+
+       l_encoding_value_ptr = l_tmp_data;
+       // update pointer array
+       for (compno = 0; compno < p_image->numcomps; ++compno) {
+               l_tmp_ptr[compno] = l_encoding_value_ptr;
+               l_encoding_value_ptr += l_data_stride;
+       }
+
+       // get encoding parameters
+       get_all_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res,l_tmp_ptr);
+
+       // step calculations
+       l_step_p = 1;
+       l_step_c = l_max_prec * l_step_p;
+       l_step_r = p_image->numcomps * l_step_c;
+       l_step_l = l_max_res * l_step_r;
+
+       // set values for first packet iterator
+       l_pi->tp_on = p_cp->m_specific_param.m_enc.m_tp_on;
+       l_current_pi = l_pi;
+
+       // memory allocation for include
+       l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16));
+       if (!l_current_pi->include) {
+               opj_free(l_tmp_data);
+               opj_free(l_tmp_ptr);
+               pi_destroy_v2(l_pi, l_bound);
+               return 00;
+       }
+       memset(l_current_pi->include,0,l_tcp->numlayers * l_step_l* sizeof(OPJ_INT16));
+
+       // special treatment for the first packet iterator
+       l_current_comp = l_current_pi->comps;
+       l_img_comp = p_image->comps;
+       l_tccp = l_tcp->tccps;
+       l_current_pi->tx0 = l_tx0;
+       l_current_pi->ty0 = l_ty0;
+       l_current_pi->tx1 = l_tx1;
+       l_current_pi->ty1 = l_ty1;
+       l_current_pi->dx = l_dx_min;
+       l_current_pi->dy = l_dy_min;
+       l_current_pi->step_p = l_step_p;
+       l_current_pi->step_c = l_step_c;
+       l_current_pi->step_r = l_step_r;
+       l_current_pi->step_l = l_step_l;
+
+       /* allocation for components and number of components has already been calculated by pi_create */
+       for (compno = 0; compno < l_current_pi->numcomps; ++compno) {
+               opj_pi_resolution_t *l_res = l_current_comp->resolutions;
+               l_encoding_value_ptr = l_tmp_ptr[compno];
+
+               l_current_comp->dx = l_img_comp->dx;
+               l_current_comp->dy = l_img_comp->dy;
+
+               /* resolutions have already been initialized */
+               for (resno = 0; resno < l_current_comp->numresolutions; resno++) {
+                       l_res->pdx = *(l_encoding_value_ptr++);
+                       l_res->pdy = *(l_encoding_value_ptr++);
+                       l_res->pw =  *(l_encoding_value_ptr++);
+                       l_res->ph =  *(l_encoding_value_ptr++);
+                       ++l_res;
+               }
+
+               ++l_current_comp;
+               ++l_img_comp;
+               ++l_tccp;
+       }
+       ++l_current_pi;
+
+       for (pino = 1 ; pino<l_bound ; ++pino ) {
+               opj_pi_comp_t *l_current_comp = l_current_pi->comps;
+               opj_image_comp_t * l_img_comp = p_image->comps;
+               l_tccp = l_tcp->tccps;
+
+               l_current_pi->tx0 = l_tx0;
+               l_current_pi->ty0 = l_ty0;
+               l_current_pi->tx1 = l_tx1;
+               l_current_pi->ty1 = l_ty1;
+               l_current_pi->dx = l_dx_min;
+               l_current_pi->dy = l_dy_min;
+               l_current_pi->step_p = l_step_p;
+               l_current_pi->step_c = l_step_c;
+               l_current_pi->step_r = l_step_r;
+               l_current_pi->step_l = l_step_l;
+
+               /* allocation for components and number of components has already been calculated by pi_create */
+               for (compno = 0; compno < l_current_pi->numcomps; ++compno) {
+                       opj_pi_resolution_t *l_res = l_current_comp->resolutions;
+                       l_encoding_value_ptr = l_tmp_ptr[compno];
+
+                       l_current_comp->dx = l_img_comp->dx;
+                       l_current_comp->dy = l_img_comp->dy;
+                       /* resolutions have already been initialized */
+                       for (resno = 0; resno < l_current_comp->numresolutions; resno++) {
+                               l_res->pdx = *(l_encoding_value_ptr++);
+                               l_res->pdy = *(l_encoding_value_ptr++);
+                               l_res->pw =  *(l_encoding_value_ptr++);
+                               l_res->ph =  *(l_encoding_value_ptr++);
+                               ++l_res;
+                       }
+                       ++l_current_comp;
+                       ++l_img_comp;
+                       ++l_tccp;
+               }
+
+               // special treatment
+               l_current_pi->include = (l_current_pi-1)->include;
+               ++l_current_pi;
+       }
+
+       opj_free(l_tmp_data);
+       l_tmp_data = 00;
+       opj_free(l_tmp_ptr);
+       l_tmp_ptr = 00;
+
+       if (l_tcp->POC && ( p_cp->m_specific_param.m_enc.m_cinema || p_t2_mode == FINAL_PASS)) {
+               pi_update_encode_poc_and_final(p_cp,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min);
+       }
+       else {
+               pi_update_encode_not_poc(p_cp,p_image->numcomps,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min);
+       }
+
+       return l_pi;
+}
 
 
 void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) {
@@ -1216,7 +1494,172 @@ opj_bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int p
        return OPJ_FALSE;
 }
 
+/**
+ * Updates the encoding parameters of the codec.
+ *
+ * @param      p_image         the image being encoded.
+ * @param      p_cp            the coding parameters.
+ * @param      p_tile_no       index of the tile being encoded.
+*/
+void pi_update_encoding_parameters(    const opj_image_t *p_image,
+                                                                       opj_cp_v2_t *p_cp,
+                                                                       OPJ_UINT32 p_tile_no )
+{
+       /* encoding parameters to set */
+       OPJ_UINT32 l_max_res;
+       OPJ_UINT32 l_max_prec;
+       OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1;
+       OPJ_UINT32 l_dx_min,l_dy_min;
+
+       /* pointers */
+       opj_tcp_v2_t *l_tcp = 00;
+
+       /* preconditions */
+       assert(p_cp != 00);
+       assert(p_image != 00);
+       assert(p_tile_no < p_cp->tw * p_cp->th);
+
+       l_tcp = &(p_cp->tcps[p_tile_no]);
+
+       /* get encoding parameters */
+       get_encoding_parameters(p_image,p_cp,p_tile_no,&l_tx0,&l_tx1,&l_ty0,&l_ty1,&l_dx_min,&l_dy_min,&l_max_prec,&l_max_res);
 
+       if (l_tcp->POC) {
+               pi_update_encode_poc_and_final(p_cp,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min);
+       }
+       else {
+               pi_update_encode_not_poc(p_cp,p_image->numcomps,p_tile_no,l_tx0,l_tx1,l_ty0,l_ty1,l_max_prec,l_max_res,l_dx_min,l_dy_min);
+       }
+
+}
+
+/**
+ * Gets the encoding parameters needed to update the coding parameters and all the pocs.
+ *
+ * @param      p_image                 the image being encoded.
+ * @param      p_cp                    the coding parameters.
+ * @param      p_tileno                        the tile index of the tile being encoded.
+ * @param      p_tx0                   pointer that will hold the X0 parameter for the tile
+ * @param      p_tx1                   pointer that will hold the X1 parameter for the tile
+ * @param      p_ty0                   pointer that will hold the Y0 parameter for the tile
+ * @param      p_ty1                   pointer that will hold the Y1 parameter for the tile
+ * @param      p_max_prec              pointer that will hold the the maximum precision for all the bands of the tile
+ * @param      p_max_res               pointer that will hold the the maximum number of resolutions for all the poc inside the tile.
+ * @param      dx_min                  pointer that will hold the the minimum dx of all the components of all the resolutions for the tile.
+ * @param      dy_min                  pointer that will hold the the minimum dy of all the components of all the resolutions for the tile.
+ */
+void get_encoding_parameters(  const opj_image_t *p_image,
+                                                               const opj_cp_v2_t *p_cp,
+                                                               OPJ_UINT32 p_tileno,
+                                                               OPJ_INT32 * p_tx0,
+                                                               OPJ_INT32  * p_tx1,
+                                                               OPJ_INT32  * p_ty0,
+                                                               OPJ_INT32  * p_ty1,
+                                                               OPJ_UINT32 * p_dx_min,
+                                                               OPJ_UINT32 * p_dy_min,
+                                                               OPJ_UINT32 * p_max_prec,
+                                                               OPJ_UINT32 * p_max_res )
+{
+       /* loop */
+       OPJ_UINT32  compno, resno;
+       /* pointers */
+       const opj_tcp_v2_t *l_tcp = 00;
+       const opj_tccp_t * l_tccp = 00;
+       const opj_image_comp_t * l_img_comp = 00;
+
+       /* position in x and y of tile */
+       OPJ_UINT32 p, q;
+
+       /* preconditions */
+       assert(p_cp != 00);
+       assert(p_image != 00);
+       assert(p_tileno < p_cp->tw * p_cp->th);
+
+       /* initializations */
+       l_tcp = &p_cp->tcps [p_tileno];
+       l_img_comp = p_image->comps;
+       l_tccp = l_tcp->tccps;
+
+       /* here calculation of tx0, tx1, ty0, ty1, maxprec, dx and dy */
+       p = p_tileno % p_cp->tw;
+       q = p_tileno / p_cp->tw;
+
+       /* find extent of tile */
+       *p_tx0 = int_max(p_cp->tx0 + p * p_cp->tdx, p_image->x0);
+       *p_tx1 = int_min(p_cp->tx0 + (p + 1) * p_cp->tdx, p_image->x1);
+       *p_ty0 = int_max(p_cp->ty0 + q * p_cp->tdy, p_image->y0);
+       *p_ty1 = int_min(p_cp->ty0 + (q + 1) * p_cp->tdy, p_image->y1);
+
+       /* max precision is 0 (can only grow) */
+       *p_max_prec = 0;
+       *p_max_res = 0;
+
+       /* take the largest value for dx_min and dy_min */
+       *p_dx_min = 0x7fffffff;
+       *p_dy_min  = 0x7fffffff;
+
+       for (compno = 0; compno < p_image->numcomps; ++compno) {
+               /* arithmetic variables to calculate */
+               OPJ_UINT32 l_level_no;
+               OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1;
+               OPJ_INT32 l_px0, l_py0, l_px1, py1;
+               OPJ_UINT32 l_pdx, l_pdy;
+               OPJ_UINT32 l_pw, l_ph;
+               OPJ_UINT32 l_product;
+               OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1;
+
+               l_tcx0 = int_ceildiv(*p_tx0, l_img_comp->dx);
+               l_tcy0 = int_ceildiv(*p_ty0, l_img_comp->dy);
+               l_tcx1 = int_ceildiv(*p_tx1, l_img_comp->dx);
+               l_tcy1 = int_ceildiv(*p_ty1, l_img_comp->dy);
+
+               if (l_tccp->numresolutions > *p_max_res) {
+                       *p_max_res = l_tccp->numresolutions;
+               }
+
+               /* use custom size for precincts */
+               for (resno = 0; resno < l_tccp->numresolutions; ++resno) {
+                       OPJ_UINT32 l_dx, l_dy;
+
+                       /* precinct width and height */
+                       l_pdx = l_tccp->prcw[resno];
+                       l_pdy = l_tccp->prch[resno];
+
+                       l_dx = l_img_comp->dx * (1 << (l_pdx + l_tccp->numresolutions - 1 - resno));
+                       l_dy = l_img_comp->dy * (1 << (l_pdy + l_tccp->numresolutions - 1 - resno));
+
+                       /* take the minimum size for dx for each comp and resolution */
+                       *p_dx_min = uint_min(*p_dx_min, l_dx);
+                       *p_dy_min = uint_min(*p_dy_min, l_dy);
+
+                       /* various calculations of extents */
+                       l_level_no = l_tccp->numresolutions - 1 - resno;
+
+                       l_rx0 = int_ceildivpow2(l_tcx0, l_level_no);
+                       l_ry0 = int_ceildivpow2(l_tcy0, l_level_no);
+                       l_rx1 = int_ceildivpow2(l_tcx1, l_level_no);
+                       l_ry1 = int_ceildivpow2(l_tcy1, l_level_no);
+
+                       l_px0 = int_floordivpow2(l_rx0, l_pdx) << l_pdx;
+                       l_py0 = int_floordivpow2(l_ry0, l_pdy) << l_pdy;
+                       l_px1 = int_ceildivpow2(l_rx1, l_pdx) << l_pdx;
+
+                       py1 = int_ceildivpow2(l_ry1, l_pdy) << l_pdy;
+
+                       l_pw = (l_rx0==l_rx1)?0:((l_px1 - l_px0) >> l_pdx);
+                       l_ph = (l_ry0==l_ry1)?0:((py1 - l_py0) >> l_pdy);
+
+                       l_product = l_pw * l_ph;
+
+                       /* update precision */
+                       if (l_product > *p_max_prec) {
+                               *p_max_prec = l_product;
+                       }
+               }
+               ++l_img_comp;
+               ++l_tccp;
+       }
+}
 
 /**
  * Gets the encoding parameters needed to update the coding parameters and all the pocs.
@@ -1435,7 +1878,164 @@ opj_pi_iterator_t * pi_create(  const opj_image_t *image,
        return l_pi;
 }
 
+/**
+ * Updates the coding parameters if the encoding is used with Progression order changes and final (or cinema parameters are used).
+ *
+ * @param      p_cp            the coding parameters to modify
+ * @param      p_tileno        the tile index being concerned.
+ * @param      p_tx0           X0 parameter for the tile
+ * @param      p_tx1           X1 parameter for the tile
+ * @param      p_ty0           Y0 parameter for the tile
+ * @param      p_ty1           Y1 parameter for the tile
+ * @param      p_max_prec      the maximum precision for all the bands of the tile
+ * @param      p_max_res       the maximum number of resolutions for all the poc inside the tile.
+ * @param      dx_min          the minimum dx of all the components of all the resolutions for the tile.
+ * @param      dy_min          the minimum dy of all the components of all the resolutions for the tile.
+ */
+void pi_update_encode_poc_and_final (opj_cp_v2_t *p_cp,
+                                                                        OPJ_UINT32 p_tileno,
+                                                                        OPJ_INT32 p_tx0,
+                                                                        OPJ_INT32 p_tx1,
+                                                                        OPJ_INT32 p_ty0,
+                                                                        OPJ_INT32 p_ty1,
+                                                                        OPJ_UINT32 p_max_prec,
+                                                                        OPJ_UINT32 p_max_res,
+                                     OPJ_UINT32 p_dx_min,
+                                                                        OPJ_UINT32 p_dy_min)
+{
+       // loop
+       OPJ_UINT32 pino;
+       // tile coding parameter
+       opj_tcp_v2_t *l_tcp = 00;
+       // current poc being updated
+       opj_poc_t * l_current_poc = 00;
+
+       // number of pocs
+       OPJ_UINT32 l_poc_bound;
+
+       // preconditions in debug
+       assert(p_cp != 00);
+       assert(p_tileno < p_cp->tw * p_cp->th);
+
+       // initializations
+       l_tcp = &p_cp->tcps [p_tileno];
+       /* number of iterations in the loop */
+       l_poc_bound = l_tcp->numpocs+1;
+
+       // start at first element, and to make sure the compiler will not make a calculation each time in the loop
+       // store a pointer to the current element to modify rather than l_tcp->pocs[i]
+       l_current_poc = l_tcp->pocs;
+
+       l_current_poc->compS = l_current_poc->compno0;
+       l_current_poc->compE = l_current_poc->compno1;
+       l_current_poc->resS = l_current_poc->resno0;
+       l_current_poc->resE = l_current_poc->resno1;
+       l_current_poc->layE = l_current_poc->layno1;
+
+       // special treatment for the first element
+       l_current_poc->layS = 0;
+       l_current_poc->prg  = l_current_poc->prg1;
+       l_current_poc->prcS = 0;
+
+       l_current_poc->prcE = p_max_prec;
+       l_current_poc->txS = p_tx0;
+       l_current_poc->txE = p_tx1;
+       l_current_poc->tyS = p_ty0;
+       l_current_poc->tyE = p_ty1;
+       l_current_poc->dx = p_dx_min;
+       l_current_poc->dy = p_dy_min;
+
+       ++ l_current_poc;
+       for (pino = 1;pino < l_poc_bound ; ++pino) {
+               l_current_poc->compS = l_current_poc->compno0;
+               l_current_poc->compE= l_current_poc->compno1;
+               l_current_poc->resS = l_current_poc->resno0;
+               l_current_poc->resE = l_current_poc->resno1;
+               l_current_poc->layE = l_current_poc->layno1;
+               l_current_poc->prg  = l_current_poc->prg1;
+               l_current_poc->prcS = 0;
+               // special treatment here different from the first element
+               l_current_poc->layS = (l_current_poc->layE > (l_current_poc-1)->layE) ? l_current_poc->layE : 0;
+
+               l_current_poc->prcE = p_max_prec;
+               l_current_poc->txS = p_tx0;
+               l_current_poc->txE = p_tx1;
+               l_current_poc->tyS = p_ty0;
+               l_current_poc->tyE = p_ty1;
+               l_current_poc->dx = p_dx_min;
+               l_current_poc->dy = p_dy_min;
+               ++ l_current_poc;
+       }
+}
+
+/**
+ * Updates the coding parameters if the encoding is not used with Progression order changes and final (and cinema parameters are used).
+ *
+ * @param      p_cp            the coding parameters to modify
+ * @param      p_tileno        the tile index being concerned.
+ * @param      p_tx0           X0 parameter for the tile
+ * @param      p_tx1           X1 parameter for the tile
+ * @param      p_ty0           Y0 parameter for the tile
+ * @param      p_ty1           Y1 parameter for the tile
+ * @param      p_max_prec      the maximum precision for all the bands of the tile
+ * @param      p_max_res       the maximum number of resolutions for all the poc inside the tile.
+ * @param      dx_min          the minimum dx of all the components of all the resolutions for the tile.
+ * @param      dy_min          the minimum dy of all the components of all the resolutions for the tile.
+ */
+void pi_update_encode_not_poc (        opj_cp_v2_t *p_cp,
+                                                               OPJ_UINT32 p_num_comps,
+                                                               OPJ_UINT32 p_tileno,
+                                                               OPJ_INT32 p_tx0,
+                                                               OPJ_INT32 p_tx1,
+                                                               OPJ_INT32 p_ty0,
+                                                               OPJ_INT32 p_ty1,
+                                                               OPJ_UINT32 p_max_prec,
+                                                               OPJ_UINT32 p_max_res,
+                                OPJ_UINT32 p_dx_min,
+                                                               OPJ_UINT32 p_dy_min)
+{
+       // loop
+       OPJ_UINT32 pino;
+       // tile coding parameter
+       opj_tcp_v2_t *l_tcp = 00;
+       // current poc being updated
+       opj_poc_t * l_current_poc = 00;
+       // number of pocs
+       OPJ_UINT32 l_poc_bound;
+
+       // preconditions in debug
+       assert(p_cp != 00);
+       assert(p_tileno < p_cp->tw * p_cp->th);
+
+       // initializations
+       l_tcp = &p_cp->tcps [p_tileno];
+
+       /* number of iterations in the loop */
+       l_poc_bound = l_tcp->numpocs+1;
 
+       // start at first element, and to make sure the compiler will not make a calculation each time in the loop
+       // store a pointer to the current element to modify rather than l_tcp->pocs[i]
+       l_current_poc = l_tcp->pocs;
+
+       for (pino = 0; pino < l_poc_bound ; ++pino) {
+               l_current_poc->compS = 0;
+               l_current_poc->compE = p_num_comps;/*p_image->numcomps;*/
+               l_current_poc->resS = 0;
+               l_current_poc->resE = p_max_res;
+               l_current_poc->layS = 0;
+               l_current_poc->layE = l_tcp->numlayers;
+               l_current_poc->prg  = l_tcp->prg;
+               l_current_poc->prcS = 0;
+               l_current_poc->prcE = p_max_prec;
+               l_current_poc->txS = p_tx0;
+               l_current_poc->txE = p_tx1;
+               l_current_poc->tyS = p_ty0;
+               l_current_poc->tyE = p_ty1;
+               l_current_poc->dx = p_dx_min;
+               l_current_poc->dy = p_dy_min;
+               ++ l_current_poc;
+       }
+}
 
 /**
  * Destroys a packet iterator array.
@@ -1561,3 +2161,354 @@ void pi_update_decode_not_poc (opj_pi_iterator_t * p_pi,opj_tcp_v2_t * p_tcp,OPJ
                ++l_current_pi;
        }
 }
+
+
+void pi_create_encode_v2(      opj_pi_iterator_t *pi,
+                                                       opj_cp_v2_t *cp,
+                                                       OPJ_UINT32 tileno,
+                                                       OPJ_UINT32 pino,
+                                                       OPJ_UINT32 tpnum,
+                                                       OPJ_INT32 tppos,
+                                                       J2K_T2_MODE t2_mode)
+{
+       const OPJ_CHAR *prog;
+       OPJ_INT32 i,l;
+       OPJ_UINT32 incr_top=1,resetX=0;
+       opj_tcp_v2_t *tcps =&cp->tcps[tileno];
+       opj_poc_t *tcp= &tcps->pocs[pino];
+
+       prog = j2k_convert_progression_order(tcp->prg);
+
+       pi[pino].first = 1;
+       pi[pino].poc.prg = tcp->prg;
+
+       if(!(cp->m_specific_param.m_enc.m_tp_on&& ((!cp->m_specific_param.m_enc.m_cinema && (t2_mode == FINAL_PASS)) || cp->m_specific_param.m_enc.m_cinema))){
+               pi[pino].poc.resno0 = tcp->resS;
+               pi[pino].poc.resno1 = tcp->resE;
+               pi[pino].poc.compno0 = tcp->compS;
+               pi[pino].poc.compno1 = tcp->compE;
+               pi[pino].poc.layno0 = tcp->layS;
+               pi[pino].poc.layno1 = tcp->layE;
+               pi[pino].poc.precno0 = tcp->prcS;
+               pi[pino].poc.precno1 = tcp->prcE;
+               pi[pino].poc.tx0 = tcp->txS;
+               pi[pino].poc.ty0 = tcp->tyS;
+               pi[pino].poc.tx1 = tcp->txE;
+               pi[pino].poc.ty1 = tcp->tyE;
+       }else {
+               for(i=tppos+1;i<4;i++){
+                       switch(prog[i]){
+                       case 'R':
+                               pi[pino].poc.resno0 = tcp->resS;
+                               pi[pino].poc.resno1 = tcp->resE;
+                               break;
+                       case 'C':
+                               pi[pino].poc.compno0 = tcp->compS;
+                               pi[pino].poc.compno1 = tcp->compE;
+                               break;
+                       case 'L':
+                               pi[pino].poc.layno0 = tcp->layS;
+                               pi[pino].poc.layno1 = tcp->layE;
+                               break;
+                       case 'P':
+                               switch(tcp->prg){
+                                       case LRCP:
+                                       case RLCP:
+                                               pi[pino].poc.precno0 = tcp->prcS;
+                                               pi[pino].poc.precno1 = tcp->prcE;
+                                               break;
+                                       default:
+                                               pi[pino].poc.tx0 = tcp->txS;
+                                               pi[pino].poc.ty0 = tcp->tyS;
+                                               pi[pino].poc.tx1 = tcp->txE;
+                                               pi[pino].poc.ty1 = tcp->tyE;
+                                               break;
+                               }
+                               break;
+                       }
+               }
+
+               if(tpnum==0){
+                       for(i=tppos;i>=0;i--){
+                               switch(prog[i]){
+                                               case 'C':
+                                                       tcp->comp_t = tcp->compS;
+                                                       pi[pino].poc.compno0 = tcp->comp_t;
+                                                       pi[pino].poc.compno1 = tcp->comp_t+1;
+                                                       tcp->comp_t+=1;
+                                                       break;
+                                               case 'R':
+                                                       tcp->res_t = tcp->resS;
+                                                       pi[pino].poc.resno0 = tcp->res_t;
+                                                       pi[pino].poc.resno1 = tcp->res_t+1;
+                                                       tcp->res_t+=1;
+                                                       break;
+                                               case 'L':
+                                                       tcp->lay_t = tcp->layS;
+                                                       pi[pino].poc.layno0 = tcp->lay_t;
+                                                       pi[pino].poc.layno1 = tcp->lay_t+1;
+                                                       tcp->lay_t+=1;
+                                                       break;
+                                               case 'P':
+                                                       switch(tcp->prg){
+                                                               case LRCP:
+                                                               case RLCP:
+                                                                       tcp->prc_t = tcp->prcS;
+                                                                       pi[pino].poc.precno0 = tcp->prc_t;
+                                                                       pi[pino].poc.precno1 = tcp->prc_t+1;
+                                                                       tcp->prc_t+=1;
+                                                                       break;
+                                                               default:
+                                                                       tcp->tx0_t = tcp->txS;
+                                                                       tcp->ty0_t = tcp->tyS;
+                                                                       pi[pino].poc.tx0 = tcp->tx0_t;
+                                                                       pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx);
+                                                                       pi[pino].poc.ty0 = tcp->ty0_t;
+                                                                       pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy);
+                                                                       tcp->tx0_t = pi[pino].poc.tx1;
+                                                                       tcp->ty0_t = pi[pino].poc.ty1;
+                                                                       break;
+                                                       }
+                                                       break;
+                               }
+                       }
+                       incr_top=1;
+               }else{
+                       for(i=tppos;i>=0;i--){
+                               switch(prog[i]){
+                                               case 'C':
+                                                       pi[pino].poc.compno0 = tcp->comp_t-1;
+                                                       pi[pino].poc.compno1 = tcp->comp_t;
+                                                       break;
+                                               case 'R':
+                                                       pi[pino].poc.resno0 = tcp->res_t-1;
+                                                       pi[pino].poc.resno1 = tcp->res_t;
+                                                       break;
+                                               case 'L':
+                                                       pi[pino].poc.layno0 = tcp->lay_t-1;
+                                                       pi[pino].poc.layno1 = tcp->lay_t;
+                                                       break;
+                                               case 'P':
+                                                       switch(tcp->prg){
+                                                               case LRCP:
+                                                               case RLCP:
+                                                                       pi[pino].poc.precno0 = tcp->prc_t-1;
+                                                                       pi[pino].poc.precno1 = tcp->prc_t;
+                                                                       break;
+                                                               default:
+                                                                       pi[pino].poc.tx0 = tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx);
+                                                                       pi[pino].poc.tx1 = tcp->tx0_t ;
+                                                                       pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy);
+                                                                       pi[pino].poc.ty1 = tcp->ty0_t ;
+                                                                       break;
+                                                       }
+                                                       break;
+                               }
+                               if(incr_top==1){
+                                       switch(prog[i]){
+                                                       case 'R':
+                                                               if(tcp->res_t==tcp->resE){
+                                                                       l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                                                       if(l==1){
+                                                                               tcp->res_t = tcp->resS;
+                                                                               pi[pino].poc.resno0 = tcp->res_t;
+                                                                               pi[pino].poc.resno1 = tcp->res_t+1;
+                                                                               tcp->res_t+=1;
+                                                                               incr_top=1;
+                                                                       }else{
+                                                                               incr_top=0;
+                                                                       }
+                                                               }else{
+                                                                       pi[pino].poc.resno0 = tcp->res_t;
+                                                                       pi[pino].poc.resno1 = tcp->res_t+1;
+                                                                       tcp->res_t+=1;
+                                                                       incr_top=0;
+                                                               }
+                                                               break;
+                                                       case 'C':
+                                                               if(tcp->comp_t ==tcp->compE){
+                                                                       l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                                                       if(l==1){
+                                                                               tcp->comp_t = tcp->compS;
+                                                                               pi[pino].poc.compno0 = tcp->comp_t;
+                                                                               pi[pino].poc.compno1 = tcp->comp_t+1;
+                                                                               tcp->comp_t+=1;
+                                                                               incr_top=1;
+                                                                       }else{
+                                                                               incr_top=0;
+                                                                       }
+                                                               }else{
+                                                                       pi[pino].poc.compno0 = tcp->comp_t;
+                                                                       pi[pino].poc.compno1 = tcp->comp_t+1;
+                                                                       tcp->comp_t+=1;
+                                                                       incr_top=0;
+                                                               }
+                                                               break;
+                                                       case 'L':
+                                                               if(tcp->lay_t == tcp->layE){
+                                                                       l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                                                       if(l==1){
+                                                                               tcp->lay_t = tcp->layS;
+                                                                               pi[pino].poc.layno0 = tcp->lay_t;
+                                                                               pi[pino].poc.layno1 = tcp->lay_t+1;
+                                                                               tcp->lay_t+=1;
+                                                                               incr_top=1;
+                                                                       }else{
+                                                                               incr_top=0;
+                                                                       }
+                                                               }else{
+                                                                       pi[pino].poc.layno0 = tcp->lay_t;
+                                                                       pi[pino].poc.layno1 = tcp->lay_t+1;
+                                                                       tcp->lay_t+=1;
+                                                                       incr_top=0;
+                                                               }
+                                                               break;
+                                                       case 'P':
+                                                               switch(tcp->prg){
+                                                                       case LRCP:
+                                                                       case RLCP:
+                                                                               if(tcp->prc_t == tcp->prcE){
+                                                                                       l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                                                                       if(l==1){
+                                                                                               tcp->prc_t = tcp->prcS;
+                                                                                               pi[pino].poc.precno0 = tcp->prc_t;
+                                                                                               pi[pino].poc.precno1 = tcp->prc_t+1;
+                                                                                               tcp->prc_t+=1;
+                                                                                               incr_top=1;
+                                                                                       }else{
+                                                                                               incr_top=0;
+                                                                                       }
+                                                                               }else{
+                                                                                       pi[pino].poc.precno0 = tcp->prc_t;
+                                                                                       pi[pino].poc.precno1 = tcp->prc_t+1;
+                                                                                       tcp->prc_t+=1;
+                                                                                       incr_top=0;
+                                                                               }
+                                                                               break;
+                                                                       default:
+                                                                               if(tcp->tx0_t >= tcp->txE){
+                                                                                       if(tcp->ty0_t >= tcp->tyE){
+                                                                                               l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                                                                               if(l==1){
+                                                                                                       tcp->ty0_t = tcp->tyS;
+                                                                                                       pi[pino].poc.ty0 = tcp->ty0_t;
+                                                                                                       pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy);
+                                                                                                       tcp->ty0_t = pi[pino].poc.ty1;
+                                                                                                       incr_top=1;resetX=1;
+                                                                                               }else{
+                                                                                                       incr_top=0;resetX=0;
+                                                                                               }
+                                                                                       }else{
+                                                                                               pi[pino].poc.ty0 = tcp->ty0_t;
+                                                                                               pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy);
+                                                                                               tcp->ty0_t = pi[pino].poc.ty1;
+                                                                                               incr_top=0;resetX=1;
+                                                                                       }
+                                                                                       if(resetX==1){
+                                                                                               tcp->tx0_t = tcp->txS;
+                                                                                               pi[pino].poc.tx0 = tcp->tx0_t;
+                                                                                               pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx);
+                                                                                               tcp->tx0_t = pi[pino].poc.tx1;
+                                                                                       }
+                                                                               }else{
+                                                                                       pi[pino].poc.tx0 = tcp->tx0_t;
+                                                                                       pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx);
+                                                                                       tcp->tx0_t = pi[pino].poc.tx1;
+                                                                                       incr_top=0;
+                                                                               }
+                                                                               break;
+                                                               }
+                                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+OPJ_INT32 pi_check_next_level( OPJ_INT32 pos,
+                                                               opj_cp_v2_t *cp,
+                                                               OPJ_UINT32 tileno,
+                                                               OPJ_UINT32 pino,
+                                                               const OPJ_CHAR *prog)
+{
+       OPJ_INT32 i,l;
+       opj_tcp_v2_t *tcps =&cp->tcps[tileno];
+       opj_poc_t *tcp = &tcps->pocs[pino];
+
+       if(pos>=0){
+               for(i=pos;pos>=0;i--){
+                       switch(prog[i]){
+               case 'R':
+                       if(tcp->res_t==tcp->resE){
+                               l=pi_check_next_level(pos-1,cp,tileno,pino,prog);
+                               if(l==1){
+                                       return 1;
+                               }else{
+                                       return 0;
+                               }
+                       }else{
+                               return 1;
+                       }
+                       break;
+               case 'C':
+                       if(tcp->comp_t==tcp->compE){
+                               l=pi_check_next_level(pos-1,cp,tileno,pino,prog);
+                               if(l==1){
+                                       return 1;
+                               }else{
+                                       return 0;
+                               }
+                       }else{
+                               return 1;
+                       }
+                       break;
+               case 'L':
+                       if(tcp->lay_t==tcp->layE){
+                               l=pi_check_next_level(pos-1,cp,tileno,pino,prog);
+                               if(l==1){
+                                       return 1;
+                               }else{
+                                       return 0;
+                               }
+                       }else{
+                               return 1;
+                       }
+                       break;
+               case 'P':
+                       switch(tcp->prg){
+                               case LRCP||RLCP:
+                                       if(tcp->prc_t == tcp->prcE){
+                                               l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                               if(l==1){
+                                                       return 1;
+                                               }else{
+                                                       return 0;
+                                               }
+                                       }else{
+                                               return 1;
+                                       }
+                                       break;
+                       default:
+                               if(tcp->tx0_t == tcp->txE){
+                                       //TY
+                                       if(tcp->ty0_t == tcp->tyE){
+                                               l=pi_check_next_level(i-1,cp,tileno,pino,prog);
+                                               if(l==1){
+                                                       return 1;
+                                               }else{
+                                                       return 0;
+                                               }
+                                       }else{
+                                               return 1;
+                                       }//TY
+                               }else{
+                                       return 1;
+                               }
+                               break;
+                       }//end case P
+               }//end switch
+               }//end for
+       }//end if
+       return 0;
+}
index 5c7b99813d3498607f05084d42c5fdbad7379c60..d1c8abf50954988cfae52407b1d189dff4b18c22 100644 (file)
@@ -110,6 +110,33 @@ Create a packet iterator for Encoder
 @see pi_destroy
 */
 opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno,J2K_T2_MODE t2_mode);
+
+/**
+ * Creates a packet iterator for encoding.
+ *
+ * @param      p_image         the image being encoded.
+ * @param      p_cp            the coding parameters.
+ * @param      p_tile_no       index of the tile being encoded.
+ * @param      p_t2_mode       the type of pass for generating the packet iterator
+ * @return     a list of packet iterator that points to the first packet of the tile (not true).
+*/
+opj_pi_iterator_t *pi_initialise_encode_v2(    const struct opj_image *image,
+                                                                                       struct opj_cp_v2 *cp,
+                                                                                       OPJ_UINT32 tileno,
+                                                                                       J2K_T2_MODE t2_mode);
+
+
+/**
+ * Updates the encoding parameters of the codec.
+ *
+ * @param      p_image         the image being encoded.
+ * @param      p_cp            the coding parameters.
+ * @param      p_tile_no       index of the tile being encoded.
+*/
+void pi_update_encoding_parameters(    const struct opj_image *p_image,
+                                                                       struct opj_cp_v2 *p_cp,
+                                                                       OPJ_UINT32 p_tile_no );
+
 /**
 Modify the packet iterator for enabling tile part generation
 @param pi Handle to the packet iterator generated in pi_initialise_encode  
@@ -123,6 +150,19 @@ Modify the packet iterator for enabling tile part generation
 @return Returns true if an error is detected 
 */
 opj_bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp);
+
+/**
+Modify the packet iterator for enabling tile part generation
+@param pi Handle to the packet iterator generated in pi_initialise_encode
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which to list the packets
+@param tpnum Tile part number of the current tile
+@param tppos The position of the tile part flag in the progression order
+*/
+void pi_create_encode_v2( opj_pi_iterator_t *pi, struct opj_cp_v2 *cp,OPJ_UINT32 tileno, OPJ_UINT32 pino,OPJ_UINT32 tpnum, OPJ_INT32 tppos, J2K_T2_MODE t2_mode);
+
+
+
 /**
 Create a packet iterator for Decoder
 @param image Raw image for which the packets will be listed
index 32257912c21b9a11005335df5e358ac48c6cf35b..5ace77bee50d3a1502dbfcf779add20c7ed174bd 100644 (file)
@@ -274,6 +274,17 @@ static double t1_getwmsedec(
                double stepsize,
                int numcomps,
                int mct);
+
+static OPJ_FLOAT64 t1_getwmsedec_v2(
+               OPJ_INT32 nmsedec,
+               OPJ_UINT32 compno,
+               OPJ_UINT32 level,
+               OPJ_UINT32 orient,
+               OPJ_INT32 bpno,
+               OPJ_UINT32 qmfbid,
+               OPJ_FLOAT64 stepsize,
+               OPJ_UINT32 numcomps,
+               const OPJ_FLOAT64 * mct_norms);
 /**
 Encode 1 code-block
 @param t1 T1 handle
@@ -300,6 +311,20 @@ static void t1_encode_cblk(
                int numcomps,
                int mct,
                opj_tcd_tile_t * tile);
+
+static void t1_encode_cblk_v2(
+               opj_t1_t *t1,
+               opj_tcd_cblk_enc_v2_t* cblk,
+               OPJ_UINT32 orient,
+               OPJ_UINT32 compno,
+               OPJ_UINT32 level,
+               OPJ_UINT32 qmfbid,
+               OPJ_FLOAT64 stepsize,
+               OPJ_UINT32 cblksty,
+               OPJ_UINT32 numcomps,
+               opj_tcd_tile_v2_t * tile,
+               const OPJ_FLOAT64 * mct_norms);
+
 /**
 Decode 1 code-block
 @param t1 T1 handle
@@ -1165,6 +1190,36 @@ static double t1_getwmsedec(
        return wmsedec;
 }
 
+/** mod fixed_quality */
+static OPJ_FLOAT64 t1_getwmsedec_v2(
+               OPJ_INT32 nmsedec,
+               OPJ_UINT32 compno,
+               OPJ_UINT32 level,
+               OPJ_UINT32 orient,
+               OPJ_INT32 bpno,
+               OPJ_UINT32 qmfbid,
+               OPJ_FLOAT64 stepsize,
+               OPJ_UINT32 numcomps,
+               const OPJ_FLOAT64 * mct_norms)
+{
+       OPJ_FLOAT64 w1 = 1, w2, wmsedec;
+
+       if (mct_norms) {
+               w1 = mct_norms[compno];
+       }
+
+       if (qmfbid == 1) {
+               w2 = dwt_getnorm(level, orient);
+       } else {        /* if (qmfbid == 0) */
+               w2 = dwt_getnorm_real(level, orient);
+       }
+
+       wmsedec = w1 * w2 * stepsize * (1 << bpno);
+       wmsedec *= wmsedec * nmsedec / 8192.0;
+
+       return wmsedec;
+}
+
 static opj_bool allocate_buffers(
                opj_t1_t *t1,
                int w,
@@ -1655,28 +1710,24 @@ opj_t1_t* t1_create_v2()
        opj_t1_t *l_t1 = 00;
 
        l_t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t));
-       if
-               (!l_t1)
-       {
+       if (!l_t1) {
                return 00;
        }
        memset(l_t1,0,sizeof(opj_t1_t));
 
        /* create MQC and RAW handles */
        l_t1->mqc = mqc_create();
-       if
-               (! l_t1->mqc)
-       {
+       if (! l_t1->mqc) {
                t1_destroy(l_t1);
                return 00;
        }
+
        l_t1->raw = raw_create();
-       if
-               (! l_t1->raw)
-       {
+       if (! l_t1->raw) {
                t1_destroy(l_t1);
                return 00;
        }
+
        return l_t1;
 }
 
@@ -1873,6 +1924,241 @@ static void t1_decode_cblk_v2(
        }
 }
 
+opj_bool t1_encode_cblks_v2(
+               opj_t1_t *t1,
+               opj_tcd_tile_v2_t *tile,
+               opj_tcp_v2_t *tcp,
+               const OPJ_FLOAT64 * mct_norms)
+{
+       OPJ_UINT32 compno, resno, bandno, precno, cblkno;
+
+       tile->distotile = 0;            /* fixed_quality */
+
+       for (compno = 0; compno < tile->numcomps; ++compno) {
+               opj_tcd_tilecomp_v2_t* tilec = &tile->comps[compno];
+               opj_tccp_t* tccp = &tcp->tccps[compno];
+               OPJ_UINT32 tile_w = tilec->x1 - tilec->x0;
+
+               for (resno = 0; resno < tilec->numresolutions; ++resno) {
+                       opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+                       for (bandno = 0; bandno < res->numbands; ++bandno) {
+                               opj_tcd_band_v2_t* restrict band = &res->bands[bandno];
+
+                               for (precno = 0; precno < res->pw * res->ph; ++precno) {
+                                       opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+                                       for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) {
+                                               opj_tcd_cblk_enc_v2_t* cblk = &prc->cblks.enc[cblkno];
+                                               OPJ_INT32 * restrict datap;
+                                               OPJ_INT32* restrict tiledp;
+                                               OPJ_UINT32 cblk_w;
+                                               OPJ_UINT32 cblk_h;
+                                               OPJ_UINT32 i, j;
+
+                                               OPJ_INT32 x = cblk->x0 - band->x0;
+                                               OPJ_INT32 y = cblk->y0 - band->y0;
+                                               if (band->bandno & 1) {
+                                                       opj_tcd_resolution_v2_t *pres = &tilec->resolutions[resno - 1];
+                                                       x += pres->x1 - pres->x0;
+                                               }
+                                               if (band->bandno & 2) {
+                                                       opj_tcd_resolution_v2_t *pres = &tilec->resolutions[resno - 1];
+                                                       y += pres->y1 - pres->y0;
+                                               }
+
+                                               if(!allocate_buffers(
+                                                                       t1,
+                                                                       cblk->x1 - cblk->x0,
+                                                                       cblk->y1 - cblk->y0))
+                                               {
+                                                       return OPJ_FALSE;
+                                               }
+
+                                               datap=t1->data;
+                                               cblk_w = t1->w;
+                                               cblk_h = t1->h;
+
+                                               tiledp=&tilec->data[(y * tile_w) + x];
+                                               if (tccp->qmfbid == 1) {
+                                                       for (j = 0; j < cblk_h; ++j) {
+                                                               for (i = 0; i < cblk_w; ++i) {
+                                                                       OPJ_INT32 tmp = tiledp[(j * tile_w) + i];
+                                                                       datap[(j * cblk_w) + i] = tmp << T1_NMSEDEC_FRACBITS;
+                                                               }
+                                                       }
+                                               } else {                /* if (tccp->qmfbid == 0) */
+                                                       for (j = 0; j < cblk_h; ++j) {
+                                                               for (i = 0; i < cblk_w; ++i) {
+                                                                       OPJ_INT32 tmp = tiledp[(j * tile_w) + i];
+                                                                       datap[(j * cblk_w) + i] =
+                                                                               fix_mul(
+                                                                               tmp,
+                                                                               8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS);
+                                                               }
+                                                       }
+                                               }
+
+                                               t1_encode_cblk_v2(
+                                                               t1,
+                                                               cblk,
+                                                               band->bandno,
+                                                               compno,
+                                                               tilec->numresolutions - 1 - resno,
+                                                               tccp->qmfbid,
+                                                               band->stepsize,
+                                                               tccp->cblksty,
+                                                               tile->numcomps,
+                                                               tile,
+                                                               mct_norms);
+
+                                       } /* cblkno */
+                               } /* precno */
+                       } /* bandno */
+               } /* resno  */
+       } /* compno  */
+       return OPJ_TRUE;
+}
+
+/** mod fixed_quality */
+static void t1_encode_cblk_v2(
+               opj_t1_t *t1,
+               opj_tcd_cblk_enc_v2_t* cblk,
+               OPJ_UINT32 orient,
+               OPJ_UINT32 compno,
+               OPJ_UINT32 level,
+               OPJ_UINT32 qmfbid,
+               OPJ_FLOAT64 stepsize,
+               OPJ_UINT32 cblksty,
+               OPJ_UINT32 numcomps,
+               opj_tcd_tile_v2_t * tile,
+               const OPJ_FLOAT64 * mct_norms)
+{
+       OPJ_FLOAT64 cumwmsedec = 0.0;
+
+       opj_mqc_t *mqc = t1->mqc;       /* MQC component */
+
+       OPJ_UINT32 passno;
+       OPJ_INT32 bpno;
+       OPJ_UINT32 passtype;
+       OPJ_INT32 nmsedec = 0;
+       OPJ_INT32 max;
+       OPJ_UINT32 i;
+       OPJ_BYTE type = T1_TYPE_MQ;
+       OPJ_FLOAT64 tempwmsedec;
+
+       max = 0;
+       for (i = 0; i < t1->w * t1->h; ++i) {
+               OPJ_INT32 tmp = abs(t1->data[i]);
+               max = int_max(max, tmp);
+       }
+
+       cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0;
+
+       bpno = cblk->numbps - 1;
+       passtype = 2;
+
+       mqc_resetstates(mqc);
+       mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+       mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+       mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+       mqc_init_enc(mqc, cblk->data);
+
+       for (passno = 0; bpno >= 0; ++passno) {
+               opj_tcd_pass_v2_t *pass = &cblk->passes[passno];
+               OPJ_UINT32 correction = 3;
+               type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+
+               switch (passtype) {
+                       case 0:
+                               t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty);
+                               break;
+                       case 1:
+                               t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty);
+                               break;
+                       case 2:
+                               t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty);
+                               /* code switch SEGMARK (i.e. SEGSYM) */
+                               if (cblksty & J2K_CCP_CBLKSTY_SEGSYM)
+                                       mqc_segmark_enc(mqc);
+                               break;
+               }
+
+               /* fixed_quality */
+               tempwmsedec = t1_getwmsedec_v2(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms) ;
+               cumwmsedec += tempwmsedec;
+               tile->distotile += tempwmsedec;
+
+               /* Code switch "RESTART" (i.e. TERMALL) */
+               if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) {
+                       if (type == T1_TYPE_RAW) {
+                               mqc_flush(mqc);
+                               correction = 1;
+                               /* correction = mqc_bypass_flush_enc(); */
+                       } else {                        /* correction = mqc_restart_enc(); */
+                               mqc_flush(mqc);
+                               correction = 1;
+                       }
+                       pass->term = 1;
+               } else {
+                       if (((bpno < ((OPJ_INT32) (cblk->numbps) - 4) && (passtype > 0))
+                               || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) {
+                               if (type == T1_TYPE_RAW) {
+                                       mqc_flush(mqc);
+                                       correction = 1;
+                                       /* correction = mqc_bypass_flush_enc(); */
+                               } else {                /* correction = mqc_restart_enc(); */
+                                       mqc_flush(mqc);
+                                       correction = 1;
+                               }
+                               pass->term = 1;
+                       } else {
+                               pass->term = 0;
+                       }
+               }
+
+               if (++passtype == 3) {
+                       passtype = 0;
+                       bpno--;
+               }
+
+               if (pass->term && bpno > 0) {
+                       type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+                       if (type == T1_TYPE_RAW)
+                               mqc_bypass_init_enc(mqc);
+                       else
+                               mqc_restart_init_enc(mqc);
+               }
+
+               pass->distortiondec = cumwmsedec;
+               pass->rate = mqc_numbytes(mqc) + correction;    /* FIXME */
+
+               /* Code-switch "RESET" */
+               if (cblksty & J2K_CCP_CBLKSTY_RESET)
+                       mqc_reset_enc(mqc);
+       }
+
+       /* Code switch "ERTERM" (i.e. PTERM) */
+       if (cblksty & J2K_CCP_CBLKSTY_PTERM)
+               mqc_erterm_enc(mqc);
+       else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY))
+               mqc_flush(mqc);
+
+       cblk->totalpasses = passno;
+
+       for (passno = 0; passno<cblk->totalpasses; passno++) {
+               opj_tcd_pass_v2_t *pass = &cblk->passes[passno];
+               if (pass->rate > mqc_numbytes(mqc))
+                       pass->rate = mqc_numbytes(mqc);
+               /*Preventing generation of FF as last data byte of a pass*/
+               if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){
+                       pass->rate--;
+               }
+               pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate);
+       }
+}
+
+
 static void t1_dec_refpass(
                opj_t1_t *t1,
                OPJ_INT32 bpno,
index bebf47ca99ef1042f68b2b020158fcd66e74f40e..ca74e955e8545c76fee090b816824e9c179d6405 100644 (file)
@@ -132,6 +132,12 @@ Encode the code-blocks of a tile
 @param tcp Tile coding parameters
 */
 void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp);
+
+opj_bool t1_encode_cblks_v2(opj_t1_t *t1,
+                                                       struct opj_tcd_tile_v2 *tile,
+                                                       struct opj_tcp_v2 *tcp,
+                                                       const OPJ_FLOAT64 * mct_norms);
+
 /**
 Decode the code-blocks of a tile
 @param t1 T1 handle
index 63e6e3a8fc7e6100c97d37eb22ac25012490ce05..a091ef2230643e5a3c545de5f23a996ad0169fee 100644 (file)
@@ -58,6 +58,28 @@ Encode a packet of a tile to a destination buffer
 @return 
 */
 static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_codestream_info_t *cstr_info, int tileno);
+
+/**
+Encode a packet of a tile to a destination buffer
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@param dest Destination buffer
+@param len Length of the destination buffer
+@param cstr_info Codestream information structure
+@param tileno Number of the tile encoded
+@return
+*/
+static opj_bool t2_encode_packet_v2(
+                                                        OPJ_UINT32 tileno,
+                                                        opj_tcd_tile_v2_t *tile,
+                                                        opj_tcp_v2_t *tcp,
+                                                        opj_pi_iterator_t *pi,
+                                                        OPJ_BYTE *dest,
+                                                        OPJ_UINT32 * p_data_written,
+                                                        OPJ_UINT32 len,
+                                                        opj_codestream_info_t *cstr_info);
+
 /**
 @param cblk
 @param index
@@ -754,6 +776,128 @@ int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlaye
   return (c - dest);
 }
 
+opj_bool t2_encode_packets_v2(
+                                          opj_t2_v2_t* p_t2,
+                                          OPJ_UINT32 p_tile_no,
+                                          opj_tcd_tile_v2_t *p_tile,
+                                          OPJ_UINT32 p_maxlayers,
+                                          OPJ_BYTE *p_dest,
+                                          OPJ_UINT32 * p_data_written,
+                                          OPJ_UINT32 p_max_len,
+                                          opj_codestream_info_t *cstr_info,
+                                          OPJ_UINT32 p_tp_num,
+                                          OPJ_INT32 p_tp_pos,
+                                          OPJ_UINT32 p_pino,
+                                          J2K_T2_MODE p_t2_mode)
+{
+       OPJ_BYTE *l_current_data = p_dest;
+       OPJ_UINT32 l_nb_bytes = 0;
+       OPJ_UINT32 compno;
+       OPJ_UINT32 poc;
+       opj_pi_iterator_t *l_pi = 00;
+       opj_pi_iterator_t *l_current_pi = 00;
+       opj_image_t *l_image = p_t2->image;
+       opj_cp_v2_t *l_cp = p_t2->cp;
+       opj_tcp_v2_t *l_tcp = &l_cp->tcps[p_tile_no];
+       OPJ_UINT32 pocno = l_cp->m_specific_param.m_enc.m_cinema == CINEMA4K_24? 2: 1;
+       OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? l_image->numcomps : 1;
+       OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1;
+
+       l_pi = pi_initialise_encode_v2(l_image, l_cp, p_tile_no, p_t2_mode);
+       if (!l_pi) {
+               return OPJ_FALSE;
+       }
+
+       * p_data_written = 0;
+
+       if (p_t2_mode == THRESH_CALC ){ /* Calculating threshold */
+               l_current_pi = l_pi;
+
+               for     (compno = 0; compno < l_max_comp; ++compno) {
+                       OPJ_UINT32 l_comp_len = 0;
+                       l_current_pi = l_pi;
+
+                       for (poc = 0; poc < pocno ; ++poc) {
+                               OPJ_UINT32 l_tp_num = compno;
+
+                               pi_create_encode_v2(l_pi, l_cp,p_tile_no,poc,l_tp_num,p_tp_pos,p_t2_mode);
+
+                               while (pi_next(l_current_pi)) {
+                                       if (l_current_pi->layno < p_maxlayers) {
+                                               l_nb_bytes = 0;
+
+                                               if (! t2_encode_packet_v2(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) {
+                                                       pi_destroy_v2(l_pi, l_nb_pocs);
+                                                       return OPJ_FALSE;
+                                               }
+
+                                               l_comp_len += l_nb_bytes;
+                                               l_current_data += l_nb_bytes;
+                                               p_max_len -= l_nb_bytes;
+
+                                               * p_data_written += l_nb_bytes;
+                                       }
+                               }
+
+                               if (l_cp->m_specific_param.m_enc.m_max_comp_size) {
+                                       if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) {
+                                               pi_destroy_v2(l_pi, l_nb_pocs);
+                                               return OPJ_FALSE;
+                                       }
+                               }
+
+                               ++l_current_pi;
+                       }
+               }
+       }
+       else {  /* t2_mode == FINAL_PASS  */
+               pi_create_encode_v2(l_pi, l_cp,p_tile_no,p_pino,p_tp_num,p_tp_pos,p_t2_mode);
+
+               l_current_pi = &l_pi[p_pino];
+
+               while (pi_next(l_current_pi)) {
+                       if (l_current_pi->layno < p_maxlayers) {
+                               l_nb_bytes=0;
+
+                               if (! t2_encode_packet_v2(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) {
+                                       pi_destroy_v2(l_pi, l_nb_pocs);
+                                       return OPJ_FALSE;
+                               }
+
+                               l_current_data += l_nb_bytes;
+                               p_max_len -= l_nb_bytes;
+
+                               * p_data_written += l_nb_bytes;
+
+                               /* INDEX >> */
+                               if(cstr_info) {
+                                       if(cstr_info->index_write) {
+                                               opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no];
+                                               opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno];
+                                               if (!cstr_info->packno) {
+                                                       info_PK->start_pos = info_TL->end_header + 1;
+                                               } else {
+                                                       info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1;
+                                               }
+                                               info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1;
+                                               info_PK->end_ph_pos += info_PK->start_pos - 1;  // End of packet header which now only represents the distance
+                                                                                                                                                                                                                                               // to start of packet is incremented by value of start of packet
+                                       }
+
+                                       cstr_info->packno++;
+                               }
+                               /* << INDEX */
+                               ++p_tile->packno;
+                       }
+               }
+       }
+
+       pi_destroy_v2(l_pi, l_nb_pocs);
+
+       return OPJ_TRUE;
+}
+
+
 int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info) {
        unsigned char *c = src;
        opj_pi_iterator_t *pi;
@@ -1052,6 +1196,232 @@ static opj_bool t2_decode_packet_v2(
        return OPJ_TRUE;
 }
 
+static opj_bool t2_encode_packet_v2(
+                                                        OPJ_UINT32 tileno,
+                                                        opj_tcd_tile_v2_t * tile,
+                                                        opj_tcp_v2_t * tcp,
+                                                        opj_pi_iterator_t *pi,
+                                                        OPJ_BYTE *dest,
+                                                        OPJ_UINT32 * p_data_written,
+                                                        OPJ_UINT32 length,
+                                                        opj_codestream_info_t *cstr_info)
+{
+       OPJ_UINT32 bandno, cblkno;
+       OPJ_BYTE *c = dest;
+       OPJ_UINT32 l_nb_bytes;
+       OPJ_UINT32 compno = pi->compno; /* component value */
+       OPJ_UINT32 resno  = pi->resno;          /* resolution level value */
+       OPJ_UINT32 precno = pi->precno; /* precinct value */
+       OPJ_UINT32 layno  = pi->layno;          /* quality layer value */
+       OPJ_UINT32 l_nb_blocks;
+       opj_tcd_band_v2_t *band = 00;
+       opj_tcd_cblk_enc_v2_t* cblk = 00;
+       opj_tcd_pass_v2_t *pass = 00;
+
+       opj_tcd_tilecomp_v2_t *tilec = &tile->comps[compno];
+       opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+       opj_bio_t *bio = 00;    /* BIO component */
+
+       /* <SOP 0xff91> */
+       if (tcp->csty & J2K_CP_CSTY_SOP) {
+               c[0] = 255;
+               c[1] = 145;
+               c[2] = 0;
+               c[3] = 4;
+               c[4] = (tile->packno % 65536) / 256;
+               c[5] = (tile->packno % 65536) % 256;
+               c += 6;
+               length -= 6;
+       }
+       /* </SOP> */
+
+       if (!layno) {
+               band = res->bands;
+
+               for(bandno = 0; bandno < res->numbands; ++bandno) {
+                       opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+                       tgt_reset(prc->incltree);
+                       tgt_reset(prc->imsbtree);
+
+                       l_nb_blocks = prc->cw * prc->ch;
+                       for     (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) {
+                               opj_tcd_cblk_enc_v2_t* cblk = &prc->cblks.enc[cblkno];
+
+                               cblk->numpasses = 0;
+                               tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps);
+                       }
+                       ++band;
+               }
+       }
+
+       bio = bio_create();
+       bio_init_enc(bio, c, length);
+       bio_write(bio, 1, 1);           /* Empty header bit */
+
+       /* Writing Packet header */
+       band = res->bands;
+       for (bandno = 0; bandno < res->numbands; ++bandno)      {
+               opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+               l_nb_blocks = prc->cw * prc->ch;
+               cblk = prc->cblks.enc;
+
+               for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) {
+                       opj_tcd_layer_t *layer = &cblk->layers[layno];
+
+                       if (!cblk->numpasses && layer->numpasses) {
+                               tgt_setvalue(prc->incltree, cblkno, layno);
+                       }
+
+                       ++cblk;
+               }
+
+               cblk = prc->cblks.enc;
+               for (cblkno = 0; cblkno < l_nb_blocks; cblkno++) {
+                       opj_tcd_layer_t *layer = &cblk->layers[layno];
+                       OPJ_UINT32 increment = 0;
+                       OPJ_UINT32 nump = 0;
+                       OPJ_UINT32 len = 0, passno;
+                       OPJ_UINT32 l_nb_passes;
+
+                       /* cblk inclusion bits */
+                       if (!cblk->numpasses) {
+                               tgt_encode(bio, prc->incltree, cblkno, layno + 1);
+                       } else {
+                               bio_write(bio, layer->numpasses != 0, 1);
+                       }
+
+                       /* if cblk not included, go to the next cblk  */
+                       if (!layer->numpasses) {
+                               ++cblk;
+                               continue;
+                       }
+
+                       /* if first instance of cblk --> zero bit-planes information */
+                       if (!cblk->numpasses) {
+                               cblk->numlenbits = 3;
+                               tgt_encode(bio, prc->imsbtree, cblkno, 999);
+                       }
+
+                       /* number of coding passes included */
+                       t2_putnumpasses(bio, layer->numpasses);
+                       l_nb_passes = cblk->numpasses + layer->numpasses;
+                       pass = cblk->passes +  cblk->numpasses;
+
+                       /* computation of the increase of the length indicator and insertion in the header     */
+                       for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) {
+                               ++nump;
+                               len += pass->len;
+
+                               if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
+                                       increment = int_max(increment, int_floorlog2(len) + 1 - (cblk->numlenbits + int_floorlog2(nump)));
+                                       len = 0;
+                                       nump = 0;
+                               }
+
+                               ++pass;
+                       }
+                       t2_putcommacode(bio, increment);
+
+                       /* computation of the new Length indicator */
+                       cblk->numlenbits += increment;
+
+                       pass = cblk->passes +  cblk->numpasses;
+                       /* insertion of the codeword segment length */
+                       for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) {
+                               nump++;
+                               len += pass->len;
+
+                               if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
+                                       bio_write(bio, len, cblk->numlenbits + int_floorlog2(nump));
+                                       len = 0;
+                                       nump = 0;
+                               }
+                               ++pass;
+                       }
+
+                       ++cblk;
+               }
+
+               ++band;
+       }
+
+       if (bio_flush(bio)) {
+               bio_destroy(bio);
+               return OPJ_FALSE;               /* modified to eliminate longjmp !! */
+       }
+
+       l_nb_bytes = bio_numbytes(bio);
+       c += l_nb_bytes;
+       length -= l_nb_bytes;
+
+       bio_destroy(bio);
+
+       /* <EPH 0xff92> */
+       if (tcp->csty & J2K_CP_CSTY_EPH) {
+               c[0] = 255;
+               c[1] = 146;
+               c += 2;
+               length -= 2;
+       }
+       /* </EPH> */
+
+       /* << INDEX */
+       // End of packet header position. Currently only represents the distance to start of packet
+       // Will be updated later by incrementing with packet start value
+       if(cstr_info && cstr_info->index_write) {
+               opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
+               info_PK->end_ph_pos = (OPJ_INT32)(c - dest);
+       }
+       /* INDEX >> */
+
+       /* Writing the packet body */
+       band = res->bands;
+       for (bandno = 0; bandno < res->numbands; bandno++) {
+               opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+               l_nb_blocks = prc->cw * prc->ch;
+               cblk = prc->cblks.enc;
+
+               for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) {
+                       opj_tcd_layer_t *layer = &cblk->layers[layno];
+
+                       if (!layer->numpasses) {
+                               ++cblk;
+                               continue;
+                       }
+
+                       if (layer->len > length) {
+                               return OPJ_FALSE;
+                       }
+
+                       memcpy(c, layer->data, layer->len);
+                       cblk->numpasses += layer->numpasses;
+                       c += layer->len;
+                       length -= layer->len;
+
+                       /* << INDEX */
+                       if(cstr_info && cstr_info->index_write) {
+                               opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
+                               info_PK->disto += layer->disto;
+                               if (cstr_info->D_max < info_PK->disto) {
+                                       cstr_info->D_max = info_PK->disto;
+                               }
+                       }
+
+                       ++cblk;
+                       /* INDEX >> */
+               }
+               ++band;
+       }
+
+       * p_data_written += (c - dest);
+
+       return OPJ_TRUE;
+}
+
 static opj_bool t2_skip_packet(
                                                         opj_t2_v2_t* p_t2,
                                                         opj_tcd_tile_v2_t *p_tile,
index f1637fba4ad8cd3e81a5690d8d00e5ca0f632c51..2273c44e8e759d628d4ab5bf945f057790b2c914 100644 (file)
@@ -85,6 +85,33 @@ Encode the packets of a tile to a destination buffer
 @param cur_totnum_tp The total number of tile parts in the current tile
 */
 int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_codestream_info_t *cstr_info,int tpnum, int tppos,int pino,J2K_T2_MODE t2_mode,int cur_totnum_tp);
+
+/**
+Encode the packets of a tile to a destination buffer
+@param t2 T2 handle
+@param tileno number of the tile encoded
+@param tile the tile for which to write the packets
+@param maxlayers maximum number of layers
+@param dest the destination buffer
+@param len the length of the destination buffer
+@param cstr_info Codestream information structure
+@param tpnum Tile part number of the current tile
+@param tppos The position of the tile part flag in the progression order
+@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
+*/
+opj_bool t2_encode_packets_v2( opj_t2_v2_t* t2,
+                                                               OPJ_UINT32 tileno,
+                                                               struct opj_tcd_tile_v2 *tile,
+                                                               OPJ_UINT32 maxlayers,
+                                                               OPJ_BYTE *dest,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               OPJ_UINT32 len,
+                                                               struct opj_codestream_info *cstr_info,
+                                                               OPJ_UINT32 tpnum,
+                                                               OPJ_INT32 tppos,
+                                                               OPJ_UINT32 pino,
+                                                               J2K_T2_MODE t2_mode);
+
 /**
 Decode the packets of a tile from a source buffer
 @param t2 T2 handle
index ea09a17f94702d5028e9704dbac7273798bf8a8c..3b866dd167c53aa40a42a2aed849bfcf75b006b7 100644 (file)
 
 #include "opj_includes.h"
 
+/* ----------------------------------------------------------------------- */
+
+static opj_bool tcd_dc_level_shift_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool tcd_mct_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool tcd_dwt_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool tcd_t1_encode ( opj_tcd_v2_t *p_tcd );
+
+static opj_bool tcd_t2_encode (        opj_tcd_v2_t *p_tcd,
+                                                               OPJ_BYTE * p_dest_data,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               OPJ_UINT32 p_max_dest_size,
+                                                               opj_codestream_info_t *p_cstr_info );
+
+static opj_bool tcd_rate_allocate_encode(      opj_tcd_v2_t *p_tcd,
+                                                                                       OPJ_BYTE * p_dest_data,
+                                                                                       OPJ_UINT32 p_max_dest_size,
+                                                                                       opj_codestream_info_t *p_cstr_info );
+
+/* ----------------------------------------------------------------------- */
+
+
 void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
        int tileno, compno, resno, bandno, precno;/*, cblkno;*/
 
@@ -95,6 +119,12 @@ void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
 */
 static opj_bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_v2_t * p_code_block);
 
+/**
+ * Allocates memory for an encoding code block.
+ */
+static opj_bool tcd_code_block_enc_allocate (opj_tcd_cblk_enc_v2_t * p_code_block);
+
+
 /**
 Free the memory allocated for encoding
 @param tcd TCD handle
@@ -992,6 +1022,14 @@ void tcd_rateallocate_fixed(opj_tcd_t *tcd) {
        }
 }
 
+void tcd_rateallocate_fixed_v2(opj_tcd_v2_t *tcd) {
+       OPJ_UINT32 layno;
+
+       for (layno = 0; layno < tcd->tcp->numlayers; layno++) {
+               tcd_makelayer_fixed_v2(tcd, layno, 1);
+       }
+}
+
 void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) {
        int compno, resno, bandno, precno, cblkno, passno;
        
@@ -1062,6 +1100,184 @@ void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) {
        }
 }
 
+void tcd_makelayer_v2( opj_tcd_v2_t *tcd,
+                                               OPJ_UINT32 layno,
+                                               OPJ_FLOAT64 thresh,
+                                               OPJ_UINT32 final)
+{
+       OPJ_UINT32 compno, resno, bandno, precno, cblkno;
+       OPJ_UINT32 passno;
+
+       opj_tcd_tile_v2_t *tcd_tile = tcd->tcd_image->tiles;
+
+       tcd_tile->distolayer[layno] = 0;        /* fixed_quality */
+
+       for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+               opj_tcd_tilecomp_v2_t *tilec = &tcd_tile->comps[compno];
+
+               for (resno = 0; resno < tilec->numresolutions; resno++) {
+                       opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+                       for (bandno = 0; bandno < res->numbands; bandno++) {
+                               opj_tcd_band_v2_t *band = &res->bands[bandno];
+
+                               for (precno = 0; precno < res->pw * res->ph; precno++) {
+                                       opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+                                       for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+                                               opj_tcd_cblk_enc_v2_t *cblk = &prc->cblks.enc[cblkno];
+                                               opj_tcd_layer_t *layer = &cblk->layers[layno];
+                                               OPJ_UINT32 n;
+
+                                               if (layno == 0) {
+                                                       cblk->numpassesinlayers = 0;
+                                               }
+
+                                               n = cblk->numpassesinlayers;
+
+                                               for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) {
+                                                       OPJ_INT32 dr;
+                                                       OPJ_FLOAT64 dd;
+                                                       opj_tcd_pass_v2_t *pass = &cblk->passes[passno];
+
+                                                       if (n == 0) {
+                                                               dr = pass->rate;
+                                                               dd = pass->distortiondec;
+                                                       } else {
+                                                               dr = pass->rate - cblk->passes[n - 1].rate;
+                                                               dd = pass->distortiondec - cblk->passes[n - 1].distortiondec;
+                                                       }
+
+                                                       if (!dr) {
+                                                               if (dd != 0)
+                                                                       n = passno + 1;
+                                                               continue;
+                                                       }
+                                                       if (dd / dr >= thresh)
+                                                               n = passno + 1;
+                                               }
+
+                                               layer->numpasses = n - cblk->numpassesinlayers;
+
+                                               if (!layer->numpasses) {
+                                                       layer->disto = 0;
+                                                       continue;
+                                               }
+
+                                               if (cblk->numpassesinlayers == 0) {
+                                                       layer->len = cblk->passes[n - 1].rate;
+                                                       layer->data = cblk->data;
+                                                       layer->disto = cblk->passes[n - 1].distortiondec;
+                                               } else {
+                                                       layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate;
+                                                       layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate;
+                                                       layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec;
+                                               }
+
+                                               tcd_tile->distolayer[layno] += layer->disto;    /* fixed_quality */
+
+                                               if (final)
+                                                       cblk->numpassesinlayers = n;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+void tcd_makelayer_fixed_v2(opj_tcd_v2_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final) {
+       OPJ_UINT32 compno, resno, bandno, precno, cblkno;
+       OPJ_INT32 value;                        /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */
+       OPJ_INT32 matrice[10][10][3];
+       OPJ_UINT32 i, j, k;
+
+       opj_cp_v2_t *cp = tcd->cp;
+       opj_tcd_tile_v2_t *tcd_tile = tcd->tcd_image->tiles;
+       opj_tcp_v2_t *tcd_tcp = tcd->tcp;
+
+       for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+               opj_tcd_tilecomp_v2_t *tilec = &tcd_tile->comps[compno];
+
+               for (i = 0; i < tcd_tcp->numlayers; i++) {
+                       for (j = 0; j < tilec->numresolutions; j++) {
+                               for (k = 0; k < 3; k++) {
+                                       matrice[i][j][k] =
+                                               (OPJ_INT32) (cp->m_specific_param.m_enc.m_matrice[i * tilec->numresolutions * 3 + j * 3 + k]
+                                               * (OPJ_FLOAT32) (tcd->image->comps[compno].prec / 16.0));
+                               }
+                       }
+               }
+
+               for (resno = 0; resno < tilec->numresolutions; resno++) {
+                       opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+                       for (bandno = 0; bandno < res->numbands; bandno++) {
+                               opj_tcd_band_v2_t *band = &res->bands[bandno];
+
+                               for (precno = 0; precno < res->pw * res->ph; precno++) {
+                                       opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+                                       for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+                                               opj_tcd_cblk_enc_v2_t *cblk = &prc->cblks.enc[cblkno];
+                                               opj_tcd_layer_t *layer = &cblk->layers[layno];
+                                               OPJ_UINT32 n;
+                                               OPJ_INT32 imsb = tcd->image->comps[compno].prec - cblk->numbps; /* number of bit-plan equal to zero */
+
+                                               /* Correction of the matrix of coefficient to include the IMSB information */
+                                               if (layno == 0) {
+                                                       value = matrice[layno][resno][bandno];
+                                                       if (imsb >= value) {
+                                                               value = 0;
+                                                       } else {
+                                                               value -= imsb;
+                                                       }
+                                               } else {
+                                                       value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno];
+                                                       if (imsb >= matrice[layno - 1][resno][bandno]) {
+                                                               value -= (imsb - matrice[layno - 1][resno][bandno]);
+                                                               if (value < 0) {
+                                                                       value = 0;
+                                                               }
+                                                       }
+                                               }
+
+                                               if (layno == 0) {
+                                                       cblk->numpassesinlayers = 0;
+                                               }
+
+                                               n = cblk->numpassesinlayers;
+                                               if (cblk->numpassesinlayers == 0) {
+                                                       if (value != 0) {
+                                                               n = 3 * value - 2 + cblk->numpassesinlayers;
+                                                       } else {
+                                                               n = cblk->numpassesinlayers;
+                                                       }
+                                               } else {
+                                                       n = 3 * value + cblk->numpassesinlayers;
+                                               }
+
+                                               layer->numpasses = n - cblk->numpassesinlayers;
+
+                                               if (!layer->numpasses)
+                                                       continue;
+
+                                               if (cblk->numpassesinlayers == 0) {
+                                                       layer->len = cblk->passes[n - 1].rate;
+                                                       layer->data = cblk->data;
+                                               } else {
+                                                       layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate;
+                                                       layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate;
+                                               }
+
+                                               if (final)
+                                                       cblk->numpassesinlayers = n;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
 opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
        int compno, resno, bandno, precno, cblkno, passno, layno;
        double min, max;
@@ -1229,97 +1445,286 @@ opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_code
        return OPJ_TRUE;
 }
 
-int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
-       int compno;
-       int l, i, numpacks = 0;
-       opj_tcd_tile_t *tile = NULL;
-       opj_tcp_t *tcd_tcp = NULL;
-       opj_cp_t *cp = NULL;
+opj_bool tcd_rateallocate_v2(  opj_tcd_v2_t *tcd,
+                                                               OPJ_BYTE *dest,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               OPJ_UINT32 len,
+                                                               opj_codestream_info_t *cstr_info)
+{
+       OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno;
+       OPJ_UINT32 passno;
+       OPJ_FLOAT64 min, max;
+       OPJ_FLOAT64 cumdisto[100];      /* fixed_quality */
+       const OPJ_FLOAT64 K = 1;                /* 1.1; fixed_quality */
+       OPJ_FLOAT64 maxSE = 0;
 
-       opj_tcp_t *tcp = &tcd->cp->tcps[0];
-       opj_tccp_t *tccp = &tcp->tccps[0];
-       opj_image_t *image = tcd->image;
-       
-       opj_t1_t *t1 = NULL;            /* T1 component */
-       opj_t2_t *t2 = NULL;            /* T2 component */
+       opj_cp_v2_t *cp = tcd->cp;
+       opj_tcd_tile_v2_t *tcd_tile = tcd->tcd_image->tiles;
+       opj_tcp_v2_t *tcd_tcp = tcd->tcp;
 
-       tcd->tcd_tileno = tileno;
-       tcd->tcd_tile = tcd->tcd_image->tiles;
-       tcd->tcp = &tcd->cp->tcps[tileno];
+       min = DBL_MAX;
+       max = 0;
 
-       tile = tcd->tcd_tile;
-       tcd_tcp = tcd->tcp;
-       cp = tcd->cp;
+       tcd_tile->numpix = 0;           /* fixed_quality */
 
-       if(tcd->cur_tp_num == 0){
-               tcd->encoding_time = opj_clock();       /* time needed to encode a tile */
-               /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */
-               if(cstr_info) {
-                       opj_tcd_tilecomp_t *tilec_idx = &tile->comps[0];        /* based on component 0 */
-                       for (i = 0; i < tilec_idx->numresolutions; i++) {
-                               opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[i];
-                               
-                               cstr_info->tile[tileno].pw[i] = res_idx->pw;
-                               cstr_info->tile[tileno].ph[i] = res_idx->ph;
-                               
-                               numpacks += res_idx->pw * res_idx->ph;
-                               
-                               cstr_info->tile[tileno].pdx[i] = tccp->prcw[i];
-                               cstr_info->tile[tileno].pdy[i] = tccp->prch[i];
-                       }
-                       cstr_info->tile[tileno].packet = (opj_packet_info_t*) opj_calloc(cstr_info->numcomps * cstr_info->numlayers * numpacks, sizeof(opj_packet_info_t));
-               }
-               /* << INDEX */
-               
-               /*---------------TILE-------------------*/
-               
-               for (compno = 0; compno < tile->numcomps; compno++) {
-                       int x, y;
-                       
-                       int adjust = image->comps[compno].sgnd ? 0 : 1 << (image->comps[compno].prec - 1);
-                       int offset_x = int_ceildiv(image->x0, image->comps[compno].dx);
-                       int offset_y = int_ceildiv(image->y0, image->comps[compno].dy);
-                       
-                       opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
-                       int tw = tilec->x1 - tilec->x0;
-                       int w = int_ceildiv(image->x1 - image->x0, image->comps[compno].dx);
-                       
-                       /* extract tile data */
-                       
-                       if (tcd_tcp->tccps[compno].qmfbid == 1) {
-                               for (y = tilec->y0; y < tilec->y1; y++) {
-                                       /* start of the src tile scanline */
-                                       int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
-                                       /* start of the dst tile scanline */
-                                       int *tile_data = &tilec->data[(y - tilec->y0) * tw];
-                                       for (x = tilec->x0; x < tilec->x1; x++) {
-                                               *tile_data++ = *data++ - adjust;
-                                       }
-                               }
-                       } else if (tcd_tcp->tccps[compno].qmfbid == 0) {
-                               for (y = tilec->y0; y < tilec->y1; y++) {
-                                       /* start of the src tile scanline */
-                                       int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
-                                       /* start of the dst tile scanline */
-                                       int *tile_data = &tilec->data[(y - tilec->y0) * tw];
-                                       for (x = tilec->x0; x < tilec->x1; x++) {
-                                               *tile_data++ = (*data++ - adjust) << 11;
-                                       }
-                                       
-                               }
-                       }
-               }
-               
-               /*----------------MCT-------------------*/
-               if (tcd_tcp->mct) {
-                       int samples = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
-                       if (tcd_tcp->tccps[0].qmfbid == 0) {
-                               mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
-                       } else {
-                               mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
-                       }
-               }
-               
+       for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+               opj_tcd_tilecomp_v2_t *tilec = &tcd_tile->comps[compno];
+               tilec->numpix = 0;
+
+               for (resno = 0; resno < tilec->numresolutions; resno++) {
+                       opj_tcd_resolution_v2_t *res = &tilec->resolutions[resno];
+
+                       for (bandno = 0; bandno < res->numbands; bandno++) {
+                               opj_tcd_band_v2_t *band = &res->bands[bandno];
+
+                               for (precno = 0; precno < res->pw * res->ph; precno++) {
+                                       opj_tcd_precinct_v2_t *prc = &band->precincts[precno];
+
+                                       for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+                                               opj_tcd_cblk_enc_v2_t *cblk = &prc->cblks.enc[cblkno];
+
+                                               for (passno = 0; passno < cblk->totalpasses; passno++) {
+                                                       opj_tcd_pass_v2_t *pass = &cblk->passes[passno];
+                                                       OPJ_INT32 dr;
+                                                       OPJ_FLOAT64 dd, rdslope;
+
+                                                       if (passno == 0) {
+                                                               dr = pass->rate;
+                                                               dd = pass->distortiondec;
+                                                       } else {
+                                                               dr = pass->rate - cblk->passes[passno - 1].rate;
+                                                               dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec;
+                                                       }
+
+                                                       if (dr == 0) {
+                                                               continue;
+                                                       }
+
+                                                       rdslope = dd / dr;
+                                                       if (rdslope < min) {
+                                                               min = rdslope;
+                                                       }
+
+                                                       if (rdslope > max) {
+                                                               max = rdslope;
+                                                       }
+                                               } /* passno */
+
+                                               /* fixed_quality */
+                                               tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+                                               tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+                                       } /* cbklno */
+                               } /* precno */
+                       } /* bandno */
+               } /* resno */
+
+               maxSE += (((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0)
+                       * ((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) -1.0))
+                       * ((OPJ_FLOAT64)(tilec->numpix));
+       } /* compno */
+
+       /* index file */
+       if(cstr_info) {
+               opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno];
+               tile_info->numpix = tcd_tile->numpix;
+               tile_info->distotile = tcd_tile->distotile;
+               tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof(OPJ_FLOAT64));
+       }
+
+       for (layno = 0; layno < tcd_tcp->numlayers; layno++) {
+               OPJ_FLOAT64 lo = min;
+               OPJ_FLOAT64 hi = max;
+               opj_bool success = OPJ_FALSE;
+               OPJ_UINT32 maxlen = tcd_tcp->rates[layno] ? uint_min(((OPJ_UINT32) ceil(tcd_tcp->rates[layno])), len) : len;
+               OPJ_FLOAT64 goodthresh = 0;
+               OPJ_FLOAT64 stable_thresh = 0;
+               OPJ_UINT32 i;
+               OPJ_FLOAT64 distotarget;                /* fixed_quality */
+
+               /* fixed_quality */
+               distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10, tcd_tcp->distoratio[layno] / 10));
+
+               /* Don't try to find an optimal threshold but rather take everything not included yet, if
+                 -r xx,yy,zz,0   (disto_alloc == 1 and rates == 0)
+                 -q xx,yy,zz,0   (fixed_quality == 1 and distoratio == 0)
+                 ==> possible to have some lossy layers and the last layer for sure lossless */
+               if ( ((cp->m_specific_param.m_enc.m_disto_alloc==1) && (tcd_tcp->rates[layno]>0)) || ((cp->m_specific_param.m_enc.m_fixed_quality==1) && (tcd_tcp->distoratio[layno]>0))) {
+                       opj_t2_v2_t*t2 = t2_create_v2(tcd->image, cp);
+                       OPJ_FLOAT64 thresh = 0;
+
+                       if (t2 == 00) {
+                               return OPJ_FALSE;
+                       }
+
+                       for     (i = 0; i < 128; ++i) {
+                               OPJ_FLOAT64 distoachieved = 0;  /* fixed_quality */
+
+                               thresh = (lo + hi) / 2;
+
+                               tcd_makelayer_v2(tcd, layno, thresh, 0);
+
+                               if (cp->m_specific_param.m_enc.m_fixed_quality) {       /* fixed_quality */
+                                       if(cp->m_specific_param.m_enc.m_cinema){
+                                               if (! t2_encode_packets_v2(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) {
+
+                                                       lo = thresh;
+                                                       continue;
+                                               }
+                                               else {
+                                                       distoachieved = layno == 0 ?
+                                                                       tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno];
+
+                                                       if (distoachieved < distotarget) {
+                                                               hi=thresh;
+                                                               stable_thresh = 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;
+                                                       stable_thresh = thresh;
+                                                       continue;
+                                               }
+                                               lo = thresh;
+                                       }
+                               } else {
+                                       if (! t2_encode_packets_v2(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC))
+                                       {
+                                               /* TODO: what to do with l ??? seek / tell ??? */
+                                               /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */
+                                               lo = thresh;
+                                               continue;
+                                       }
+
+                                       hi = thresh;
+                                       stable_thresh = thresh;
+                               }
+                       }
+
+                       success = OPJ_TRUE;
+                       goodthresh = stable_thresh == 0? thresh : stable_thresh;
+
+                       t2_destroy_v2(t2);
+               } else {
+                       success = OPJ_TRUE;
+                       goodthresh = min;
+               }
+
+               if (!success) {
+                       return OPJ_FALSE;
+               }
+
+               if(cstr_info) { /* Threshold for Marcela Index */
+                       cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh;
+               }
+
+               tcd_makelayer_v2(tcd, layno, goodthresh, 1);
+
+               /* fixed_quality */
+               cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
+       }
+
+       return OPJ_TRUE;
+}
+
+
+int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
+       int compno;
+       int l, i, numpacks = 0;
+       opj_tcd_tile_t *tile = NULL;
+       opj_tcp_t *tcd_tcp = NULL;
+       opj_cp_t *cp = NULL;
+
+       opj_tcp_t *tcp = &tcd->cp->tcps[0];
+       opj_tccp_t *tccp = &tcp->tccps[0];
+       opj_image_t *image = tcd->image;
+       
+       opj_t1_t *t1 = NULL;            /* T1 component */
+       opj_t2_t *t2 = NULL;            /* T2 component */
+
+       tcd->tcd_tileno = tileno;
+       tcd->tcd_tile = tcd->tcd_image->tiles;
+       tcd->tcp = &tcd->cp->tcps[tileno];
+
+       tile = tcd->tcd_tile;
+       tcd_tcp = tcd->tcp;
+       cp = tcd->cp;
+
+       if(tcd->cur_tp_num == 0){
+               tcd->encoding_time = opj_clock();       /* time needed to encode a tile */
+               /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */
+               if(cstr_info) {
+                       opj_tcd_tilecomp_t *tilec_idx = &tile->comps[0];        /* based on component 0 */
+                       for (i = 0; i < tilec_idx->numresolutions; i++) {
+                               opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[i];
+                               
+                               cstr_info->tile[tileno].pw[i] = res_idx->pw;
+                               cstr_info->tile[tileno].ph[i] = res_idx->ph;
+                               
+                               numpacks += res_idx->pw * res_idx->ph;
+                               
+                               cstr_info->tile[tileno].pdx[i] = tccp->prcw[i];
+                               cstr_info->tile[tileno].pdy[i] = tccp->prch[i];
+                       }
+                       cstr_info->tile[tileno].packet = (opj_packet_info_t*) opj_calloc(cstr_info->numcomps * cstr_info->numlayers * numpacks, sizeof(opj_packet_info_t));
+               }
+               /* << INDEX */
+               
+               /*---------------TILE-------------------*/
+               
+               for (compno = 0; compno < tile->numcomps; compno++) {
+                       int x, y;
+                       
+                       int adjust = image->comps[compno].sgnd ? 0 : 1 << (image->comps[compno].prec - 1);
+                       int offset_x = int_ceildiv(image->x0, image->comps[compno].dx);
+                       int offset_y = int_ceildiv(image->y0, image->comps[compno].dy);
+                       
+                       opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+                       int tw = tilec->x1 - tilec->x0;
+                       int w = int_ceildiv(image->x1 - image->x0, image->comps[compno].dx);
+                       
+                       /* extract tile data */
+                       
+                       if (tcd_tcp->tccps[compno].qmfbid == 1) {
+                               for (y = tilec->y0; y < tilec->y1; y++) {
+                                       /* start of the src tile scanline */
+                                       int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
+                                       /* start of the dst tile scanline */
+                                       int *tile_data = &tilec->data[(y - tilec->y0) * tw];
+                                       for (x = tilec->x0; x < tilec->x1; x++) {
+                                               *tile_data++ = *data++ - adjust;
+                                       }
+                               }
+                       } else if (tcd_tcp->tccps[compno].qmfbid == 0) {
+                               for (y = tilec->y0; y < tilec->y1; y++) {
+                                       /* start of the src tile scanline */
+                                       int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
+                                       /* start of the dst tile scanline */
+                                       int *tile_data = &tilec->data[(y - tilec->y0) * tw];
+                                       for (x = tilec->x0; x < tilec->x1; x++) {
+                                               *tile_data++ = (*data++ - adjust) << 11;
+                                       }
+                                       
+                               }
+                       }
+               }
+               
+               /*----------------MCT-------------------*/
+               if (tcd_tcp->mct) {
+                       int samples = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
+                       if (tcd_tcp->tccps[0].qmfbid == 0) {
+                               mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
+                       } else {
+                               mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
+                       }
+               }
+               
                /*----------------DWT---------------------*/
                
                for (compno = 0; compno < tile->numcomps; compno++) {
@@ -1993,54 +2398,200 @@ opj_bool FUNCTION (    opj_tcd_v2_t *p_tcd,                                                                            \
 }                                                                                                                                                              \
 
 
-/* V2 ENCODE MACRO_TCD_ALLOCATE(tcd_init_encode_tile,opj_tcd_cblk_enc_t,1.f,enc,tcd_code_block_enc_allocate) */
+MACRO_TCD_ALLOCATE(tcd_init_encode_tile, opj_tcd_cblk_enc_v2_t, 1.f, enc, tcd_code_block_enc_allocate)
 MACRO_TCD_ALLOCATE(tcd_init_decode_tile, opj_tcd_cblk_dec_v2_t, 0.5f, dec, tcd_code_block_dec_allocate)
 
 #undef MACRO_TCD_ALLOCATE
 
-
-OPJ_UINT32 tcd_get_decoded_tile_size ( opj_tcd_v2_t *p_tcd )
+/**
+ * Allocates memory for an encoding code block.
+ */
+opj_bool tcd_code_block_enc_allocate (opj_tcd_cblk_enc_v2_t * p_code_block)
 {
-       OPJ_UINT32 i;
-       OPJ_UINT32 l_data_size = 0;
-       opj_image_comp_t * l_img_comp = 00;
-       opj_tcd_tilecomp_v2_t * l_tile_comp = 00;
-       opj_tcd_resolution_v2_t * l_res = 00;
-       OPJ_UINT32 l_size_comp, l_remaining;
+       if (! p_code_block->data) {
 
-       l_tile_comp = p_tcd->tcd_image->tiles->comps;
-       l_img_comp = p_tcd->image->comps;
+               p_code_block->data = (OPJ_BYTE*) opj_malloc(8192+1);
+               if(! p_code_block->data) {
+                       return OPJ_FALSE;
+               }
 
-       for (i=0;i<p_tcd->image->numcomps;++i) {
-               l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
-               l_remaining = l_img_comp->prec & 7;  /* (%8) */
+               p_code_block->data+=1;
 
-               if(l_remaining) {
-                       ++l_size_comp;
+               /* no memset since data */
+               p_code_block->layers = (opj_tcd_layer_t*) opj_malloc(100 * sizeof(opj_tcd_layer_t));
+               if (! p_code_block->layers) {
+                       return OPJ_FALSE;
                }
 
-               if (l_size_comp == 3) {
-                       l_size_comp = 4;
+               p_code_block->passes = (opj_tcd_pass_v2_t*) opj_malloc(100 * sizeof(opj_tcd_pass_v2_t));
+               if (! p_code_block->passes) {
+                       return OPJ_FALSE;
                }
-
-               l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1;
-               l_data_size += l_size_comp * (l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0);
-               ++l_img_comp;
-               ++l_tile_comp;
        }
 
-       return l_data_size;
-}
+       memset(p_code_block->layers,0,100 * sizeof(opj_tcd_layer_t));
+       memset(p_code_block->passes,0,100 * sizeof(opj_tcd_pass_v2_t));
 
+       return OPJ_TRUE;
+}
 
-opj_bool tcd_decode_tile_v2(
-                                        opj_tcd_v2_t *p_tcd,
-                                        OPJ_BYTE *p_src,
-                                        OPJ_UINT32 p_max_length,
-                                        OPJ_UINT32 p_tile_no,
-                                        opj_codestream_index_t *p_cstr_index)
+/**
+ * Allocates memory for a decoding code block.
+ */
+opj_bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_v2_t * p_code_block)
 {
-       OPJ_UINT32 l_data_read;
+       OPJ_UINT32 l_seg_size;
+
+       if (! p_code_block->data) {
+
+               p_code_block->data = (OPJ_BYTE*) opj_malloc(8192);
+               if (! p_code_block->data) {
+                       return OPJ_FALSE;
+               }
+               /*fprintf(stderr, "Allocate 8192 elements of code_block->data\n");*/
+
+               l_seg_size = J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t);
+               p_code_block->segs = (opj_tcd_seg_t *) opj_malloc(l_seg_size);
+               if (! p_code_block->segs) {
+                       return OPJ_FALSE;
+               }
+               memset(p_code_block->segs,0,l_seg_size);
+               /*fprintf(stderr, "Allocate %d elements of code_block->data\n", J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/
+
+               p_code_block->m_current_max_segs = J2K_DEFAULT_NB_SEGS;
+               /*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/
+       }
+       /* TODO */
+       /*p_code_block->numsegs = 0; */
+
+       return OPJ_TRUE;
+}
+
+OPJ_UINT32 tcd_get_decoded_tile_size ( opj_tcd_v2_t *p_tcd )
+{
+       OPJ_UINT32 i;
+       OPJ_UINT32 l_data_size = 0;
+       opj_image_comp_t * l_img_comp = 00;
+       opj_tcd_tilecomp_v2_t * l_tile_comp = 00;
+       opj_tcd_resolution_v2_t * l_res = 00;
+       OPJ_UINT32 l_size_comp, l_remaining;
+
+       l_tile_comp = p_tcd->tcd_image->tiles->comps;
+       l_img_comp = p_tcd->image->comps;
+
+       for (i=0;i<p_tcd->image->numcomps;++i) {
+               l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
+               l_remaining = l_img_comp->prec & 7;  /* (%8) */
+
+               if(l_remaining) {
+                       ++l_size_comp;
+               }
+
+               if (l_size_comp == 3) {
+                       l_size_comp = 4;
+               }
+
+               l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1;
+               l_data_size += l_size_comp * (l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0);
+               ++l_img_comp;
+               ++l_tile_comp;
+       }
+
+       return l_data_size;
+}
+
+opj_bool tcd_encode_tile_v2(opj_tcd_v2_t *p_tcd,
+                                                       OPJ_UINT32 p_tile_no,
+                                                       OPJ_BYTE *p_dest,
+                                                       OPJ_UINT32 * p_data_written,
+                                                       OPJ_UINT32 p_max_length,
+                                                       opj_codestream_info_t *p_cstr_info)
+{
+
+       if (p_tcd->cur_tp_num == 0) {
+
+               p_tcd->tcd_tileno = p_tile_no;
+               p_tcd->tcp = &p_tcd->cp->tcps[p_tile_no];
+
+               /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */
+               if(p_cstr_info)  {
+                       OPJ_UINT32 l_num_packs = 0;
+                       OPJ_UINT32 i;
+                       opj_tcd_tilecomp_v2_t *l_tilec_idx = &p_tcd->tcd_image->tiles->comps[0];        /* based on component 0 */
+                       opj_tccp_t *l_tccp = p_tcd->tcp->tccps; /* based on component 0 */
+
+                       for (i = 0; i < l_tilec_idx->numresolutions; i++) {
+                               opj_tcd_resolution_v2_t *l_res_idx = &l_tilec_idx->resolutions[i];
+
+                               p_cstr_info->tile[p_tile_no].pw[i] = l_res_idx->pw;
+                               p_cstr_info->tile[p_tile_no].ph[i] = l_res_idx->ph;
+
+                               l_num_packs += l_res_idx->pw * l_res_idx->ph;
+                               p_cstr_info->tile[p_tile_no].pdx[i] = l_tccp->prcw[i];
+                               p_cstr_info->tile[p_tile_no].pdy[i] = l_tccp->prch[i];
+                       }
+                       p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc(p_cstr_info->numcomps * p_cstr_info->numlayers * l_num_packs, sizeof(opj_packet_info_t));
+               }
+               /* << INDEX */
+
+               /* FIXME _ProfStart(PGROUP_DC_SHIFT); */
+               /*---------------TILE-------------------*/
+               if (! tcd_dc_level_shift_encode(p_tcd)) {
+                       return OPJ_FALSE;
+               }
+               /* FIXME _ProfStop(PGROUP_DC_SHIFT); */
+
+               /* FIXME _ProfStart(PGROUP_MCT); */
+               if (! tcd_mct_encode(p_tcd)) {
+                       return OPJ_FALSE;
+               }
+               /* FIXME _ProfStop(PGROUP_MCT); */
+
+               /* FIXME _ProfStart(PGROUP_DWT); */
+               if (! tcd_dwt_encode(p_tcd)) {
+                       return OPJ_FALSE;
+               }
+               /* FIXME  _ProfStop(PGROUP_DWT); */
+
+               /* FIXME  _ProfStart(PGROUP_T1); */
+               if (! tcd_t1_encode(p_tcd)) {
+                       return OPJ_FALSE;
+               }
+               /* FIXME _ProfStop(PGROUP_T1); */
+
+               /* FIXME _ProfStart(PGROUP_RATE); */
+               if (! tcd_rate_allocate_encode(p_tcd,p_dest,p_max_length,p_cstr_info)) {
+                       return OPJ_FALSE;
+               }
+               /* FIXME _ProfStop(PGROUP_RATE); */
+
+       }
+       /*--------------TIER2------------------*/
+
+       /* INDEX */
+       if (p_cstr_info) {
+               p_cstr_info->index_write = 1;
+       }
+       /* FIXME _ProfStart(PGROUP_T2); */
+
+       if (! tcd_t2_encode(p_tcd,p_dest,p_data_written,p_max_length,p_cstr_info)) {
+               return OPJ_FALSE;
+       }
+       /* FIXME _ProfStop(PGROUP_T2); */
+
+       /*---------------CLEAN-------------------*/
+
+       return OPJ_TRUE;
+}
+
+opj_bool tcd_decode_tile_v2(
+                                        opj_tcd_v2_t *p_tcd,
+                                        OPJ_BYTE *p_src,
+                                        OPJ_UINT32 p_max_length,
+                                        OPJ_UINT32 p_tile_no,
+                                        opj_codestream_index_t *p_cstr_index)
+{
+       OPJ_UINT32 l_data_read;
        p_tcd->tcd_tileno = p_tile_no;
        p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]);
 
@@ -2315,38 +2866,6 @@ void tcd_free_tile(opj_tcd_v2_t *p_tcd)
 }
 
 
-/**
- * Allocates memory for a decoding code block.
- */
-opj_bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_v2_t * p_code_block)
-{
-       OPJ_UINT32 l_seg_size;
-
-       if (! p_code_block->data) {
-
-               p_code_block->data = (OPJ_BYTE*) opj_malloc(8192);
-               if (! p_code_block->data) {
-                       return OPJ_FALSE;
-               }
-               /*fprintf(stderr, "Allocate 8192 elements of code_block->data\n");*/
-
-               l_seg_size = J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t);
-               p_code_block->segs = (opj_tcd_seg_t *) opj_malloc(l_seg_size);
-               if (! p_code_block->segs) {
-                       return OPJ_FALSE;
-               }
-               memset(p_code_block->segs,0,l_seg_size);
-               /*fprintf(stderr, "Allocate %d elements of code_block->data\n", J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/
-
-               p_code_block->m_current_max_segs = J2K_DEFAULT_NB_SEGS;
-               /*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/
-       }
-       /* TODO */
-       /*p_code_block->numsegs = 0; */
-
-       return OPJ_TRUE;
-}
-
 opj_bool tcd_t2_decode (
                                        opj_tcd_v2_t *p_tcd,
                                        OPJ_BYTE * p_src_data,
@@ -2623,4 +3142,344 @@ void tcd_code_block_dec_deallocate (opj_tcd_precinct_v2_t * p_precinct)
        }
 }
 
+OPJ_UINT32 tcd_get_encoded_tile_size ( opj_tcd_v2_t *p_tcd )
+{
+       OPJ_UINT32 i,l_data_size = 0;
+       opj_image_comp_t * l_img_comp = 00;
+       opj_tcd_tilecomp_v2_t * l_tilec = 00;
+       OPJ_UINT32 l_size_comp, l_remaining;
+
+       l_tilec = p_tcd->tcd_image->tiles->comps;
+       l_img_comp = p_tcd->image->comps;
+       for (i=0;i<p_tcd->image->numcomps;++i) {
+               l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
+               l_remaining = l_img_comp->prec & 7;  /* (%8) */
+
+               if (l_remaining) {
+                       ++l_size_comp;
+               }
+
+               if (l_size_comp == 3) {
+                       l_size_comp = 4;
+               }
+
+               l_data_size += l_size_comp * (l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0);
+               ++l_img_comp;
+               ++l_tilec;
+       }
+
+       return l_data_size;
+}
+               
+opj_bool tcd_dc_level_shift_encode ( opj_tcd_v2_t *p_tcd )
+{
+       OPJ_UINT32 compno;
+       opj_tcd_tilecomp_v2_t * l_tile_comp = 00;
+       opj_tccp_t * l_tccp = 00;
+       opj_image_comp_t * l_img_comp = 00;
+       opj_tcp_v2_t * l_tcp = 00;
+       opj_tcd_tile_v2_t * l_tile;
+       OPJ_UINT32 l_nb_elem,i;
+       OPJ_INT32 * l_current_ptr;
+
+       l_tile = p_tcd->tcd_image->tiles;
+       l_tile_comp = l_tile->comps;
+       l_tcp = p_tcd->tcp;
+       l_tccp = p_tcd->tcp->tccps;
+       l_img_comp = p_tcd->image->comps;
+
+       for (compno = 0; compno < l_tile->numcomps; compno++) {
+               l_current_ptr = l_tile_comp->data;
+               l_nb_elem = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0);
+
+               if (l_tccp->qmfbid == 1) {
+                       for     (i = 0; i < l_nb_elem; ++i) {
+                               *l_current_ptr -= l_tccp->m_dc_level_shift ;
+                               ++l_current_ptr;
+                       }
+               }
+               else {
+                       for (i = 0; i < l_nb_elem; ++i) {
+                               *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) << 11 ;
+                               ++l_current_ptr;
+                       }
+               }
+
+               ++l_img_comp;
+               ++l_tccp;
+               ++l_tile_comp;
+       }
+
+       return OPJ_TRUE;
+}
+
+opj_bool tcd_mct_encode ( opj_tcd_v2_t *p_tcd )
+{
+       opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+       opj_tcd_tilecomp_v2_t * l_tile_comp = p_tcd->tcd_image->tiles->comps;
+       OPJ_UINT32 samples = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0);
+       OPJ_UINT32 i;
+       OPJ_BYTE ** l_data = 00;
+       opj_tcp_v2_t * l_tcp = p_tcd->tcp;
+
+       if(!p_tcd->tcp->mct) {
+               return OPJ_TRUE;
+       }
+
+       if (p_tcd->tcp->mct == 2) {
+               if (! p_tcd->tcp->m_mct_coding_matrix) {
+                       return OPJ_TRUE;
+               }
+
+        l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*));
+               if (! l_data) {
+                       return OPJ_FALSE;
+               }
+
+               for (i=0;i<l_tile->numcomps;++i) {
+                       l_data[i] = (OPJ_BYTE*) l_tile_comp->data;
+                       ++l_tile_comp;
+               }
+
+               if (! mct_encode_custom(// MCT data
+                                       (OPJ_BYTE*) p_tcd->tcp->m_mct_coding_matrix,
+                                       // size of components
+                                       samples,
+                                       // components
+                                       l_data,
+                                       // nb of components (i.e. size of pData)
+                                       l_tile->numcomps,
+                                       // tells if the data is signed
+                                       p_tcd->image->comps->sgnd) )
+               {
+            opj_free(l_data);
+                       return OPJ_FALSE;
+               }
+
+               opj_free(l_data);
+       }
+       else if (l_tcp->tccps->qmfbid == 0) {
+               mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples);
+       }
+       else {
+               mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples);
+       }
+
+       return OPJ_TRUE;
+}
+
+opj_bool tcd_dwt_encode ( opj_tcd_v2_t *p_tcd )
+{
+       opj_tcd_tile_v2_t * l_tile = p_tcd->tcd_image->tiles;
+       opj_tcd_tilecomp_v2_t * l_tile_comp = p_tcd->tcd_image->tiles->comps;
+       opj_tccp_t * l_tccp = p_tcd->tcp->tccps;
+       OPJ_UINT32 compno;
+
+       for (compno = 0; compno < l_tile->numcomps; ++compno) {
+               if (l_tccp->qmfbid == 1) {
+                       if (! dwt_encode_v2(l_tile_comp)) {
+                               return OPJ_FALSE;
+                       }
+               }
+               else if (l_tccp->qmfbid == 0) {
+                       if (! dwt_encode_real_v2(l_tile_comp)) {
+                               return OPJ_FALSE;
+                       }
+               }
+
+               ++l_tile_comp;
+               ++l_tccp;
+       }
+
+       return OPJ_TRUE;
+}
+
+opj_bool tcd_t1_encode ( opj_tcd_v2_t *p_tcd )
+{
+       opj_t1_t * l_t1;
+       const OPJ_FLOAT64 * l_mct_norms;
+       opj_tcp_v2_t * l_tcp = p_tcd->tcp;
+
+       l_t1 = t1_create_v2();
+       if (l_t1 == 00) {
+               return OPJ_FALSE;
+       }
+
+       if (l_tcp->mct == 1) {
+               // irreversible encoding
+               if (l_tcp->tccps->qmfbid == 0) {
+                       l_mct_norms = get_mct_norms_real();
+               }
+               else {
+                       l_mct_norms = get_mct_norms();
+               }
+       }
+       else {
+               l_mct_norms = (const OPJ_FLOAT64 *) (l_tcp->mct_norms);
+       }
+
+       if (! t1_encode_cblks_v2(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms)) {
+        t1_destroy_v2(l_t1);
+               return OPJ_FALSE;
+       }
+
+       t1_destroy_v2(l_t1);
+
+       return OPJ_TRUE;
+}
+
+opj_bool tcd_t2_encode (opj_tcd_v2_t *p_tcd,
+                                               OPJ_BYTE * p_dest_data,
+                                               OPJ_UINT32 * p_data_written,
+                                               OPJ_UINT32 p_max_dest_size,
+                                               opj_codestream_info_t *p_cstr_info )
+{
+       opj_t2_v2_t * l_t2;
+
+       l_t2 = t2_create_v2(p_tcd->image, p_tcd->cp);
+       if (l_t2 == 00) {
+               return OPJ_FALSE;
+       }
+
+       if (! t2_encode_packets_v2(
+                                       l_t2,
+                                       p_tcd->tcd_tileno,
+                                       p_tcd->tcd_image->tiles,
+                                       p_tcd->tcp->numlayers,
+                                       p_dest_data,
+                                       p_data_written,
+                                       p_max_dest_size,
+                                       p_cstr_info,
+                                       p_tcd->tp_num,
+                                       p_tcd->tp_pos,
+                                       p_tcd->cur_pino,
+                                       FINAL_PASS))
+       {
+               t2_destroy_v2(l_t2);
+               return OPJ_FALSE;
+       }
+
+       t2_destroy_v2(l_t2);
+
+       /*---------------CLEAN-------------------*/
+       return OPJ_TRUE;
+}
+
+
+opj_bool tcd_rate_allocate_encode(     opj_tcd_v2_t *p_tcd,
+                                                                       OPJ_BYTE * p_dest_data,
+                                                                       OPJ_UINT32 p_max_dest_size,
+                                                                       opj_codestream_info_t *p_cstr_info )
+{
+       opj_cp_v2_t * l_cp = p_tcd->cp;
+       OPJ_UINT32 l_nb_written = 0;
+
+       if (p_cstr_info)  {
+               p_cstr_info->index_write = 0;
+       }
 
+       if (l_cp->m_specific_param.m_enc.m_disto_alloc|| l_cp->m_specific_param.m_enc.m_fixed_quality)  {
+               /* fixed_quality */
+               /* Normal Rate/distortion allocation */
+               if (! tcd_rateallocate_v2(p_tcd, p_dest_data,&l_nb_written, p_max_dest_size, p_cstr_info)) {
+                       return OPJ_FALSE;
+               }
+       }
+       else {
+               /* Fixed layer allocation */
+               tcd_rateallocate_fixed_v2(p_tcd);
+       }
+
+       return OPJ_TRUE;
+}
+
+
+opj_bool tcd_copy_tile_data (  opj_tcd_v2_t *p_tcd,
+                                                               OPJ_BYTE * p_src,
+                                                               OPJ_UINT32 p_src_length )
+{
+       OPJ_UINT32 i,j,l_data_size = 0;
+       opj_image_comp_t * l_img_comp = 00;
+       opj_tcd_tilecomp_v2_t * l_tilec = 00;
+       OPJ_UINT32 l_size_comp, l_remaining;
+       OPJ_UINT32 l_nb_elem;
+
+       l_data_size = tcd_get_encoded_tile_size(p_tcd);
+       if (l_data_size != p_src_length) {
+               return OPJ_FALSE;
+       }
+
+       l_tilec = p_tcd->tcd_image->tiles->comps;
+       l_img_comp = p_tcd->image->comps;
+       for (i=0;i<p_tcd->image->numcomps;++i) {
+               l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
+               l_remaining = l_img_comp->prec & 7;  /* (%8) */
+               l_nb_elem = (l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0);
+
+               if (l_remaining) {
+                       ++l_size_comp;
+               }
+
+               if (l_size_comp == 3) {
+                       l_size_comp = 4;
+               }
+
+               switch (l_size_comp) {
+                       case 1:
+                               {
+                                       OPJ_CHAR * l_src_ptr = (OPJ_CHAR *) p_src;
+                                       OPJ_INT32 * l_dest_ptr = l_tilec->data;
+
+                                       if (l_img_comp->sgnd) {
+                                               for (j=0;j<l_nb_elem;++j) {
+                                                       *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++));
+                                               }
+                                       }
+                                       else {
+                                               for (j=0;j<l_nb_elem;++j) {
+                                                       *(l_dest_ptr++) = (*(l_src_ptr++))&0xff;
+                                               }
+                                       }
+
+                                       p_src = (OPJ_BYTE*) l_src_ptr;
+                               }
+                               break;
+                       case 2:
+                               {
+                                       OPJ_INT32 * l_dest_ptr = l_tilec->data;
+                                       OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src;
+
+                                       if (l_img_comp->sgnd) {
+                                               for (j=0;j<l_nb_elem;++j) {
+                                                       *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++));
+                                               }
+                                       }
+                                       else {
+                                               for (j=0;j<l_nb_elem;++j) {
+                                                       *(l_dest_ptr++) = (*(l_src_ptr++))&0xffff;
+                                               }
+                                       }
+
+                                       p_src = (OPJ_BYTE*) l_src_ptr;
+                               }
+                               break;
+                       case 4:
+                               {
+                                       OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_src;
+                                       OPJ_INT32 * l_dest_ptr = l_tilec->data;
+
+                                       for (j=0;j<l_nb_elem;++j) {
+                                               *(l_dest_ptr++) = (OPJ_INT32) (*(l_src_ptr++));
+                                       }
+
+                                       p_src = (OPJ_BYTE*) l_src_ptr;
+                               }
+                               break;
+               }
+
+               ++l_img_comp;
+               ++l_tilec;
+       }
+
+       return OPJ_TRUE;
+}
index cb9967cdd8d4ccebde0a0f7c36d49da1bc87b8f5..bd2fe69efcd42d2175a19fcb1e3606d2d6491ce9 100644 (file)
@@ -431,10 +431,28 @@ Initialize the tile decoder
 */
 void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp);
 void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int tileno, opj_codestream_info_t *cstr_info);
+
 void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final);
+void tcd_makelayer_fixed_v2(opj_tcd_v2_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final);
+
 void tcd_rateallocate_fixed(opj_tcd_t *tcd);
+void tcd_rateallocate_fixed_v2(opj_tcd_v2_t *tcd);
+
 void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final);
+
+void tcd_makelayer_v2( opj_tcd_v2_t *tcd,
+                                               OPJ_UINT32 layno,
+                                               OPJ_FLOAT64 thresh,
+                                               OPJ_UINT32 final);
+
 opj_bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info);
+
+opj_bool tcd_rateallocate_v2(  opj_tcd_v2_t *tcd,
+                                                               OPJ_BYTE *dest,
+                                                               OPJ_UINT32 * p_data_written,
+                                                               OPJ_UINT32 len,
+                                                               opj_codestream_info_t *cstr_info);
+
 /**
 Encode a tile from the raw image into a buffer
 @param tcd TCD handle
@@ -469,6 +487,24 @@ OPJ_UINT32 tcd_get_decoded_tile_size (
                                                 opj_tcd_v2_t *p_tcd
                                                 );
 
+/**
+ * Encodes a tile from the raw image into the given buffer.
+ * @param      p_tcd                   Tile Coder handle
+ * @param      p_tile_no               Index of the tile to encode.
+ * @param      p_dest                  Destination buffer
+ * @param      p_data_written  pointer to an int that is incremented by the number of bytes really written on p_dest
+ * @param      p_len                   Maximum length of the destination buffer
+ * @param      p_cstr_info             Codestream information structure
+ * @return  true if the coding is successfull.
+*/
+opj_bool tcd_encode_tile_v2(opj_tcd_v2_t *p_tcd,
+                                                       OPJ_UINT32 p_tile_no,
+                                                       OPJ_BYTE *p_dest,
+                                                       OPJ_UINT32 * p_data_written,
+                                                       OPJ_UINT32 p_len,
+                                                       struct opj_codestream_info *p_cstr_info);
+
+
 /**
 Decode a tile from a buffer into a raw image
 @param tcd TCD handle
@@ -486,11 +522,33 @@ opj_bool tcd_decode_tile_v2(opj_tcd_v2_t *tcd,
 /**
  * Copies tile data from the system onto the given memory block.
  */
-opj_bool tcd_update_tile_data (
-                                                opj_tcd_v2_t *p_tcd,
-                                                OPJ_BYTE * p_dest,
-                                                OPJ_UINT32 p_dest_length
-                                                );
+opj_bool tcd_update_tile_data (        opj_tcd_v2_t *p_tcd,
+                                                               OPJ_BYTE * p_dest,
+                                                               OPJ_UINT32 p_dest_length );
+
+/**
+ *
+ */
+OPJ_UINT32 tcd_get_encoded_tile_size ( opj_tcd_v2_t *p_tcd );
+
+/**
+ * Initialize the tile coder and may reuse some meory.
+ * @param      p_tcd           TCD handle.
+ * @param      p_image         raw image.
+ * @param      p_cp            coding parameters.
+ * @param      p_tile_no       current tile index to encode.
+ *
+ * @return true if the encoding values could be set (false otherwise).
+*/
+opj_bool tcd_init_encode_tile (        opj_tcd_v2_t *p_tcd,
+                                                               OPJ_UINT32 p_tile_no );
+
+/**
+ * Copies tile data from the given memory block onto the system.
+ */
+opj_bool tcd_copy_tile_data (opj_tcd_v2_t *p_tcd,
+                                                        OPJ_BYTE * p_src,
+                                                        OPJ_UINT32 p_src_length );
 
 /* ----------------------------------------------------------------------- */
 /*@}*/