Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
  3.  * Copyright (c) 2002-2007, Professor Benoit Macq
  4.  * Copyright (c) 2003-2007, Francois-Olivier Devaux
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  *
  16.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
  17.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  20.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26.  * POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #include "openjpeg.h"
  34. #include "../libopenjpeg/j2k.h"
  35. #include "../libopenjpeg/jp2.h"
  36. #include "../libopenjpeg/cio.h"
  37. #include "mj2.h"
  38.  
  39. static int int_ceildiv(int a, int b) {
  40.         return (a + b - 1) / b;
  41. }
  42.  
  43. /**
  44. Size of memory first allocated for MOOV box
  45. */
  46. #define TEMP_BUF 10000
  47.  
  48.  
  49. /* -------------------------------------------------------------------------- */
  50.  
  51. /**
  52. sample error callback expecting a FILE* client object
  53. */
  54. void error_callback(const char *msg, void *client_data) {
  55.         FILE *stream = (FILE*)client_data;
  56.         fprintf(stream, "[ERROR] %s", msg);
  57. }
  58. /**
  59. sample warning callback expecting a FILE* client object
  60. */
  61. void warning_callback(const char *msg, void *client_data) {
  62.         FILE *stream = (FILE*)client_data;
  63.         fprintf(stream, "[WARNING] %s", msg);
  64. }
  65. /**
  66. sample debug callback expecting a FILE* client object
  67. */
  68. void info_callback(const char *msg, void *client_data) {
  69.         FILE *stream = (FILE*)client_data;
  70.         fprintf(stream, "[INFO] %s", msg);
  71. }
  72.  
  73. /* -------------------------------------------------------------------------- */
  74.  
  75.  
  76.  
  77. static void read_siz_marker(FILE *file, opj_image_t *image)
  78. {
  79.   int len,i;
  80.   char buf, buf2[2];
  81.   unsigned char *siz_buffer;
  82.         opj_cio_t *cio;
  83.  
  84.   fseek(file, 0, SEEK_SET);
  85.   do {
  86.     fread(&buf,1,1, file);
  87.     if (buf==(char)0xff)
  88.       fread(&buf,1,1, file);
  89.   }
  90.   while (!(buf==(char)0x51));
  91.  
  92.   fread(buf2,2,1,file);         /* Lsiz                */
  93.   len = ((buf2[0])<<8) + buf2[1];
  94.  
  95.   siz_buffer = (unsigned char*) malloc(len * sizeof(unsigned char));
  96.   fread(siz_buffer,len, 1, file);
  97.         cio = opj_cio_open(NULL, siz_buffer, len);
  98.  
  99.   cio_read(cio, 2);                     /* Rsiz (capabilities) */
  100.   image->x1 = cio_read(cio, 4); /* Xsiz                */
  101.   image->y1 = cio_read(cio, 4); /* Ysiz                */
  102.   image->x0 = cio_read(cio, 4); /* X0siz               */
  103.   image->y0 = cio_read(cio, 4); /* Y0siz               */
  104.   cio_skip(cio, 16);                    /* XTsiz, YTsiz, XT0siz, YT0siz        */
  105.  
  106.   image->numcomps = cio_read(cio,2);    /* Csiz                */
  107.   image->comps =
  108.     (opj_image_comp_t *) malloc(image->numcomps * sizeof(opj_image_comp_t));
  109.        
  110.   for (i = 0; i < image->numcomps; i++) {
  111.     int tmp;
  112.     tmp = cio_read(cio,1);              /* Ssiz_i          */
  113.     image->comps[i].prec = (tmp & 0x7f) + 1;
  114.     image->comps[i].sgnd = tmp >> 7;
  115.     image->comps[i].dx = cio_read(cio,1);       /* XRsiz_i         */
  116.     image->comps[i].dy = cio_read(cio,1);       /* YRsiz_i         */
  117.     image->comps[i].resno_decoded = 0;  /* number of resolution decoded */
  118.     image->comps[i].factor = 0; /* reducing factor by component */
  119.   }
  120.   fseek(file, 0, SEEK_SET);
  121.         opj_cio_close(cio);
  122.   free(siz_buffer);
  123. }
  124.  
  125. static void setparams(opj_mj2_t *movie, opj_image_t *image) {
  126.   int i, depth_0, depth, sign;
  127.  
  128.   movie->tk[0].sample_rate = 25;
  129.   movie->tk[0].w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
  130.   movie->tk[0].h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
  131.   mj2_init_stdmovie(movie);
  132.  
  133.   movie->tk[0].depth = image->comps[0].prec;
  134.        
  135.   if (image->numcomps==3) {
  136.     if ((image->comps[0].dx == 1)
  137.         && (image->comps[1].dx == 1)
  138.         && (image->comps[2].dx == 1))
  139.       movie->tk[0].CbCr_subsampling_dx = 1;
  140.     else
  141.         if ((image->comps[0].dx == 1)
  142.         && (image->comps[1].dx == 2)
  143.         && (image->comps[2].dx == 2))
  144.       movie->tk[0].CbCr_subsampling_dx = 2;
  145.     else
  146.       fprintf(stderr,"Image component sizes are incoherent\n");
  147.    
  148.     if ((image->comps[0].dy == 1)
  149.         && (image->comps[1].dy == 1)
  150.         && (image->comps[2].dy == 1))
  151.       movie->tk[0].CbCr_subsampling_dy = 1;
  152.     else
  153.         if ((image->comps[0].dy == 1)
  154.         && (image->comps[1].dy == 2)
  155.         && (image->comps[2].dy == 2))
  156.       movie->tk[0].CbCr_subsampling_dy = 2;
  157.     else
  158.       fprintf(stderr,"Image component sizes are incoherent\n");
  159.   }
  160.  
  161.   movie->tk[0].sample_rate = 25;
  162.  
  163.   movie->tk[0].jp2_struct.numcomps = image->numcomps;   // NC  
  164.        
  165.         /* Init Standard jp2 structure */
  166.        
  167.         movie->tk[0].jp2_struct.comps =
  168.     (opj_jp2_comps_t *) malloc(movie->tk[0].jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
  169.   movie->tk[0].jp2_struct.precedence = 0;   /* PRECEDENCE*/
  170.   movie->tk[0].jp2_struct.approx = 0;   /* APPROX*/
  171.   movie->tk[0].jp2_struct.brand = JP2_JP2;      /* BR         */
  172.   movie->tk[0].jp2_struct.minversion = 0;       /* MinV       */
  173.   movie->tk[0].jp2_struct.numcl = 1;
  174.   movie->tk[0].jp2_struct.cl = (unsigned int *) malloc(movie->tk[0].jp2_struct.numcl * sizeof(int));
  175.   movie->tk[0].jp2_struct.cl[0] = JP2_JP2;      /* CL0 : JP2  */
  176.   movie->tk[0].jp2_struct.C = 7;      /* C : Always 7*/
  177.   movie->tk[0].jp2_struct.UnkC = 0;      /* UnkC, colorspace specified in colr box*/
  178.   movie->tk[0].jp2_struct.IPR = 0;      /* IPR, no intellectual property*/
  179.   movie->tk[0].jp2_struct.w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
  180.   movie->tk[0].jp2_struct.h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
  181.  
  182.   depth_0 = image->comps[0].prec - 1;
  183.   sign = image->comps[0].sgnd;
  184.   movie->tk[0].jp2_struct.bpc = depth_0 + (sign << 7);
  185.  
  186.   for (i = 1; i < image->numcomps; i++) {
  187.     depth = image->comps[i].prec - 1;
  188.     sign = image->comps[i].sgnd;
  189.     if (depth_0 != depth)
  190.       movie->tk[0].jp2_struct.bpc = 255;
  191.   }
  192.  
  193.   for (i = 0; i < image->numcomps; i++)
  194.     movie->tk[0].jp2_struct.comps[i].bpcc =
  195.     image->comps[i].prec - 1 + (image->comps[i].sgnd << 7);
  196.  
  197.   if ((image->numcomps == 1 || image->numcomps == 3)
  198.     && (movie->tk[0].jp2_struct.bpc != 255))
  199.     movie->tk[0].jp2_struct.meth = 1;
  200.   else
  201.     movie->tk[0].jp2_struct.meth = 2;
  202.        
  203.     if (image->numcomps == 1)
  204.      movie->tk[0].jp2_struct.enumcs = 17;  // Grayscale
  205.  
  206.     else  
  207.         if ((image->comps[0].dx == 1)
  208.         && (image->comps[1].dx == 1)
  209.         && (image->comps[2].dx == 1)
  210.     && (image->comps[0].dy == 1)
  211.         && (image->comps[1].dy == 1)
  212.         && (image->comps[2].dy == 1))
  213.      movie->tk[0].jp2_struct.enumcs = 16;    // RGB
  214.  
  215.     else  
  216.         if ((image->comps[0].dx == 1)
  217.         && (image->comps[1].dx == 2)
  218.         && (image->comps[2].dx == 2)
  219.     && (image->comps[0].dy == 1)
  220.         && (image->comps[1].dy == 2)
  221.         && (image->comps[2].dy == 2))
  222.      movie->tk[0].jp2_struct.enumcs = 18;  // YUV
  223.  
  224.   else
  225.     movie->tk[0].jp2_struct.enumcs = 0; // Unkown profile */
  226. }
  227.  
  228. int main(int argc, char *argv[]) {
  229.         opj_cinfo_t* cinfo;
  230.         opj_event_mgr_t event_mgr;              /* event manager */  
  231.   unsigned int snum;
  232.   opj_mj2_t *movie;
  233.   mj2_sample_t *sample;
  234.   unsigned char* frame_codestream;
  235.   FILE *mj2file, *j2kfile;
  236.   char j2kfilename[50];
  237.   unsigned char *buf;
  238.   int offset, mdat_initpos;
  239.   opj_image_t img;
  240.         opj_cio_t *cio;
  241.         mj2_cparameters_t parameters;
  242.        
  243.   if (argc != 3) {
  244.     printf("Usage: %s source_location mj2_filename\n",argv[0]);
  245.     printf("Example: %s input/input output.mj2\n",argv[0]);
  246.     return 1;
  247.   }
  248.  
  249.   mj2file = fopen(argv[2], "wb");
  250.  
  251.   if (!mj2file) {
  252.     fprintf(stderr, "failed to open %s for writing\n", argv[2]);
  253.     return 1;
  254.   }
  255.  
  256.         /*
  257.         configure the event callbacks (not required)
  258.         setting of each callback is optionnal
  259.         */
  260.         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
  261.         event_mgr.error_handler = error_callback;
  262.         event_mgr.warning_handler = warning_callback;
  263.         event_mgr.info_handler = info_callback;
  264.  
  265.         /* get a MJ2 decompressor handle */
  266.         cinfo = mj2_create_compress();
  267.  
  268.         /* catch events using our callbacks and give a local context */
  269.         opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);  
  270.        
  271.         /* setup the decoder encoding parameters using user parameters */
  272.         movie = (opj_mj2_t*) cinfo->mj2_handle;
  273.         mj2_setup_encoder((opj_mj2_t*)cinfo->mj2_handle, &parameters);
  274.  
  275.  
  276.         /* Writing JP, FTYP and MDAT boxes
  277.         Assuming that the JP and FTYP boxes won't be longer than 300 bytes */
  278.        
  279.   buf = (unsigned char*) malloc (300 * sizeof(unsigned char));
  280.   cio = opj_cio_open(movie->cinfo, buf, 300);
  281.   mj2_write_jp(cio);
  282.   mj2_write_ftyp(movie, cio);
  283.   mdat_initpos = cio_tell(cio);
  284.   cio_skip(cio, 4);
  285.   cio_write(cio,MJ2_MDAT, 4);  
  286.   fwrite(buf,cio_tell(cio),1,mj2file);
  287.   free(buf);
  288.        
  289.   // Insert each j2k codestream in a JP2C box  
  290.   snum=0;
  291.   offset = 0;  
  292.   while(1)
  293.   {
  294.     sample = &movie->tk[0].sample[snum];
  295.     sprintf(j2kfilename,"%s_%05d.j2k",argv[1],snum);
  296.     j2kfile = fopen(j2kfilename, "rb");
  297.     if (!j2kfile) {
  298.       if (snum==0) {  // Could not open a single codestream
  299.                                 fprintf(stderr, "failed to open %s for reading\n",j2kfilename);
  300.                                 return 1;
  301.       }
  302.       else {          // Tried to open a inexistant codestream
  303.                                 fprintf(stdout,"%d frames are being added to the MJ2 file\n",snum);
  304.                                 break;
  305.       }
  306.     }
  307.  
  308.     // Calculating offset for samples and chunks
  309.     offset += cio_tell(cio);    
  310.     sample->offset = offset;
  311.     movie->tk[0].chunk[snum].offset = offset;  // There will be one sample per chunk
  312.    
  313.     // Calculating sample size
  314.     fseek(j2kfile,0,SEEK_END); 
  315.     sample->sample_size = ftell(j2kfile) + 8; // Sample size is codestream + JP2C box header
  316.     fseek(j2kfile,0,SEEK_SET);
  317.    
  318.     // Reading siz marker of j2k image for the first codestream
  319.     if (snum==0)             
  320.       read_siz_marker(j2kfile, &img);
  321.    
  322.     // Writing JP2C box header                     
  323.     frame_codestream = (unsigned char*) malloc (sample->sample_size+8);
  324.                 cio = opj_cio_open(movie->cinfo, frame_codestream, sample->sample_size);    
  325.     cio_write(cio,sample->sample_size, 4);  // Sample size
  326.     cio_write(cio,JP2_JP2C, 4); // JP2C
  327.    
  328.     // Writing codestream from J2K file to MJ2 file
  329.     fread(frame_codestream+8,sample->sample_size-8,1,j2kfile);
  330.     fwrite(frame_codestream,sample->sample_size,1,mj2file);
  331.     cio_skip(cio, sample->sample_size-8);
  332.    
  333.     // Ending loop
  334.     fclose(j2kfile);
  335.     snum++;
  336.     movie->tk[0].sample = (mj2_sample_t*)
  337.                 realloc(movie->tk[0].sample, (snum+1) * sizeof(mj2_sample_t));
  338.     movie->tk[0].chunk = (mj2_chunk_t*)
  339.                 realloc(movie->tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t));
  340.     free(frame_codestream);
  341.   }
  342.  
  343.   // Writing the MDAT box length in header
  344.   offset += cio_tell(cio);
  345.   buf = (unsigned char*) malloc (4 * sizeof(unsigned char));
  346.         cio = opj_cio_open(movie->cinfo, buf, 4);
  347.   cio_write(cio,offset-mdat_initpos,4);
  348.   fseek(mj2file,(long)mdat_initpos,SEEK_SET);
  349.   fwrite(buf,4,1,mj2file);
  350.   fseek(mj2file,0,SEEK_END);
  351.   free(buf);
  352.        
  353.   // Setting movie parameters
  354.   movie->tk[0].num_samples=snum;
  355.   movie->tk[0].num_chunks=snum;
  356.   setparams(movie, &img);
  357.        
  358.   // Writing MOOV box
  359.         buf = (unsigned char*) malloc ((TEMP_BUF+snum*20) * sizeof(unsigned char));
  360.         cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+snum*20));
  361.         mj2_write_moov(movie, cio);
  362.   fwrite(buf,cio_tell(cio),1,mj2file);
  363.        
  364.   // Ending program
  365.   fclose(mj2file);
  366.   free(img.comps);
  367.   opj_cio_close(cio);
  368.   mj2_destroy_compress(movie);
  369.        
  370.   return 0;
  371. }
  372.