Library testbed. This program can access most library functionality.
#include "image.h"
#include <glib.h>
#include <locale.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#define COMBINE_13
#if defined(_MSC_VER)
#define strcasecmp _stricmp
#define snprintf _snprintf
#define strtof (float)strtod
#endif
static struct
{
const char *Program;
const char *Output;
int ModifyFlags;
bool Inverse;
const char *Lens;
float Scale;
float Crop;
float Focal;
float Aperture;
float Distance;
Image::InterpolationMethod Interpolation;
} opts =
{
NULL,
"out-%s",
0,
false,
"Sigma 14mm f/2.8 EX",
1.0,
0,
0,
0,
1.0,
Image::I_NEAREST,
};
static void DisplayVersion ()
{
g_print ("lensfun version %d.%d.%d: test image modifier routines\n",
g_print ("Copyright (C) 2007 Andrew Zabolotny\n\n");
g_print ("For distribution rules and conditions of use see the file\n");
g_print ("COPYING which is part of the distribution.\n");
}
static void DisplayUsage ()
{
DisplayVersion ();
g_print ("\nCommand-line options:\n\n");
g_print (" -d --distortion Apply lens distortion\n");
g_print (" -g# --geometry=# Convert image geometry to given (one of:\n");
g_print (" rectilinear,fisheye,panoramic,equirectangular,\n");
g_print (" orthographic, stereographic, equisolid, thoby)\n");
g_print (" -t --tca Apply lens chromatic aberrations\n");
g_print (" -v --vignetting Apply lens vignetting\n");
g_print (" -c --cci Apply lens Color Correction Index\n");
g_print (" -i --inverse Inverse correction of the image (e.g. simulate\n");
g_print (" lens distortions instead of correcting them)\n");
g_print (" -s# --scale=# Apply additional scale on the image\n");
g_print (" -l# --lens=# Use calibration data for this lens\n");
g_print (" -C# --crop=# Set camera crop factor\n");
g_print (" -F# --focal=# Set focal length at which image has been taken\n");
g_print (" -A# --aperture=# Set aperture at which image has been taken\n");
g_print (" -D# --distance=# Set subject distance at which image has been taken\n");
g_print (" -I# --interpol=# Choose interpolation algorithm (n[earest], b[ilinear], l[anczos])\n");
g_print (" -o# --output=# Set file name for output image\n");
g_print (" -V --version Display program version and exit\n");
g_print (" -h --help Display this help text\n");
}
static float _atof (const char *s)
{
char *end = NULL;
float r = strtof (s, &end);
if (end && *end)
{
g_print ("ERROR: Invalid number `%s', parsed as %g\n", s, r);
g_print ("Use your locale-specific number format (e.g. ',' or '.' etc)\n");
exit (-1);
}
return r;
}
static Image *ApplyModifier (int modflags, bool reverse, Image *img,
{
Image *newimg = new Image ();
newimg->Resize (img->width, img->height);
#ifdef COMBINE_13
int lwidth = img->width * 2 * 3;
#else
int lwidth = img->width * 2;
lwidth *= 3;
#endif
float *pos = new float [lwidth];
int step_start = reverse ? 2 : 0;
int step_delta = reverse ? -1 : +1;
int step_finish = reverse ? -1 : 3;
for (int step = step_start; step != step_finish; step += step_delta)
{
RGBpixel *dst = newimg->image;
char *imgdata = (char *)img->image;
bool ok = true;
img->InitInterpolation (opts.Interpolation);
for (unsigned y = 0; ok && y < img->height; y++)
switch (step)
{
#ifdef COMBINE_13
case 0:
ok = false;
break;
case 2:
#else
case 0:
#endif
if (ok)
{
float *src = pos;
for (unsigned x = 0; x < img->width; x++)
{
dst->red = img->GetR (src [0], src [1]);
dst->green = img->GetG (src [2], src [3]);
dst->blue = img->GetB (src [4], src [5]);
src += 2 * 3;
dst++;
}
}
break;
case 1:
LF_CR_4 (RED, GREEN, BLUE, UNKNOWN), 0);
imgdata += img->width * 4;
break;
#ifndef COMBINE_13
case 2:
if (ok)
{
float *src = pos;
for (unsigned x = 0; x < img->width; x++)
{
img->Get (*dst, src [0], src [1]);
src += 2;
dst++;
}
}
break;
#endif
}
if (ok && (step == 0 || step == 2))
{
Image *tmp = newimg;
newimg = img;
img = tmp;
}
}
delete [] pos;
delete newimg;
return img;
}
static bool smartstreq (const char *str, const char *pattern)
{
const char *src = str;
while (*src)
{
char cs = toupper (*src++);
char cp = toupper (*pattern++);
if (!cs)
return (src != str);
if (!cp)
return false;
if (cs != cp)
return false;
}
return true;
}
int main (int argc, char **argv)
{
static struct option long_options[] =
{
{"output", required_argument, NULL, 'o'},
{"distortion", no_argument, NULL, 'd'},
{"geometry", optional_argument, NULL, 'g'},
{"tca", no_argument, NULL, 't'},
{"vignetting", no_argument, NULL, 'v'},
{"cci", no_argument, NULL, 'c'},
{"inverse", no_argument, NULL, 'i'},
{"scale", required_argument, NULL, 's'},
{"autoscale", no_argument, NULL, 'S'},
{"lens", required_argument, NULL, 'l'},
{"crop", required_argument, NULL, 'C'},
{"focal", required_argument, NULL, 'F'},
{"aperture", required_argument, NULL, 'A'},
{"distance", required_argument, NULL, 'D'},
{"interpol", required_argument, NULL, 'I'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{0, 0, 0, 0}
};
setlocale (LC_ALL, "");
opts.Program = argv [0];
int c;
while ((c = getopt_long (argc, argv, "o:dg::tvcis:Sl:C:F:A:D:I:hV", long_options, NULL)) != EOF)
{
switch (c)
{
case 'o':
opts.Output = optarg;
break;
case 'd':
break;
case 'g':
if (optarg)
{
if (!strcasecmp (optarg, "rectilinear"))
else if (!strcasecmp (optarg, "fisheye"))
else if (!strcasecmp (optarg, "panoramic"))
else if (!strcasecmp (optarg, "equirectangular"))
else if (!strcasecmp (optarg, "orthographic"))
else if (!strcasecmp (optarg, "stereographic"))
else if (!strcasecmp (optarg, "equisolid"))
else if (!strcasecmp (optarg, "thoby"))
else
{
g_print ("Target lens geometry must be one of 'rectilinear', 'fisheye', 'panoramic', 'equirectangular'\n'orthographic', 'stereographic', 'equisolid', 'thoby'\n");
return -1;
}
}
break;
case 't':
break;
case 'v':
break;
case 'c':
break;
case 'i':
opts.Inverse = true;
break;
case 's':
opts.Scale = _atof (optarg);
break;
case 'S':
opts.Scale = 0.0;
break;
case'l':
opts.Lens = optarg;
break;
case 'C':
opts.Crop = _atof (optarg);
break;
case 'F':
opts.Focal = _atof (optarg);
break;
case 'A':
opts.Aperture = _atof (optarg);
break;
case 'D':
opts.Distance = _atof (optarg);
break;
case 'I':
if (smartstreq (optarg, "nearest"))
opts.Interpolation = Image::I_NEAREST;
else if (smartstreq (optarg, "bilinear"))
opts.Interpolation = Image::I_BILINEAR;
else if (smartstreq (optarg, "lanczos"))
opts.Interpolation = Image::I_LANCZOS;
else
{
g_print ("Unknown interpolation method `%s'\n", optarg);
return -1;
}
break;
case 'h':
DisplayUsage ();
return 0;
case 'V':
DisplayVersion ();
return 0;
default:
return -1;
}
}
if (optind >= argc)
{
g_print ("No files given on command line\n\n");
DisplayUsage ();
return -1;
}
if (!lenses)
{
g_print ("Cannot find the lens `%s' in database\n", opts.Lens);
return -1;
}
const lfLens *lens = lenses [0];
if (!opts.Crop)
if (!opts.Focal)
if (!opts.Aperture)
g_print ("%sCorrecting image as taken by lens `%s, %s'\n"
" at crop factor %g, focal length %g, aperture %g, distance %g\n",
opts.Inverse ?
"Inverse " :
"", lens->
Maker, lens->
Model,
opts.Crop, opts.Focal, opts.Aperture, opts.Distance);
for (; optind < argc; optind++)
{
Image *img = new Image ();
g_print ("Loading `%s' ...", argv [optind]);
if (!img->Open (argv [optind]))
{
g_print ("\rWarning: failed to open file `%s'\n", argv [optind]);
delete img;
continue;
}
if (!img->LoadPNG ())
{
g_print ("\rWarning: failed to parse PNG data from file `%s'\n", argv [optind]);
delete img;
continue;
}
g_print ("\b\b\b[%ux%u], processing", img->width, img->height);
opts.Aperture, opts.Distance, opts.Scale, opts.TargetGeom,
opts.ModifyFlags, opts.Inverse);
if (!mod)
{
g_print ("\rWarning: failed to create modifier\n");
delete img;
continue;
}
g_print ("[tca]");
g_print ("[vign]");
g_print ("[cci]");
g_print ("[dist]");
g_print ("[geom]");
if (opts.Scale != 1.0)
g_print ("[scale]");
g_print (" ...");
clock_t st;
clock_t xt = clock ();
while (xt == (st = clock ()))
;
img = ApplyModifier (modflags, opts.Inverse, img, mod);
clock_t et = clock ();
g_print ("\b\b\b(%.2g secs)", double (et - st) / CLOCKS_PER_SEC);
char out_fname [200];
snprintf (out_fname, sizeof (out_fname), opts.Output, argv [optind]);
g_print (", saving `%s'...", out_fname);
bool ok = img->SavePNG (out_fname);
delete img;
g_print ("\b\b\b\b, %s\n", ok ? "done" : "FAILED");
}
return 0;
}
void lf_free(void *data)
The basics of memory allocation: never free objects allocated by the library yourselves,...
#define LF_VERSION_MICRO
Library micro version number.
Definition: lensfun.h:52
#define LF_VERSION_MAJOR
Major library version number.
Definition: lensfun.h:48
#define LF_VERSION_MINOR
Minor library version number.
Definition: lensfun.h:50
#define LF_CR_4(a, b, c, d)
This macro defines a pixel format consisting of four components.
Definition: lensfun.h:1571
@ LF_MODIFY_TCA
Correct (or apply) lens transversal chromatic aberrations.
Definition: lensfun.h:1502
@ LF_MODIFY_CCI
Correct (or apply) lens color contribution index.
Definition: lensfun.h:1506
@ LF_MODIFY_VIGNETTING
Correct (or apply) lens vignetting.
Definition: lensfun.h:1504
@ LF_MODIFY_GEOMETRY
Convert image geometry.
Definition: lensfun.h:1510
@ LF_MODIFY_DISTORTION
Correct (or apply) lens distortion.
Definition: lensfun.h:1508
@ LF_MODIFY_SCALE
Additional resize of image.
Definition: lensfun.h:1512
@ LF_PF_U8
Unsigned 8-bit R,G,B.
Definition: lensfun.h:1521
lfDatabase * lf_db_new(void)
Create a new empty database object.
lfLensType
Lens type.
Definition: lensfun.h:630
@ LF_FISHEYE
Fisheye lens Ref: http://wiki.panotools.org/Fisheye_Projection.
Definition: lensfun.h:639
@ LF_FISHEYE_EQUISOLID
equisolid fisheye
Definition: lensfun.h:652
@ LF_FISHEYE_THOBY
fisheye Thoby (for Nikkor 10.5)
Definition: lensfun.h:654
@ LF_FISHEYE_ORTHOGRAPHIC
orthographic fisheye
Definition: lensfun.h:648
@ LF_EQUIRECTANGULAR
Equirectangular (not that there are such lenses, but useful to convert images TO this type,...
Definition: lensfun.h:646
@ LF_RECTILINEAR
A rectilinear lens - 99% of all lenses are of this type.
Definition: lensfun.h:634
@ LF_FISHEYE_STEREOGRAPHIC
stereographic fisheye
Definition: lensfun.h:650
@ LF_PANORAMIC
Panoramic (cylindrical)
Definition: lensfun.h:641
This file defines the interface to the lensfun library.
A lens database object.
Definition: lensfun.h:1155
void Destroy()
Destroy the database object and free all loaded data.
const lfLens ** FindLenses(const lfCamera *camera, const char *maker, const char *model, int sflags=0) const
Parse a human-friendly lens description (ex: "smc PENTAX-F 35-105mm F4-5.6" or "SIGMA AF 28-300 F3....
lfError Load()
Load the whole lens database.
Lens data.
Definition: lensfun.h:670
lfMLstr Model
Lens model (ex: "Zoom-Rolleinar")
Definition: lensfun.h:674
lfMLstr Maker
Lens maker (ex: "Rollei")
Definition: lensfun.h:672
float CropFactor
Crop factor at which calibration measurements were taken.
Definition: lensfun.h:704
float MinFocal
Minimum focal length, mm (ex: 35).
Definition: lensfun.h:676
float MinAperture
Aperture at minimum focal length (ex: 3.5).
Definition: lensfun.h:680
A modifier object contains optimized data required to rectify a image.
Definition: lensfun.h:1707
void Destroy()
Destroy the modifier object.
int Initialize(const lfLens *lens, lfPixelFormat format, float focal, float aperture, float distance, float scale, lfLensType targeom, int flags, bool reverse)
Initialize the process of correcting aberrations in a image.
bool ApplySubpixelGeometryDistortion(float xu, float yu, int width, int height, float *res) const
Apply stage 1 & 3 in one step.
bool ApplyColorModification(void *pixels, float x, float y, int width, int height, int comp_role, int row_stride) const
Image correction step 2: fix image colors.
bool ApplyGeometryDistortion(float xu, float yu, int width, int height, float *res) const
Image correction step 3: apply the transforms on a block of pixel coordinates.
bool ApplySubpixelDistortion(float xu, float yu, int width, int height, float *res) const
Image correction stage 1: apply subpixel distortions.
static lfModifier * Create(const lfLens *lens, float crop, int width, int height)
Create a empty image modifier object.