/* Contributed to Open JPEG by Glenn Pearson, contract software developer, U.S. National Library of Medicine.
The base code in this file was developed by the author as part of a video archiving
-project for the U.S. National Library of Medicine, Bethesda, MD.
+project for the U.S. National Library of Medicine, Bethesda, MD.
It is the policy of NLM (and U.S. government) to not assert copyright.
A non-exclusive copy of this code has been contributed to the Open JPEG project.
/**
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);
+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);
+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);
+void info_callback(const char *msg, void *client_data)
+{
+ FILE *stream = (FILE*)client_data;
+ fprintf(stream, "[INFO] %s", msg);
}
/* -------------------------------------------------------------------------- */
void help_display()
{
- /* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
- fprintf(stdout," Help for the 'mj2_to_metadata' Program\n");
- fprintf(stdout," ======================================\n");
- fprintf(stdout,"The -h option displays this information on screen.\n\n");
-
- fprintf(stdout,"mj2_to_metadata generates an XML file from a Motion JPEG 2000 file.\n");
- fprintf(stdout,"The generated XML shows the structural, but not (yet) curatorial,\n");
- fprintf(stdout,"metadata from the movie header and from the JPEG 2000 image and tile\n");
- fprintf(stdout,"headers of a sample frame. Excluded: low-level packed-bits image data.\n\n");
-
- fprintf(stdout,"By Default\n");
- fprintf(stdout,"----------\n");
- fprintf(stdout,"The metadata includes the jp2 image and tile headers of the first frame.\n");
- fprintf(stdout,"\n");
- fprintf(stdout,"Metadata values are shown in 'raw' form (e.g., hexadecimal) as stored in the\n");
- fprintf(stdout,"file, and, if apt, in a 'derived' form that is more quickly grasped.\n");
- fprintf(stdout,"\n");
- fprintf(stdout,"Notes explaining the XML are embedded as terse comments. These include\n");
- fprintf(stdout," meaning of non-obvious tag abbreviations;\n");
- fprintf(stdout," range and precision of valid values;\n");
- fprintf(stdout," interpretations of values, such as enumerations; and\n");
- fprintf(stdout," current implementation limitations.\n");
- fprintf(stdout,"\n");
- fprintf(stdout,"The sample-size and chunk-offset tables, each with 1 row per frame, are not reported.\n");
- fprintf(stdout,"\n");
- fprintf(stdout,"The file is self-contained and no verification (e.g., against a DTD) is requested.\n");
- fprintf(stdout,"\n");
- fprintf(stdout,"Required Parameters (except with -h)\n");
- fprintf(stdout,"------------------------------------\n");
- fprintf(stdout,"[Caution: file strings that contain spaces should be wrapped with quotes.]\n");
- fprintf(stdout,"-i input.mj2 : where 'input' is any source file name or path.\n");
- fprintf(stdout," MJ2 files created with 'frames_to_mj2' are supported so far.\n");
- fprintf(stdout," These are silent, single-track, 'MJ2 Simple Profile' videos.\n");
- fprintf(stdout,"-o output.xml : where 'output' is any destination file name or path.\n");
- fprintf(stdout,"\n");
- fprintf(stdout,"Optional Parameters\n");
- fprintf(stdout,"-------------------\n");
- fprintf(stdout,"-h : Display this help information.\n");
- fprintf(stdout,"-n : Suppress all mj2_to_metadata notes.\n");
- fprintf(stdout,"-t : Include sample-size and chunk-offset tables.\n");
- fprintf(stdout,"-f n : where n > 0. Include jp2 header info for frame n [default=1].\n");
- fprintf(stdout,"-f 0 : No jp2 header info.\n");
- fprintf(stdout,"-r : Suppress all 'raw' data for which a 'derived' form exists.\n");
- fprintf(stdout,"-d : Suppress all 'derived' data.\n");
- fprintf(stdout," (If both -r and -d given, -r will be ignored.)\n");
- fprintf(stdout,"-v string : Verify against the DTD file located by the string.\n");
- fprintf(stdout," Prepend quoted 'string' with either SYSTEM or PUBLIC keyword.\n");
- fprintf(stdout," Thus, for the distributed DTD placed in the same directory as\n");
- fprintf(stdout," the output file: -v \"SYSTEM mj2_to_metadata.dtd\"\n");
- fprintf(stdout," \"PUBLIC\" is used with an access protocol (e.g., http:) + URL.\n");
- /* More to come */
- fprintf(stdout,"\n");
- /* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
+ /* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
+ fprintf(stdout, " Help for the 'mj2_to_metadata' Program\n");
+ fprintf(stdout, " ======================================\n");
+ fprintf(stdout, "The -h option displays this information on screen.\n\n");
+
+ fprintf(stdout,
+ "mj2_to_metadata generates an XML file from a Motion JPEG 2000 file.\n");
+ fprintf(stdout,
+ "The generated XML shows the structural, but not (yet) curatorial,\n");
+ fprintf(stdout,
+ "metadata from the movie header and from the JPEG 2000 image and tile\n");
+ fprintf(stdout,
+ "headers of a sample frame. Excluded: low-level packed-bits image data.\n\n");
+
+ fprintf(stdout, "By Default\n");
+ fprintf(stdout, "----------\n");
+ fprintf(stdout,
+ "The metadata includes the jp2 image and tile headers of the first frame.\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout,
+ "Metadata values are shown in 'raw' form (e.g., hexadecimal) as stored in the\n");
+ fprintf(stdout,
+ "file, and, if apt, in a 'derived' form that is more quickly grasped.\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout,
+ "Notes explaining the XML are embedded as terse comments. These include\n");
+ fprintf(stdout, " meaning of non-obvious tag abbreviations;\n");
+ fprintf(stdout, " range and precision of valid values;\n");
+ fprintf(stdout, " interpretations of values, such as enumerations; and\n");
+ fprintf(stdout, " current implementation limitations.\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout,
+ "The sample-size and chunk-offset tables, each with 1 row per frame, are not reported.\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout,
+ "The file is self-contained and no verification (e.g., against a DTD) is requested.\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Required Parameters (except with -h)\n");
+ fprintf(stdout, "------------------------------------\n");
+ fprintf(stdout,
+ "[Caution: file strings that contain spaces should be wrapped with quotes.]\n");
+ fprintf(stdout,
+ "-i input.mj2 : where 'input' is any source file name or path.\n");
+ fprintf(stdout,
+ " MJ2 files created with 'frames_to_mj2' are supported so far.\n");
+ fprintf(stdout,
+ " These are silent, single-track, 'MJ2 Simple Profile' videos.\n");
+ fprintf(stdout,
+ "-o output.xml : where 'output' is any destination file name or path.\n");
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Optional Parameters\n");
+ fprintf(stdout, "-------------------\n");
+ fprintf(stdout, "-h : Display this help information.\n");
+ fprintf(stdout, "-n : Suppress all mj2_to_metadata notes.\n");
+ fprintf(stdout,
+ "-t : Include sample-size and chunk-offset tables.\n");
+ fprintf(stdout,
+ "-f n : where n > 0. Include jp2 header info for frame n [default=1].\n");
+ fprintf(stdout, "-f 0 : No jp2 header info.\n");
+ fprintf(stdout,
+ "-r : Suppress all 'raw' data for which a 'derived' form exists.\n");
+ fprintf(stdout, "-d : Suppress all 'derived' data.\n");
+ fprintf(stdout,
+ " (If both -r and -d given, -r will be ignored.)\n");
+ fprintf(stdout,
+ "-v string : Verify against the DTD file located by the string.\n");
+ fprintf(stdout,
+ " Prepend quoted 'string' with either SYSTEM or PUBLIC keyword.\n");
+ fprintf(stdout,
+ " Thus, for the distributed DTD placed in the same directory as\n");
+ fprintf(stdout,
+ " the output file: -v \"SYSTEM mj2_to_metadata.dtd\"\n");
+ fprintf(stdout,
+ " \"PUBLIC\" is used with an access protocol (e.g., http:) + URL.\n");
+ /* More to come */
+ fprintf(stdout, "\n");
+ /* "1234567890123456789012345678901234567890123456789012345678901234567890123456789" */
}
/* ------------- */
-int main(int argc, char *argv[]) {
-
- opj_dinfo_t* dinfo;
- opj_event_mgr_t event_mgr; /* event manager */
-
- FILE *file, *xmlout;
-/* char xmloutname[50]; */
- opj_mj2_t *movie;
-
- char* infile = 0;
- char* outfile = 0;
- char* s, S1, S2, S3;
- int len;
- unsigned int sampleframe = 1; /* First frame */
- char* stringDTD = NULL;
- BOOL notes = TRUE;
- BOOL sampletables = FALSE;
- BOOL raw = TRUE;
- BOOL derived = TRUE;
- mj2_dparameters_t parameters;
-
- while (TRUE) {
- /* ':' after letter means it takes an argument */
- int c = getopt(argc, argv, "i:o:f:v:hntrd");
- /* FUTURE: Reserve 'p' for pruning file (which will probably make -t redundant) */
- if (c == -1)
- break;
- switch (c) {
- case 'i': /* IN file */
- infile = optarg;
- s = optarg;
- while (*s) { s++; } /* Run to filename end */
- s--;
- S3 = *s;
- s--;
- S2 = *s;
- s--;
- S1 = *s;
-
- if ((S1 == 'm' && S2 == 'j' && S3 == '2')
- || (S1 == 'M' && S2 == 'J' && S3 == '2')) {
- break;
- }
- fprintf(stderr, "Input file name must have .mj2 extension, not .%c%c%c.\n", S1, S2, S3);
- return 1;
-
- /* ----------------------------------------------------- */
- case 'o': /* OUT file */
- outfile = optarg;
- while (*outfile) { outfile++; } /* Run to filename end */
- outfile--;
- S3 = *outfile;
- outfile--;
- S2 = *outfile;
- outfile--;
- S1 = *outfile;
-
- outfile = optarg;
-
- if ((S1 == 'x' && S2 == 'm' && S3 == 'l')
- || (S1 == 'X' && S2 == 'M' && S3 == 'L'))
- break;
-
- fprintf(stderr,
- "Output file name must have .xml extension, not .%c%c%c\n", S1, S2, S3);
- return 1;
-
- /* ----------------------------------------------------- */
- case 'f': /* Choose sample frame. 0 = none */
- sscanf(optarg, "%u", &sampleframe);
- break;
-
- /* ----------------------------------------------------- */
- case 'v': /* Verification by DTD. */
- stringDTD = optarg;
- /* We will not insist upon last 3 chars being "dtd", since non-file
- access protocol may be used. */
- if(strchr(stringDTD,'"') != NULL) {
- fprintf(stderr, "-D's string must not contain any embedded double-quote characters.\n");
- return 1;
- }
-
- if (strncmp(stringDTD,"PUBLIC ",7) == 0 || strncmp(stringDTD,"SYSTEM ",7) == 0)
- break;
-
- fprintf(stderr, "-D's string must start with \"PUBLIC \" or \"SYSTEM \"\n");
- return 1;
-
- /* ----------------------------------------------------- */
- case 'n': /* Suppress comments */
- notes = FALSE;
- break;
-
- /* ----------------------------------------------------- */
- case 't': /* Show sample size and chunk offset tables */
- sampletables = TRUE;
- break;
-
- /* ----------------------------------------------------- */
- case 'h': /* Display an help description */
- help_display();
- return 0;
-
- /* ----------------------------------------------------- */
- case 'r': /* Suppress raw data */
- raw = FALSE;
- break;
-
- /* ----------------------------------------------------- */
- case 'd': /* Suppress derived data */
- derived = FALSE;
- break;
-
- /* ----------------------------------------------------- */
- default:
- return 1;
- } /* switch */
- } /* while */
-
- if(!raw && !derived)
- raw = TRUE; /* At least one of 'raw' and 'derived' must be true */
+int main(int argc, char *argv[])
+{
+
+ opj_dinfo_t* dinfo;
+ opj_event_mgr_t event_mgr; /* event manager */
+
+ FILE *file, *xmlout;
+ /* char xmloutname[50]; */
+ opj_mj2_t *movie;
+
+ char* infile = 0;
+ char* outfile = 0;
+ char* s, S1, S2, S3;
+ int len;
+ unsigned int sampleframe = 1; /* First frame */
+ char* stringDTD = NULL;
+ BOOL notes = TRUE;
+ BOOL sampletables = FALSE;
+ BOOL raw = TRUE;
+ BOOL derived = TRUE;
+ mj2_dparameters_t parameters;
+
+ while (TRUE) {
+ /* ':' after letter means it takes an argument */
+ int c = getopt(argc, argv, "i:o:f:v:hntrd");
+ /* FUTURE: Reserve 'p' for pruning file (which will probably make -t redundant) */
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case 'i': /* IN file */
+ infile = optarg;
+ s = optarg;
+ while (*s) {
+ s++; /* Run to filename end */
+ }
+ s--;
+ S3 = *s;
+ s--;
+ S2 = *s;
+ s--;
+ S1 = *s;
+
+ if ((S1 == 'm' && S2 == 'j' && S3 == '2')
+ || (S1 == 'M' && S2 == 'J' && S3 == '2')) {
+ break;
+ }
+ fprintf(stderr, "Input file name must have .mj2 extension, not .%c%c%c.\n", S1,
+ S2, S3);
+ return 1;
+
+ /* ----------------------------------------------------- */
+ case 'o': /* OUT file */
+ outfile = optarg;
+ while (*outfile) {
+ outfile++; /* Run to filename end */
+ }
+ outfile--;
+ S3 = *outfile;
+ outfile--;
+ S2 = *outfile;
+ outfile--;
+ S1 = *outfile;
+
+ outfile = optarg;
+
+ if ((S1 == 'x' && S2 == 'm' && S3 == 'l')
+ || (S1 == 'X' && S2 == 'M' && S3 == 'L')) {
+ break;
+ }
+
+ fprintf(stderr,
+ "Output file name must have .xml extension, not .%c%c%c\n", S1, S2, S3);
+ return 1;
+
+ /* ----------------------------------------------------- */
+ case 'f': /* Choose sample frame. 0 = none */
+ sscanf(optarg, "%u", &sampleframe);
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'v': /* Verification by DTD. */
+ stringDTD = optarg;
+ /* We will not insist upon last 3 chars being "dtd", since non-file
+ access protocol may be used. */
+ if (strchr(stringDTD, '"') != NULL) {
+ fprintf(stderr,
+ "-D's string must not contain any embedded double-quote characters.\n");
+ return 1;
+ }
+
+ if (strncmp(stringDTD, "PUBLIC ", 7) == 0 ||
+ strncmp(stringDTD, "SYSTEM ", 7) == 0) {
+ break;
+ }
+
+ fprintf(stderr, "-D's string must start with \"PUBLIC \" or \"SYSTEM \"\n");
+ return 1;
+
+ /* ----------------------------------------------------- */
+ case 'n': /* Suppress comments */
+ notes = FALSE;
+ break;
+
+ /* ----------------------------------------------------- */
+ case 't': /* Show sample size and chunk offset tables */
+ sampletables = TRUE;
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'h': /* Display an help description */
+ help_display();
+ return 0;
+
+ /* ----------------------------------------------------- */
+ case 'r': /* Suppress raw data */
+ raw = FALSE;
+ break;
+
+ /* ----------------------------------------------------- */
+ case 'd': /* Suppress derived data */
+ derived = FALSE;
+ break;
+
+ /* ----------------------------------------------------- */
+ default:
+ return 1;
+ } /* switch */
+ } /* while */
+
+ if (!raw && !derived) {
+ raw = TRUE; /* At least one of 'raw' and 'derived' must be true */
+ }
/* Error messages */
- /* -------------- */
- if (!infile || !outfile) {
- fprintf(stderr,"Correct usage: mj2_to_metadata -i mj2-file -o xml-file (plus options)\n");
- return 1;
- }
-
-/* was:
- if (argc != 3) {
- printf("Bad syntax: Usage: MJ2_to_metadata inputfile.mj2 outputfile.xml\n");
- printf("Example: MJ2_to_metadata foreman.mj2 foreman.xml\n");
- return 1;
- }
-*/
- len = strlen(infile);
- if(infile[0] == ' ')
- {
- infile++; /* There may be a leading blank if user put space after -i */
- }
-
- file = fopen(infile, "rb"); /* was: argv[1] */
-
- if (!file) {
- fprintf(stderr, "Failed to open %s for reading.\n", infile); /* was: argv[1] */
- return 1;
- }
-
- len = strlen(outfile);
- if(outfile[0] == ' ')
- {
- outfile++; /* There may be a leading blank if user put space after -o */
- }
-
- // Checking output file
- xmlout = fopen(outfile, "w"); /* was: argv[2] */
- if (!xmlout) {
- fprintf(stderr, "Failed to open %s for writing.\n", outfile); /* was: argv[2] */
- return 1;
- }
- // Leave it open
-
- /*
- 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 */
- dinfo = mj2_create_decompress();
-
- /* catch events using our callbacks and give a local context */
- opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
-
- /* setup the decoder decoding parameters using user parameters */
- movie = (opj_mj2_t*) dinfo->mj2_handle;
- mj2_setup_decoder(dinfo->mj2_handle, ¶meters);
-
- if (mj2_read_struct(file, movie)) // Creating the movie structure
- {
+ /* -------------- */
+ if (!infile || !outfile) {
+ fprintf(stderr,
+ "Correct usage: mj2_to_metadata -i mj2-file -o xml-file (plus options)\n");
+ return 1;
+ }
+
+ /* was:
+ if (argc != 3) {
+ printf("Bad syntax: Usage: MJ2_to_metadata inputfile.mj2 outputfile.xml\n");
+ printf("Example: MJ2_to_metadata foreman.mj2 foreman.xml\n");
+ return 1;
+ }
+ */
+ len = strlen(infile);
+ if (infile[0] == ' ') {
+ infile++; /* There may be a leading blank if user put space after -i */
+ }
+
+ file = fopen(infile, "rb"); /* was: argv[1] */
+
+ if (!file) {
+ fprintf(stderr, "Failed to open %s for reading.\n", infile); /* was: argv[1] */
+ return 1;
+ }
+
+ len = strlen(outfile);
+ if (outfile[0] == ' ') {
+ outfile++; /* There may be a leading blank if user put space after -o */
+ }
+
+ // Checking output file
+ xmlout = fopen(outfile, "w"); /* was: argv[2] */
+ if (!xmlout) {
+ fprintf(stderr, "Failed to open %s for writing.\n", outfile); /* was: argv[2] */
+ fclose(file);
+ return 1;
+ }
+ // Leave it open
+
+ /*
+ configure the event callbacks (not required)
+ setting of each callback is optional
+ */
+ 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 */
+ dinfo = mj2_create_decompress();
+
+ /* catch events using our callbacks and give a local context */
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+
+ /* setup the decoder decoding parameters using user parameters */
+ movie = (opj_mj2_t*) dinfo->mj2_handle;
+ mj2_setup_decoder(dinfo->mj2_handle, ¶meters);
+
+ if (mj2_read_struct(file, movie)) { // Creating the movie structure
+ fclose(xmlout);
+ return 1;
+ }
+
+ xml_write_init(notes, sampletables, raw, derived);
+ xml_write_struct(file, xmlout, movie, sampleframe, stringDTD, &event_mgr);
fclose(xmlout);
- return 1;
- }
-
- xml_write_init(notes, sampletables, raw, derived);
- xml_write_struct(file, xmlout, movie, sampleframe, stringDTD, &event_mgr);
- fclose(xmlout);
- fprintf(stderr,"Metadata correctly extracted to XML file \n");;
+ fprintf(stderr, "Metadata correctly extracted to XML file \n");;
- /* free remaining structures */
- if(dinfo) {
- mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle);
- }
+ /* free remaining structures */
+ if (dinfo) {
+ mj2_destroy_decompress((opj_mj2_t*)dinfo->mj2_handle);
+ }
- return 0;
+ return 0;
}