From 097496a9f0a0e2d0c02724aaa7121b82bf9d3a92 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Mon, 23 Apr 2012 13:23:38 +0000 Subject: [PATCH] [1.5] Integrate patch from winfried posted on the mailing list. See here for more info: https://groups.google.com/group/openjpeg/msg/7e30b6e288ad5908 --- applications/mj2/extract_j2k_from_mj2.c | 92 +++++--- applications/mj2/frames_to_mj2.c | 121 +++++++---- applications/mj2/mj2.h | 2 +- applications/mj2/mj2_to_frames.c | 196 ++++++++--------- applications/mj2/wrap_j2k_in_mj2.c | 267 ++++++++++-------------- libopenjpeg/openjpeg.h | 4 + 6 files changed, 358 insertions(+), 324 deletions(-) diff --git a/applications/mj2/extract_j2k_from_mj2.c b/applications/mj2/extract_j2k_from_mj2.c index 9242c4e7..e2e0f489 100644 --- a/applications/mj2/extract_j2k_from_mj2.c +++ b/applications/mj2/extract_j2k_from_mj2.c @@ -61,34 +61,52 @@ void info_callback(const char *msg, void *client_data) { } /* -------------------------------------------------------------------------- */ - +#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a" int main(int argc, char *argv[]) { opj_dinfo_t* dinfo; opj_event_mgr_t event_mgr; /* event manager */ - int tnum; + int tnum, failed; unsigned int snum; opj_mj2_t *movie; mj2_tk_t *track; mj2_sample_t *sample; unsigned char* frame_codestream; - FILE *file, *outfile; - char outfilename[50]; + FILE *mj2file, *outfile; + char *outfilename; mj2_dparameters_t parameters; if (argc != 3) { - printf("Usage: %s mj2filename output_location\n",argv[0]); - printf("Example: %s foreman.mj2 output/foreman\n",argv[0]); + printf("\nUsage: %s mj2filename output_location\n",argv[0]); + printf("Example: %s foreman.mj2 output/foreman\n\n",argv[0]); return 1; } - file = fopen(argv[1], "rb"); + mj2file = fopen(argv[1], "rb"); - if (!file) { + if (!mj2file) { fprintf(stderr, "failed to open %s for reading\n", argv[1]); return 1; } + { + unsigned char buf[28]; + memset(buf, 0, 28); + fread(buf, 1, 24, mj2file); + + if(memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 + && memcmp(buf+20, "\x6d\x6a\x70\x32", 4) == 0) + { + rewind(mj2file); + } + else + { + fclose(mj2file); + fprintf(stderr,"%s:%d: %s\n\tThis file is not an MJ2 file." + "Quitting\n",__FILE__,__LINE__, argv[0]); + return 1; + } + } /* configure the event callbacks (not required) setting of each callback is optionnal @@ -98,9 +116,15 @@ int main(int argc, char *argv[]) { event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; + failed = 1; + outfilename = (char*)malloc(strlen(argv[2]) + 32); + if(outfilename == NULL) goto fin; + /* get a MJ2 decompressor handle */ dinfo = mj2_create_decompress(); + if(dinfo == NULL) goto fin; + /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); @@ -109,42 +133,62 @@ int main(int argc, char *argv[]) { movie = (opj_mj2_t*) dinfo->mj2_handle; mj2_setup_decoder(movie, ¶meters); - if (mj2_read_struct(file, movie)) // Creating the movie structure - return 1; +/* Create the movie structure: */ + if (mj2_read_struct(mj2file, movie)) + goto fin; - // Decode first video track +/* Decode first video track : */ tnum = 0; while (movie->tk[tnum].track_type != 0) tnum ++; track = &movie->tk[tnum]; + if(track->jp2_struct.enumcs != ENUMCS_SRGB + && track->jp2_struct.enumcs != ENUMCS_GRAY) + { + fprintf(stderr,"%s:%d: %s\n" + "\tERROR: this MJ2 file does not contain J2K frames.\n" + "\tPlease try mj2_to_frames for this file.\n", + __FILE__,__LINE__, argv[0]); + goto fin; + } + fprintf(stdout,"Extracting %d frames from file...\n",track->num_samples); for (snum=0; snum < track->num_samples; snum++) { sample = &track->sample[snum]; - frame_codestream = (unsigned char*) malloc (sample->sample_size-8); // Skipping JP2C marker - fseek(file,sample->offset+8,SEEK_SET); - fread(frame_codestream,sample->sample_size-8,1, file); // Assuming that jp and ftyp markers size do + frame_codestream = (unsigned char*) + malloc (sample->sample_size-8); /* Skipping JP2C marker */ + fseek(mj2file,sample->offset+8,SEEK_SET); +/* Assuming that jp and ftyp markers size do: */ + fread(frame_codestream,sample->sample_size-8,1, mj2file); sprintf(outfilename,"%s_%05d.j2k",argv[2],snum); outfile = fopen(outfilename, "wb"); if (!outfile) { fprintf(stderr, "failed to open %s for writing\n",outfilename); - return 1; + goto fin; } fwrite(frame_codestream,sample->sample_size-8,1,outfile); fclose(outfile); free(frame_codestream); - } - fclose(file); + } fprintf(stdout, "%d frames correctly extracted\n", snum); - + failed = 0; + +fin: + fclose(mj2file); + + free(outfilename); + /* free remaining structures */ - if(dinfo) { - mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle); - } - - return 0; -} + if(dinfo) + { + mj2_destroy_decompress(movie); + free(dinfo); + } + + return failed; +}/* main() */ diff --git a/applications/mj2/frames_to_mj2.c b/applications/mj2/frames_to_mj2.c index 10cea009..f14440b0 100644 --- a/applications/mj2/frames_to_mj2.c +++ b/applications/mj2/frames_to_mj2.c @@ -43,10 +43,6 @@ Size of memory first allocated for MOOV box */ #define TEMP_BUF 10000 -#define ENUMCS_GRAY 16 -#define ENUMCS_SRGB 17 -#define ENUMCS_SYCC 18 - /* -------------------------------------------------------------------------- */ /** @@ -238,7 +234,7 @@ int main(int argc, char **argv) opj_cparameters_t *j2k_parameters; /* J2K compression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_cio_t *cio; - int value; + int value, failed; opj_mj2_t *movie; opj_image_t *img; int i, j; @@ -257,13 +253,13 @@ int main(int argc, char **argv) memset(&mj2_parameters, 0, sizeof(mj2_cparameters_t)); /* default value */ /* ------------- */ - mj2_parameters.w = 352; // CIF default value - mj2_parameters.h = 288; // CIF default value - mj2_parameters.CbCr_subsampling_dx = 2; // CIF default value - mj2_parameters.CbCr_subsampling_dy = 2; // CIF default value + mj2_parameters.w = 352; /* CIF default value */ + mj2_parameters.h = 288; /* CIF default value */ + mj2_parameters.CbCr_subsampling_dx = 2; /* CIF default value */ + mj2_parameters.CbCr_subsampling_dy = 2; /* CIF default value */ mj2_parameters.frame_rate = 25; mj2_parameters.prec = 8; /* DEFAULT */ - mj2_parameters.enumcs = ENUMCS_SYCC; /* FIXME: ENUMCS_YUV420 */ + mj2_parameters.enumcs = ENUMCS_SYCC; mj2_parameters.meth = 1; /* enumerated color space */ /* @@ -620,7 +616,7 @@ int main(int argc, char **argv) /* -------------- */ if (!mj2_parameters.cod_format || !mj2_parameters.decod_format) { fprintf(stderr, - "Usage: %s -i yuv-file -o mj2-file (+ options)\n",argv[0]); + "\nUsage: %s -i yuv-file -o mj2-file (+ options)\n\n",argv[0]); return 1; } if(prec < 1 || prec > 16) @@ -682,9 +678,11 @@ int main(int argc, char **argv) fprintf(stderr, "failed to open %s for writing\n", argv[2]); return 1; } - + failed = 1; /* get a MJ2 decompressor handle */ cinfo = mj2_create_compress(); + if(cinfo == NULL) goto fin; + movie = (opj_mj2_t*)cinfo->mj2_handle; /* catch events using our callbacks and give a local context */ @@ -697,7 +695,7 @@ int main(int argc, char **argv) yuv_num_frames(&movie->tk[0],mj2_parameters.infile); if (movie->tk[0].num_samples == 0) { - return 1; + goto fin; } // One sample per chunk @@ -705,19 +703,25 @@ int main(int argc, char **argv) malloc(movie->tk[0].num_samples * sizeof(mj2_chunk_t)); movie->tk[0].sample = (mj2_sample_t*) malloc(movie->tk[0].num_samples * sizeof(mj2_sample_t)); + + if(movie->tk[0].chunk == NULL || movie->tk[0].sample == NULL) + goto fin; if (mj2_init_stdmovie(movie)) { fprintf(stderr, "Error with movie initialization"); - return 1; + goto fin; } // 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)); + if(buf == NULL) goto fin; cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, 300); + if(cio == NULL) goto fin; + mj2_write_jp(cio); mj2_write_ftyp(movie, cio); @@ -729,59 +733,74 @@ int main(int argc, char **argv) fwrite(buf,cio_tell(cio),1,mj2file); offset = cio_tell(cio); + +/* if(cio->openmode == OPJ_STREAM_READ) */ free(buf); opj_cio_close(cio); - free(buf); + buf = NULL; numframes = 0; for(i = 0; i < movie->num_stk + movie->num_htk + movie->num_vtk; i++) { - if(movie->tk[i].track_type != 0) + mj2_tk_t *track; + + track = &movie->tk[i]; + numframes = track->num_samples; + + if(track->track_type != 0) { fprintf(stderr, "Unable to write sound or hint tracks\n"); } else { - mj2_tk_t *tk; int buflen = 0; - tk = &movie->tk[i]; - tk->num_chunks = tk->num_samples; - numframes = tk->num_samples; - tk->depth = prec; + track->num_chunks = track->num_samples; + track->depth = prec; fprintf(stderr, "Video Track number %d\n", i); - img = mj2_image_create(tk, j2k_parameters); + img = mj2_image_create(track, j2k_parameters); + if(img == NULL) goto fin; - buflen = 2 * (tk->w * tk->h * 8); + buflen = 2 * (track->w * track->h * 8); buf = (unsigned char *) malloc(buflen*sizeof(unsigned char)); - + if(buf == NULL) + { + opj_image_destroy(img); + goto fin; + } for(sampleno = 0; sampleno < numframes; sampleno++) { double init_time = opj_clock(); double elapsed_time; - if(yuvtoimage(tk, img, sampleno, j2k_parameters, + if(yuvtoimage(track, img, sampleno, j2k_parameters, mj2_parameters.infile)) { fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno); - return 1; + opj_image_destroy(img); + goto fin; } /* setup the encoder parameters using the current image and user parameters */ opj_setup_encoder(cinfo, j2k_parameters, img); cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, buflen); - + + if(cio == NULL) goto fin; + cio_skip(cio, 4); - cio_write(cio, JP2_JP2C, 4); // JP2C + cio_write(cio, JP2_JP2C, 4); /* encode the image */ bSuccess = opj_encode(cinfo, cio, img, NULL); if (!bSuccess) { + opj_image_destroy(img); +/* if(cio->openmode == OPJ_STREAM_READ) */ free(buf); opj_cio_close(cio); + buf = NULL; fprintf(stderr, "failed to encode image\n"); - return 1; + goto fin; } len = cio_tell(cio) - 8; @@ -789,9 +808,9 @@ int main(int argc, char **argv) cio_write(cio, len+8,4); opj_cio_close(cio); - tk->sample[sampleno].sample_size = len+8; - tk->sample[sampleno].offset = offset; - tk->chunk[sampleno].offset = offset; // There is one sample per chunk + track->sample[sampleno].sample_size = len+8; + track->sample[sampleno].offset = offset; + track->chunk[sampleno].offset = offset; // There is one sample per chunk fwrite(buf, 1, len+8, mj2file); offset += len+8; @@ -801,43 +820,59 @@ int main(int argc, char **argv) total_time += elapsed_time; } /* for(sampleno */ - free(buf); + free(buf); buf = NULL; opj_image_destroy(img); - } + } /* if(track ) */ }/* for(i */ fseek(mj2file, mdat_initpos, SEEK_SET); buf = (unsigned char*) malloc(4*sizeof(unsigned char)); -// Init a cio to write box length variable in a little endian way + if(buf == NULL) goto fin; + +/* Init a cio to write box length variable in a little endian way */ cio = opj_cio_open(NULL, buf, 4); + + if(cio == NULL) goto fin; + cio_write(cio, offset - mdat_initpos, 4); fwrite(buf, 4, 1, mj2file); fseek(mj2file,0,SEEK_END); - free(buf); +/* if(cio->openmode == OPJ_STREAM_READ) */ free(buf); + opj_cio_close(cio); -// Writing MOOV box +/* Writing MOOV box */ buf = (unsigned char*) malloc ((TEMP_BUF+numframes*20) * sizeof(unsigned char)); + + if(buf == NULL) goto fin; + cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+numframes*20)); + + if(cio == NULL) goto fin; + mj2_write_moov(movie, cio); fwrite(buf,cio_tell(cio),1,mj2file); - free(buf); +/* if(cio->openmode == OPJ_STREAM_READ) */ free(buf); + opj_cio_close(cio); fprintf(stdout,"Total encoding time: %.2f s for %d frames (%.1f fps)\n", total_time, numframes, (float)numframes/total_time); + failed = 0; - // Ending program - +fin: fclose(mj2file); /* free remaining compression structures */ + if(cinfo) + { mj2_destroy_compress(movie); free(cinfo); - + } if(j2k_parameters->cp_comment) free(j2k_parameters->cp_comment); if(j2k_parameters->cp_matrice) free(j2k_parameters->cp_matrice); - opj_cio_close(cio); - return 0; + if(failed) remove(mj2_parameters.outfile); + + return failed; } diff --git a/applications/mj2/mj2.h b/applications/mj2/mj2.h index 2e3d0b15..b6b4ae87 100644 --- a/applications/mj2/mj2.h +++ b/applications/mj2/mj2.h @@ -137,7 +137,7 @@ typedef struct mj2_url { URN */ typedef struct mj2_urn { - int name[2]; + int name[4]; int location[4]; } mj2_urn_t; diff --git a/applications/mj2/mj2_to_frames.c b/applications/mj2/mj2_to_frames.c index c5a41602..b807f882 100644 --- a/applications/mj2/mj2_to_frames.c +++ b/applications/mj2/mj2_to_frames.c @@ -69,45 +69,67 @@ void info_callback(const char *msg, void *client_data) { } /* -------------------------------------------------------------------------- */ - +#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a" int main(int argc, char *argv[]) { mj2_dparameters_t mj2_parameters; /* decompression parameters */ opj_dinfo_t* dinfo; opj_event_mgr_t event_mgr; /* event manager */ opj_cio_t *cio = NULL; - unsigned int tnum, snum; + unsigned int tnum, snum, failed; opj_mj2_t *movie; mj2_tk_t *track; mj2_sample_t *sample; unsigned char* frame_codestream; - FILE *file, *outfile; - char outfilename[50]; + FILE *infile, *outfile; opj_image_t *img = NULL; unsigned int max_codstrm_size = 0; double total_time = 0; unsigned int numframes = 0; if (argc != 3) { - printf("Usage: %s inputfile.mj2 outputfile.yuv\n",argv[0]); + printf("\nUsage: %s inputfile.mj2 outputfile.yuv\n\n",argv[0]); return 1; } - file = fopen(argv[1], "rb"); + infile = fopen(argv[1], "rb"); - if (!file) { + if (!infile) { fprintf(stderr, "failed to open %s for reading\n", argv[1]); return 1; } - - // Checking output file - outfile = fopen(argv[2], "w"); - if (!file) { - fprintf(stderr, "failed to open %s for writing\n", argv[2]); - return 1; + { + unsigned char buf[28]; + size_t n; + + memset(buf, 0, 28); + n = fread(buf, 1, 24, infile); + + if(memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 + && memcmp(buf+20, "\x6d\x6a\x70\x32", 4) == 0) + { + rewind(infile); } - fclose(outfile); - + else + { + fclose(infile); + fprintf(stderr,"%s:%d: %s\n\tThis file is not an MJ2 file." + "Quitting\n",__FILE__,__LINE__,argv[0]); + return 1; + } + } +/* Checking output file: */ + outfile = fopen(argv[2], "w"); + + if (!outfile) { + fprintf(stderr, "failed to open %s for writing\n", argv[2]); + fclose(infile); + return 1; + } + fclose(outfile); remove(argv[2]); + + frame_codestream = NULL; + failed = 1; /* configure the event callbacks (not required) setting of each callback is optionnal @@ -119,6 +141,8 @@ int main(int argc, char *argv[]) { /* get a MJ2 decompressor handle */ dinfo = mj2_create_decompress(); + if(dinfo == NULL) goto fin; + movie = (opj_mj2_t*)dinfo->mj2_handle; /* catch events using our callbacks and give a local context */ @@ -130,11 +154,12 @@ int main(int argc, char *argv[]) { /* setup the decoder decoding parameters using user parameters */ mj2_setup_decoder(movie, &mj2_parameters); - - if (mj2_read_struct(file, movie)) // Creating the movie structure - return 1; + +/* Create the movie structure: */ + if (mj2_read_struct(infile, movie)) + goto fin; - // Decode first video track +/* Decode first video track */ for (tnum=0; tnum < (unsigned int)(movie->num_htk + movie->num_stk + movie->num_vtk); tnum++) { if (movie->tk[tnum].track_type == 0) break; @@ -142,24 +167,34 @@ int main(int argc, char *argv[]) { if (movie->tk[tnum].track_type != 0) { printf("Error. Movie does not contain any video track\n"); - return 1; + goto fin; } track = &movie->tk[tnum]; - - // Output info on first video tracl + + if(track->jp2_struct.enumcs != ENUMCS_SYCC) + { + fprintf(stderr,"%s:%d: %s\n" + "\tERROR: this MJ2 file does not contain YUV frames.\n" + "\tPlease try extract_j2k_from_mj2 for this file.\n", + __FILE__,__LINE__,argv[0]); + goto fin; + } +/* Output info on first video track: */ fprintf(stdout,"The first video track contains %d frames.\nWidth: %d, Height: %d \n\n", track->num_samples, track->w, track->h); max_codstrm_size = track->sample[0].sample_size-8; - frame_codestream = (unsigned char*) malloc(max_codstrm_size * sizeof(unsigned char)); + frame_codestream = (unsigned char*) + malloc(max_codstrm_size * sizeof(unsigned char)); + if(frame_codestream == NULL) goto fin; numframes = track->num_samples; for (snum=0; snum < numframes; snum++) { - double init_time = opj_clock(); - double elapsed_time; + double init_time = opj_clock(); + double elapsed_time; sample = &track->sample[snum]; if (sample->sample_size-8 > max_codstrm_size) { @@ -167,85 +202,54 @@ int main(int argc, char *argv[]) { if ((frame_codestream = (unsigned char*) realloc(frame_codestream, max_codstrm_size)) == NULL) { printf("Error reallocation memory\n"); - return 1; + goto fin; }; } - fseek(file,sample->offset+8,SEEK_SET); - fread(frame_codestream, sample->sample_size-8, 1, file); // Assuming that jp and ftyp markers size do + fseek(infile,sample->offset+8,SEEK_SET); +/* Assuming that jp and ftyp markers size do: */ + fread(frame_codestream, sample->sample_size-8, 1, infile); /* open a byte stream */ - cio = opj_cio_open((opj_common_ptr)dinfo, frame_codestream, sample->sample_size-8); + cio = opj_cio_open((opj_common_ptr)dinfo, frame_codestream, sample->sample_size-8); + + if(cio == NULL) goto fin; + + img = opj_decode(dinfo, cio); + + if(img == NULL) goto fin; + +/* Convert frame to YUV: */ + if (!imagetoyuv(img, argv[2])) + goto fin; + + opj_cio_close(cio); + + opj_image_destroy(img); + + elapsed_time = opj_clock()-init_time; + fprintf(stderr, "Frame number %d/%d decoded in %.2f mseconds\n", + snum + 1, numframes, elapsed_time*1000); + total_time += elapsed_time; + + }/* for (snum */ + + fprintf(stdout, "%d frame(s) correctly decompressed\n", snum); + fprintf(stdout,"Total decoding time: %.2f seconds (%.1f fps)\n", + total_time, (float)numframes/total_time); - img = opj_decode(dinfo, cio); // Decode J2K to image + failed = 0; -#ifdef WANT_SYCC_TO_RGB - if(img->color_space == CLRSPC_SYCC) - { - color_sycc_to_rgb(img); - } -#endif +fin: + fclose(infile); - if(img->icc_profile_buf) - { -#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) - color_apply_icc_profile(img); -#endif - - free(img->icc_profile_buf); - img->icc_profile_buf = NULL; img->icc_profile_len = 0; - } - - if (((img->numcomps == 3) && (img->comps[0].dx == img->comps[1].dx / 2) - && (img->comps[0].dx == img->comps[2].dx / 2 ) && (img->comps[0].dx == 1)) - || (img->numcomps == 1)) { - - if (!imagetoyuv(img, argv[2])) // Convert image to YUV - return 1; - } - else if ((img->numcomps == 3) && - (img->comps[0].dx == 1) && (img->comps[1].dx == 1)&& - (img->comps[2].dx == 1))// If YUV 4:4:4 input --> to bmp - { - fprintf(stdout,"The frames will be output in a bmp format (output_1.bmp, ...)\n"); - sprintf(outfilename,"output_%d.bmp",snum); - if (imagetobmp(img, outfilename)) // Convert image to BMP - return 1; - - } - else { - fprintf(stdout,"Image component dimensions are unknown. Unable to output image\n"); - fprintf(stdout,"The frames will be output in a j2k file (output_1.j2k, ...)\n"); - - sprintf(outfilename,"output_%d.j2k",snum); - outfile = fopen(outfilename, "wb"); - if (!outfile) { - fprintf(stderr, "failed to open %s for writing\n",outfilename); - return 1; - } - fwrite(frame_codestream,sample->sample_size-8,1,outfile); - fclose(outfile); - } - /* close the byte stream */ - opj_cio_close(cio); - /* free image data structure */ - opj_image_destroy(img); - elapsed_time = opj_clock()-init_time; - fprintf(stderr, "Frame number %d/%d decoded in %.2f mseconds\n", snum + 1, numframes, elapsed_time*1000); - total_time += elapsed_time; - - } - - free(frame_codestream); - fclose(file); + if(frame_codestream) free(frame_codestream); /* free remaining structures */ - if(dinfo) { - mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle); - } + if(dinfo) + { + mj2_destroy_decompress(movie); free(dinfo); + } - fprintf(stdout, "%d frame(s) correctly decompressed\n", snum); - fprintf(stdout,"Total decoding time: %.2f seconds (%.1f fps)\n", total_time, (float)numframes/total_time); - - return 0; -} + return failed; +}/* main() */ diff --git a/applications/mj2/wrap_j2k_in_mj2.c b/applications/mj2/wrap_j2k_in_mj2.c index 04ff7475..0382774b 100644 --- a/applications/mj2/wrap_j2k_in_mj2.c +++ b/applications/mj2/wrap_j2k_in_mj2.c @@ -45,10 +45,6 @@ Size of memory first allocated for MOOV box */ #define TEMP_BUF 10000 -#define ENUMCS_GRAY 16 -#define ENUMCS_SRGB 17 -#define ENUMCS_SYCC 18 - #define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51" /* -------------------------------------------------------------------------- */ @@ -77,6 +73,8 @@ static int test_image(const char *fname, mj2_cparameters_t *cp) if(memcmp(src, J2K_CODESTREAM_MAGIC, 4) != 0) { + fprintf(stderr,"%s:%d:\n\tONLY J2K files are accepted. Quitting.\n", + __FILE__,__LINE__); free(src); return success; } memset(&dparameters, 0, sizeof(opj_dparameters_t)); @@ -89,8 +87,12 @@ static int test_image(const char *fname, mj2_cparameters_t *cp) cio = opj_cio_open((opj_common_ptr)dinfo, src, src_len); + if(cio == NULL) goto fin; + image = opj_decode(dinfo, cio); + if(image == NULL) goto fin; + free(src); cio->buffer = NULL; opj_cio_close(cio); @@ -101,68 +103,17 @@ static int test_image(const char *fname, mj2_cparameters_t *cp) cp->h = image->comps[0].h; cp->prec = image->comps[0].prec; - if(image->numcomps > 2 ) + if(image->numcomps > 2)/* RGB or RGBA */ { - 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))// horizontal and vertical - { -// Y420 - cp->enumcs = ENUMCS_SYCC; - cp->CbCr_subsampling_dx = 2; - cp->CbCr_subsampling_dy = 2; - } - 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 == 1) - && (image->comps[2].dy == 1))// horizontal only - { -// Y422 - cp->enumcs = ENUMCS_SYCC; - cp->CbCr_subsampling_dx = 2; - cp->CbCr_subsampling_dy = 1; - } - 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)) - { -// Y444 or RGB - - if(image->color_space == CLRSPC_SRGB) - { cp->enumcs = ENUMCS_SRGB; - -// cp->CbCr_subsampling_dx = 0; -// cp->CbCr_subsampling_dy = 0; - } - else - { - cp->enumcs = ENUMCS_SYCC; - - cp->CbCr_subsampling_dx = 1; - cp->CbCr_subsampling_dy = 1; - } - } - else - { - goto fin; - } +/* cp->CbCr_subsampling_dx = 0; */ +/* cp->CbCr_subsampling_dy = 0; */ } - else + else /* GRAY or GRAYA */ { cp->enumcs = ENUMCS_GRAY; -// cp->CbCr_subsampling_dx = 0; -// cp->CbCr_subsampling_dy = 0; +/* cp->CbCr_subsampling_dx = 0; */ +/* cp->CbCr_subsampling_dy = 0; */ } if(image->icc_profile_buf) { @@ -228,8 +179,10 @@ static void read_siz_marker(FILE *file, opj_image_t *image) siz_buffer = (unsigned char*) malloc(len * sizeof(unsigned char)); fread(siz_buffer,len, 1, file); - cio = opj_cio_open(NULL, siz_buffer, len); - + cio = opj_cio_open(NULL, siz_buffer, len); + + if(cio == NULL) goto fin; + cio_read(cio, 2); /* Rsiz (capabilities) */ image->x1 = cio_read(cio, 4); /* Xsiz */ image->y1 = cio_read(cio, 4); /* Ysiz */ @@ -252,7 +205,9 @@ static void read_siz_marker(FILE *file, opj_image_t *image) image->comps[i].factor = 0; /* reducing factor by component */ } fseek(file, 0, SEEK_SET); - opj_cio_close(cio); + opj_cio_close(cio); + +fin: free(siz_buffer); } @@ -261,50 +216,28 @@ static void setparams(opj_mj2_t *movie, opj_image_t *image) { 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 = 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 ((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 ((image->comps[0].dy == 1) - && (image->comps[1].dy == 1) - && (image->comps[2].dy == 1)) - movie->tk[0].CbCr_subsampling_dy = 1; - 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"); - } - + + movie->tk[0].CbCr_subsampling_dx = 0; + movie->tk[0].CbCr_subsampling_dy = 0; movie->tk[0].sample_rate = 25; - movie->tk[0].jp2_struct.numcomps = image->numcomps; // NC + 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.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 = (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*/ @@ -333,29 +266,6 @@ static void setparams(opj_mj2_t *movie, opj_image_t *image) { else movie->tk[0].jp2_struct.meth = 2; - if (image->numcomps == 1) - movie->tk[0].jp2_struct.enumcs = 17; // Grayscale - - 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 ((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[]) { @@ -368,14 +278,14 @@ int main(int argc, char *argv[]) { FILE *mj2file, *j2kfile; char *j2kfilename; unsigned char *buf; - int offset, mdat_initpos; + int offset, mdat_initpos, failed; opj_image_t img; opj_cio_t *cio; mj2_cparameters_t parameters; if (argc != 3) { - printf("Usage: %s source_location mj2_filename\n",argv[0]); - printf("Example: %s input/input output.mj2\n",argv[0]); + printf("\nUsage: %s source_location mj2_filename\n",argv[0]); + printf("Example: %s input/input output.mj2\n\n",argv[0]); return 1; } @@ -385,6 +295,7 @@ int main(int argc, char *argv[]) { fprintf(stderr, "failed to open %s for writing\n", argv[2]); return 1; } + failed = 1; memset(&img, 0, sizeof(opj_image_t)); /* configure the event callbacks (not required) @@ -398,6 +309,8 @@ int main(int argc, char *argv[]) { /* get a MJ2 decompressor handle */ cinfo = mj2_create_compress(); + if(cinfo == NULL) goto fin; + /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); @@ -406,7 +319,7 @@ int main(int argc, char *argv[]) { movie = (opj_mj2_t*) cinfo->mj2_handle; j2kfilename = (char*)malloc(strlen(argv[1]) + 12);/* max. '%6d' */ - sprintf(j2kfilename, "%s_00001.j2k",argv[1]); + sprintf(j2kfilename, "%s_00000.j2k",argv[1]); if(test_image(j2kfilename, ¶meters) == 0) goto fin; @@ -415,11 +328,18 @@ int main(int argc, char *argv[]) { mj2_setup_encoder(movie, ¶meters); - /* Writing JP, FTYP and MDAT boxes - Assuming that the JP and FTYP boxes won't be longer than 300 bytes */ +/* 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)); + + if(buf == NULL) goto fin; + cio = opj_cio_open(movie->cinfo, buf, 300); + + if(cio == NULL) goto fin; + mj2_write_jp(cio); mj2_write_ftyp(movie, cio); mdat_initpos = cio_tell(cio); @@ -428,7 +348,7 @@ int main(int argc, char *argv[]) { fwrite(buf,cio_tell(cio),1,mj2file); free(buf); - // Insert each j2k codestream in a JP2C box +/* Insert each j2k codestream in a JP2C box */ snum=0; offset = 0; while(1) @@ -436,43 +356,44 @@ int main(int argc, char *argv[]) { 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; - } - else { // Tried to open a inexistant codestream - fprintf(stdout,"%d frames are being added to the MJ2 file\n",snum); - break; - } - } + if (!j2kfile) + { +/* No more files found: done. Leave while(1) loop: */ + fprintf(stdout,"%d frames are being added to the MJ2 file\n",snum); + break; + } - // Calculating offset for samples and chunks +/* Calculating offset for samples and chunks: */ offset += cio_tell(cio); sample->offset = offset; - movie->tk[0].chunk[snum].offset = offset; // There will be one sample per chunk +/* There will be one sample per chunk: */ + movie->tk[0].chunk[snum].offset = offset; - // Calculating sample size +/* Calculating sample size: */ fseek(j2kfile,0,SEEK_END); - sample->sample_size = ftell(j2kfile) + 8; // Sample size is codestream + JP2C box header +/* Sample size is codestream + JP2C box header: */ + sample->sample_size = ftell(j2kfile) + 8; fseek(j2kfile,0,SEEK_SET); - // Reading siz marker of j2k image for the first codestream +/* Reading siz marker of j2k image for the first codestream */ if (snum==0) read_siz_marker(j2kfile, &img); - // Writing JP2C box header - frame_codestream = (unsigned char*) malloc (sample->sample_size+8); - 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 + frame_codestream = (unsigned char*) + malloc (sample->sample_size+8); + cio = opj_cio_open(movie->cinfo, frame_codestream, sample->sample_size); + + if(cio == NULL) goto fin; + +/* Writing JP2C box header: */ + cio_write(cio,sample->sample_size, 4); + cio_write(cio,JP2_JP2C, 4); - // Writing codestream from J2K file to MJ2 file +/* 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(cio, sample->sample_size-8); - // Ending loop fclose(j2kfile); snum++; movie->tk[0].sample = (mj2_sample_t*) @@ -480,37 +401,63 @@ int main(int argc, char *argv[]) { movie->tk[0].chunk = (mj2_chunk_t*) realloc(movie->tk[0].chunk, (snum+1) * sizeof(mj2_chunk_t)); free(frame_codestream); - } + }/* while(1) */ - // Writing the MDAT box length in header +/* Writing the MDAT box length in header */ offset += cio_tell(cio); buf = (unsigned char*) malloc (4 * sizeof(unsigned char)); - cio = opj_cio_open(movie->cinfo, buf, 4); + + if(buf == NULL) goto fin; + + cio = opj_cio_open(movie->cinfo, buf, 4); + + if(cio == NULL) goto fin; + 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 + +/* if(cio->openmode == OPJ_STREAM_READ) */ free(buf); + opj_cio_close(cio); + +/* Setting movie parameters: */ movie->tk[0].num_samples=snum; movie->tk[0].num_chunks=snum; setparams(movie, &img); - // Writing MOOV box - 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); +/* Writing MOOV box */ + buf = (unsigned char*) malloc ((TEMP_BUF+snum*20) * sizeof(unsigned char)); + + if(buf == NULL) goto fin; + + cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+snum*20)); + + if(cio == NULL) goto fin; + + mj2_write_moov(movie, cio); fwrite(buf,cio_tell(cio),1,mj2file); - // Ending program free(img.comps); + +/* if(cio->openmode == OPJ_STREAM_READ) */ free(buf); opj_cio_close(cio); + failed = 0; buf = NULL; + fin: fclose(mj2file); - mj2_destroy_compress(movie); + + if(failed) remove(argv[2]); + + if(buf) free(buf); + + if(cinfo) + { + mj2_destroy_compress(movie); + free(cinfo); + } free(j2kfilename); - return 0; + return failed; } diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h index 53e9fac0..59147c8b 100644 --- a/libopenjpeg/openjpeg.h +++ b/libopenjpeg/openjpeg.h @@ -135,6 +135,10 @@ typedef enum COLOR_SPACE { CLRSPC_SYCC = 3 /**< YUV */ } OPJ_COLOR_SPACE; +#define ENUMCS_SRGB 16 +#define ENUMCS_GRAY 17 +#define ENUMCS_SYCC 18 + /** Supported codec */