113int main(
int argc,
char* argv[])
115#if defined(MEMORY_LEAK_CHECK) && defined(_DEBUG)
116#if defined(WIN32) || defined(_WIN32)
119 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
120 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
121 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
122 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
124 int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
125 tmp = tmp | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF;
134 long int verbosity = 100;
138 printf(
"Usage: iccDumpProfile {-v} {int} profile {tagId to dump/\"ALL\"}\n");
140 printf(
"\nThe -v option causes profile validation to be performed."
141 "\nThe optional integer parameter specifies verboseness of output (1-100, default=100).\n");
142 printf(
"iccDumpProfile built with IccProfLib version " ICCPROFLIBVER "\n\n");
150 bool bDumpValidation =
false;
152 if (!strncmp(argv[1],
"-V", 2) || !strncmp(argv[1],
"-v", 2)) {
158 char *endptr =
nullptr;
159 verbosity = strtol(argv[nArg], &endptr, 10);
160 if ((verbosity != 0L) && (errno != ERANGE) && ((endptr ==
nullptr) || (*endptr ==
'\0'))) {
164 else if (verbosity > 100)
170 else if (argv[nArg] == endptr) {
175 bDumpValidation =
true;
179 char* endptr =
nullptr;
180 verbosity = strtol(argv[nArg], &endptr, 10);
181 if ((verbosity != 0L) && (errno != ERANGE) && ((endptr ==
nullptr) || (*endptr ==
'\0'))) {
185 else if (verbosity > 100)
199 printf(
"Built with IccProfLib version " ICCPROFLIBVER "\n\n");
201 printf(
"Unable to parse '%s' as ICC profile!\n", argv[nArg]);
205 pHdr = &pIcc->m_Header;
208 printf(
"Profile: '%s'\n", argv[nArg]);
212 printf(
"Profile ID: Profile ID not calculated.\n");
213 printf(
"Size: %d (0x%x) bytes\n", pHdr->
size, pHdr->
size);
215 printf(
"\nHeader\n");
219 printf(
"Creation Date: %d/%d/%d (M/D/Y) %02u:%02u:%02u\n",
233 printf(
"Profile SubClass: Not Defined\n");
238 printf(
"Illuminant: X=%.4lf, Y=%.4lf, Z=%.4lf\n",
244 printf(
"Spectral PCS Range: start=%.1fnm, end=%.1fnm, steps=%d\n",
250 printf(
"Spectral PCS Range: Not Defined\n");
254 printf(
"BiSpectral Range: start=%.1fnm, end=%.1fnm, steps=%d\n",
260 printf(
"BiSpectral Range: Not Defined\n");
267 printf(
"MCS Color Space: Not Defined\n");
270 printf(
"\nProfile Tags\n");
271 printf(
"------------\n");
273 printf(
"%28s ID %8s\t%8s\t%8s\n",
"Tag",
"Offset",
"Size",
"Pad");
274 printf(
"%28s ------ %8s\t%8s\t%8s\n",
"----",
"------",
"----",
"---");
277 TagEntryList::iterator i, j;
280 for (n=0, i=pIcc->m_Tags->begin(); i!=pIcc->m_Tags->end(); i++, n++) {
282 closest = pHdr->
size;
283 for (j = pIcc->m_Tags->begin(); j != pIcc->m_Tags->end(); j++) {
284 if ((i != j) && (j->TagInfo.offset >= i->TagInfo.offset + i->TagInfo.size) && ((
int)j->TagInfo.offset <= closest)) {
285 closest = j->TagInfo.offset;
290 pad = closest - i->TagInfo.offset - i->TagInfo.size;
292 printf(
"%28s %s %8d\t%8d\t%8d\n", Fmt.
GetTagSigName(i->TagInfo.sig),
293 icGetSig(buf, i->TagInfo.sig,
false), i->TagInfo.offset, i->TagInfo.size, pad);
301 for (n=0, i = pIcc->m_Tags->begin(); i != pIcc->m_Tags->end(); i++, n++)
302 for (m=0, j = pIcc->m_Tags->begin(); j != pIcc->m_Tags->end(); j++, m++)
303 if ((i != j) && (i->TagInfo.sig == j->TagInfo.sig)) {
304 printf(
"%28s is duplicated at positions %d and %d!\n", Fmt.
GetTagSigName(i->TagInfo.sig), n, m);
321 if (bDumpValidation) {
323 int rndup, smallest_offset = pHdr->
size;
330 sReport +=
"File size is not a multiple of 4 bytes (last tag needs padding?).\n";
334 for (i=pIcc->m_Tags->begin(); i!=pIcc->m_Tags->end(); i++) {
335 rndup = 4 * ((i->TagInfo.size + 3) / 4);
336 pad = rndup - i->TagInfo.size;
339 if (i->TagInfo.offset + i->TagInfo.size > pHdr->
size) {
341 sprintf(str,
"Tag %s (offset %d, size %d) ends beyond EOF.\n",
342 Fmt.
GetTagSigName(i->TagInfo.sig), i->TagInfo.offset, i->TagInfo.size);
348 if ((
int)i->TagInfo.offset < smallest_offset) {
349 smallest_offset = (int)i->TagInfo.offset;
353 closest = pHdr->
size;
354 for (j=pIcc->m_Tags->begin(); j!=pIcc->m_Tags->end(); j++) {
355 if ((i!=j) && (j->TagInfo.offset > i->TagInfo.offset) && ((
int)j->TagInfo.offset <= closest)) {
356 closest = j->TagInfo.offset;
361 if ((closest < (
int)i->TagInfo.offset + (int)i->TagInfo.size) && (closest < (int)pHdr->
size)) {
363 sprintf(str,
"Tag %s (offset %d, size %d) overlaps with following tag data starting at offset %d.\n",
364 Fmt.
GetTagSigName(i->TagInfo.sig), i->TagInfo.offset, i->TagInfo.size, closest);
370 if (closest > (
int)i->TagInfo.offset + rndup) {
372 sprintf(str,
"Tag %s (size %d) is followed by %d unnecessary additional bytes (from offset %d).\n",
373 Fmt.
GetTagSigName(i->TagInfo.sig), i->TagInfo.size, closest-(i->TagInfo.offset+rndup), (i->TagInfo.offset+rndup));
381 if ((n > 0) && (smallest_offset > 128 + 4 + (n * 12))) {
383 sprintf(str,
"First tag data is at offset %d rather than immediately after tag table (offset %d).\n",
384 smallest_offset, 128 + 4 + (n * 12));
391 if (!
stricmp(argv[nArg+1],
"ALL")) {
392 for (i=pIcc->m_Tags->begin(); i!=pIcc->m_Tags->end(); i++) {
393 DumpTag(pIcc, i->TagInfo.sig, verbosity);
404 if (bDumpValidation) {
405 printf(
"\nValidation Report\n");
406 printf(
"-----------------\n");
409 printf(
"Profile is valid");
414 printf(
"Profile has warning(s)");
419 printf(
"Profile violates ICC specification");
424 printf(
"Profile has Critical Error(s) that violate ICC specification");
430 printf(
"Profile has unknown status!");
438 fwrite(sReport.c_str(), sReport.length(), 1, stdout);
442#if defined(_DEBUG) || defined(DEBUG)
443 printf(
"EXIT %d\n", nValid);