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