/*****************************************************************************/
// Copyright 2006-2019 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.
/*****************************************************************************/

// 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_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.7.1"

/*****************************************************************************/

static bool gFourColorBayer = false;

static int32 gMosaicPlane = -1;

static bool gIgnoreEnhanced = false;

static uint32 gPreferredSize = 0;
static uint32 gMinimumSize   = 0;
static uint32 gMaximumSize   = 0;

static uint32 gProxyDNGSize = 0;

static bool gLossyMosaicJXL = false;
static bool gLosslessJXL    = false;

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 gDumpTransparency;
static dng_string gDumpDepthMap;
static dng_string gDumpTIF;
static dng_string gDumpDNG;

static dng_string gCameraProfileName;

/*****************************************************************************/

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);

            host.SetLossyMosaicJXL (gLossyMosaicJXL);
            host.SetLosslessJXL    (gLosslessJXL   );

            }

        host.SetIgnoreEnhanced (gIgnoreEnhanced);

        // 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);

            if (info.fEnhancedIndex != -1 && !host.IgnoreEnhanced ())
                {

                dng_timer timer ("Read enhanced image time");

                negative->ReadEnhancedImage (host, stream, info);

                }

            else
                {

                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);

                }

            if (info.fDepthIndex != -1)
                {

                dng_timer timer ("Depth map read time");

                negative->ReadDepthMap (host, stream, info);

                }

            const bool hasSemanticMasks = !info.fSemanticMaskIndices.empty ();

            if (hasSemanticMasks)
                {

                dng_timer timer ("DNG semantic mask read time");

                negative->ReadSemanticMasks (host,
                                             stream,
                                             info);

                }

            negative->ValidateRawImageDigest (host);

            }

        // Option to write stage 1 image.

        if (gDumpStage1.NotEmpty ())
            {

            if (negative->Stage1Image ())
                {

                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 ();

        // Build stage 2 image.

        if (negative->Stage1Image ())
            {

            dng_timer timer ("Linearization time");

            negative->BuildStage2Image (host);

            }

        if (gDumpStage2.NotEmpty ())
            {

            dng_file_stream stream2 (gDumpStage2.Get (), true);

            if (negative->Stage2Image ())
                {

                const dng_image &stage2 = *negative->Stage2Image ();

                dng_image_writer writer;

                writer.WriteTIFF (host,
                                  stream2,
                                  stage2,
                                  stage2.Planes () >= 3 ? piRGB
                                                        : piBlackIsZero);

                }

            gDumpStage2.Clear ();

            }

        // Four color Bayer option.

        if (gFourColorBayer)
            {
            negative->SetFourColorBayer ();
            }

        // Build stage 3 image.

        if (negative->Stage2Image ())
            {

            dng_timer timer ("Interpolate time");

            negative->BuildStage3Image (host,
                                        gMosaicPlane);

            }

        else
            {

            negative->ResizeTransparencyToMatchStage3 (host);

            negative->ResizeDepthToMatchStage3 (host);

            }

        // Resize semantic masks to match stage 3.

        negative->ResizeSemanticMasksToMatchStage3 (host);

        // Convert to proxy, if requested.

        if (gProxyDNGSize)
            {

            dng_timer timer ("ConvertToProxy time");

            dng_image_writer writer;

            negative->ConvertToProxy (host,
                                      writer,
                                      gProxyDNGSize);

            }

        else if (host.LossyMosaicJXL ())
            {

            dng_timer timer ("Lossy JXL compress mosaic time");

            dng_image_writer writer;

            negative->LossyCompressMosaicJXL (host,
                                              writer);

            }

        if (host.LosslessJXL ())
            {

            dng_timer timer ("Lossless JXL compress time");

            dng_image_writer writer;

            negative->LosslessCompressJXL (host,
                                           writer);

            }

        // 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 ();

            }

        if (gDumpTransparency.NotEmpty ())
            {

            if (negative->TransparencyMask ())
                {

                dng_file_stream stream2 (gDumpTransparency.Get (), true);

                const dng_image &transparencyMask = *negative->TransparencyMask ();

                dng_image_writer writer;

                writer.WriteTIFF (host,
                                  stream2,
                                  transparencyMask,
                                  piBlackIsZero);

                }

            gDumpTransparency.Clear ();

            }

        if (gDumpDepthMap.NotEmpty ())
            {

            if (negative->HasDepthMap ())
                {

                dng_file_stream stream2 (gDumpDepthMap.Get (), true);

                const dng_image &depthMap = *negative->DepthMap ();

                dng_image_writer writer;

                writer.WriteTIFF (host,
                                  stream2,
                                  depthMap,
                                  piBlackIsZero);

                }

            gDumpDepthMap.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->RawLossyCompressedImage () != 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->RawLossyCompressedImage () != 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->SetImage (host,
                                            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_SaveDefault,
                                 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 (gCameraProfileName.NotEmpty ())
                {

                dng_camera_profile_id profileID (gCameraProfileName);

                render.SetCameraProfileID (profileID);

                }

            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);
                negative->GetXMP ()->RemoveProperties (XMP_NS_CRD);
                negative->GetXMP ()->RemoveProperties (XMP_NS_CRLCP);

                }

            #endif

            // Write TIF file.

            dng_file_stream stream2 (gDumpTIF.Get (), true);

                {

                const dng_camera_profile *profilePtr = nullptr;

                dng_camera_profile profile;

                if (!negative->IsMonochrome ())
                    {

                    const auto &profileID = render.CameraProfileID ();

                    if (negative->GetProfileByID (profileID, profile))
                        profilePtr = &profile;

                    }

                dng_timer timer ("Write TIFF time");

                dng_image_writer writer;

                writer.WriteTIFF (host,
                                  stream2,
                                  *finalImage.Get (),
                                  finalImage->Planes () >= 3 ? piRGB
                                                             : piBlackIsZero,
                                  ccUncompressed,
                                  &negative->Metadata (),
                                  &render.FinalSpace (profilePtr));

                }

            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-2023 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"
                     "-ignoreEnhanced       Ignore the enhanced image IFD\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"
                     "-lossyMosaicJXL       Writes DNG with lossy mosaic JXL\n"
                     "-losslessJXL          Writes DNG with lossless JXL\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"
                     "-csP3                 Color space: \"Display P3\"\n"
                     "-cs2020               Color space: \"Rec. 2020 / BT.2100\"\n"
                     "-16                   16-bits/channel output\n"
                     "-32                   32-bits/channel floating-point output\n"
                     "-profile <name>       Name of camera profile to use for rendering\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"
                     "-transparency <file>  Write transparency mask to \"<file>.tif\"\n"
                     "-depthMap <file>      Write depth map 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 ("ignoreEnhanced", true))
                {
                gIgnoreEnhanced = 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 ("lossyMosaicJXL", true))
                {

                gLossyMosaicJXL = true;

                }

            else if (option.Matches ("losslessJXL", true))
                {

                gLosslessJXL = true;

                }

            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 ("csP3", true))
                {

                gFinalSpace = &dng_space_DisplayP3::Get ();

                }

            else if (option.Matches ("cs2020", true))
                {

                gFinalSpace = &dng_space_Rec2020::Get ();

                }

            else if (option.Matches ("16"))
                {

                gFinalPixelType = ttShort;

                }

            else if (option.Matches ("32"))
                {

                gFinalPixelType = ttFloat;

                }

            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 ("profile"))
                {

                gCameraProfileName.Clear ();

                if (index + 1 < argc)
                    {
                    gCameraProfileName.Set (argv [++index]);
                    }

                if (gCameraProfileName.IsEmpty () || gCameraProfileName.StartsWith ("-"))
                    {
                    fprintf (stderr, "*** Missing profile name after -profile\n");
                    return 1;
                    }

                }

            else if (option.Matches ("transparency"))
                {

                gDumpTransparency.Clear ();

                if (index + 1 < argc)
                    {
                    gDumpTransparency.Set (argv [++index]);
                    }

                if (gDumpTransparency.IsEmpty () || gDumpTransparency.StartsWith ("-"))
                    {
                    fprintf (stderr, "*** Missing file name after -transparency\n");
                    return 1;
                    }

                if (!gDumpTransparency.EndsWith (".tif"))
                    {
                    gDumpTransparency.Append (".tif");
                    }

                }

            else if (option.Matches ("depthMap"))
                {

                gDumpDepthMap.Clear ();

                if (index + 1 < argc)
                    {
                    gDumpDepthMap.Set (argv [++index]);
                    }

                if (gDumpDepthMap.IsEmpty () || gDumpDepthMap.StartsWith ("-"))
                    {
                    fprintf (stderr, "*** Missing file name after -depthMap\n");
                    return 1;
                    }

                if (!gDumpDepthMap.EndsWith (".tif"))
                    {
                    gDumpDepthMap.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

/*****************************************************************************/
