X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=mj2%2Fwrap_j2k_in_mj2.c;h=7615cfde73c3ccf59387fef0ece52cce042e6e22;hb=b5ff4ffedcf5a944723631f7e680c8f5a45ae34f;hp=e777220bf8f87bbd006a069f6ecc52412a28bcb1;hpb=0130af0ff4239e236791c61060309fead6dea260;p=openjpeg.git diff --git a/mj2/wrap_j2k_in_mj2.c b/mj2/wrap_j2k_in_mj2.c index e777220b..7615cfde 100644 --- a/mj2/wrap_j2k_in_mj2.c +++ b/mj2/wrap_j2k_in_mj2.c @@ -1,33 +1,85 @@ +/* + * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2007, Professor Benoit Macq + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #include -#include -#include +#include #include +#include "openjpeg.h" +#include "j2k.h" +#include "jp2.h" +#include "cio.h" #include "mj2.h" -#include -#include -#include -#define MJ2_MJ2 0x6d6a7032 -#define MJ2_MJ2S 0x6d6a3273 -#define JP2_JP2C 0x6a703263 -#define MJ2_MDAT 0x6d646174 +static int int_ceildiv(int a, int b) { + return (a + b - 1) / b; +} + +/** +Size of memory first allocated for MOOV box +*/ +#define TEMP_BUF 10000 + + +/* -------------------------------------------------------------------------- */ + +/** +sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[ERROR] %s", msg); +} +/** +sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[WARNING] %s", msg); +} +/** +sample debug callback expecting a FILE* client object +*/ +void info_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[INFO] %s", msg); +} -//MEMORY LEAK -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC -#include // Must be included first -#include -#endif -//MEM +/* -------------------------------------------------------------------------- */ -jmp_buf j2k_error; -void j2k_read_siz_marker(FILE *file, j2k_image_t *j2k_img) + +static void read_siz_marker(FILE *file, opj_image_t *image) { int len,i; char buf, buf2[2]; - char *siz_buffer; + unsigned char *siz_buffer; + opj_cio_t *cio; fseek(file, 0, SEEK_SET); do { @@ -40,55 +92,67 @@ void j2k_read_siz_marker(FILE *file, j2k_image_t *j2k_img) fread(buf2,2,1,file); /* Lsiz */ len = ((buf2[0])<<8) + buf2[1]; - siz_buffer = (char*) malloc(len * sizeof(char)); + siz_buffer = (unsigned char*) malloc(len * sizeof(unsigned char)); fread(siz_buffer,len, 1, file); - cio_init(siz_buffer,len); + cio = opj_cio_open(NULL, siz_buffer, len); - cio_read(2); /* Rsiz (capabilities) */ - j2k_img->x1 = cio_read(4); /* Xsiz */ - j2k_img->y1 = cio_read(4); /* Ysiz */ - j2k_img->x0 = cio_read(4); /* X0siz */ - j2k_img->y0 = cio_read(4); /* Y0siz */ - cio_skip(16); /* XTsiz, YTsiz, XT0siz, YT0siz */ + cio_read(cio, 2); /* Rsiz (capabilities) */ + image->x1 = cio_read(cio, 4); /* Xsiz */ + image->y1 = cio_read(cio, 4); /* Ysiz */ + image->x0 = cio_read(cio, 4); /* X0siz */ + image->y0 = cio_read(cio, 4); /* Y0siz */ + cio_skip(cio, 16); /* XTsiz, YTsiz, XT0siz, YT0siz */ - j2k_img->numcomps = cio_read(2); /* Csiz */ - j2k_img->comps = - (j2k_comp_t *) malloc(j2k_img->numcomps * sizeof(j2k_comp_t)); - for (i = 0; i < j2k_img->numcomps; i++) { + image->numcomps = cio_read(cio,2); /* Csiz */ + image->comps = + (opj_image_comp_t *) malloc(image->numcomps * sizeof(opj_image_comp_t)); + + for (i = 0; i < image->numcomps; i++) { int tmp; - tmp = cio_read(1); /* Ssiz_i */ - j2k_img->comps[i].prec = (tmp & 0x7f) + 1; - j2k_img->comps[i].sgnd = tmp >> 7; - j2k_img->comps[i].dx = cio_read(1); /* XRsiz_i */ - j2k_img->comps[i].dy = cio_read(1); /* YRsiz_i */ - j2k_img->comps[i].resno_decoded = 0; /* number of resolution decoded */ - j2k_img->comps[i].factor = 0; /* reducing factor by component */ + tmp = cio_read(cio,1); /* Ssiz_i */ + image->comps[i].prec = (tmp & 0x7f) + 1; + image->comps[i].sgnd = tmp >> 7; + image->comps[i].dx = cio_read(cio,1); /* XRsiz_i */ + image->comps[i].dy = cio_read(cio,1); /* YRsiz_i */ + image->comps[i].resno_decoded = 0; /* number of resolution decoded */ + image->comps[i].factor = 0; /* reducing factor by component */ } - free(siz_buffer); fseek(file, 0, SEEK_SET); + opj_cio_close(cio); + free(siz_buffer); } -void setparams(mj2_movie_t *movie, j2k_image_t *img) { +static void setparams(opj_mj2_t *movie, opj_image_t *image) { int i, depth_0, depth, sign; movie->tk[0].sample_rate = 25; - movie->tk[0].w = int_ceildiv(img->x1 - img->x0, img->comps[0].dx); - movie->tk[0].h = int_ceildiv(img->y1 - img->y0, img->comps[0].dy); + movie->tk[0].w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx); + movie->tk[0].h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy); mj2_init_stdmovie(movie); - movie->tk[0].depth = img->comps[0].prec; - - if (img->numcomps==3) { - if ((img->comps[0].dx == 1) && (img->comps[1].dx == 1) && (img->comps[1].dx == 1)) + movie->tk[0].depth = image->comps[0].prec; + + if (image->numcomps==3) { + if ((image->comps[0].dx == 1) + && (image->comps[1].dx == 1) + && (image->comps[2].dx == 1)) movie->tk[0].CbCr_subsampling_dx = 1; - else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && (img->comps[1].dx == 2)) + else + if ((image->comps[0].dx == 1) + && (image->comps[1].dx == 2) + && (image->comps[2].dx == 2)) movie->tk[0].CbCr_subsampling_dx = 2; else fprintf(stderr,"Image component sizes are incoherent\n"); - if ((img->comps[0].dy == 1) && (img->comps[1].dy == 1) && (img->comps[1].dy == 1)) + if ((image->comps[0].dy == 1) + && (image->comps[1].dy == 1) + && (image->comps[2].dy == 1)) movie->tk[0].CbCr_subsampling_dy = 1; - else if ((img->comps[0].dy == 1) && (img->comps[1].dy == 2) && (img->comps[1].dy == 2)) + else + if ((image->comps[0].dy == 1) + && (image->comps[1].dy == 2) + && (image->comps[2].dy == 2)) movie->tk[0].CbCr_subsampling_dy = 2; else fprintf(stderr,"Image component sizes are incoherent\n"); @@ -96,61 +160,86 @@ void setparams(mj2_movie_t *movie, j2k_image_t *img) { movie->tk[0].sample_rate = 25; - movie->tk[0].jp2_struct.numcomps = img->numcomps; // NC - jp2_init_stdjp2(&movie->tk[0].jp2_struct); + movie->tk[0].jp2_struct.numcomps = image->numcomps; // NC + + /* Init Standard jp2 structure */ + + movie->tk[0].jp2_struct.comps = + (opj_jp2_comps_t *) malloc(movie->tk[0].jp2_struct.numcomps * sizeof(opj_jp2_comps_t)); + movie->tk[0].jp2_struct.precedence = 0; /* PRECEDENCE*/ + movie->tk[0].jp2_struct.approx = 0; /* APPROX*/ + movie->tk[0].jp2_struct.brand = JP2_JP2; /* BR */ + movie->tk[0].jp2_struct.minversion = 0; /* MinV */ + movie->tk[0].jp2_struct.numcl = 1; + movie->tk[0].jp2_struct.cl = (unsigned int *) malloc(movie->tk[0].jp2_struct.numcl * sizeof(int)); + movie->tk[0].jp2_struct.cl[0] = JP2_JP2; /* CL0 : JP2 */ + movie->tk[0].jp2_struct.C = 7; /* C : Always 7*/ + movie->tk[0].jp2_struct.UnkC = 0; /* UnkC, colorspace specified in colr box*/ + movie->tk[0].jp2_struct.IPR = 0; /* IPR, no intellectual property*/ + movie->tk[0].jp2_struct.w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx); + movie->tk[0].jp2_struct.h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy); - movie->tk[0].jp2_struct.w = int_ceildiv(img->x1 - img->x0, img->comps[0].dx); - movie->tk[0].jp2_struct.h = int_ceildiv(img->y1 - img->y0, img->comps[0].dy); - - depth_0 = img->comps[0].prec - 1; - sign = img->comps[0].sgnd; + depth_0 = image->comps[0].prec - 1; + sign = image->comps[0].sgnd; movie->tk[0].jp2_struct.bpc = depth_0 + (sign << 7); - for (i = 1; i < img->numcomps; i++) { - depth = img->comps[i].prec - 1; - sign = img->comps[i].sgnd; + for (i = 1; i < image->numcomps; i++) { + depth = image->comps[i].prec - 1; + sign = image->comps[i].sgnd; if (depth_0 != depth) movie->tk[0].jp2_struct.bpc = 255; } - for (i = 0; i < img->numcomps; i++) + for (i = 0; i < image->numcomps; i++) movie->tk[0].jp2_struct.comps[i].bpcc = - img->comps[i].prec - 1 + (img->comps[i].sgnd << 7); + image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); - if ((img->numcomps == 1 || img->numcomps == 3) + if ((image->numcomps == 1 || image->numcomps == 3) && (movie->tk[0].jp2_struct.bpc != 255)) movie->tk[0].jp2_struct.meth = 1; else movie->tk[0].jp2_struct.meth = 2; - - if (img->numcomps == 1) - movie->tk[0].jp2_struct.enumcs = 17; // Grayscale + + if (image->numcomps == 1) + movie->tk[0].jp2_struct.enumcs = 17; // Grayscale - else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 1) && (img->comps[1].dx == 1) && - (img->comps[0].dy == 1) && (img->comps[1].dy == 1) && (img->comps[1].dy == 1)) - movie->tk[0].jp2_struct.enumcs = 16; // RGB + else + if ((image->comps[0].dx == 1) + && (image->comps[1].dx == 1) + && (image->comps[2].dx == 1) + && (image->comps[0].dy == 1) + && (image->comps[1].dy == 1) + && (image->comps[2].dy == 1)) + movie->tk[0].jp2_struct.enumcs = 16; // RGB - else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && (img->comps[1].dx == 2) && - (img->comps[0].dy == 1) && (img->comps[1].dy == 2) && (img->comps[1].dy == 2)) - movie->tk[0].jp2_struct.enumcs = 18; // YUV + else + if ((image->comps[0].dx == 1) + && (image->comps[1].dx == 2) + && (image->comps[2].dx == 2) + && (image->comps[0].dy == 1) + && (image->comps[1].dy == 2) + && (image->comps[2].dy == 2)) + movie->tk[0].jp2_struct.enumcs = 18; // YUV else movie->tk[0].jp2_struct.enumcs = 0; // Unkown profile */ } int main(int argc, char *argv[]) { - + opj_cinfo_t* cinfo; + opj_event_mgr_t event_mgr; /* event manager */ unsigned int snum; - mj2_movie_t movie; + opj_mj2_t *movie; mj2_sample_t *sample; unsigned char* frame_codestream; FILE *mj2file, *j2kfile; char j2kfilename[50]; - char *buf; + unsigned char *buf; int offset, mdat_initpos; - j2k_image_t img; - int i; - + opj_image_t img; + opj_cio_t *cio; + mj2_cparameters_t parameters; + if (argc != 3) { printf("Bad syntax: Usage: MJ2_Wrapper source_location mj2_filename\n"); printf("Example: MJ2_Wrapper input/input output.mj2\n"); @@ -163,57 +252,63 @@ int main(int argc, char *argv[]) { fprintf(stderr, "failed to open %s for writing\n", argv[2]); return 1; } + + /* + configure the event callbacks (not required) + setting of each callback is optionnal + */ + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + /* get a MJ2 decompressor handle */ + cinfo = mj2_create_compress(); + + /* catch events using our callbacks and give a local context */ + opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); + + /* setup the decoder encoding parameters using user parameters */ + movie = (opj_mj2_t*) cinfo->mj2_handle; + mj2_setup_encoder((opj_mj2_t*)cinfo->mj2_handle, ¶meters); + - // Initialing the movie (parameters used in the JP and FTYP boxes - movie.num_htk = 0; // No hint tracks - movie.num_stk = 0; // No sound tracks - movie.num_vtk = 1; // One video track - movie.tk = (mj2_tk_t*) malloc (sizeof(mj2_tk_t)); //Memory allocation for the video track - movie.tk[0].sample = (mj2_sample_t*) malloc (sizeof(mj2_sample_t)); - movie.tk[0].chunk = (mj2_chunk_t *) malloc(sizeof(mj2_chunk_t)); - movie.tk[0].track_type = 0; // Video track - movie.tk[0].track_ID = 1; // Track ID = 1 - movie.brand = MJ2_MJ2; // One brand: MJ2 - movie.num_cl = 2; // Two compatible brands: MJ2 and MJ2S - movie.cl = (unsigned int *) malloc(movie.num_cl * sizeof(unsigned int)); - movie.cl[0] = MJ2_MJ2; - movie.cl[1] = MJ2_MJ2S; - movie.minversion = 0; // Minimum version: 0 - - // Writing JP, FTYP and MDAT boxes - buf = (char*) malloc (300 * sizeof(char)); // Assuming that the JP and FTYP - // boxes won't be longer than 300 bytes - cio_init(buf , 300); - mj2_write_jp(); - mj2_write_ftyp(&movie); - mdat_initpos = cio_tell(); - cio_skip(4); - cio_write(MJ2_MDAT, 4); - fwrite(buf,cio_tell(),1,mj2file); + /* Writing JP, FTYP and MDAT boxes + Assuming that the JP and FTYP boxes won't be longer than 300 bytes */ + + buf = (unsigned char*) malloc (300 * sizeof(unsigned char)); + cio = opj_cio_open(movie->cinfo, buf, 300); + mj2_write_jp(cio); + mj2_write_ftyp(movie, cio); + mdat_initpos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio,MJ2_MDAT, 4); + fwrite(buf,cio_tell(cio),1,mj2file); free(buf); - + // Insert each j2k codestream in a JP2C box snum=0; offset = 0; while(1) { - sample = &movie.tk[0].sample[snum]; - sprintf(j2kfilename,"%s_%d.j2k",argv[1],snum); + sample = &movie->tk[0].sample[snum]; + sprintf(j2kfilename,"%s_%05d.j2k",argv[1],snum); j2kfile = fopen(j2kfilename, "rb"); if (!j2kfile) { if (snum==0) { // Could not open a single codestream - fprintf(stderr, "failed to open %s for reading\n",j2kfilename); - return 1; + fprintf(stderr, "failed to open %s for reading\n",j2kfilename); + return 1; } else { // Tried to open a inexistant codestream - fprintf(stdout,"%d frames created\n",snum); - break; + fprintf(stdout,"%d frames are being added to the MJ2 file\n",snum); + break; } } + // Calculating offset for samples and chunks - offset += cio_tell(); + offset += cio_tell(cio); sample->offset = offset; - movie.tk[0].chunk[snum].offset = offset; // There will be one sample per chunk + movie->tk[0].chunk[snum].offset = offset; // There will be one sample per chunk // Calculating sample size fseek(j2kfile,0,SEEK_END); @@ -222,66 +317,55 @@ int main(int argc, char *argv[]) { // Reading siz marker of j2k image for the first codestream if (snum==0) - j2k_read_siz_marker(j2kfile, &img); + read_siz_marker(j2kfile, &img); // Writing JP2C box header frame_codestream = (unsigned char*) malloc (sample->sample_size+8); - cio_init(frame_codestream, sample->sample_size); - cio_write(sample->sample_size, 4); // Sample size - cio_write(JP2_JP2C, 4); // JP2C + cio = opj_cio_open(movie->cinfo, frame_codestream, sample->sample_size); + cio_write(cio,sample->sample_size, 4); // Sample size + cio_write(cio,JP2_JP2C, 4); // JP2C // Writing codestream from J2K file to MJ2 file fread(frame_codestream+8,sample->sample_size-8,1,j2kfile); fwrite(frame_codestream,sample->sample_size,1,mj2file); - cio_skip(sample->sample_size-8); + cio_skip(cio, sample->sample_size-8); // Ending loop fclose(j2kfile); snum++; - movie.tk[0].sample = realloc(movie.tk[0].sample, (snum+1) * sizeof(mj2_sample_t)); - movie.tk[0].chunk = realloc(movie.tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t)); + movie->tk[0].sample = (mj2_sample_t*) + realloc(movie->tk[0].sample, (snum+1) * sizeof(mj2_sample_t)); + movie->tk[0].chunk = (mj2_chunk_t*) + realloc(movie->tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t)); free(frame_codestream); } // Writing the MDAT box length in header - offset += cio_tell(); - buf = (char*) malloc (4 * sizeof(char)); - cio_init(buf,4); - cio_write(offset-mdat_initpos,4); // Write MDAT length in MDAT box header + offset += cio_tell(cio); + buf = (unsigned char*) malloc (4 * sizeof(unsigned char)); + cio = opj_cio_open(movie->cinfo, buf, 4); + cio_write(cio,offset-mdat_initpos,4); fseek(mj2file,(long)mdat_initpos,SEEK_SET); fwrite(buf,4,1,mj2file); fseek(mj2file,0,SEEK_END); free(buf); - + // Setting movie parameters - movie.tk[0].num_samples=snum; - movie.tk[0].num_chunks=snum; - setparams(&movie, &img); - + movie->tk[0].num_samples=snum; + movie->tk[0].num_chunks=snum; + setparams(movie, &img); + // Writing MOOV box - i=1; - buf = (char*) malloc (10000 * sizeof(char)); - cio_init(buf , i*10000); - if (setjmp(j2k_error)) { - i++; - buf = realloc(buf,i*10000* sizeof(char)); - cio_init(buf , i*10000); - } - mj2_write_moov(&movie); - fwrite(buf,cio_tell(),1,mj2file); - + buf = (unsigned char*) malloc ((TEMP_BUF+snum*20) * sizeof(unsigned char)); + cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+snum*20)); + mj2_write_moov(movie, cio); + fwrite(buf,cio_tell(cio),1,mj2file); + // Ending program fclose(mj2file); free(img.comps); - free(buf); - mj2_memory_free(&movie); - - - //MEMORY LEAK - #ifdef _DEBUG - _CrtDumpMemoryLeaks(); - #endif - //MEM - + opj_cio_close(cio); + mj2_destroy_compress(movie); + return 0; -} \ No newline at end of file +}