[1.5] Integrate patch from winfried posted on the mailing list. See here for more info: https://groups.google.com/group/openjpeg/msg/7e30b6e288ad5908

This commit is contained in:
Mathieu Malaterre 2012-04-23 13:23:38 +00:00
parent 6b649f3bf6
commit 097496a9f0
6 changed files with 358 additions and 324 deletions

View File

@ -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, &parameters);
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() */

View File

@ -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;
}

View File

@ -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;

View File

@ -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() */

View File

@ -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, &parameters) == 0) goto fin;
@ -415,11 +328,18 @@ int main(int argc, char *argv[]) {
mj2_setup_encoder(movie, &parameters);
/* 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;
}

View File

@ -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
*/