Blame apps/lenstool/lenstool.cpp

Packit Service 48484a
/*
Packit Service 48484a
    Test for library image modificator object.
Packit Service 48484a
*/
Packit Service 48484a
Packit Service 48484a
Packit Service 48484a
#include <glib.h>
Packit Service 48484a
#include <locale.h>
Packit Service 48484a
#include <getopt.h>
Packit Service 48484a
#include <stdio.h>
Packit Service 48484a
#include <stdlib.h>
Packit Service 48484a
#include <string.h>
Packit Service 48484a
#include <time.h>
Packit Service 48484a
#include <ctype.h>
Packit Service 48484a
#include "lensfun.h"
Packit Service 48484a
#include "image.h"
Packit Service 48484a
#include "auxfun.h"
Packit Service 48484a
Packit Service 48484a
/* Define this to apply stage 1 & 3 corrections in one step,
Packit Service 48484a
   see main comment to the lfModifier class */
Packit Service 48484a
#define COMBINE_13
Packit Service 48484a
Packit Service 48484a
#if defined(_MSC_VER)
Packit Service 48484a
#define strcasecmp _stricmp
Packit Service 48484a
#define snprintf _snprintf
Packit Service 48484a
#define strtof (float)strtod
Packit Service 48484a
#endif 
Packit Service 48484a
Packit Service 48484a
Packit Service 48484a
static struct
Packit Service 48484a
{
Packit Service 48484a
    const char *Program;
Packit Service 48484a
    const char *Input;
Packit Service 48484a
    const char *Output;
Packit Service 48484a
    int ModifyFlags;
Packit Service 48484a
    bool Inverse;
Packit Service 48484a
    const char *Lens;
Packit Service 48484a
    const char *Camera;
Packit Service 48484a
    float Scale;
Packit Service 48484a
    float Crop;
Packit Service 48484a
    float Focal;
Packit Service 48484a
    float Aperture;
Packit Service 48484a
    float Distance;
Packit Service 48484a
    Image::InterpolationMethod Interpolation;
Packit Service 48484a
    lfLensType TargetGeom;
Packit Service 48484a
    bool Verbose;
Packit Service 48484a
} opts =
Packit Service 48484a
{
Packit Service 48484a
    NULL,
Packit Service 48484a
    NULL,
Packit Service 48484a
    "output.png",
Packit Service 48484a
    0,
Packit Service 48484a
    false,
Packit Service 48484a
    NULL,
Packit Service 48484a
    NULL,
Packit Service 48484a
    1.0f,
Packit Service 48484a
    0,
Packit Service 48484a
    0,
Packit Service 48484a
    0,
Packit Service 48484a
    1.0f,
Packit Service 48484a
    Image::I_LANCZOS,
Packit Service 48484a
    LF_RECTILINEAR,
Packit Service 48484a
    false
Packit Service 48484a
};
Packit Service 48484a
Packit Service 48484a
Packit Service 48484a
static void DisplayVersion ()
Packit Service 48484a
{
Packit Service 48484a
    g_print ("Lenstool reference implementation for Lensfun version %d.%d.%d\n",
Packit Service 48484a
        LF_VERSION_MAJOR, LF_VERSION_MINOR, LF_VERSION_MICRO);
Packit Service 48484a
    g_print ("Copyright (C) 2007 Andrew Zabolotny\n\n");
Packit Service 48484a
    g_print ("For distribution rules and conditions of use see the file\n");
Packit Service 48484a
    g_print ("COPYING which is part of the distribution.\n");
Packit Service 48484a
}
Packit Service 48484a
Packit Service 48484a
static void DisplayUsage ()
Packit Service 48484a
{
Packit Service 48484a
    DisplayVersion ();
Packit Service 48484a
    g_print ("\nCommand-line options:\n\n");
Packit Service 48484a
    g_print ("  -d    --distortion Apply lens distortion\n");
Packit Service 48484a
    g_print ("  -g#   --geometry=# Convert image geometry to given (one of:\n");
Packit Service 48484a
    g_print ("                     rectilinear,fisheye,panoramic,equirectangular,\n");
Packit Service 48484a
    g_print ("                     orthographic, stereographic, equisolid, thoby)\n");
Packit Service 48484a
    g_print ("  -t    --tca        Apply lens chromatic aberrations\n");
Packit Service 48484a
    g_print ("  -v    --vignetting Apply lens vignetting\n");
Packit Service 48484a
    g_print ("  -a    --all        Apply all possible corrections (tca, vign, dist)\n");
Packit Service 48484a
    g_print ("  -i    --inverse    Inverse correction of the image (e.g. simulate\n");
Packit Service 48484a
    g_print ("                     lens distortions instead of correcting them)\n");
Packit Service 48484a
    g_print ("\n");
Packit Service 48484a
    g_print ("  -C#   --camera=#   Camera name\n");
Packit Service 48484a
    g_print ("  -c#   --crop=#     Set camera crop factor in case the camera is not given\n");
Packit Service 48484a
    g_print ("\n");
Packit Service 48484a
    g_print ("  -L#   --lens=#     Lens name to search for in the database\n");
Packit Service 48484a
    g_print ("  -F#   --focal=#    Set focal length at which image has been taken\n");
Packit Service 48484a
    g_print ("  -A#   --aperture=# Set aperture at which image has been taken\n");
Packit Service 48484a
    g_print ("  -D#   --distance=# Set subject distance at which image has been taken\n");
Packit Service 48484a
    g_print ("\n");
Packit Service 48484a
    g_print ("  -s#   --scale=#    Apply additional scale on the image\n");
Packit Service 48484a
    g_print ("  -I#   --interpol=# Choose interpolation algorithm (n[earest], b[ilinear], l[anczos])\n");
Packit Service 48484a
    g_print ("\n");
Packit Service 48484a
    g_print ("  -o#   --output=#   Set file name for output image\n");
Packit Service 48484a
    g_print ("        --verbose    Verbose output\n");
Packit Service 48484a
    g_print ("        --version    Display program version and exit\n");
Packit Service 48484a
    g_print ("  -h    --help       Display this help text\n");
Packit Service 48484a
}
Packit Service 48484a
Packit Service 48484a
static bool ParseParameters(int argc, char **argv)
Packit Service 48484a
{
Packit Service 48484a
    static struct option long_options[] = {
Packit Service 48484a
        {"output", required_argument, NULL, 'o'},
Packit Service 48484a
        {"distortion", no_argument, NULL, 'd'},
Packit Service 48484a
        {"geometry", optional_argument, NULL, 'g'},
Packit Service 48484a
        {"tca", no_argument, NULL, 't'},
Packit Service 48484a
        {"vignetting", no_argument, NULL, 'v'},
Packit Service 48484a
        {"all", no_argument, NULL, 'a'},
Packit Service 48484a
        {"inverse", no_argument, NULL, 'i'},
Packit Service 48484a
        {"scale", required_argument, NULL, 'S'},
Packit Service 48484a
        {"lens", required_argument, NULL, 'L'},
Packit Service 48484a
        {"camera", required_argument, NULL, 'C'},
Packit Service 48484a
        {"crop", required_argument, NULL, 'c'},
Packit Service 48484a
        {"focal", required_argument, NULL, 'F'},
Packit Service 48484a
        {"aperture", required_argument, NULL, 'A'},
Packit Service 48484a
        {"distance", required_argument, NULL, 'D'},
Packit Service 48484a
        {"interpol", required_argument, NULL, 'I'},
Packit Service 48484a
        {"help", no_argument, NULL, 'h'},
Packit Service 48484a
        {"version", no_argument, NULL, 4},
Packit Service 48484a
        {"verbose", no_argument, NULL, 5},
Packit Service 48484a
        {0, 0, 0, 0}
Packit Service 48484a
    };
Packit Service 48484a
Packit Service 48484a
    opts.Program = argv [0];
Packit Service 48484a
Packit Service 48484a
    int c;
Packit Service 48484a
    while ((c = getopt_long (argc, argv, "o:dg::tvaiS:L:C:c:F:A:D:I:h", long_options, NULL)) != EOF) {
Packit Service 48484a
        switch (c) {
Packit Service 48484a
            case 'o':
Packit Service 48484a
                opts.Output = optarg;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'd':
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_DISTORTION;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'g':
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_GEOMETRY;
Packit Service 48484a
                if (optarg) {
Packit Service 48484a
                    if (!strcasecmp (optarg, "rectilinear"))
Packit Service 48484a
                        opts.TargetGeom = LF_RECTILINEAR;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "fisheye"))
Packit Service 48484a
                        opts.TargetGeom = LF_FISHEYE;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "panoramic"))
Packit Service 48484a
                        opts.TargetGeom = LF_PANORAMIC;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "equirectangular"))
Packit Service 48484a
                        opts.TargetGeom = LF_EQUIRECTANGULAR;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "orthographic"))
Packit Service 48484a
                        opts.TargetGeom = LF_FISHEYE_ORTHOGRAPHIC;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "stereographic"))
Packit Service 48484a
                        opts.TargetGeom = LF_FISHEYE_STEREOGRAPHIC;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "equisolid"))
Packit Service 48484a
                        opts.TargetGeom = LF_FISHEYE_EQUISOLID;
Packit Service 48484a
                    else if (!strcasecmp (optarg, "thoby"))
Packit Service 48484a
                        opts.TargetGeom = LF_FISHEYE_THOBY;
Packit Service 48484a
                    else {
Packit Service 48484a
                        DisplayUsage();
Packit Service 48484a
                        g_print ("\nTarget lens geometry must be one of 'rectilinear', 'fisheye', 'panoramic', 'equirectangular'\n'orthographic', 'stereographic', 'equisolid', 'thoby'\n");
Packit Service 48484a
                        return false;
Packit Service 48484a
                    }
Packit Service 48484a
                }
Packit Service 48484a
                break;
Packit Service 48484a
            case 't':
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_TCA;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'v':
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_VIGNETTING;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'a':
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_VIGNETTING;
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_TCA;
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_DISTORTION;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'i':
Packit Service 48484a
                opts.Inverse = true;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'S':
Packit Service 48484a
                opts.ModifyFlags |= LF_MODIFY_SCALE;
Packit Service 48484a
                opts.Scale = _atof (optarg);
Packit Service 48484a
                break;
Packit Service 48484a
            case'L':
Packit Service 48484a
                opts.Lens = optarg;
Packit Service 48484a
                break;
Packit Service 48484a
            case'C':
Packit Service 48484a
                opts.Camera = optarg;
Packit Service 48484a
                break;
Packit Service 48484a
            case 'c':
Packit Service 48484a
                opts.Crop = _atof (optarg);
Packit Service 48484a
                break;
Packit Service 48484a
            case 'F':
Packit Service 48484a
                opts.Focal = _atof (optarg);
Packit Service 48484a
                break;
Packit Service 48484a
            case 'A':
Packit Service 48484a
                opts.Aperture = _atof (optarg);
Packit Service 48484a
                break;
Packit Service 48484a
            case 'D':
Packit Service 48484a
                opts.Distance = _atof (optarg);
Packit Service 48484a
                break;
Packit Service 48484a
            case 'I':
Packit Service 48484a
                if (smartstreq (optarg, "nearest"))
Packit Service 48484a
                    opts.Interpolation = Image::I_NEAREST;
Packit Service 48484a
                else if (smartstreq (optarg, "bilinear"))
Packit Service 48484a
                    opts.Interpolation = Image::I_BILINEAR;
Packit Service 48484a
                else if (smartstreq (optarg, "lanczos"))
Packit Service 48484a
                    opts.Interpolation = Image::I_LANCZOS;
Packit Service 48484a
                else {
Packit Service 48484a
                    DisplayUsage();
Packit Service 48484a
                    g_print ("\nUnknown interpolation method `%s'\n", optarg);
Packit Service 48484a
                    return false;
Packit Service 48484a
                }
Packit Service 48484a
                break;
Packit Service 48484a
            case 'h':
Packit Service 48484a
                DisplayUsage ();
Packit Service 48484a
                return false;
Packit Service 48484a
            case 4:
Packit Service 48484a
                DisplayVersion ();
Packit Service 48484a
                return false;
Packit Service 48484a
            case 5:
Packit Service 48484a
                opts.Verbose = true;
Packit Service 48484a
                break;
Packit Service 48484a
            default:
Packit Service 48484a
                return false;
Packit Service 48484a
        }
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    if (optind <= argc)
Packit Service 48484a
        opts.Input = argv [optind];
Packit Service 48484a
Packit Service 48484a
    if (!opts.Lens && !opts.Camera) {
Packit Service 48484a
        DisplayUsage();
Packit Service 48484a
        g_print ("\nAt least a lens or camera name is required to perform a database lookup!\n");
Packit Service 48484a
        return false;
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    if (!opts.Lens && opts.Input) {
Packit Service 48484a
        DisplayUsage();
Packit Service 48484a
        g_print ("\nNo lens information (-L) supplied to process specified input image!\n");
Packit Service 48484a
        return false;
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    return true;
Packit Service 48484a
}
Packit Service 48484a
Packit Service 48484a
Packit Service 48484a
static Image *ApplyModifier (int modflags, bool reverse, Image *img,
Packit Service 48484a
                             const lfModifier *mod)
Packit Service 48484a
{
Packit Service 48484a
    // Create a new image where we will copy the modified image
Packit Service 48484a
    Image *newimg = new Image ();
Packit Service 48484a
    // Output image always equals input image size, although
Packit Service 48484a
    // this is not a requirement of the library, it's just a
Packit Service 48484a
    // limitation of the testbed.
Packit Service 48484a
    newimg->Resize (img->width, img->height);
Packit Service 48484a
Packit Service 48484a
#ifdef COMBINE_13
Packit Service 48484a
    int lwidth = img->width * 2 * 3;
Packit Service 48484a
#else
Packit Service 48484a
    int lwidth = img->width * 2;
Packit Service 48484a
    if (modflags & LF_MODIFY_TCA)
Packit Service 48484a
        lwidth *= 3;
Packit Service 48484a
#endif
Packit Service 48484a
    float *pos = new float [lwidth];
Packit Service 48484a
Packit Service 48484a
    int step_start = reverse ? 2 : 0;
Packit Service 48484a
    int step_delta = reverse ? -1 : +1;
Packit Service 48484a
    int step_finish = reverse ? -1 : 3;
Packit Service 48484a
Packit Service 48484a
    for (int step = step_start; step != step_finish; step += step_delta)
Packit Service 48484a
    {
Packit Service 48484a
        RGBpixel *dst = newimg->image;
Packit Service 48484a
        char *imgdata = (char *)img->image;
Packit Service 48484a
        bool ok = true;
Packit Service 48484a
Packit Service 48484a
        img->InitInterpolation (opts.Interpolation);
Packit Service 48484a
Packit Service 48484a
        for (unsigned y = 0; ok && y < img->height; y++)
Packit Service 48484a
            switch (step)
Packit Service 48484a
            {
Packit Service 48484a
#ifdef COMBINE_13
Packit Service 48484a
                case 0:
Packit Service 48484a
                    ok = false;
Packit Service 48484a
                    break;
Packit Service 48484a
Packit Service 48484a
                case 2:
Packit Service 48484a
                    /* TCA and geometry correction */
Packit Service 48484a
                    ok = mod->ApplySubpixelGeometryDistortion (0.0, y, img->width, 1, pos);
Packit Service 48484a
#else
Packit Service 48484a
                case 0:
Packit Service 48484a
                    /* TCA correction */
Packit Service 48484a
                    ok = mod->ApplySubpixelDistortion (0.0, y, img->width, 1, pos);
Packit Service 48484a
#endif
Packit Service 48484a
                    if (ok)
Packit Service 48484a
                    {
Packit Service 48484a
                        float *src = pos;
Packit Service 48484a
                        for (unsigned x = 0; x < img->width; x++)
Packit Service 48484a
                        {
Packit Service 48484a
                            dst->red   = img->GetR (src [0], src [1]);
Packit Service 48484a
                            dst->green = img->GetG (src [2], src [3]);
Packit Service 48484a
                            dst->blue  = img->GetB (src [4], src [5]);
Packit Service 48484a
                            src += 2 * 3;
Packit Service 48484a
                            dst++;
Packit Service 48484a
                        }
Packit Service 48484a
                    }
Packit Service 48484a
                    break;
Packit Service 48484a
Packit Service 48484a
                case 1:
Packit Service 48484a
                    /* Colour correction: vignetting */
Packit Service 48484a
                    ok = mod->ApplyColorModification (imgdata, 0.0, y, img->width, 1,
Packit Service 48484a
                        LF_CR_4 (RED, GREEN, BLUE, UNKNOWN), 0);
Packit Service 48484a
                    imgdata += img->width * 4;
Packit Service 48484a
                    break;
Packit Service 48484a
Packit Service 48484a
#ifndef COMBINE_13
Packit Service 48484a
                case 2:
Packit Service 48484a
                    /* Distortion and geometry correction, scaling */
Packit Service 48484a
                    ok = mod->ApplyGeometryDistortion (0.0, y, newimg->width, 1, pos);
Packit Service 48484a
                    if (ok)
Packit Service 48484a
                    {
Packit Service 48484a
                        float *src = pos;
Packit Service 48484a
                        for (unsigned x = 0; x < img->width; x++)
Packit Service 48484a
                        {
Packit Service 48484a
                            img->Get (*dst, src [0], src [1]);
Packit Service 48484a
                            src += 2;
Packit Service 48484a
                            dst++;
Packit Service 48484a
                        }
Packit Service 48484a
                    }
Packit Service 48484a
                    break;
Packit Service 48484a
#endif
Packit Service 48484a
            }
Packit Service 48484a
        // After TCA and distortion steps switch img and newimg.
Packit Service 48484a
        // This is crucial since newimg is now the input image
Packit Service 48484a
        // to the next stage.
Packit Service 48484a
        if (ok && (step == 0 || step == 2))
Packit Service 48484a
        {
Packit Service 48484a
            Image *tmp = newimg;
Packit Service 48484a
            newimg = img;
Packit Service 48484a
            img = tmp;
Packit Service 48484a
        }
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    delete [] pos;
Packit Service 48484a
    delete newimg;
Packit Service 48484a
    return img;
Packit Service 48484a
}
Packit Service 48484a
Packit Service 48484a
Packit Service 48484a
Packit Service 48484a
int main (int argc, char **argv)
Packit Service 48484a
{
Packit Service 48484a
    setlocale (LC_ALL, "");
Packit Service 48484a
Packit Service 48484a
    if (!ParseParameters(argc, argv))
Packit Service 48484a
        return -1;
Packit Service 48484a
Packit Service 48484a
    // load database
Packit Service 48484a
    lfDatabase *ldb = new lfDatabase ();
Packit Service 48484a
Packit Service 48484a
    if (ldb->Load () != LF_NO_ERROR) {
Packit Service 48484a
        ldb->Destroy();
Packit Service 48484a
        g_print ("\rERROR: Database could not be loaded\n");
Packit Service 48484a
        return -1;
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    // try to find camera in the database
Packit Service 48484a
    const lfCamera *cam = NULL;
Packit Service 48484a
    if (opts.Camera) {
Packit Service 48484a
        const lfCamera ** cameras = ldb->FindCamerasExt(NULL, opts.Camera);
Packit Service 48484a
        if (cameras)
Packit Service 48484a
            cam = cameras[0];
Packit Service 48484a
        else
Packit Service 48484a
            g_print ("Cannot find a camera matching `%s' in database\n", opts.Camera);
Packit Service 48484a
        lf_free (cameras);
Packit Service 48484a
     }
Packit Service 48484a
Packit Service 48484a
    // try to find a matching lens in the database
Packit Service 48484a
    const lfLens *lens = NULL;
Packit Service 48484a
    if (opts.Lens) {
Packit Service 48484a
        const lfLens **lenses = ldb->FindLenses (cam, NULL, opts.Lens);
Packit Service 48484a
        if (lenses)
Packit Service 48484a
            lens = lenses [0];
Packit Service 48484a
        else
Packit Service 48484a
            g_print ("Cannot find a lens matching `%s' in database\n", opts.Lens);
Packit Service 48484a
        lf_free (lenses);
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    // print camera and lens information if in verbose mode or if no input file is specified
Packit Service 48484a
    if (opts.Verbose || !opts.Input) {
Packit Service 48484a
        if (cam && lens) {
Packit Service 48484a
            g_print("Matching lens and camera combination found in the database:\n");
Packit Service 48484a
            PrintCamera(cam, ldb);
Packit Service 48484a
            PrintLens(lens, ldb);
Packit Service 48484a
        } else if (!cam && lens) {
Packit Service 48484a
            g_print("Matching lens found in the database:\n");
Packit Service 48484a
            PrintLens(lens, ldb);
Packit Service 48484a
        } else if (!lens && cam) {
Packit Service 48484a
            g_print("Matching camera found in the database:\n");
Packit Service 48484a
            PrintCamera(cam, ldb);
Packit Service 48484a
        }
Packit Service 48484a
    } else {
Packit Service 48484a
        if (cam && lens) {
Packit Service 48484a
            g_print("= Selecting %s / %s\n", cam->Model, lens->Model);
Packit Service 48484a
        } else if (!cam && lens) {
Packit Service 48484a
            g_print("= Selecting %s\n", lens->Model);
Packit Service 48484a
        }
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    // nothing to process, so lets quit here
Packit Service 48484a
    if (!opts.Input) {
Packit Service 48484a
        ldb->Destroy();
Packit Service 48484a
        return 0;
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    // assume standard values if parameters are not specified
Packit Service 48484a
    if (cam)
Packit Service 48484a
        opts.Crop = cam->CropFactor;
Packit Service 48484a
    else if (!opts.Crop)
Packit Service 48484a
        opts.Crop = lens->CropFactor;    
Packit Service 48484a
    if (!opts.Focal)
Packit Service 48484a
        opts.Focal = lens->MinFocal;
Packit Service 48484a
    if (!opts.Aperture)
Packit Service 48484a
        opts.Aperture = lens->MinAperture;
Packit Service 48484a
Packit Service 48484a
    if (opts.Verbose) {
Packit Service 48484a
        g_print("\nProcessing parameters:\n"
Packit Service 48484a
                "    |- Image crop factor: %g\n"
Packit Service 48484a
                "    |- Focal length: %gmm\n"
Packit Service 48484a
                "    |- Aperture: f/%g\n"
Packit Service 48484a
                "    |- Distance: %gm\n\n",
Packit Service 48484a
                opts.Crop, opts.Focal, opts.Aperture, opts.Distance);
Packit Service 48484a
    } else {
Packit Service 48484a
        g_print("= Processing parameters: Crop %g, Focal %gmm, Aperture f/%g, Distance: %gm\n",
Packit Service 48484a
                opts.Crop, opts.Focal, opts.Aperture, opts.Distance);
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
    Image *img = new Image ();
Packit Service 48484a
    g_print ("~ Loading `%s' ... ", opts.Input);
Packit Service 48484a
    if (!img->Open (opts.Input)) {
Packit Service 48484a
        g_print ("\rERROR: failed to open file `%s'\n", opts.Input);
Packit Service 48484a
        delete img;
Packit Service 48484a
        ldb->Destroy();
Packit Service 48484a
        return -1;
Packit Service 48484a
    }
Packit Service 48484a
    if (!img->LoadPNG ()) {
Packit Service 48484a
        g_print ("\rERROR: failed to parse PNG data from file `%s'\n", opts.Input);
Packit Service 48484a
        delete img;
Packit Service 48484a
        ldb->Destroy();
Packit Service 48484a
        return -1;
Packit Service 48484a
    }
Packit Service 48484a
    g_print ("done.\n~ Image size [%ux%u].\n", img->width, img->height);
Packit Service 48484a
Packit Service 48484a
    lfModifier *mod = lfModifier::Create (lens, opts.Crop, img->width, img->height);
Packit Service 48484a
    if (!mod) {
Packit Service 48484a
        g_print ("\rWarning: failed to create modifier\n");
Packit Service 48484a
        delete img;
Packit Service 48484a
        ldb->Destroy();
Packit Service 48484a
        return -1;
Packit Service 48484a
    }
Packit Service 48484a
    int modflags = mod->Initialize (
Packit Service 48484a
        lens, LF_PF_U8, opts.Focal,
Packit Service 48484a
        opts.Aperture, opts.Distance, opts.Scale, opts.TargetGeom,
Packit Service 48484a
        opts.ModifyFlags, opts.Inverse);
Packit Service 48484a
Packit Service 48484a
    g_print("~ Selected modifications: ");
Packit Service 48484a
    if (modflags & LF_MODIFY_TCA)
Packit Service 48484a
        g_print ("[tca]");
Packit Service 48484a
    if (modflags & LF_MODIFY_VIGNETTING)
Packit Service 48484a
        g_print ("[vign]");
Packit Service 48484a
    if (modflags & LF_MODIFY_DISTORTION)
Packit Service 48484a
        g_print ("[dist]");
Packit Service 48484a
    if (modflags & LF_MODIFY_GEOMETRY)
Packit Service 48484a
        g_print ("[geom]");
Packit Service 48484a
    if (opts.Scale != 1.0)
Packit Service 48484a
        g_print ("[scale]");
Packit Service 48484a
    if (modflags==0)
Packit Service 48484a
        g_print ("[NOTHING]");
Packit Service 48484a
    g_print ("\n");
Packit Service 48484a
Packit Service 48484a
    g_print("~ Run processing chain... ");
Packit Service 48484a
Packit Service 48484a
    clock_t st;
Packit Service 48484a
    clock_t xt = clock ();
Packit Service 48484a
    while (xt == (st = clock ()))
Packit Service 48484a
        ;
Packit Service 48484a
Packit Service 48484a
    img = ApplyModifier (modflags, opts.Inverse, img, mod);
Packit Service 48484a
Packit Service 48484a
    clock_t et = clock ();
Packit Service 48484a
    g_print ("done (%.3g secs)\n", double (et - st) / CLOCKS_PER_SEC);
Packit Service 48484a
Packit Service 48484a
    mod->Destroy ();
Packit Service 48484a
Packit Service 48484a
    g_print ("~ Save output as `%s'...", opts.Output);
Packit Service 48484a
    bool ok = img->SavePNG (opts.Output);
Packit Service 48484a
Packit Service 48484a
    delete img;
Packit Service 48484a
    ldb->Destroy ();
Packit Service 48484a
Packit Service 48484a
    if (ok) {
Packit Service 48484a
        g_print (" done\n");
Packit Service 48484a
        return 0;
Packit Service 48484a
    } else {
Packit Service 48484a
        g_print (" FAILED\n");
Packit Service 48484a
        return -1;
Packit Service 48484a
    }
Packit Service 48484a
Packit Service 48484a
}