Home | History | Annotate | Download | only in source
      1 /*****************************************************************************/
      2 // Copyright 2006-2012 Adobe Systems Incorporated
      3 // All Rights Reserved.
      4 //
      5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
      6 // accordance with the terms of the Adobe license agreement accompanying it.
      7 /*****************************************************************************/
      8 
      9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_validate.cpp#2 $ */
     10 /* $DateTime: 2012/06/14 20:24:41 $ */
     11 /* $Change: 835078 $ */
     12 /* $Author: tknoll $ */
     13 
     14 // Process exit codes
     15 // ------------------
     16 //
     17 // As usual, 0 indicates success.
     18 //
     19 // If an exception occurs, the exit code will be equal to:
     20 //
     21 //    DNG SDK error code - 100000 + 100
     22 //
     23 // For example, the error dng_error_memory, which has a DNG SDK error code of
     24 // 100005, is returned as an exit code of 105.
     25 //
     26 // This convention accounts for the fact that the shell truncates process exit
     27 // codes to 8 bits and that the exit code 1 is used by ASAN to signal that a
     28 // memory error occurred (so mapping the first DNG SDK error code to an exit
     29 // code of 1 would not be a good idea).
     30 
     31 /*****************************************************************************/
     32 
     33 #include "dng_color_space.h"
     34 #include "dng_date_time.h"
     35 #include "dng_exceptions.h"
     36 #include "dng_file_stream.h"
     37 #include "dng_globals.h"
     38 #include "dng_host.h"
     39 #include "dng_ifd.h"
     40 #include "dng_image_writer.h"
     41 #include "dng_info.h"
     42 #include "dng_linearization_info.h"
     43 #include "dng_mosaic_info.h"
     44 #include "dng_negative.h"
     45 #include "dng_preview.h"
     46 #include "dng_render.h"
     47 #include "dng_simple_image.h"
     48 #include "dng_tag_codes.h"
     49 #include "dng_tag_types.h"
     50 #include "dng_tag_values.h"
     51 
     52 #if qDNGUseXMP
     53 #include "dng_xmp.h"
     54 #include "dng_xmp_sdk.h"
     55 #endif
     56 
     57 /*****************************************************************************/
     58 
     59 #if qDNGValidateTarget
     60 
     61 /*****************************************************************************/
     62 
     63 #define kDNGValidateVersion "1.4"
     64 
     65 /*****************************************************************************/
     66 
     67 static bool gFourColorBayer = false;
     68 
     69 static int32 gMosaicPlane = -1;
     70 
     71 static uint32 gPreferredSize = 0;
     72 static uint32 gMinimumSize   = 0;
     73 static uint32 gMaximumSize   = 0;
     74 
     75 static uint32 gProxyDNGSize = 0;
     76 
     77 static const dng_color_space *gFinalSpace = &dng_space_sRGB::Get ();
     78 
     79 static uint32 gFinalPixelType = ttByte;
     80 
     81 static dng_string gDumpStage1;
     82 static dng_string gDumpStage2;
     83 static dng_string gDumpStage3;
     84 static dng_string gDumpTIF;
     85 static dng_string gDumpDNG;
     86 
     87 /*****************************************************************************/
     88 
     89 static dng_error_code dng_validate (const char *filename)
     90 	{
     91 
     92 	printf ("Validating \"%s\"...\n", filename);
     93 
     94 	try
     95 		{
     96 
     97 		dng_file_stream stream (filename);
     98 
     99 		dng_host host;
    100 
    101 		host.SetPreferredSize (gPreferredSize);
    102 		host.SetMinimumSize   (gMinimumSize  );
    103 		host.SetMaximumSize   (gMaximumSize  );
    104 
    105 		host.ValidateSizes ();
    106 
    107 		if (host.MinimumSize ())
    108 			{
    109 
    110 			host.SetForPreview (true);
    111 
    112 			gDumpDNG.Clear ();
    113 
    114 			}
    115 
    116 		if (gDumpDNG.NotEmpty ())
    117 			{
    118 
    119 			host.SetSaveDNGVersion (dngVersion_SaveDefault);
    120 
    121 			host.SetSaveLinearDNG (false);
    122 
    123 			host.SetKeepOriginalFile (false);
    124 
    125 			}
    126 
    127 		// Read into the negative.
    128 
    129 		AutoPtr<dng_negative> negative;
    130 
    131 			{
    132 
    133 			dng_info info;
    134 
    135 			info.Parse (host, stream);
    136 
    137 			info.PostParse (host);
    138 
    139 			if (!info.IsValidDNG ())
    140 				{
    141 				return dng_error_bad_format;
    142 				}
    143 
    144 			negative.Reset (host.Make_dng_negative ());
    145 
    146 			negative->Parse (host, stream, info);
    147 
    148 			negative->PostParse (host, stream, info);
    149 
    150 				{
    151 
    152 				dng_timer timer ("Raw image read time");
    153 
    154 				negative->ReadStage1Image (host, stream, info);
    155 
    156 				}
    157 
    158 			if (info.fMaskIndex != -1)
    159 				{
    160 
    161 				dng_timer timer ("Transparency mask read time");
    162 
    163 				negative->ReadTransparencyMask (host, stream, info);
    164 
    165 				}
    166 
    167 			negative->ValidateRawImageDigest (host);
    168 
    169 			}
    170 
    171 		// Option to write stage 1 image.
    172 
    173 		if (gDumpStage1.NotEmpty ())
    174 			{
    175 
    176 			dng_file_stream stream2 (gDumpStage1.Get (), true);
    177 
    178 			const dng_image &stage1 = *negative->Stage1Image ();
    179 
    180 			dng_image_writer writer;
    181 
    182 			writer.WriteTIFF (host,
    183 							  stream2,
    184 							  stage1,
    185 							  stage1.Planes () >= 3 ? piRGB
    186 												    : piBlackIsZero);
    187 
    188 			gDumpStage1.Clear ();
    189 
    190 			}
    191 
    192 		// Metadata.
    193 
    194 		negative->SynchronizeMetadata ();
    195 
    196 		// Four color Bayer option.
    197 
    198 		if (gFourColorBayer)
    199 			{
    200 			negative->SetFourColorBayer ();
    201 			}
    202 
    203 		// Build stage 2 image.
    204 
    205 			{
    206 
    207 			dng_timer timer ("Linearization time");
    208 
    209 			negative->BuildStage2Image (host);
    210 
    211 			}
    212 
    213 		if (gDumpStage2.NotEmpty ())
    214 			{
    215 
    216 			dng_file_stream stream2 (gDumpStage2.Get (), true);
    217 
    218 			const dng_image &stage2 = *negative->Stage2Image ();
    219 
    220 			dng_image_writer writer;
    221 
    222 			writer.WriteTIFF (host,
    223 							  stream2,
    224 							  stage2,
    225 							  stage2.Planes () >= 3 ? piRGB
    226 												    : piBlackIsZero);
    227 
    228 			gDumpStage2.Clear ();
    229 
    230 			}
    231 
    232 		// Build stage 3 image.
    233 
    234 			{
    235 
    236 			dng_timer timer ("Interpolate time");
    237 
    238 			negative->BuildStage3Image (host,
    239 									    gMosaicPlane);
    240 
    241 			}
    242 
    243 		// Convert to proxy, if requested.
    244 
    245 		if (gProxyDNGSize)
    246 			{
    247 
    248 			dng_timer timer ("ConvertToProxy time");
    249 
    250 			dng_image_writer writer;
    251 
    252 			negative->ConvertToProxy (host,
    253 									  writer,
    254 									  gProxyDNGSize);
    255 
    256 			}
    257 
    258 		// Flatten transparency, if required.
    259 
    260 		if (negative->NeedFlattenTransparency (host))
    261 			{
    262 
    263 			dng_timer timer ("FlattenTransparency time");
    264 
    265 			negative->FlattenTransparency (host);
    266 
    267 			}
    268 
    269 		if (gDumpStage3.NotEmpty ())
    270 			{
    271 
    272 			dng_file_stream stream2 (gDumpStage3.Get (), true);
    273 
    274 			const dng_image &stage3 = *negative->Stage3Image ();
    275 
    276 			dng_image_writer writer;
    277 
    278 			writer.WriteTIFF (host,
    279 							  stream2,
    280 							  stage3,
    281 							  stage3.Planes () >= 3 ? piRGB
    282 												    : piBlackIsZero);
    283 
    284 			gDumpStage3.Clear ();
    285 
    286 			}
    287 
    288 		// Output DNG file if requested.
    289 
    290 		if (gDumpDNG.NotEmpty ())
    291 			{
    292 
    293 			// Build the preview list.
    294 
    295 			dng_preview_list previewList;
    296 
    297 			dng_date_time_info dateTimeInfo;
    298 
    299 			CurrentDateTimeAndZone (dateTimeInfo);
    300 
    301 			for (uint32 previewIndex = 0; previewIndex < 2; previewIndex++)
    302 				{
    303 
    304 				// Skip preview if writing a compresssed main image to save space
    305 				// in this example code.
    306 
    307 				if (negative->RawJPEGImage () != NULL && previewIndex > 0)
    308 					{
    309 					break;
    310 					}
    311 
    312 				// Report timing.
    313 
    314 				dng_timer timer (previewIndex == 0 ? "Build thumbnail time"
    315 												   : "Build preview time");
    316 
    317 				// Render a preview sized image.
    318 
    319 				AutoPtr<dng_image> previewImage;
    320 
    321 					{
    322 
    323 					dng_render render (host, *negative);
    324 
    325 					render.SetFinalSpace (negative->IsMonochrome () ? dng_space_GrayGamma22::Get ()
    326 																	: dng_space_sRGB       ::Get ());
    327 
    328 					render.SetFinalPixelType (ttByte);
    329 
    330 					render.SetMaximumSize (previewIndex == 0 ? 256 : 1024);
    331 
    332 					previewImage.Reset (render.Render ());
    333 
    334 					}
    335 
    336 				// Don't write the preview if it is same size as thumbnail.
    337 
    338 				if (previewIndex > 0 &&
    339 					Max_uint32 (previewImage->Bounds ().W (),
    340 								previewImage->Bounds ().H ()) <= 256)
    341 					{
    342 					break;
    343 					}
    344 
    345 				// If we have compressed JPEG data, create a compressed thumbnail.  Otherwise
    346 				// save a uncompressed thumbnail.
    347 
    348 				bool useCompressedPreview = (negative->RawJPEGImage () != NULL) ||
    349 											(previewIndex > 0);
    350 
    351 				AutoPtr<dng_preview> preview (useCompressedPreview ?
    352 											  (dng_preview *) new dng_jpeg_preview :
    353 											  (dng_preview *) new dng_image_preview);
    354 
    355 				// Setup up preview info.
    356 
    357 				preview->fInfo.fApplicationName   .Set ("dng_validate");
    358 				preview->fInfo.fApplicationVersion.Set (kDNGValidateVersion);
    359 
    360 				preview->fInfo.fSettingsName.Set ("Default");
    361 
    362 				preview->fInfo.fColorSpace = previewImage->Planes () == 1 ?
    363 											 previewColorSpace_GrayGamma22 :
    364 											 previewColorSpace_sRGB;
    365 
    366 				preview->fInfo.fDateTime = dateTimeInfo.Encode_ISO_8601 ();
    367 
    368 				if (!useCompressedPreview)
    369 					{
    370 
    371 					dng_image_preview *imagePreview = dynamic_cast<dng_image_preview *> (preview.Get ());
    372 
    373 					imagePreview->fImage.Reset (previewImage.Release ());
    374 
    375 					}
    376 
    377 				else
    378 					{
    379 
    380 					dng_jpeg_preview *jpegPreview = dynamic_cast<dng_jpeg_preview *> (preview.Get ());
    381 
    382 					int32 quality = (previewIndex == 0 ? 8 : 5);
    383 
    384 					dng_image_writer writer;
    385 
    386 					writer.EncodeJPEGPreview (host,
    387 										      *previewImage,
    388 										      *jpegPreview,
    389 											  quality);
    390 
    391 					}
    392 
    393 				previewList.Append (preview);
    394 
    395 				}
    396 
    397 			// Write DNG file.
    398 
    399 			dng_file_stream stream2 (gDumpDNG.Get (), true);
    400 
    401 				{
    402 
    403 				dng_timer timer ("Write DNG time");
    404 
    405 				dng_image_writer writer;
    406 
    407 				writer.WriteDNG (host,
    408 								 stream2,
    409 								 *negative.Get (),
    410 								 &previewList,
    411 								 dngVersion_Current,
    412 								 false);
    413 
    414 				}
    415 
    416 			gDumpDNG.Clear ();
    417 
    418 			}
    419 
    420 		// Output TIF file if requested.
    421 
    422 		if (gDumpTIF.NotEmpty ())
    423 			{
    424 
    425 			// Render final image.
    426 
    427 			dng_render render (host, *negative);
    428 
    429 			render.SetFinalSpace     (*gFinalSpace   );
    430 			render.SetFinalPixelType (gFinalPixelType);
    431 
    432 			if (host.MinimumSize ())
    433 				{
    434 
    435 				dng_point stage3Size = negative->Stage3Image ()->Size ();
    436 
    437 				render.SetMaximumSize (Max_uint32 (stage3Size.v,
    438 												   stage3Size.h));
    439 
    440 				}
    441 
    442 			AutoPtr<dng_image> finalImage;
    443 
    444 				{
    445 
    446 				dng_timer timer ("Render time");
    447 
    448 				finalImage.Reset (render.Render ());
    449 
    450 				}
    451 
    452 			finalImage->Rotate (negative->Orientation ());
    453 
    454 			// Now that Camera Raw supports non-raw formats, we should
    455 			// not keep any Camera Raw settings in the XMP around when
    456 			// writing rendered files.
    457 
    458 			#if qDNGUseXMP
    459 
    460 			if (negative->GetXMP ())
    461 				{
    462 
    463 				negative->GetXMP ()->RemoveProperties (XMP_NS_CRS);
    464 				negative->GetXMP ()->RemoveProperties (XMP_NS_CRSS);
    465 
    466 				}
    467 
    468 			#endif
    469 
    470 			// Write TIF file.
    471 
    472 			dng_file_stream stream2 (gDumpTIF.Get (), true);
    473 
    474 				{
    475 
    476 				dng_timer timer ("Write TIFF time");
    477 
    478 				dng_image_writer writer;
    479 
    480 				writer.WriteTIFF (host,
    481 								  stream2,
    482 								  *finalImage.Get (),
    483 								  finalImage->Planes () >= 3 ? piRGB
    484 															 : piBlackIsZero,
    485 								  ccUncompressed,
    486 								  negative.Get (),
    487 								  &render.FinalSpace ());
    488 
    489 				}
    490 
    491 			gDumpTIF.Clear ();
    492 
    493 			}
    494 
    495 		}
    496 
    497 	catch (const dng_exception &except)
    498 		{
    499 
    500 		return except.ErrorCode ();
    501 
    502 		}
    503 
    504 	catch (...)
    505 		{
    506 
    507 		return dng_error_unknown;
    508 
    509 		}
    510 
    511 	printf ("Validation complete\n");
    512 
    513 	return dng_error_none;
    514 
    515 	}
    516 
    517 /*****************************************************************************/
    518 
    519 int main (int argc, char *argv [])
    520 	{
    521 
    522 	try
    523 		{
    524 
    525 		if (argc == 1)
    526 			{
    527 
    528 			fprintf (stderr,
    529 					 "\n"
    530 					 "dng_validate, version " kDNGValidateVersion " "
    531 					 #if qDNG64Bit
    532 					 "(64-bit)"
    533 					 #else
    534 					 "(32-bit)"
    535 					 #endif
    536 					 "\n"
    537 					 "Copyright 2005-2012 Adobe Systems, Inc.\n"
    538 					 "\n"
    539 					 "Usage:  %s [options] file1 file2 ...\n"
    540 					 "\n"
    541 					 "Valid options:\n"
    542 					 "-v            Verbose mode\n"
    543 					 "-d <num>      Dump line limit (implies -v)\n"
    544 					 "-b4           Use four-color Bayer interpolation\n"
    545 					 "-s <num>      Use this sample of multi-sample CFAs\n"
    546 					 "-size <num>   Preferred preview image size\n"
    547 					 "-min <num>    Minimum preview image size\n"
    548 					 "-max <num>    Maximum preview image size\n"
    549 					 "-proxy <num>  Target size for proxy DNG\n"
    550 					 "-cs1          Color space: \"sRGB\" (default)\n"
    551 					 "-cs2          Color space: \"Adobe RGB\"\n"
    552 					 "-cs3          Color space: \"ProPhoto RGB\"\n"
    553 					 "-cs4          Color space: \"ColorMatch RGB\"\n"
    554 					 "-cs5          Color space: \"Gray Gamma 1.8\"\n"
    555 					 "-cs6          Color space: \"Gray Gamma 2.2\"\n"
    556 					 "-16           16-bits/channel output\n"
    557 					 "-1 <file>     Write stage 1 image to \"<file>.tif\"\n"
    558 					 "-2 <file>     Write stage 2 image to \"<file>.tif\"\n"
    559 					 "-3 <file>     Write stage 3 image to \"<file>.tif\"\n"
    560 					 "-tif <file>   Write TIF image to \"<file>.tif\"\n"
    561 					 "-dng <file>   Write DNG image to \"<file>.dng\"\n"
    562 					 "\n",
    563 					 argv [0]);
    564 
    565 			return 1;
    566 
    567 			}
    568 
    569 		int index;
    570 
    571 		for (index = 1; index < argc && argv [index] [0] == '-'; index++)
    572 			{
    573 
    574 			dng_string option;
    575 
    576 			option.Set (&argv [index] [1]);
    577 
    578 			if (option.Matches ("v", true))
    579 				{
    580 				gVerbose = true;
    581 				}
    582 
    583 			else if (option.Matches ("d", true))
    584 				{
    585 
    586 				gVerbose = true;
    587 
    588 				gDumpLineLimit = 0;
    589 
    590 				if (index + 1 < argc)
    591 					{
    592 					gDumpLineLimit = atoi (argv [++index]);
    593 					}
    594 
    595 				if (!gDumpLineLimit)
    596 					{
    597 					fprintf (stderr, "*** Invalid number after -d\n");
    598 					return 1;
    599 					}
    600 
    601 				}
    602 
    603 			else if (option.Matches ("s", true))
    604 				{
    605 
    606 				if (index + 1 < argc)
    607 					{
    608 					gMosaicPlane = atoi (argv [++index]);
    609 					}
    610 
    611 				else
    612 					{
    613 					fprintf (stderr, "*** Missing number after -s\n");
    614 					return 1;
    615 					}
    616 
    617 				}
    618 
    619 			else if (option.Matches ("b4", true))
    620 				{
    621 				gFourColorBayer = true;
    622 				}
    623 
    624 			else if (option.Matches ("size", true))
    625 				{
    626 
    627 				if (index + 1 < argc)
    628 					{
    629 					gPreferredSize = (uint32) atoi (argv [++index]);
    630 					}
    631 
    632 				else
    633 					{
    634 					fprintf (stderr, "*** Missing number after -size\n");
    635 					return 1;
    636 					}
    637 
    638 				}
    639 
    640 			else if (option.Matches ("min", true))
    641 				{
    642 
    643 				if (index + 1 < argc)
    644 					{
    645 					gMinimumSize = (uint32) atoi (argv [++index]);
    646 					}
    647 
    648 				else
    649 					{
    650 					fprintf (stderr, "*** Missing number after -min\n");
    651 					return 1;
    652 					}
    653 
    654 				}
    655 
    656 			else if (option.Matches ("max", true))
    657 				{
    658 
    659 				if (index + 1 < argc)
    660 					{
    661 					gMaximumSize = (uint32) atoi (argv [++index]);
    662 					}
    663 
    664 				else
    665 					{
    666 					fprintf (stderr, "*** Missing number after -max\n");
    667 					return 1;
    668 					}
    669 
    670 				}
    671 
    672 			else if (option.Matches ("proxy", true))
    673 				{
    674 
    675 				if (index + 1 < argc)
    676 					{
    677 					gProxyDNGSize = (uint32) atoi (argv [++index]);
    678 					}
    679 
    680 				else
    681 					{
    682 					fprintf (stderr, "*** Missing number after -proxy\n");
    683 					return 1;
    684 					}
    685 
    686 				}
    687 
    688 			else if (option.Matches ("cs1", true))
    689 				{
    690 
    691 				gFinalSpace = &dng_space_sRGB::Get ();
    692 
    693 				}
    694 
    695 			else if (option.Matches ("cs2", true))
    696 				{
    697 
    698 				gFinalSpace = &dng_space_AdobeRGB::Get ();
    699 
    700 				}
    701 
    702 			else if (option.Matches ("cs3", true))
    703 				{
    704 
    705 				gFinalSpace = &dng_space_ProPhoto::Get ();
    706 
    707 				}
    708 
    709 			else if (option.Matches ("cs4", true))
    710 				{
    711 
    712 				gFinalSpace = &dng_space_ColorMatch::Get ();
    713 
    714 				}
    715 
    716 			else if (option.Matches ("cs5", true))
    717 				{
    718 
    719 				gFinalSpace = &dng_space_GrayGamma18::Get ();
    720 
    721 				}
    722 
    723 			else if (option.Matches ("cs6", true))
    724 				{
    725 
    726 				gFinalSpace = &dng_space_GrayGamma22::Get ();
    727 
    728 				}
    729 
    730 			else if (option.Matches ("16"))
    731 				{
    732 
    733 				gFinalPixelType = ttShort;
    734 
    735 				}
    736 
    737 			else if (option.Matches ("1"))
    738 				{
    739 
    740 				gDumpStage1.Clear ();
    741 
    742 				if (index + 1 < argc)
    743 					{
    744 					gDumpStage1.Set (argv [++index]);
    745 					}
    746 
    747 				if (gDumpStage1.IsEmpty () || gDumpStage1.StartsWith ("-"))
    748 					{
    749 					fprintf (stderr, "*** Missing file name after -1\n");
    750 					return 1;
    751 					}
    752 
    753 				if (!gDumpStage1.EndsWith (".tif"))
    754 					{
    755 					gDumpStage1.Append (".tif");
    756 					}
    757 
    758 				}
    759 
    760 			else if (option.Matches ("2"))
    761 				{
    762 
    763 				gDumpStage2.Clear ();
    764 
    765 				if (index + 1 < argc)
    766 					{
    767 					gDumpStage2.Set (argv [++index]);
    768 					}
    769 
    770 				if (gDumpStage2.IsEmpty () || gDumpStage2.StartsWith ("-"))
    771 					{
    772 					fprintf (stderr, "*** Missing file name after -2\n");
    773 					return 1;
    774 					}
    775 
    776 				if (!gDumpStage2.EndsWith (".tif"))
    777 					{
    778 					gDumpStage2.Append (".tif");
    779 					}
    780 
    781 				}
    782 
    783 			else if (option.Matches ("3"))
    784 				{
    785 
    786 				gDumpStage3.Clear ();
    787 
    788 				if (index + 1 < argc)
    789 					{
    790 					gDumpStage3.Set (argv [++index]);
    791 					}
    792 
    793 				if (gDumpStage3.IsEmpty () || gDumpStage3.StartsWith ("-"))
    794 					{
    795 					fprintf (stderr, "*** Missing file name after -3\n");
    796 					return 1;
    797 					}
    798 
    799 				if (!gDumpStage3.EndsWith (".tif"))
    800 					{
    801 					gDumpStage3.Append (".tif");
    802 					}
    803 
    804 				}
    805 
    806 			else if (option.Matches ("tif", true))
    807 				{
    808 
    809 				gDumpTIF.Clear ();
    810 
    811 				if (index + 1 < argc)
    812 					{
    813 					gDumpTIF.Set (argv [++index]);
    814 					}
    815 
    816 				if (gDumpTIF.IsEmpty () || gDumpTIF.StartsWith ("-"))
    817 					{
    818 					fprintf (stderr, "*** Missing file name after -tif\n");
    819 					return 1;
    820 					}
    821 
    822 				if (!gDumpTIF.EndsWith (".tif"))
    823 					{
    824 					gDumpTIF.Append (".tif");
    825 					}
    826 
    827 				}
    828 
    829 			else if (option.Matches ("dng", true))
    830 				{
    831 
    832 				gDumpDNG.Clear ();
    833 
    834 				if (index + 1 < argc)
    835 					{
    836 					gDumpDNG.Set (argv [++index]);
    837 					}
    838 
    839 				if (gDumpDNG.IsEmpty () || gDumpDNG.StartsWith ("-"))
    840 					{
    841 					fprintf (stderr, "*** Missing file name after -dng\n");
    842 					return 1;
    843 					}
    844 
    845 				if (!gDumpDNG.EndsWith (".dng"))
    846 					{
    847 					gDumpDNG.Append (".dng");
    848 					}
    849 
    850 				}
    851 
    852 			else
    853 				{
    854 				fprintf (stderr, "*** Unknown option \"-%s\"\n", option.Get ());
    855 				return 1;
    856 				}
    857 
    858 			}
    859 
    860 		if (index == argc)
    861 			{
    862 			fprintf (stderr, "*** No file specified\n");
    863 			return 1;
    864 			}
    865 
    866 		#if qDNGUseXMP
    867 
    868 		dng_xmp_sdk::InitializeSDK ();
    869 
    870 		#endif
    871 
    872 		int result = 0;
    873 
    874 		while (index < argc)
    875 			{
    876 
    877 			dng_error_code error_code = dng_validate (argv [index++]);
    878 			if (error_code != dng_error_none)
    879 				{
    880 
    881 				result = error_code - dng_error_unknown + 100;
    882 
    883 				}
    884 
    885 			}
    886 
    887 		#if qDNGUseXMP
    888 
    889 		dng_xmp_sdk::TerminateSDK ();
    890 
    891 		#endif
    892 
    893 		return result;
    894 
    895 		}
    896 
    897 	catch (...)
    898 		{
    899 
    900 		}
    901 
    902 	fprintf (stderr, "*** Exception thrown in main routine\n");
    903 
    904 	return 1;
    905 
    906 	}
    907 
    908 /*****************************************************************************/
    909 
    910 #endif
    911 
    912 /*****************************************************************************/
    913