diff options
Diffstat (limited to 'src/bin/mj2/mj2_to_metadata.c')
| -rw-r--r-- | src/bin/mj2/mj2_to_metadata.c | 519 |
1 files changed, 262 insertions, 257 deletions
diff --git a/src/bin/mj2/mj2_to_metadata.c b/src/bin/mj2/mj2_to_metadata.c index 2ec2829d..21d3977e 100644 --- a/src/bin/mj2/mj2_to_metadata.c +++ b/src/bin/mj2/mj2_to_metadata.c @@ -3,7 +3,7 @@ /* 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. @@ -23,23 +23,26 @@ can be bound by the Open JPEG open-source license and disclaimer, expressed else /** 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); } /* -------------------------------------------------------------------------- */ @@ -50,263 +53,265 @@ void info_callback(const char *msg, void *client_data) { 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] */ + 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 + 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; } |
