Modifications to increase modularity of jp2 coding/decoding
[openjpeg.git] / codec / image_to_j2k.c
index 5fcfcc57a0534f7379949690b6af7031fc2557c6..2a24f456918adad51010fc9e868c4fafba631b17 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+
+
+//MEMORY LEAK
+
+#ifdef _DEBUG
+
+#define _CRTDBG_MAP_ALLOC
+
+#include <stdlib.h>  // Must be included first
+
+#include <crtdbg.h>
+
+#endif
+
+//MEM
+
 #include <openjpeg.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 void help_display()
 {
-  printf("HELP\n----\n\n");
-  printf("- the option -help displays the readme.txt file on screen\n\n");
-
-
-  printf("List of parameters for the coder JPEG 2000 :\n");
-  printf("\n");
-  printf
-    ("- The markers COD and QCD are writed both of two in the main_header and never appear in the tile_header.  The markers in the main header are : SOC SIZ COD QCD COM.\n");
-  printf("\n");
-  printf
-    ("- This coder can encode mega image, a test was made on a 24000x24000 pixels color image.  You need enough disk space memory (twice the original) to encode the image. (i.e. for a 1.5 Gb image you need a minimum of 3Gb of disk memory)\n");
-  printf("\n");
-  printf("REMARKS :\n");
-  printf("---------\n");
-  printf("\n");
-  printf
-    ("* the value of rate enter in the code line is the compression factor !\n");
-  printf("exemple :\n");
-  printf("\n");
-  printf
-    ("-r 20,10,1 means quality 1 : compress 20x, quality 2 : compress 10x and quality 3 : compress 1x = lossless\n");
-  printf("\n");
-  printf("By default :\n");
-  printf("------------\n");
-  printf("\n");
-  printf(" * lossless\n");
-  printf(" * 1 tile\n");
-  printf(" * size of precinct 2^15 x 2^15 (means 1 precinct)\n");
-  printf(" * size of code-block 64 x 64\n");
-  printf(" * Number of resolution : 6\n");
-  printf(" * No SOP marker in the codestream\n");
-  printf(" * No EPH marker in the codestream\n");
-  printf(" * No sub-sampling in x and y direction\n");
-  printf(" * No mode switch activated\n");
-  printf(" * progression order : LRCP\n");
-  printf(" * No index file\n");
-  printf(" * No ROI upshifted\n");
-  printf(" * No offset of the origin of the image\n");
-  printf(" * No offset of the origin of the tiles\n");
-  printf(" * Reversible DWT 5-3\n");
-  printf("\n");
-  printf("Parameters :\n");
-  printf("------------\n");
-  printf("\n");
-  printf
-    ("-i             : source file  (-i source.pnm also *.pgm, *.ppm) required\n");
-  printf("\n");
-  printf("-o             : destination file (-o dest.j2k) required\n");
-  printf("\n");
-  printf("-help          : Display the help information optional\n ");
-  printf("\n");
-  printf("-r             : different rates (-r 20,10,5) optional\n ");
-  printf("\n");
-  printf("-n             : Number of resolution (-n 3) optional\n");
-  printf("\n");
-  printf("-b             : size of code block (-b 32,32) optional\n");
-  printf("\n");
-  printf("-c             : size of precinct (-c 128,128) optional\n");
-  printf("\n");
-  printf("-t             : size of tile (-t 512,512) optional\n");
-  printf("\n");
-  printf
-    ("-p             : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] optional\n");
-  printf("\n");
-  printf
-    ("-s             : subsampling factor (-s 2,2) [-s X,Y] optional\n");
-  printf("\n");
-  printf
-    ("-SOP           : write SOP marker before each packet optional\n");
-  printf("\n");
-  printf
-    ("-EPH           : write EPH marker after each header packet optional\n");
-  printf("\n");
-  printf
-    ("-M             : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL) 8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] optional\n");
-  printf
-    ("                    for several mode switch you have to add the value of each mode you want\n");
-  printf
-    ("                    ex : RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
-  printf("\n");
-  printf
-    ("-x             : Create an index file *.Idx (-x index_name.Idx) optional\n");
-  printf("\n");
-  printf
-    ("-ROI:c=%%d,U=%%d : quantization indices upshifted for component c=%%d [%%d = 0,1,2]\n");
-  printf
-    ("                 with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI:c=0,U=25) optional\n");
-  printf("\n");
-  printf
-    ("-d             : offset of the origin of the image (-d 150,300) optional\n");
-  printf("\n");
-  printf
-    ("-T             : offset of the origin of the tiles (-T 100,75) optional\n");
-  printf("\n");
-  printf("-I             : Use the irreversible DWT 9-7 (-I) optional\n");
-  printf("\n");
-  printf("IMPORTANT :\n");
-  printf("-----------\n");
-  printf("\n");
-  printf("* subsampling bigger than 2 can produce error\n");
-  printf("\n");
-  printf("The index file respect the structure below :\n");
-  printf("---------------------------------------------\n");
-  printf("\n");
-  printf("Image_height Image_width\n");
-  printf("progression order\n");
-  printf("Tiles_size_X Tiles_size_Y\n");
-  printf("Components_nb\n");
-  printf("Layers_nb\n");
-  printf("decomposition_levels\n");
-  printf("Precincts_size_X Precincts_size_Y\n");
-  printf("Main_header_end_position\n");
-  printf("Codestream_size\n");
-  printf("Tile0 start_pos end_Theader end_pos\n");
-  printf("Tile1  ''           ''        ''\n");
-  printf("...\n");
-  printf("TileN  ''           ''        ''\n");
-  printf("Tpacket_0 Tile layer res. comp. prec. start_pos end_pos\n");
-  printf("...\n");
-  printf("Tpacket_M  ''    ''   ''   ''    ''       ''       ''\n");
+  fprintf(stdout,"HELP\n----\n\n");
+  fprintf(stdout,"- the -h option displays this help information on screen\n\n");
+
+
+  fprintf(stdout,"List of parameters for the coder JPEG 2000:\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"REMARKS:\n");
+  fprintf(stdout,"---------\n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"The markers written to the main_header are : SOC SIZ COD QCD COM.\n");
+  fprintf
+    (stdout,"COD and QCD never appear in the tile_header.\n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"- This coder can encode a mega image, a test was made on a 24000x24000 pixels \n");
+  fprintf
+    (stdout,"color image.  You need enough disk space memory (twice the original) to encode \n");
+  fprintf
+    (stdout,"the image,i.e. for a 1.5 GB image you need a minimum of 3GB of disk memory)\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"By default:\n");
+  fprintf(stdout,"------------\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout," * Lossless\n");
+  fprintf(stdout," * 1 tile\n");
+  fprintf(stdout," * Size of precinct : 2^15 x 2^15 (means 1 precinct)\n");
+  fprintf(stdout," * Size of code-block : 64 x 64\n");
+  fprintf(stdout," * Number of resolutions: 6\n");
+  fprintf(stdout," * No SOP marker in the codestream\n");
+  fprintf(stdout," * No EPH marker in the codestream\n");
+  fprintf(stdout," * No sub-sampling in x or y direction\n");
+  fprintf(stdout," * No mode switch activated\n");
+  fprintf(stdout," * Progression order: LRCP\n");
+  fprintf(stdout," * No index file\n");
+  fprintf(stdout," * No ROI upshifted\n");
+  fprintf(stdout," * No offset of the origin of the image\n");
+  fprintf(stdout," * No offset of the origin of the tiles\n");
+  fprintf(stdout," * Reversible DWT 5-3\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"Parameters:\n");
+  fprintf(stdout,"------------\n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"Required Parameters (except with -h):\n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-i           : source file  (-i source.pnm also *.pgm, *.ppm) \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-o           : destination file (-o dest.j2k or .jp2) \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"Optional Parameters:\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-h           : display the help information \n ");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-r           : different compression ratios for successive layers (-r 20,10,5)\n ");
+  fprintf(stdout,"              - The rate specified for each quality level is the desired \n");
+  fprintf(stdout,"                compression factor.\n");
+  fprintf(stdout,"                Example: -r 20,10,1 means quality 1: compress 20x, \n");
+  fprintf(stdout,"                  quality 2: compress 10x and quality 3: compress lossless\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"               (options -r and -q cannot be used together)\n ");
+  fprintf(stdout,"\n");
+
+  fprintf(stdout,"-q           : different psnr for successive layers (-q 30,40,50) \n ");
+
+  fprintf(stdout,"               (options -r and -q cannot be used together)\n ");
+
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-n           : number of resolutions (-n 3) \n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-b           : size of code block (-b 32,32) \n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-c           : size of precinct (-c 128,128) \n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-t           : size of tile (-t 512,512) \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-p           : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-s           : subsampling factor (-s 2,2) [-s X,Y] \n");
+  fprintf(stdout,"          Remark: subsampling bigger than 2 can produce error\n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-SOP         : write SOP marker before each packet \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-EPH         : write EPH marker after each header packet \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-M           : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n");
+  fprintf
+    (stdout,"                 8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] \n");
+  fprintf
+    (stdout,"                 Indicate multiple modes by adding their values. \n");
+  fprintf
+    (stdout,"                 ex: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-x           : create an index file *.Idx (-x index_name.Idx) \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-ROI         : c=%%d,U=%%d : quantization indices upshifted \n");
+  fprintf
+    (stdout,"               for component c=%%d [%%d = 0,1,2]\n");
+  fprintf
+    (stdout,"               with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI:c=0,U=25) \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-d           : offset of the origin of the image (-d 150,300) \n");
+  fprintf(stdout,"\n");
+  fprintf
+    (stdout,"-T           : offset of the origin of the tiles (-T 100,75) \n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"-I           : use the irreversible DWT 9-7 (-I) \n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"IMPORTANT:\n");
+  fprintf(stdout,"-----------\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"The index file has the structure below:\n");
+  fprintf(stdout,"---------------------------------------\n");
+  fprintf(stdout,"\n");
+  fprintf(stdout,"Image_height Image_width\n");
+  fprintf(stdout,"progression order\n");
+  fprintf(stdout,"Tiles_size_X Tiles_size_Y\n");
+  fprintf(stdout,"Components_nb\n");
+  fprintf(stdout,"Layers_nb\n");
+  fprintf(stdout,"decomposition_levels\n");
+  fprintf(stdout,"[Precincts_size_X_res_Nr Precincts_size_Y_res_Nr]...\n");
+  fprintf(stdout,"   [Precincts_size_X_res_0 Precincts_size_Y_res_0]\n");
+  fprintf(stdout,"Main_header_end_position\n");
+  fprintf(stdout,"Codestream_size\n");
+  fprintf(stdout,"Tile_0 start_pos end_Theader end_pos TotalDisto NumPix MaxMSE\n");
+  fprintf(stdout,"Tile_1   ''           ''        ''        ''       ''    ''\n");
+  fprintf(stdout,"...\n");
+  fprintf(stdout,"Tile_Nt   ''           ''        ''        ''       ''    ''\n");
+  fprintf(stdout,"Tpacket_0 Tile layer res. comp. prec. start_pos end_pos disto\n");
+  fprintf(stdout,"...\n");
+  fprintf(stdout,"Tpacket_Np ''   ''    ''   ''    ''       ''       ''     ''\n");
+
+  fprintf(stdout,"MaxDisto\n");
+
+  fprintf(stdout,"TotalDisto\n\n");
 }
 
 int give_progression(char progression[4])
@@ -276,6 +318,10 @@ int main(int argc, char **argv)
   int ir = 0;
   int res_spec = 0;            /*   For various precinct sizes specification                 */
   char sep;
+  char *j2k_codestream;
+  char *jp2_codestream;
+  FILE *f;
+
 
   /* default value */
   /* ------------- */
@@ -285,7 +331,7 @@ int main(int argc, char **argv)
   cblockh_init = 64;
   cp.tw = 1;
   cp.th = 1;
-  img.index_on = 0;
+  cp.index_on = 0;
   Prog_order = 0;
   numpocs = 0;
   mode = 0;
@@ -297,9 +343,10 @@ int main(int argc, char **argv)
   Dim[1] = 0;
   TX0 = 0;
   TY0 = 0;
-  cp.comment = NULL;
+  cp.comment = "Created by OpenJPEG version 0.9";
   cp.disto_alloc = 0;
   cp.fixed_alloc = 0;
+  cp.fixed_quality = 0;                //add fixed_quality
   /* img.PPT=0; */
 
   Tile_arg = 0;
@@ -307,9 +354,11 @@ int main(int argc, char **argv)
   tcp_init = &cp_init.tcps[0];
   tcp_init->numlayers = 0;
 
+  cp.intermed_file = 1;
+
   while (1) {
     int c = getopt(argc, argv,
-                  "i:o:r:q:t:n:c:b:x:p:s:d:h:P:S:E:M:R:T:C:I");
+                  "i:o:r:q:f:t:n:c:b:x:p:s:d:h:P:S:E:M:R:T:C:I");
     if (c == -1)
       break;
     switch (c) {
@@ -357,12 +406,38 @@ int main(int argc, char **argv)
       /* ----------------------------------------------------- */
     case 'o':                  /* OUT fill */
       outfile = optarg;
+      while (*outfile) {
+       outfile++;
+      }
+      outfile--;
+      S3 = *outfile;
+      outfile--;
+      S2 = *outfile;
+      outfile--;
+      S1 = *outfile;
+
+      outfile = optarg;
+
+      if ((S1 == 'j' && S2 == '2' && S3 == 'k')
+         || (S1 == 'J' && S2 == '2' && S3 == 'K'))
+       cp.JPEG2000_format = 0;
+      else if ((S1 == 'j' && S2 == 'p' && S3 == '2')
+              || (S1 == 'J' && S2 == 'P' && S3 == '2'))
+       cp.JPEG2000_format = 1;
+      else {
+       fprintf(stderr,
+               "Unknown output format image *.%c%c%c [only *.j2k, *.jp2]!! \n",
+               S1, S2, S3);
+       return 1;
+      }
+
+
+
       break;
       /* ----------------------------------------------------- */
     case 'r':                  /* rates rates/distorsion */
       s = optarg;
-      while (sscanf(s, "%d", &tcp_init->rates[tcp_init->numlayers])
-            == 1) {
+      while (sscanf(s, "%d", &tcp_init->rates[tcp_init->numlayers]) == 1) {
        tcp_init->numlayers++;
        while (*s && *s != ',') {
          s++;
@@ -375,7 +450,24 @@ int main(int argc, char **argv)
       cp.matrice = NULL;
       break;
       /* ----------------------------------------------------- */
-    case 'q':                  /* rates fixed */
+    case 'q':                  /* add fixed_quality */
+      s = optarg;
+      while (sscanf(s, "%f", &tcp_init->distoratio[tcp_init->numlayers])
+            == 1) {
+       tcp_init->numlayers++;
+       while (*s && *s != ',') {
+         s++;
+       }
+       if (!*s)
+         break;
+       s++;
+      }
+      cp.fixed_quality = 1;
+      cp.matrice = NULL;
+      break;
+      /* dda */
+      /* ----------------------------------------------------- */
+    case 'f':                  /* mod fixed_quality (before : -q) */
       s = optarg;
       sscanf(s, "%d", &tcp_init->numlayers);
       s++;
@@ -430,7 +522,8 @@ int main(int argc, char **argv)
        CSty |= 0x01;
        res_spec++;
        s = strpbrk(s, "]") + 2;
-      } while (sep == ',');
+      }
+      while (sep == ',');
       break;
       /* ----------------------------------------------------- */
     case 'b':                  /* code-block dimension */
@@ -445,7 +538,7 @@ int main(int argc, char **argv)
       /* ----------------------------------------------------- */
     case 'x':                  /* creation of index file */
       index = optarg;
-      img.index_on = 1;
+      cp.index_on = 1;
       break;
       /* ----------------------------------------------------- */
     case 'p':                  /* progression order */
@@ -464,8 +557,7 @@ int main(int argc, char **argv)
       break;
       /* ----------------------------------------------------- */
     case 's':                  /* subsampling factor */
-      if (sscanf(optarg, "%d,%d", &subsampling_dx, &subsampling_dy)
-         != 2) {
+      if (sscanf(optarg, "%d,%d", &subsampling_dx, &subsampling_dy) != 2) {
        fprintf(stderr,
                "'-s' sub-sampling argument error !  [-s dx,dy]\n");
        return 1;
@@ -559,19 +651,20 @@ int main(int argc, char **argv)
   /* -------------- */
   if (!infile || !outfile) {
     fprintf(stderr,
-           "usage: image_to_j2k -i image-file -o j2k-file (+ options)\n");
+           "usage: image_to_j2k -i image-file -o j2k/jp2-file (+ options)\n");
     return 1;
   }
 
-  if (cp.disto_alloc & cp.fixed_alloc) {
+  if ((cp.disto_alloc || cp.fixed_alloc || cp.fixed_quality)
+      && (!(cp.disto_alloc ^ cp.fixed_alloc ^ cp.fixed_quality))) {
     fprintf(stderr,
-           "Error: option -r and -q can not be used together !!\n");
+           "Error: options -r -q and -f can not be used together !!\n");
     return 1;
-  }
+  }                            // mod fixed_quality
 
   /* if no rate entered, lossless by default */
   if (tcp_init->numlayers == 0) {
-    tcp_init->rates[tcp_init->numlayers] = 1;
+    tcp_init->rates[tcp_init->numlayers] = 0;  //MOD antonin : losslessbug
     tcp_init->numlayers++;
     cp.disto_alloc = 1;
   }
@@ -595,8 +688,8 @@ int main(int argc, char **argv)
   case 0:
     if (Tile_arg) {
       if (!pgxtoimage
-         (infile, &img, cp.tdy, subsampling_dx, subsampling_dy, Dim,
-          cp)) {
+         (infile, &img, cp.tdy, subsampling_dx, subsampling_dy, Dim, cp))
+      {
        fprintf(stderr, "not a pgx file\n");
        return 1;
       }
@@ -657,7 +750,10 @@ int main(int argc, char **argv)
     tcp = &cp.tcps[tileno];
     tcp->numlayers = tcp_init->numlayers;
     for (j = 0; j < tcp->numlayers; j++) {
-      tcp->rates[j] = tcp_init->rates[j];
+      if (cp.fixed_quality)    // add fixed_quality
+       tcp->distoratio[j] = tcp_init->distoratio[j];
+      else
+       tcp->rates[j] = tcp_init->rates[j];
     }
     tcp->csty = CSty;
     tcp->prg = Prog_order;
@@ -730,7 +826,7 @@ int main(int argc, char **argv)
          }
          p++;
          /*printf("\nsize precinct pour level %d : %d,%d\n", j,
-                tccp->prcw[j], tccp->prch[j]);*/
+            tccp->prcw[j], tccp->prch[j]); */
        }
       } else {
        for (j = 0; j < tccp->numresolutions; j++) {
@@ -742,10 +838,78 @@ int main(int argc, char **argv)
     }
   }
 
-  len = j2k_encode(&img, &cp, outfile, cp.tdx * cp.tdy * 2, index);
-  if (len == 0) {
-    fprintf(stderr, "failed to encode image\n");
-    return 1;
+
+
+  if (cp.JPEG2000_format == 0) {       /* J2K format output */
+    if (cp.intermed_file == 1) {       /* After the encoding of each tile, j2k_encode 
+                                          stores the data in the file */
+      len = j2k_encode(&img, &cp, outfile, cp.tdx * cp.tdy * 2, index);
+      if (len == 0) {
+       fprintf(stderr, "failed to encode image\n");
+       return 1;
+      }
+    } else {
+      j2k_codestream = (char *) malloc(cp.tdx * cp.tdy * cp.tw * cp.th * 2);
+      /* Allocate memory for all tiles */
+      cio_init(j2k_codestream, cp.tdx * cp.tdy * cp.tw * cp.th * 2);
+      len =
+       j2k_encode(&img, &cp, j2k_codestream,
+                  cp.tdx * cp.tdy * cp.tw * cp.th * 2, index);
+      if (len == 0) {
+       fprintf(stderr, "failed to encode image\n");
+       return 1;
+      }
+      f = fopen(outfile, "wb");
+      if (!f) {
+       fprintf(stderr, "failed to open %s for writing\n", outfile);
+       return 1;
+      }
+      fwrite(j2k_codestream, 1, len, f);
+      free(j2k_codestream);
+      fclose(f);
+    }
+  } else {                     /* JP2 format output */
+
+    jp2_struct_t *jp2_struct;
+    jp2_struct = (jp2_struct_t *) malloc(sizeof(jp2_struct_t));
+    jp2_struct->image = &img;
+
+    /* Initialising the standard JP2 box content */
+    /* If you wish to modify those boxes, you have to modify 
+    the jp2_struct content */
+    if (jp2_init_stdjp2(jp2_struct, &img)) {
+      fprintf(stderr, "Error with jp2 initialization");
+      return 1;
+    };
+
+    if (cp.intermed_file == 1) {
+      /*For the moment, JP2 format does not use intermediary 
+      files for each tile */
+      cp.intermed_file = 0;
+    }
+    j2k_codestream = (char *) malloc(cp.tdx * cp.tdy * cp.tw * cp.th * 2);
+    jp2_codestream = (char *) malloc(cp.tdx * cp.tdy * cp.tw * cp.th * 2);
+
+    cio_init(j2k_codestream, cp.tdx * cp.tdy * cp.tw * cp.th * 2);
+    len = j2k_encode(&img, &cp, j2k_codestream,
+      cp.tdx * cp.tdy * cp.tw * cp.th * 2, index);
+    if (len == 0) {
+      fprintf(stderr, "failed to encode image\n");
+      return 1;
+    }
+    jp2_struct->j2k_codestream_len = len;
+
+    cio_init(jp2_codestream, cp.tdx * cp.tdy * cp.tw * cp.th * 2);
+    len = jp2_wrap_j2k(jp2_struct, j2k_codestream, jp2_codestream);
+    f = fopen(outfile, "wb");
+    if (!f) {
+      fprintf(stderr, "failed to open %s for writing\n", outfile);
+      return 1;
+    }
+    fwrite(jp2_codestream, 1, len, f);
+    free(jp2_codestream);
+    free(j2k_codestream);
+    fclose(f);
   }
 
   /* Remove the temporary files */
@@ -769,5 +933,28 @@ int main(int argc, char **argv)
     }
   }
 
+  /* Free memory */
+  free(img.comps);
+  free(cp_init.tcps);
+  if (tcp_init->numlayers > 9)
+    free(cp.matrice);
+  for (tileno = 0; tileno < cp.tw * cp.th; tileno++)
+    free(cp.tcps[tileno].tccps);
+  free(cp.tcps);
+
+
+
+
+
+  //MEMORY LEAK
+
+  #ifdef _DEBUG
+
+    _CrtDumpMemoryLeaks();
+
+  #endif
+
+  //MEM
+
   return 0;
 }