You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
913 lines
18 KiB
913 lines
18 KiB
/*****************************************************************************/
|
|
// Copyright 2006-2012 Adobe Systems Incorporated
|
|
// All Rights Reserved.
|
|
//
|
|
// NOTICE: Adobe permits you to use, modify, and distribute this file in
|
|
// accordance with the terms of the Adobe license agreement accompanying it.
|
|
/*****************************************************************************/
|
|
|
|
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_validate.cpp#2 $ */
|
|
/* $DateTime: 2012/06/14 20:24:41 $ */
|
|
/* $Change: 835078 $ */
|
|
/* $Author: tknoll $ */
|
|
|
|
// Process exit codes
|
|
// ------------------
|
|
//
|
|
// As usual, 0 indicates success.
|
|
//
|
|
// If an exception occurs, the exit code will be equal to:
|
|
//
|
|
// DNG SDK error code - 100000 + 100
|
|
//
|
|
// For example, the error dng_error_memory, which has a DNG SDK error code of
|
|
// 100005, is returned as an exit code of 105.
|
|
//
|
|
// This convention accounts for the fact that the shell truncates process exit
|
|
// codes to 8 bits and that the exit code 1 is used by ASAN to signal that a
|
|
// memory error occurred (so mapping the first DNG SDK error code to an exit
|
|
// code of 1 would not be a good idea).
|
|
|
|
/*****************************************************************************/
|
|
|
|
#include "dng_color_space.h"
|
|
#include "dng_date_time.h"
|
|
#include "dng_exceptions.h"
|
|
#include "dng_file_stream.h"
|
|
#include "dng_globals.h"
|
|
#include "dng_host.h"
|
|
#include "dng_ifd.h"
|
|
#include "dng_image_writer.h"
|
|
#include "dng_info.h"
|
|
#include "dng_linearization_info.h"
|
|
#include "dng_mosaic_info.h"
|
|
#include "dng_negative.h"
|
|
#include "dng_preview.h"
|
|
#include "dng_render.h"
|
|
#include "dng_simple_image.h"
|
|
#include "dng_tag_codes.h"
|
|
#include "dng_tag_types.h"
|
|
#include "dng_tag_values.h"
|
|
|
|
#if qDNGUseXMP
|
|
#include "dng_xmp.h"
|
|
#include "dng_xmp_sdk.h"
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
#if qDNGValidateTarget
|
|
|
|
/*****************************************************************************/
|
|
|
|
#define kDNGValidateVersion "1.4"
|
|
|
|
/*****************************************************************************/
|
|
|
|
static bool gFourColorBayer = false;
|
|
|
|
static int32 gMosaicPlane = -1;
|
|
|
|
static uint32 gPreferredSize = 0;
|
|
static uint32 gMinimumSize = 0;
|
|
static uint32 gMaximumSize = 0;
|
|
|
|
static uint32 gProxyDNGSize = 0;
|
|
|
|
static const dng_color_space *gFinalSpace = &dng_space_sRGB::Get ();
|
|
|
|
static uint32 gFinalPixelType = ttByte;
|
|
|
|
static dng_string gDumpStage1;
|
|
static dng_string gDumpStage2;
|
|
static dng_string gDumpStage3;
|
|
static dng_string gDumpTIF;
|
|
static dng_string gDumpDNG;
|
|
|
|
/*****************************************************************************/
|
|
|
|
static dng_error_code dng_validate (const char *filename)
|
|
{
|
|
|
|
printf ("Validating \"%s\"...\n", filename);
|
|
|
|
try
|
|
{
|
|
|
|
dng_file_stream stream (filename);
|
|
|
|
dng_host host;
|
|
|
|
host.SetPreferredSize (gPreferredSize);
|
|
host.SetMinimumSize (gMinimumSize );
|
|
host.SetMaximumSize (gMaximumSize );
|
|
|
|
host.ValidateSizes ();
|
|
|
|
if (host.MinimumSize ())
|
|
{
|
|
|
|
host.SetForPreview (true);
|
|
|
|
gDumpDNG.Clear ();
|
|
|
|
}
|
|
|
|
if (gDumpDNG.NotEmpty ())
|
|
{
|
|
|
|
host.SetSaveDNGVersion (dngVersion_SaveDefault);
|
|
|
|
host.SetSaveLinearDNG (false);
|
|
|
|
host.SetKeepOriginalFile (false);
|
|
|
|
}
|
|
|
|
// Read into the negative.
|
|
|
|
AutoPtr<dng_negative> negative;
|
|
|
|
{
|
|
|
|
dng_info info;
|
|
|
|
info.Parse (host, stream);
|
|
|
|
info.PostParse (host);
|
|
|
|
if (!info.IsValidDNG ())
|
|
{
|
|
return dng_error_bad_format;
|
|
}
|
|
|
|
negative.Reset (host.Make_dng_negative ());
|
|
|
|
negative->Parse (host, stream, info);
|
|
|
|
negative->PostParse (host, stream, info);
|
|
|
|
{
|
|
|
|
dng_timer timer ("Raw image read time");
|
|
|
|
negative->ReadStage1Image (host, stream, info);
|
|
|
|
}
|
|
|
|
if (info.fMaskIndex != -1)
|
|
{
|
|
|
|
dng_timer timer ("Transparency mask read time");
|
|
|
|
negative->ReadTransparencyMask (host, stream, info);
|
|
|
|
}
|
|
|
|
negative->ValidateRawImageDigest (host);
|
|
|
|
}
|
|
|
|
// Option to write stage 1 image.
|
|
|
|
if (gDumpStage1.NotEmpty ())
|
|
{
|
|
|
|
dng_file_stream stream2 (gDumpStage1.Get (), true);
|
|
|
|
const dng_image &stage1 = *negative->Stage1Image ();
|
|
|
|
dng_image_writer writer;
|
|
|
|
writer.WriteTIFF (host,
|
|
stream2,
|
|
stage1,
|
|
stage1.Planes () >= 3 ? piRGB
|
|
: piBlackIsZero);
|
|
|
|
gDumpStage1.Clear ();
|
|
|
|
}
|
|
|
|
// Metadata.
|
|
|
|
negative->SynchronizeMetadata ();
|
|
|
|
// Four color Bayer option.
|
|
|
|
if (gFourColorBayer)
|
|
{
|
|
negative->SetFourColorBayer ();
|
|
}
|
|
|
|
// Build stage 2 image.
|
|
|
|
{
|
|
|
|
dng_timer timer ("Linearization time");
|
|
|
|
negative->BuildStage2Image (host);
|
|
|
|
}
|
|
|
|
if (gDumpStage2.NotEmpty ())
|
|
{
|
|
|
|
dng_file_stream stream2 (gDumpStage2.Get (), true);
|
|
|
|
const dng_image &stage2 = *negative->Stage2Image ();
|
|
|
|
dng_image_writer writer;
|
|
|
|
writer.WriteTIFF (host,
|
|
stream2,
|
|
stage2,
|
|
stage2.Planes () >= 3 ? piRGB
|
|
: piBlackIsZero);
|
|
|
|
gDumpStage2.Clear ();
|
|
|
|
}
|
|
|
|
// Build stage 3 image.
|
|
|
|
{
|
|
|
|
dng_timer timer ("Interpolate time");
|
|
|
|
negative->BuildStage3Image (host,
|
|
gMosaicPlane);
|
|
|
|
}
|
|
|
|
// Convert to proxy, if requested.
|
|
|
|
if (gProxyDNGSize)
|
|
{
|
|
|
|
dng_timer timer ("ConvertToProxy time");
|
|
|
|
dng_image_writer writer;
|
|
|
|
negative->ConvertToProxy (host,
|
|
writer,
|
|
gProxyDNGSize);
|
|
|
|
}
|
|
|
|
// Flatten transparency, if required.
|
|
|
|
if (negative->NeedFlattenTransparency (host))
|
|
{
|
|
|
|
dng_timer timer ("FlattenTransparency time");
|
|
|
|
negative->FlattenTransparency (host);
|
|
|
|
}
|
|
|
|
if (gDumpStage3.NotEmpty ())
|
|
{
|
|
|
|
dng_file_stream stream2 (gDumpStage3.Get (), true);
|
|
|
|
const dng_image &stage3 = *negative->Stage3Image ();
|
|
|
|
dng_image_writer writer;
|
|
|
|
writer.WriteTIFF (host,
|
|
stream2,
|
|
stage3,
|
|
stage3.Planes () >= 3 ? piRGB
|
|
: piBlackIsZero);
|
|
|
|
gDumpStage3.Clear ();
|
|
|
|
}
|
|
|
|
// Output DNG file if requested.
|
|
|
|
if (gDumpDNG.NotEmpty ())
|
|
{
|
|
|
|
// Build the preview list.
|
|
|
|
dng_preview_list previewList;
|
|
|
|
dng_date_time_info dateTimeInfo;
|
|
|
|
CurrentDateTimeAndZone (dateTimeInfo);
|
|
|
|
for (uint32 previewIndex = 0; previewIndex < 2; previewIndex++)
|
|
{
|
|
|
|
// Skip preview if writing a compresssed main image to save space
|
|
// in this example code.
|
|
|
|
if (negative->RawJPEGImage () != NULL && previewIndex > 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Report timing.
|
|
|
|
dng_timer timer (previewIndex == 0 ? "Build thumbnail time"
|
|
: "Build preview time");
|
|
|
|
// Render a preview sized image.
|
|
|
|
AutoPtr<dng_image> previewImage;
|
|
|
|
{
|
|
|
|
dng_render render (host, *negative);
|
|
|
|
render.SetFinalSpace (negative->IsMonochrome () ? dng_space_GrayGamma22::Get ()
|
|
: dng_space_sRGB ::Get ());
|
|
|
|
render.SetFinalPixelType (ttByte);
|
|
|
|
render.SetMaximumSize (previewIndex == 0 ? 256 : 1024);
|
|
|
|
previewImage.Reset (render.Render ());
|
|
|
|
}
|
|
|
|
// Don't write the preview if it is same size as thumbnail.
|
|
|
|
if (previewIndex > 0 &&
|
|
Max_uint32 (previewImage->Bounds ().W (),
|
|
previewImage->Bounds ().H ()) <= 256)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// If we have compressed JPEG data, create a compressed thumbnail. Otherwise
|
|
// save a uncompressed thumbnail.
|
|
|
|
bool useCompressedPreview = (negative->RawJPEGImage () != NULL) ||
|
|
(previewIndex > 0);
|
|
|
|
AutoPtr<dng_preview> preview (useCompressedPreview ?
|
|
(dng_preview *) new dng_jpeg_preview :
|
|
(dng_preview *) new dng_image_preview);
|
|
|
|
// Setup up preview info.
|
|
|
|
preview->fInfo.fApplicationName .Set ("dng_validate");
|
|
preview->fInfo.fApplicationVersion.Set (kDNGValidateVersion);
|
|
|
|
preview->fInfo.fSettingsName.Set ("Default");
|
|
|
|
preview->fInfo.fColorSpace = previewImage->Planes () == 1 ?
|
|
previewColorSpace_GrayGamma22 :
|
|
previewColorSpace_sRGB;
|
|
|
|
preview->fInfo.fDateTime = dateTimeInfo.Encode_ISO_8601 ();
|
|
|
|
if (!useCompressedPreview)
|
|
{
|
|
|
|
dng_image_preview *imagePreview = dynamic_cast<dng_image_preview *> (preview.Get ());
|
|
|
|
imagePreview->fImage.Reset (previewImage.Release ());
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
|
|
dng_jpeg_preview *jpegPreview = dynamic_cast<dng_jpeg_preview *> (preview.Get ());
|
|
|
|
int32 quality = (previewIndex == 0 ? 8 : 5);
|
|
|
|
dng_image_writer writer;
|
|
|
|
writer.EncodeJPEGPreview (host,
|
|
*previewImage,
|
|
*jpegPreview,
|
|
quality);
|
|
|
|
}
|
|
|
|
previewList.Append (preview);
|
|
|
|
}
|
|
|
|
// Write DNG file.
|
|
|
|
dng_file_stream stream2 (gDumpDNG.Get (), true);
|
|
|
|
{
|
|
|
|
dng_timer timer ("Write DNG time");
|
|
|
|
dng_image_writer writer;
|
|
|
|
writer.WriteDNG (host,
|
|
stream2,
|
|
*negative.Get (),
|
|
&previewList,
|
|
dngVersion_Current,
|
|
false);
|
|
|
|
}
|
|
|
|
gDumpDNG.Clear ();
|
|
|
|
}
|
|
|
|
// Output TIF file if requested.
|
|
|
|
if (gDumpTIF.NotEmpty ())
|
|
{
|
|
|
|
// Render final image.
|
|
|
|
dng_render render (host, *negative);
|
|
|
|
render.SetFinalSpace (*gFinalSpace );
|
|
render.SetFinalPixelType (gFinalPixelType);
|
|
|
|
if (host.MinimumSize ())
|
|
{
|
|
|
|
dng_point stage3Size = negative->Stage3Image ()->Size ();
|
|
|
|
render.SetMaximumSize (Max_uint32 (stage3Size.v,
|
|
stage3Size.h));
|
|
|
|
}
|
|
|
|
AutoPtr<dng_image> finalImage;
|
|
|
|
{
|
|
|
|
dng_timer timer ("Render time");
|
|
|
|
finalImage.Reset (render.Render ());
|
|
|
|
}
|
|
|
|
finalImage->Rotate (negative->Orientation ());
|
|
|
|
// Now that Camera Raw supports non-raw formats, we should
|
|
// not keep any Camera Raw settings in the XMP around when
|
|
// writing rendered files.
|
|
|
|
#if qDNGUseXMP
|
|
|
|
if (negative->GetXMP ())
|
|
{
|
|
|
|
negative->GetXMP ()->RemoveProperties (XMP_NS_CRS);
|
|
negative->GetXMP ()->RemoveProperties (XMP_NS_CRSS);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// Write TIF file.
|
|
|
|
dng_file_stream stream2 (gDumpTIF.Get (), true);
|
|
|
|
{
|
|
|
|
dng_timer timer ("Write TIFF time");
|
|
|
|
dng_image_writer writer;
|
|
|
|
writer.WriteTIFF (host,
|
|
stream2,
|
|
*finalImage.Get (),
|
|
finalImage->Planes () >= 3 ? piRGB
|
|
: piBlackIsZero,
|
|
ccUncompressed,
|
|
negative.Get (),
|
|
&render.FinalSpace ());
|
|
|
|
}
|
|
|
|
gDumpTIF.Clear ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const dng_exception &except)
|
|
{
|
|
|
|
return except.ErrorCode ();
|
|
|
|
}
|
|
|
|
catch (...)
|
|
{
|
|
|
|
return dng_error_unknown;
|
|
|
|
}
|
|
|
|
printf ("Validation complete\n");
|
|
|
|
return dng_error_none;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int main (int argc, char *argv [])
|
|
{
|
|
|
|
try
|
|
{
|
|
|
|
if (argc == 1)
|
|
{
|
|
|
|
fprintf (stderr,
|
|
"\n"
|
|
"dng_validate, version " kDNGValidateVersion " "
|
|
#if qDNG64Bit
|
|
"(64-bit)"
|
|
#else
|
|
"(32-bit)"
|
|
#endif
|
|
"\n"
|
|
"Copyright 2005-2012 Adobe Systems, Inc.\n"
|
|
"\n"
|
|
"Usage: %s [options] file1 file2 ...\n"
|
|
"\n"
|
|
"Valid options:\n"
|
|
"-v Verbose mode\n"
|
|
"-d <num> Dump line limit (implies -v)\n"
|
|
"-b4 Use four-color Bayer interpolation\n"
|
|
"-s <num> Use this sample of multi-sample CFAs\n"
|
|
"-size <num> Preferred preview image size\n"
|
|
"-min <num> Minimum preview image size\n"
|
|
"-max <num> Maximum preview image size\n"
|
|
"-proxy <num> Target size for proxy DNG\n"
|
|
"-cs1 Color space: \"sRGB\" (default)\n"
|
|
"-cs2 Color space: \"Adobe RGB\"\n"
|
|
"-cs3 Color space: \"ProPhoto RGB\"\n"
|
|
"-cs4 Color space: \"ColorMatch RGB\"\n"
|
|
"-cs5 Color space: \"Gray Gamma 1.8\"\n"
|
|
"-cs6 Color space: \"Gray Gamma 2.2\"\n"
|
|
"-16 16-bits/channel output\n"
|
|
"-1 <file> Write stage 1 image to \"<file>.tif\"\n"
|
|
"-2 <file> Write stage 2 image to \"<file>.tif\"\n"
|
|
"-3 <file> Write stage 3 image to \"<file>.tif\"\n"
|
|
"-tif <file> Write TIF image to \"<file>.tif\"\n"
|
|
"-dng <file> Write DNG image to \"<file>.dng\"\n"
|
|
"\n",
|
|
argv [0]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
int index;
|
|
|
|
for (index = 1; index < argc && argv [index] [0] == '-'; index++)
|
|
{
|
|
|
|
dng_string option;
|
|
|
|
option.Set (&argv [index] [1]);
|
|
|
|
if (option.Matches ("v", true))
|
|
{
|
|
gVerbose = true;
|
|
}
|
|
|
|
else if (option.Matches ("d", true))
|
|
{
|
|
|
|
gVerbose = true;
|
|
|
|
gDumpLineLimit = 0;
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gDumpLineLimit = atoi (argv [++index]);
|
|
}
|
|
|
|
if (!gDumpLineLimit)
|
|
{
|
|
fprintf (stderr, "*** Invalid number after -d\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("s", true))
|
|
{
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gMosaicPlane = atoi (argv [++index]);
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf (stderr, "*** Missing number after -s\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("b4", true))
|
|
{
|
|
gFourColorBayer = true;
|
|
}
|
|
|
|
else if (option.Matches ("size", true))
|
|
{
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gPreferredSize = (uint32) atoi (argv [++index]);
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf (stderr, "*** Missing number after -size\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("min", true))
|
|
{
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gMinimumSize = (uint32) atoi (argv [++index]);
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf (stderr, "*** Missing number after -min\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("max", true))
|
|
{
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gMaximumSize = (uint32) atoi (argv [++index]);
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf (stderr, "*** Missing number after -max\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("proxy", true))
|
|
{
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gProxyDNGSize = (uint32) atoi (argv [++index]);
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf (stderr, "*** Missing number after -proxy\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("cs1", true))
|
|
{
|
|
|
|
gFinalSpace = &dng_space_sRGB::Get ();
|
|
|
|
}
|
|
|
|
else if (option.Matches ("cs2", true))
|
|
{
|
|
|
|
gFinalSpace = &dng_space_AdobeRGB::Get ();
|
|
|
|
}
|
|
|
|
else if (option.Matches ("cs3", true))
|
|
{
|
|
|
|
gFinalSpace = &dng_space_ProPhoto::Get ();
|
|
|
|
}
|
|
|
|
else if (option.Matches ("cs4", true))
|
|
{
|
|
|
|
gFinalSpace = &dng_space_ColorMatch::Get ();
|
|
|
|
}
|
|
|
|
else if (option.Matches ("cs5", true))
|
|
{
|
|
|
|
gFinalSpace = &dng_space_GrayGamma18::Get ();
|
|
|
|
}
|
|
|
|
else if (option.Matches ("cs6", true))
|
|
{
|
|
|
|
gFinalSpace = &dng_space_GrayGamma22::Get ();
|
|
|
|
}
|
|
|
|
else if (option.Matches ("16"))
|
|
{
|
|
|
|
gFinalPixelType = ttShort;
|
|
|
|
}
|
|
|
|
else if (option.Matches ("1"))
|
|
{
|
|
|
|
gDumpStage1.Clear ();
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gDumpStage1.Set (argv [++index]);
|
|
}
|
|
|
|
if (gDumpStage1.IsEmpty () || gDumpStage1.StartsWith ("-"))
|
|
{
|
|
fprintf (stderr, "*** Missing file name after -1\n");
|
|
return 1;
|
|
}
|
|
|
|
if (!gDumpStage1.EndsWith (".tif"))
|
|
{
|
|
gDumpStage1.Append (".tif");
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("2"))
|
|
{
|
|
|
|
gDumpStage2.Clear ();
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gDumpStage2.Set (argv [++index]);
|
|
}
|
|
|
|
if (gDumpStage2.IsEmpty () || gDumpStage2.StartsWith ("-"))
|
|
{
|
|
fprintf (stderr, "*** Missing file name after -2\n");
|
|
return 1;
|
|
}
|
|
|
|
if (!gDumpStage2.EndsWith (".tif"))
|
|
{
|
|
gDumpStage2.Append (".tif");
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("3"))
|
|
{
|
|
|
|
gDumpStage3.Clear ();
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gDumpStage3.Set (argv [++index]);
|
|
}
|
|
|
|
if (gDumpStage3.IsEmpty () || gDumpStage3.StartsWith ("-"))
|
|
{
|
|
fprintf (stderr, "*** Missing file name after -3\n");
|
|
return 1;
|
|
}
|
|
|
|
if (!gDumpStage3.EndsWith (".tif"))
|
|
{
|
|
gDumpStage3.Append (".tif");
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("tif", true))
|
|
{
|
|
|
|
gDumpTIF.Clear ();
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gDumpTIF.Set (argv [++index]);
|
|
}
|
|
|
|
if (gDumpTIF.IsEmpty () || gDumpTIF.StartsWith ("-"))
|
|
{
|
|
fprintf (stderr, "*** Missing file name after -tif\n");
|
|
return 1;
|
|
}
|
|
|
|
if (!gDumpTIF.EndsWith (".tif"))
|
|
{
|
|
gDumpTIF.Append (".tif");
|
|
}
|
|
|
|
}
|
|
|
|
else if (option.Matches ("dng", true))
|
|
{
|
|
|
|
gDumpDNG.Clear ();
|
|
|
|
if (index + 1 < argc)
|
|
{
|
|
gDumpDNG.Set (argv [++index]);
|
|
}
|
|
|
|
if (gDumpDNG.IsEmpty () || gDumpDNG.StartsWith ("-"))
|
|
{
|
|
fprintf (stderr, "*** Missing file name after -dng\n");
|
|
return 1;
|
|
}
|
|
|
|
if (!gDumpDNG.EndsWith (".dng"))
|
|
{
|
|
gDumpDNG.Append (".dng");
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
{
|
|
fprintf (stderr, "*** Unknown option \"-%s\"\n", option.Get ());
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
if (index == argc)
|
|
{
|
|
fprintf (stderr, "*** No file specified\n");
|
|
return 1;
|
|
}
|
|
|
|
#if qDNGUseXMP
|
|
|
|
dng_xmp_sdk::InitializeSDK ();
|
|
|
|
#endif
|
|
|
|
int result = 0;
|
|
|
|
while (index < argc)
|
|
{
|
|
|
|
dng_error_code error_code = dng_validate (argv [index++]);
|
|
if (error_code != dng_error_none)
|
|
{
|
|
|
|
result = error_code - dng_error_unknown + 100;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if qDNGUseXMP
|
|
|
|
dng_xmp_sdk::TerminateSDK ();
|
|
|
|
#endif
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
catch (...)
|
|
{
|
|
|
|
}
|
|
|
|
fprintf (stderr, "*** Exception thrown in main routine\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
#endif
|
|
|
|
/*****************************************************************************/
|