diff --git a/apps/lenstool/lenstool.cpp b/apps/lenstool/lenstool.cpp index 0aab056..399195e 100644 --- a/apps/lenstool/lenstool.cpp +++ b/apps/lenstool/lenstool.cpp @@ -360,7 +360,7 @@ int main (int argc, char **argv) lfDatabase *ldb = new lfDatabase (); if (ldb->Load () != LF_NO_ERROR) { - ldb->Destroy(); + delete ldb; g_print ("\rERROR: Database could not be loaded\n"); return -1; } @@ -410,7 +410,7 @@ int main (int argc, char **argv) // nothing to process, so lets quit here if (!opts.Input) { - ldb->Destroy(); + delete ldb; return 0; } @@ -441,22 +441,22 @@ int main (int argc, char **argv) if (!img->Open (opts.Input)) { g_print ("\rERROR: failed to open file `%s'\n", opts.Input); delete img; - ldb->Destroy(); + delete ldb; return -1; } if (!img->LoadPNG ()) { g_print ("\rERROR: failed to parse PNG data from file `%s'\n", opts.Input); delete img; - ldb->Destroy(); + delete ldb; return -1; } g_print ("done.\n~ Image size [%ux%u].\n", img->width, img->height); - lfModifier *mod = lfModifier::Create (lens, opts.Crop, img->width, img->height); + lfModifier *mod = new lfModifier (lens, opts.Crop, img->width, img->height); if (!mod) { g_print ("\rWarning: failed to create modifier\n"); delete img; - ldb->Destroy(); + delete ldb; return -1; } int modflags = mod->Initialize ( @@ -491,13 +491,13 @@ int main (int argc, char **argv) clock_t et = clock (); g_print ("done (%.3g secs)\n", double (et - st) / CLOCKS_PER_SEC); - mod->Destroy (); + delete mod; g_print ("~ Save output as `%s'...", opts.Output); bool ok = img->SavePNG (opts.Output); delete img; - ldb->Destroy (); + delete ldb; if (ok) { g_print (" done\n"); diff --git a/apps/lenstool/lenstool.cpp.0038 b/apps/lenstool/lenstool.cpp.0038 new file mode 100644 index 0000000..0aab056 --- /dev/null +++ b/apps/lenstool/lenstool.cpp.0038 @@ -0,0 +1,510 @@ +/* + Test for library image modificator object. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "lensfun.h" +#include "image.h" +#include "auxfun.h" + +/* Define this to apply stage 1 & 3 corrections in one step, + see main comment to the lfModifier class */ +#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 *Input; + const char *Output; + int ModifyFlags; + bool Inverse; + const char *Lens; + const char *Camera; + float Scale; + float Crop; + float Focal; + float Aperture; + float Distance; + Image::InterpolationMethod Interpolation; + lfLensType TargetGeom; + bool Verbose; +} opts = +{ + NULL, + NULL, + "output.png", + 0, + false, + NULL, + NULL, + 1.0f, + 0, + 0, + 0, + 1.0f, + Image::I_LANCZOS, + LF_RECTILINEAR, + false +}; + + +static void DisplayVersion () +{ + g_print ("Lenstool reference implementation for Lensfun version %d.%d.%d\n", + LF_VERSION_MAJOR, LF_VERSION_MINOR, LF_VERSION_MICRO); + 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 (" -a --all Apply all possible corrections (tca, vign, dist)\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 ("\n"); + g_print (" -C# --camera=# Camera name\n"); + g_print (" -c# --crop=# Set camera crop factor in case the camera is not given\n"); + g_print ("\n"); + g_print (" -L# --lens=# Lens name to search for in the database\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 ("\n"); + g_print (" -s# --scale=# Apply additional scale on the image\n"); + g_print (" -I# --interpol=# Choose interpolation algorithm (n[earest], b[ilinear], l[anczos])\n"); + g_print ("\n"); + g_print (" -o# --output=# Set file name for output image\n"); + g_print (" --verbose Verbose output\n"); + g_print (" --version Display program version and exit\n"); + g_print (" -h --help Display this help text\n"); +} + +static bool ParseParameters(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'}, + {"all", no_argument, NULL, 'a'}, + {"inverse", no_argument, NULL, 'i'}, + {"scale", required_argument, NULL, 'S'}, + {"lens", required_argument, NULL, 'L'}, + {"camera", required_argument, NULL, 'C'}, + {"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, 4}, + {"verbose", no_argument, NULL, 5}, + {0, 0, 0, 0} + }; + + opts.Program = argv [0]; + + int c; + while ((c = getopt_long (argc, argv, "o:dg::tvaiS:L:C:c:F:A:D:I:h", long_options, NULL)) != EOF) { + switch (c) { + case 'o': + opts.Output = optarg; + break; + case 'd': + opts.ModifyFlags |= LF_MODIFY_DISTORTION; + break; + case 'g': + opts.ModifyFlags |= LF_MODIFY_GEOMETRY; + if (optarg) { + if (!strcasecmp (optarg, "rectilinear")) + opts.TargetGeom = LF_RECTILINEAR; + else if (!strcasecmp (optarg, "fisheye")) + opts.TargetGeom = LF_FISHEYE; + else if (!strcasecmp (optarg, "panoramic")) + opts.TargetGeom = LF_PANORAMIC; + else if (!strcasecmp (optarg, "equirectangular")) + opts.TargetGeom = LF_EQUIRECTANGULAR; + else if (!strcasecmp (optarg, "orthographic")) + opts.TargetGeom = LF_FISHEYE_ORTHOGRAPHIC; + else if (!strcasecmp (optarg, "stereographic")) + opts.TargetGeom = LF_FISHEYE_STEREOGRAPHIC; + else if (!strcasecmp (optarg, "equisolid")) + opts.TargetGeom = LF_FISHEYE_EQUISOLID; + else if (!strcasecmp (optarg, "thoby")) + opts.TargetGeom = LF_FISHEYE_THOBY; + else { + DisplayUsage(); + g_print ("\nTarget lens geometry must be one of 'rectilinear', 'fisheye', 'panoramic', 'equirectangular'\n'orthographic', 'stereographic', 'equisolid', 'thoby'\n"); + return false; + } + } + break; + case 't': + opts.ModifyFlags |= LF_MODIFY_TCA; + break; + case 'v': + opts.ModifyFlags |= LF_MODIFY_VIGNETTING; + break; + case 'a': + opts.ModifyFlags |= LF_MODIFY_VIGNETTING; + opts.ModifyFlags |= LF_MODIFY_TCA; + opts.ModifyFlags |= LF_MODIFY_DISTORTION; + break; + case 'i': + opts.Inverse = true; + break; + case 'S': + opts.ModifyFlags |= LF_MODIFY_SCALE; + opts.Scale = _atof (optarg); + break; + case'L': + opts.Lens = optarg; + break; + case'C': + opts.Camera = 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 { + DisplayUsage(); + g_print ("\nUnknown interpolation method `%s'\n", optarg); + return false; + } + break; + case 'h': + DisplayUsage (); + return false; + case 4: + DisplayVersion (); + return false; + case 5: + opts.Verbose = true; + break; + default: + return false; + } + } + + if (optind <= argc) + opts.Input = argv [optind]; + + if (!opts.Lens && !opts.Camera) { + DisplayUsage(); + g_print ("\nAt least a lens or camera name is required to perform a database lookup!\n"); + return false; + } + + if (!opts.Lens && opts.Input) { + DisplayUsage(); + g_print ("\nNo lens information (-L) supplied to process specified input image!\n"); + return false; + } + + return true; +} + + +static Image *ApplyModifier (int modflags, bool reverse, Image *img, + const lfModifier *mod) +{ + // Create a new image where we will copy the modified image + Image *newimg = new Image (); + // Output image always equals input image size, although + // this is not a requirement of the library, it's just a + // limitation of the testbed. + newimg->Resize (img->width, img->height); + +#ifdef COMBINE_13 + int lwidth = img->width * 2 * 3; +#else + int lwidth = img->width * 2; + if (modflags & LF_MODIFY_TCA) + 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: + /* TCA and geometry correction */ + ok = mod->ApplySubpixelGeometryDistortion (0.0, y, img->width, 1, pos); +#else + case 0: + /* TCA correction */ + ok = mod->ApplySubpixelDistortion (0.0, y, img->width, 1, pos); +#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: + /* Colour correction: vignetting */ + ok = mod->ApplyColorModification (imgdata, 0.0, y, img->width, 1, + LF_CR_4 (RED, GREEN, BLUE, UNKNOWN), 0); + imgdata += img->width * 4; + break; + +#ifndef COMBINE_13 + case 2: + /* Distortion and geometry correction, scaling */ + ok = mod->ApplyGeometryDistortion (0.0, y, newimg->width, 1, pos); + 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 + } + // After TCA and distortion steps switch img and newimg. + // This is crucial since newimg is now the input image + // to the next stage. + if (ok && (step == 0 || step == 2)) + { + Image *tmp = newimg; + newimg = img; + img = tmp; + } + } + + delete [] pos; + delete newimg; + return img; +} + + + +int main (int argc, char **argv) +{ + setlocale (LC_ALL, ""); + + if (!ParseParameters(argc, argv)) + return -1; + + // load database + lfDatabase *ldb = new lfDatabase (); + + if (ldb->Load () != LF_NO_ERROR) { + ldb->Destroy(); + g_print ("\rERROR: Database could not be loaded\n"); + return -1; + } + + // try to find camera in the database + const lfCamera *cam = NULL; + if (opts.Camera) { + const lfCamera ** cameras = ldb->FindCamerasExt(NULL, opts.Camera); + if (cameras) + cam = cameras[0]; + else + g_print ("Cannot find a camera matching `%s' in database\n", opts.Camera); + lf_free (cameras); + } + + // try to find a matching lens in the database + const lfLens *lens = NULL; + if (opts.Lens) { + const lfLens **lenses = ldb->FindLenses (cam, NULL, opts.Lens); + if (lenses) + lens = lenses [0]; + else + g_print ("Cannot find a lens matching `%s' in database\n", opts.Lens); + lf_free (lenses); + } + + // print camera and lens information if in verbose mode or if no input file is specified + if (opts.Verbose || !opts.Input) { + if (cam && lens) { + g_print("Matching lens and camera combination found in the database:\n"); + PrintCamera(cam, ldb); + PrintLens(lens, ldb); + } else if (!cam && lens) { + g_print("Matching lens found in the database:\n"); + PrintLens(lens, ldb); + } else if (!lens && cam) { + g_print("Matching camera found in the database:\n"); + PrintCamera(cam, ldb); + } + } else { + if (cam && lens) { + g_print("= Selecting %s / %s\n", cam->Model, lens->Model); + } else if (!cam && lens) { + g_print("= Selecting %s\n", lens->Model); + } + } + + // nothing to process, so lets quit here + if (!opts.Input) { + ldb->Destroy(); + return 0; + } + + // assume standard values if parameters are not specified + if (cam) + opts.Crop = cam->CropFactor; + else if (!opts.Crop) + opts.Crop = lens->CropFactor; + if (!opts.Focal) + opts.Focal = lens->MinFocal; + if (!opts.Aperture) + opts.Aperture = lens->MinAperture; + + if (opts.Verbose) { + g_print("\nProcessing parameters:\n" + " |- Image crop factor: %g\n" + " |- Focal length: %gmm\n" + " |- Aperture: f/%g\n" + " |- Distance: %gm\n\n", + opts.Crop, opts.Focal, opts.Aperture, opts.Distance); + } else { + g_print("= Processing parameters: Crop %g, Focal %gmm, Aperture f/%g, Distance: %gm\n", + opts.Crop, opts.Focal, opts.Aperture, opts.Distance); + } + + Image *img = new Image (); + g_print ("~ Loading `%s' ... ", opts.Input); + if (!img->Open (opts.Input)) { + g_print ("\rERROR: failed to open file `%s'\n", opts.Input); + delete img; + ldb->Destroy(); + return -1; + } + if (!img->LoadPNG ()) { + g_print ("\rERROR: failed to parse PNG data from file `%s'\n", opts.Input); + delete img; + ldb->Destroy(); + return -1; + } + g_print ("done.\n~ Image size [%ux%u].\n", img->width, img->height); + + lfModifier *mod = lfModifier::Create (lens, opts.Crop, img->width, img->height); + if (!mod) { + g_print ("\rWarning: failed to create modifier\n"); + delete img; + ldb->Destroy(); + return -1; + } + int modflags = mod->Initialize ( + lens, LF_PF_U8, opts.Focal, + opts.Aperture, opts.Distance, opts.Scale, opts.TargetGeom, + opts.ModifyFlags, opts.Inverse); + + g_print("~ Selected modifications: "); + if (modflags & LF_MODIFY_TCA) + g_print ("[tca]"); + if (modflags & LF_MODIFY_VIGNETTING) + g_print ("[vign]"); + if (modflags & LF_MODIFY_DISTORTION) + g_print ("[dist]"); + if (modflags & LF_MODIFY_GEOMETRY) + g_print ("[geom]"); + if (opts.Scale != 1.0) + g_print ("[scale]"); + if (modflags==0) + g_print ("[NOTHING]"); + g_print ("\n"); + + g_print("~ Run processing chain... "); + + clock_t st; + clock_t xt = clock (); + while (xt == (st = clock ())) + ; + + img = ApplyModifier (modflags, opts.Inverse, img, mod); + + clock_t et = clock (); + g_print ("done (%.3g secs)\n", double (et - st) / CLOCKS_PER_SEC); + + mod->Destroy (); + + g_print ("~ Save output as `%s'...", opts.Output); + bool ok = img->SavePNG (opts.Output); + + delete img; + ldb->Destroy (); + + if (ok) { + g_print (" done\n"); + return 0; + } else { + g_print (" FAILED\n"); + return -1; + } + +} diff --git a/tests/test_database.cpp b/tests/test_database.cpp index d64984a..45dc38f 100644 --- a/tests/test_database.cpp +++ b/tests/test_database.cpp @@ -9,14 +9,14 @@ typedef struct { void db_setup(lfFixture *lfFix, gconstpointer data) { - lfFix->db = lf_db_new (); + lfFix->db = new lfDatabase (); lfFix->db->Load(); } void db_teardown(lfFixture *lfFix, gconstpointer data) { - lfFix->db->Destroy(); + delete lfFix->db; } diff --git a/tests/test_database.cpp.0038 b/tests/test_database.cpp.0038 new file mode 100644 index 0000000..d64984a --- /dev/null +++ b/tests/test_database.cpp.0038 @@ -0,0 +1,87 @@ +#include +#include +#include "lensfun.h" + +typedef struct { + lfDatabase* db; +} lfFixture; + + +void db_setup(lfFixture *lfFix, gconstpointer data) +{ + lfFix->db = lf_db_new (); + lfFix->db->Load(); +} + + +void db_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfFix->db->Destroy(); +} + + +// test different lens search strings +void test_DB_lens_search(lfFixture* lfFix, gconstpointer data) +{ + const lfLens **lenses = NULL; + + lenses = lfFix->db->FindLenses (NULL, NULL, "pEntax 50-200 ED"); + g_assert_nonnull(lenses); + g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); + lf_free (lenses); + + lenses = lfFix->db->FindLenses (NULL, NULL, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); + g_assert_nonnull(lenses); + g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED"); + lf_free (lenses); + + lenses = lfFix->db->FindLenses (NULL, NULL, "PENTAX fa 28mm 2.8"); + g_assert_nonnull(lenses); + g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-FA 28mm f/2.8 AL"); + lf_free (lenses); + + /*lenses = lfFix->db->FindLenses (NULL, NULL, "Fotasy M3517 35mm f/1.7"); + g_assert_nonnull(lenses); + g_assert_cmpstr(lenses[0]->Model, ==, "Fotasy M3517 35mm f/1.7"); + lf_free (lenses); + + lenses = lfFix->db->FindLenses (NULL, NULL, "Minolta MD 35mm 1/2.8"); + g_assert_nonnull(lenses); + g_assert_cmpstr(lenses[0]->Model, ==, "Minolta MD 35mm 1/2.8"); + lf_free (lenses);*/ +} + +// test different camera search strings +void test_DB_cam_search(lfFixture* lfFix, gconstpointer data) +{ + const lfCamera **cameras = NULL; + + cameras = lfFix->db->FindCamerasExt("pentax", "K100D"); + g_assert_nonnull(cameras); + g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); + lf_free (cameras); + + cameras = lfFix->db->FindCamerasExt(NULL, "K 100 D"); + g_assert_nonnull(cameras); + g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); + lf_free (cameras); + + cameras = lfFix->db->FindCamerasExt(NULL, "PentAX K100 D"); + g_assert_nonnull(cameras); + g_assert_cmpstr(cameras[0]->Model, ==, "Pentax K100D"); + lf_free (cameras); + +} + +int main (int argc, char **argv) +{ + + setlocale (LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + g_test_add("/database/lens search", lfFixture, NULL, db_setup, test_DB_lens_search, db_teardown); + g_test_add("/database/camera search", lfFixture, NULL, db_setup, test_DB_cam_search, db_teardown); + + return g_test_run(); +} diff --git a/tests/test_modifier.cpp b/tests/test_modifier.cpp index 3d091a4..f794638 100644 --- a/tests/test_modifier.cpp +++ b/tests/test_modifier.cpp @@ -31,7 +31,6 @@ void mod_setup(lfFixture *lfFix, gconstpointer data) void mod_teardown(lfFixture *lfFix, gconstpointer data) { - lfFix->mod->Destroy(); delete lfFix->lens; } @@ -55,7 +54,7 @@ void test_mod_projection_center(lfFixture* lfFix, gconstpointer data) if(g_test_verbose()) g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); - lfFix->mod = lfModifier::Create (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize ( lfFix->lens, LF_PF_U8, 12.0f, 6.7f, 2.0f, 1.0f, geom_types[i], @@ -68,6 +67,8 @@ void test_mod_projection_center(lfFixture* lfFix, gconstpointer data) g_assert_cmpfloat(in[0],==,res[0]); g_assert_cmpfloat(in[1],==,res[1]); } + + delete lfFix->mod; i++; } j++; @@ -94,7 +95,7 @@ void test_mod_projection_borders(lfFixture* lfFix, gconstpointer data) if(g_test_verbose()) g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); - lfFix->mod = lfModifier::Create (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize ( lfFix->lens, LF_PF_U8, 12.0f, 6.7f, 2.0f, 1.0f, geom_types[i], @@ -115,6 +116,7 @@ void test_mod_projection_borders(lfFixture* lfFix, gconstpointer data) g_assert_false(isnan(res[1])); } + delete lfFix->mod; i++; } j++; diff --git a/tests/test_modifier.cpp.0038 b/tests/test_modifier.cpp.0038 new file mode 100644 index 0000000..3d091a4 --- /dev/null +++ b/tests/test_modifier.cpp.0038 @@ -0,0 +1,136 @@ +#include +#include +#ifdef _MSC_VER +#define _USE_MATH_DEFINES +#endif +#include +#include "lensfun.h" + +typedef struct { + size_t img_width, img_height; + lfLens* lens; + lfModifier* mod; +} lfFixture; + +// setup a standard lens +void mod_setup(lfFixture *lfFix, gconstpointer data) +{ + lfFix->lens = new lfLens(); + lfFix->lens->CropFactor = 1.0f; + lfFix->lens->AspectRatio = 1.0f; + lfFix->lens->Type = LF_RECTILINEAR; + + lfLensCalibDistortion lensCalibDist = {LF_DIST_MODEL_POLY3, 12.0f, {0.1,0.5,0.5}}; + lfFix->lens->AddCalibDistortion(&lensCalibDist); + + // width and height have to be odd, so we have a non fractional center position + lfFix->img_height = 301; + lfFix->img_width = 301; +} + + +void mod_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfFix->mod->Destroy(); + delete lfFix->lens; +} + +// test to verifiy that projection center is image center +void test_mod_projection_center(lfFixture* lfFix, gconstpointer data) +{ + float in[2] = {0, 0}; + float res[2] = {0, 0}; + + // check mapping of center to center + lfLensType geom_types [] = {LF_RECTILINEAR, LF_PANORAMIC, LF_EQUIRECTANGULAR , LF_FISHEYE, LF_FISHEYE_EQUISOLID, LF_FISHEYE_ORTHOGRAPHIC, LF_FISHEYE_THOBY, LF_UNKNOWN}; + const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; + int j = 0; + while (geom_types[j]!=LF_UNKNOWN) { + + lfFix->lens->Type = geom_types[j]; + + int i = 0; + while (geom_types[i]!=LF_UNKNOWN) { + + if(g_test_verbose()) + g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); + + lfFix->mod = lfModifier::Create (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod->Initialize ( + lfFix->lens, LF_PF_U8, 12.0f, + 6.7f, 2.0f, 1.0f, geom_types[i], + LF_MODIFY_GEOMETRY, false); + + // check if center is not influenced + in[0] = (lfFix->img_width-1)/2; + in[1] = (lfFix->img_height-1)/2; + if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { + g_assert_cmpfloat(in[0],==,res[0]); + g_assert_cmpfloat(in[1],==,res[1]); + } + i++; + } + j++; + } +} + +// check if output becomes NaN when processing geometry conversion +void test_mod_projection_borders(lfFixture* lfFix, gconstpointer data) +{ + float in[2] = {lfFix->img_width, lfFix->img_height}; + float in2[2] = {(lfFix->img_width-1)/2, (lfFix->img_height-1)/2}; + float res[2] = {0, 0}; + + lfLensType geom_types [] = {LF_RECTILINEAR, LF_PANORAMIC, LF_EQUIRECTANGULAR, LF_FISHEYE_STEREOGRAPHIC, LF_FISHEYE, LF_FISHEYE_EQUISOLID, LF_FISHEYE_ORTHOGRAPHIC, LF_FISHEYE_THOBY, LF_UNKNOWN}; + const char* geom_names [] = {"rectilinear", "panoramic", "equirect", "fisheye-sterographic", "fisheye", "fisheye-equisolid", "fisheye-orthographic", "fisheye-thoby", NULL}; + int j = 0; + while (geom_types[j]!=LF_UNKNOWN) { + + lfFix->lens->Type = geom_types[j]; + + int i = 0; + while (geom_types[i]!=LF_UNKNOWN) { + + if(g_test_verbose()) + g_print(" ~ Conversion from %s -> %s \n", geom_names[j], geom_names[i]); + + lfFix->mod = lfModifier::Create (lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod->Initialize ( + lfFix->lens, LF_PF_U8, 12.0f, + 6.7f, 2.0f, 1.0f, geom_types[i], + LF_MODIFY_GEOMETRY, false); + + if (lfFix->mod->ApplyGeometryDistortion(0,0,1,1,res)) { + g_assert_false(isnan(res[0])); + g_assert_false(isnan(res[1])); + } + + if (lfFix->mod->ApplyGeometryDistortion(in[0],in[1],1,1,res)) { + g_assert_false(isnan(res[0])); + g_assert_false(isnan(res[1])); + } + + if (lfFix->mod->ApplyGeometryDistortion(in2[0],in2[1],1,1,res)) { + g_assert_false(isnan(res[0])); + g_assert_false(isnan(res[1])); + } + + i++; + } + j++; + } +} + + +int main (int argc, char **argv) +{ + + setlocale (LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + g_test_add("/modifier/projection center", lfFixture, NULL, mod_setup, test_mod_projection_center, mod_teardown); + g_test_add("/modifier/projection borders", lfFixture, NULL, mod_setup, test_mod_projection_borders, mod_teardown); + + return g_test_run(); +} diff --git a/tests/test_modifier_color.cpp b/tests/test_modifier_color.cpp index 4c5e2dc..6327232 100644 --- a/tests/test_modifier_color.cpp +++ b/tests/test_modifier_color.cpp @@ -107,7 +107,7 @@ void mod_setup(lfFixture *lfFix, gconstpointer data) lfFix->img_height = 300; lfFix->img_width = 300; - lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, cTypeToLfPixelFormat(), @@ -134,7 +134,7 @@ void mod_teardown(lfFixture *lfFix, gconstpointer data) else lf_free_align(lfFix->image); - lfFix->mod->Destroy(); + delete lfFix->mod; delete lfFix->lens; } diff --git a/tests/test_modifier_color.cpp.0038 b/tests/test_modifier_color.cpp.0038 new file mode 100644 index 0000000..4c5e2dc --- /dev/null +++ b/tests/test_modifier_color.cpp.0038 @@ -0,0 +1,275 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lensfun.h" + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#include +#endif +#ifdef __APPLE__ +#include +#endif + +#include "common_code.hpp" + +//TODO: find better place for cTypeToLfPixelFormat() +template +lfPixelFormat cTypeToLfPixelFormat() +{ + return LF_PF_U8; +} +template<> +lfPixelFormat cTypeToLfPixelFormat() +{ + return LF_PF_U8; +} +template<> +lfPixelFormat cTypeToLfPixelFormat() +{ + return LF_PF_U16; +} +template<> +lfPixelFormat cTypeToLfPixelFormat() +{ + return LF_PF_U32; +} +template<> +lfPixelFormat cTypeToLfPixelFormat() +{ + return LF_PF_F32; +} +template<> +lfPixelFormat cTypeToLfPixelFormat() +{ + return LF_PF_F64; +} + +typedef struct +{ + void *image; + size_t img_width, img_height; + lfLens *lens; + lfModifier *mod; +} lfFixture; + +typedef struct +{ + bool reverse; + size_t cpp; + gchar *pixDesc; + int comp_role; + size_t alignment; +} lfTestParams; + +template +void generateImage(lfFixture *lfFix, lfTestParams *p, T *pixels) +{ + T halfmax = std::numeric_limits::max() / T(2); + for(size_t i = 0; i < p->cpp * lfFix->img_width * lfFix->img_height; i++) + pixels[i] = halfmax; +} +template<> +void generateImage(lfFixture *lfFix, lfTestParams *p, float *pixels) +{ + for(size_t i = 0; i < p->cpp * lfFix->img_width * lfFix->img_height; i++) + pixels[i] = 0.5f; +} +template<> +void generateImage(lfFixture *lfFix, lfTestParams *p, double *pixels) +{ + for(size_t i = 0; i < p->cpp * lfFix->img_width * lfFix->img_height; i++) + pixels[i] = 0.5; +} + +// setup a standard lens +template +void mod_setup(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + lfFix->lens = new lfLens(); + lfFix->lens->CropFactor = 1.0f; + lfFix->lens->Type = LF_RECTILINEAR; + + // Canon EOS 5D Mark III + Canon EF 24-70mm f/2.8L II USM + lfLensCalibVignetting lensCalibVign = {LF_VIGNETTING_MODEL_PA, 24.0f, 2.8f, 1000.0f, { -0.5334f, -0.7926f, 0.5243f}}; + lfFix->lens->AddCalibVignetting(&lensCalibVign); + + lfFix->img_height = 300; + lfFix->img_width = 300; + + lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + + lfFix->mod->Initialize( + lfFix->lens, cTypeToLfPixelFormat(), + 24.0f, 2.8f, 1000.0f, 1.0f, LF_RECTILINEAR, + LF_MODIFY_VIGNETTING, p->reverse); + + lfFix->image = NULL; + + const size_t bufsize = p->cpp * lfFix->img_width * lfFix->img_height * sizeof(T); + if(p->alignment == 0) + lfFix->image = g_malloc(bufsize); + else + lfFix->image = lf_alloc_align(p->alignment, bufsize); + + generateImage(lfFix, p, (T *)lfFix->image); +} + +void mod_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + if(p->alignment == 0) + g_free(lfFix->image); + else + lf_free_align(lfFix->image); + + lfFix->mod->Destroy(); + delete lfFix->lens; +} + +template +void test_mod_color(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + for(size_t y = 0; y < lfFix->img_height; y++) + { + T *imgdata = (T *)lfFix->image + (size_t)p->cpp * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyColorModification( + imgdata, 0.0, y, lfFix->img_width, 1, + p->comp_role, p->cpp * lfFix->img_width)); + } +} + +#ifdef _OPENMP +template +void test_mod_color_parallel(lfFixture *lfFix, gconstpointer data) +{ + const lfTestParams *const p = (lfTestParams *)data; + + #pragma omp parallel for schedule(static) + for(size_t y = 0; y < lfFix->img_height; y++) + { + T *imgdata = (T *)lfFix->image + (size_t)p->cpp * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyColorModification( + imgdata, 0.0, y, lfFix->img_width, 1, + p->comp_role, p->cpp * lfFix->img_width)); + } +} +#endif + +gchar *describe(lfTestParams *p, const char *prefix, const char *f) +{ + gchar alignment[32] = ""; + g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); + + return g_strdup_printf( + "/%s/%s/%s/%s/%s", + prefix, + p->reverse ? "Vignetting" : "DeVignetting", + p->pixDesc, + f, + p->alignment == 0 ? "unaligned" : alignment + ); +} + +template +void add_set_item(lfTestParams *p, const char *f) +{ + gchar *desc = NULL; + + desc = describe(p, "modifier/color/serialFor", f); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_color, mod_teardown); + g_free(desc); + desc = NULL; + +#ifdef _OPENMP + desc = describe(p, "modifier/color/parallelFor", f); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_color_parallel, mod_teardown); + g_free(desc); + desc = NULL; +#endif +} + +void add_sets(lfTestParams *p) +{ + add_set_item(p, "lf_u8"); + add_set_item(p, "lf_u16"); + add_set_item(p, "lf_u32"); + add_set_item(p, "lf_f32"); + add_set_item(p, "lf_f64"); +} + +void free_params(gpointer mem) +{ + lfTestParams *p = (lfTestParams *)mem; + + g_free(p->pixDesc); + g_free(mem); +} + +int main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + GSList *slist = NULL; + + std::vector reverse; + reverse.push_back(false); + reverse.push_back(true); + + for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) + { + std::map pixDesc; + pixDesc["RGB"] = LF_CR_3(RED, GREEN, BLUE); + pixDesc["RGBA"] = LF_CR_4(RED, GREEN, BLUE, UNKNOWN); + pixDesc["ARGB"] = LF_CR_4(UNKNOWN, RED, GREEN, BLUE); + + for(std::map::iterator it_pixDesc = pixDesc.begin(); it_pixDesc != pixDesc.end(); ++it_pixDesc) + { + std::vector align; + align.push_back(0); + align.push_back(4 * sizeof(float)); // SSE + //align.push_back(8 * sizeof(float)); // AVX + //align.push_back(16 * sizeof(float)); // AVX512 + + for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) + { + lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); + + p->reverse = *it_reverse; + p->cpp = it_pixDesc->first.length(); + p->pixDesc = g_strdup(it_pixDesc->first.c_str()); + p->comp_role = it_pixDesc->second; + p->alignment = *it_align; + + add_sets(p); + + slist = g_slist_append(slist, p); + } + } + } + + const int res = g_test_run(); + + g_slist_free_full(slist, (GDestroyNotify)free_params); + + return res; +} diff --git a/tests/test_modifier_coord_distortion.cpp b/tests/test_modifier_coord_distortion.cpp index 6fd6773..f463350 100644 --- a/tests/test_modifier_coord_distortion.cpp +++ b/tests/test_modifier_coord_distortion.cpp @@ -51,7 +51,7 @@ void mod_setup(lfFixture *lfFix, gconstpointer data) lfFix->img_height = 300; lfFix->img_width = 300; - lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, @@ -76,7 +76,7 @@ void mod_teardown(lfFixture *lfFix, gconstpointer data) else lf_free_align(lfFix->coordBuff); - lfFix->mod->Destroy(); + delete lfFix->mod; delete lfFix->lens; } diff --git a/tests/test_modifier_coord_distortion.cpp.0038 b/tests/test_modifier_coord_distortion.cpp.0038 new file mode 100644 index 0000000..6fd6773 --- /dev/null +++ b/tests/test_modifier_coord_distortion.cpp.0038 @@ -0,0 +1,209 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lensfun.h" + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#include +#endif +#ifdef __APPLE__ +#include +#endif + +#include "common_code.hpp" + +typedef struct +{ + void *coordBuff; + size_t img_width, img_height; + lfLens *lens; + lfModifier *mod; +} lfFixture; + +typedef struct +{ + bool reverse; + gchar *distortionModel; + lfLensCalibDistortion calib; + size_t alignment; +} lfTestParams; + +// setup a standard lens +void mod_setup(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + lfFix->lens = new lfLens(); + lfFix->lens->CropFactor = 1.0f; + lfFix->lens->Type = LF_RECTILINEAR; + + lfFix->lens->AddCalibDistortion(&p->calib); + + lfFix->img_height = 300; + lfFix->img_width = 300; + + lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + + lfFix->mod->Initialize( + lfFix->lens, LF_PF_F32, + 24.0f, 2.8f, 1000.0f, 1.0f, LF_RECTILINEAR, + LF_MODIFY_DISTORTION, p->reverse); + + lfFix->coordBuff = NULL; + + const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); + if(p->alignment == 0) + lfFix->coordBuff = g_malloc(bufsize); + else + lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); +} + +void mod_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + if(p->alignment == 0) + g_free(lfFix->coordBuff); + else + lf_free_align(lfFix->coordBuff); + + lfFix->mod->Destroy(); + delete lfFix->lens; +} + +void test_mod_coord_distortion(lfFixture *lfFix, gconstpointer data) +{ + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} + +#ifdef _OPENMP +void test_mod_coord_distortion_parallel(lfFixture *lfFix, gconstpointer data) +{ + #pragma omp parallel for schedule(static) + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} +#endif + +gchar *describe(lfTestParams *p, const char *prefix) +{ + gchar alignment[32] = ""; + g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); + + return g_strdup_printf( + "/%s/%s/%s/%s", + prefix, + p->reverse ? "UnDist" : "Dist", + p->distortionModel, + p->alignment == 0 ? "unaligned" : alignment + ); +} + +void add_set_item(lfTestParams *p) +{ + gchar *desc = NULL; + + desc = describe(p, "modifier/coord/serialFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_distortion, mod_teardown); + g_free(desc); + desc = NULL; + +#ifdef _OPENMP + desc = describe(p, "modifier/coord/parallelFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_distortion_parallel, mod_teardown); + g_free(desc); + desc = NULL; +#endif +} + +void free_params(gpointer mem) +{ + lfTestParams *p = (lfTestParams *)mem; + + g_free(p->distortionModel); + g_free(mem); +} + +int main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + GSList *slist = NULL; + + std::vector reverse; + reverse.push_back(false); + reverse.push_back(true); + + for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) + { + std::map distortCalib; + // ??? + Canon EF 85mm f/1.2L II USM + distortCalib["LF_DIST_MODEL_POLY3"] = (lfLensCalibDistortion) + { + LF_DIST_MODEL_POLY3, 85.0f, { -0.00412} + }; + //Canon PowerShot G12 (fixed lens) + distortCalib["LF_DIST_MODEL_POLY5"] = (lfLensCalibDistortion) + { + LF_DIST_MODEL_POLY5, 6.1f, { -0.030571633, 0.004658548} + }; + //Canon EOS 5D Mark III + Canon EF 24-70mm f/2.8L II USM + distortCalib["LF_DIST_MODEL_PTLENS"] = (lfLensCalibDistortion) + { + LF_DIST_MODEL_PTLENS, 24.0f, {0.02964, -0.07853, 0.02943} + }; + + for(std::map::iterator it_distortCalib = distortCalib.begin(); it_distortCalib != distortCalib.end(); ++it_distortCalib) + { + std::vector align; + align.push_back(0); + align.push_back(4 * sizeof(float)); // SSE + //align.push_back(8 * sizeof(float)); // AVX + //align.push_back(16 * sizeof(float)); // AVX512 + + for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) + { + lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); + + p->reverse = *it_reverse; + p->distortionModel = g_strdup(it_distortCalib->first.c_str()); + p->calib = it_distortCalib->second; + p->alignment = *it_align; + + add_set_item(p); + + slist = g_slist_append(slist, p); + } + } + } + + const int res = g_test_run(); + + g_slist_free_full(slist, (GDestroyNotify)free_params); + + return res; +} diff --git a/tests/test_modifier_coord_geometry.cpp b/tests/test_modifier_coord_geometry.cpp index 6805b7d..d626ba8 100644 --- a/tests/test_modifier_coord_geometry.cpp +++ b/tests/test_modifier_coord_geometry.cpp @@ -51,7 +51,7 @@ void mod_setup(lfFixture *lfFix, gconstpointer data) lfFix->img_height = 300; lfFix->img_width = 300; - lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, @@ -76,7 +76,7 @@ void mod_teardown(lfFixture *lfFix, gconstpointer data) else lf_free_align(lfFix->coordBuff); - lfFix->mod->Destroy(); + delete lfFix->mod; delete lfFix->lens; } diff --git a/tests/test_modifier_coord_geometry.cpp.0038 b/tests/test_modifier_coord_geometry.cpp.0038 new file mode 100644 index 0000000..6805b7d --- /dev/null +++ b/tests/test_modifier_coord_geometry.cpp.0038 @@ -0,0 +1,212 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lensfun.h" + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#include +#endif +#ifdef __APPLE__ +#include +#endif + +#include "common_code.hpp" + +typedef struct +{ + void *coordBuff; + size_t img_width, img_height; + lfLens *lens; + lfModifier *mod; +} lfFixture; + +typedef struct +{ + bool reverse; + gchar *sourceType; + lfLensType sourceLensType; + gchar *targetType; + lfLensType targetLensType; + size_t alignment; +} lfTestParams; + +// setup a standard lens +void mod_setup(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + lfFix->lens = new lfLens(); + lfFix->lens->CropFactor = 1.0f; + lfFix->lens->Type = p->sourceLensType; + + lfFix->img_height = 300; + lfFix->img_width = 300; + + lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + + lfFix->mod->Initialize( + lfFix->lens, LF_PF_F32, + 24.0f, 2.8f, 1000.0f, 1.0f, p->targetLensType, + LF_MODIFY_GEOMETRY, p->reverse); + + lfFix->coordBuff = NULL; + + const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); + if(p->alignment == 0) + lfFix->coordBuff = g_malloc(bufsize); + else + lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); +} + +void mod_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + if(p->alignment == 0) + g_free(lfFix->coordBuff); + else + lf_free_align(lfFix->coordBuff); + + lfFix->mod->Destroy(); + delete lfFix->lens; +} + +void test_mod_coord_geometry(lfFixture *lfFix, gconstpointer data) +{ + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} + +#ifdef _OPENMP +void test_mod_coord_geometry_parallel(lfFixture *lfFix, gconstpointer data) +{ + #pragma omp parallel for schedule(static) + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} +#endif + +gchar *describe(lfTestParams *p, const char *prefix) +{ + gchar alignment[32] = ""; + g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); + + return g_strdup_printf( + "/%s/%s/%s/%s/%s", + prefix, + p->reverse ? "unGeom" : "Geom", + p->sourceType, + p->targetType, + p->alignment == 0 ? "unaligned" : alignment + ); +} + +void add_set_item(lfTestParams *p) +{ + gchar *desc = NULL; + + desc = describe(p, "modifier/coord/serialFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_geometry, mod_teardown); + g_free(desc); + desc = NULL; + +#ifdef _OPENMP + desc = describe(p, "modifier/coord/parallelFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_geometry_parallel, mod_teardown); + g_free(desc); + desc = NULL; +#endif +} + +void free_params(gpointer mem) +{ + lfTestParams *p = (lfTestParams *)mem; + + g_free(p->sourceType); + g_free(p->targetType); + g_free(mem); +} + +int main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + GSList *slist = NULL; + + std::vector reverse; + reverse.push_back(false); + reverse.push_back(true); + + for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) + { + std::map lensType; + lensType["LF_RECTILINEAR"] = LF_RECTILINEAR; + lensType["LF_FISHEYE"] = LF_FISHEYE; + lensType["LF_PANORAMIC"] = LF_PANORAMIC; + lensType["LF_EQUIRECTANGULAR"] = LF_EQUIRECTANGULAR; + lensType["LF_FISHEYE_ORTHOGRAPHIC"] = LF_FISHEYE_ORTHOGRAPHIC; + lensType["LF_FISHEYE_STEREOGRAPHIC"] = LF_FISHEYE_STEREOGRAPHIC; + lensType["LF_FISHEYE_EQUISOLID"] = LF_FISHEYE_EQUISOLID; + lensType["LF_FISHEYE_THOBY"] = LF_FISHEYE_THOBY; + + for(std::map::iterator it_sourceType = lensType.begin(); it_sourceType != lensType.end(); ++it_sourceType) + { + for(std::map::iterator it_targetType = lensType.begin(); it_targetType != lensType.end(); ++it_targetType) + { + if(it_sourceType->second == it_targetType->second) + continue; + + std::vector align; + align.push_back(0); + align.push_back(4 * sizeof(float)); // SSE + //align.push_back(8 * sizeof(float)); // AVX + //align.push_back(16 * sizeof(float)); // AVX512 + + for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) + { + lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); + + p->reverse = *it_reverse; + p->sourceType = g_strdup(it_sourceType->first.c_str()); + p->sourceLensType = it_sourceType->second; + p->targetType = g_strdup(it_targetType->first.c_str()); + p->targetLensType = it_targetType->second; + p->alignment = *it_align; + + add_set_item(p); + + slist = g_slist_append(slist, p); + } + } + } + } + + const int res = g_test_run(); + + g_slist_free_full(slist, (GDestroyNotify)free_params); + + return res; +} diff --git a/tests/test_modifier_coord_scale.cpp b/tests/test_modifier_coord_scale.cpp index c155ff8..84a4286 100644 --- a/tests/test_modifier_coord_scale.cpp +++ b/tests/test_modifier_coord_scale.cpp @@ -48,7 +48,7 @@ void mod_setup(lfFixture *lfFix, gconstpointer data) lfFix->img_height = 300; lfFix->img_width = 300; - lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, @@ -73,7 +73,7 @@ void mod_teardown(lfFixture *lfFix, gconstpointer data) else lf_free_align(lfFix->coordBuff); - lfFix->mod->Destroy(); + delete lfFix->mod; delete lfFix->lens; } diff --git a/tests/test_modifier_coord_scale.cpp.0038 b/tests/test_modifier_coord_scale.cpp.0038 new file mode 100644 index 0000000..c155ff8 --- /dev/null +++ b/tests/test_modifier_coord_scale.cpp.0038 @@ -0,0 +1,184 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lensfun.h" + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#include +#endif +#ifdef __APPLE__ +#include +#endif + +#include "common_code.hpp" + +typedef struct +{ + void *coordBuff; + size_t img_width, img_height; + lfLens *lens; + lfModifier *mod; +} lfFixture; + +typedef struct +{ + bool reverse; + float scale; + size_t alignment; +} lfTestParams; + +// setup a standard lens +void mod_setup(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + lfFix->lens = new lfLens(); + lfFix->lens->CropFactor = 1.0f; + lfFix->lens->Type = LF_RECTILINEAR; + + lfFix->img_height = 300; + lfFix->img_width = 300; + + lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + + lfFix->mod->Initialize( + lfFix->lens, LF_PF_F32, + 24.0f, 2.8f, 1000.0f, p->scale, LF_RECTILINEAR, + LF_MODIFY_SCALE, p->reverse); + + lfFix->coordBuff = NULL; + + const size_t bufsize = 2 * lfFix->img_width * lfFix->img_height * sizeof(float); + if(p->alignment == 0) + lfFix->coordBuff = g_malloc(bufsize); + else + lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); +} + +void mod_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + if(p->alignment == 0) + g_free(lfFix->coordBuff); + else + lf_free_align(lfFix->coordBuff); + + lfFix->mod->Destroy(); + delete lfFix->lens; +} + +void test_mod_coord_scale(lfFixture *lfFix, gconstpointer data) +{ + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} + +#ifdef _OPENMP +void test_mod_coord_scale_parallel(lfFixture *lfFix, gconstpointer data) +{ + #pragma omp parallel for schedule(static) + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplyGeometryDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} +#endif + +gchar *describe(lfTestParams *p, const char *prefix) +{ + gchar alignment[32] = ""; + g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); + + return g_strdup_printf( + "/%s/%s/%f/%s", + prefix, + p->reverse ? "unScale" : "Scale", + p->scale, + p->alignment == 0 ? "unaligned" : alignment + ); +} + +void add_set_item(lfTestParams *p) +{ + gchar *desc = NULL; + + desc = describe(p, "modifier/coord/serialFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale, mod_teardown); + g_free(desc); + desc = NULL; + +#ifdef _OPENMP + desc = describe(p, "modifier/coord/parallelFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_coord_scale_parallel, mod_teardown); + g_free(desc); + desc = NULL; +#endif +} + +int main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + GSList *slist = NULL; + + std::vector reverse; + reverse.push_back(false); + reverse.push_back(true); + + for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) + { + std::vector scale; + scale.push_back(0.75f); + scale.push_back(1.25f); + + for(std::vector::iterator it_scale = scale.begin(); it_scale != scale.end(); ++it_scale) + { + std::vector align; + align.push_back(0); + align.push_back(4 * sizeof(float)); // SSE + //align.push_back(8 * sizeof(float)); // AVX + //align.push_back(16 * sizeof(float)); // AVX512 + + for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) + { + lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); + + p->reverse = *it_reverse; + p->scale = *it_scale; + p->alignment = *it_align; + + add_set_item(p); + + slist = g_slist_append(slist, p); + } + } + } + + const int res = g_test_run(); + + g_slist_free_full(slist, (GDestroyNotify)g_free); + + return res; +} diff --git a/tests/test_modifier_subpix.cpp b/tests/test_modifier_subpix.cpp index d04f36d..fa29cf6 100644 --- a/tests/test_modifier_subpix.cpp +++ b/tests/test_modifier_subpix.cpp @@ -51,7 +51,7 @@ void mod_setup(lfFixture *lfFix, gconstpointer data) lfFix->img_height = 300; lfFix->img_width = 300; - lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + lfFix->mod = new lfModifier(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); lfFix->mod->Initialize( lfFix->lens, LF_PF_F32, @@ -76,7 +76,7 @@ void mod_teardown(lfFixture *lfFix, gconstpointer data) else lf_free_align(lfFix->coordBuff); - lfFix->mod->Destroy(); + delete lfFix->mod; delete lfFix->lens; } diff --git a/tests/test_modifier_subpix.cpp.0038 b/tests/test_modifier_subpix.cpp.0038 new file mode 100644 index 0000000..d04f36d --- /dev/null +++ b/tests/test_modifier_subpix.cpp.0038 @@ -0,0 +1,204 @@ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "lensfun.h" + +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#include +#endif +#ifdef __APPLE__ +#include +#endif + +#include "common_code.hpp" + +typedef struct +{ + void *coordBuff; + size_t img_width, img_height; + lfLens *lens; + lfModifier *mod; +} lfFixture; + +typedef struct +{ + bool reverse; + gchar *tcaModel; + lfLensCalibTCA calib; + size_t alignment; +} lfTestParams; + +// setup a standard lens +void mod_setup(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + lfFix->lens = new lfLens(); + lfFix->lens->CropFactor = 1.0f; + lfFix->lens->Type = LF_RECTILINEAR; + + lfFix->lens->AddCalibTCA(&p->calib); + + lfFix->img_height = 300; + lfFix->img_width = 300; + + lfFix->mod = lfModifier::Create(lfFix->lens, 1.0f, lfFix->img_width, lfFix->img_height); + + lfFix->mod->Initialize( + lfFix->lens, LF_PF_F32, + 24.0f, 2.8f, 1000.0f, 1.0f, LF_RECTILINEAR, + LF_MODIFY_TCA, p->reverse); + + lfFix->coordBuff = NULL; + + const size_t bufsize = 2 * 3 * lfFix->img_width * lfFix->img_height * sizeof(float); + if(p->alignment == 0) + lfFix->coordBuff = g_malloc(bufsize); + else + lfFix->coordBuff = lf_alloc_align(p->alignment, bufsize); +} + +void mod_teardown(lfFixture *lfFix, gconstpointer data) +{ + lfTestParams *p = (lfTestParams *)data; + + if(p->alignment == 0) + g_free(lfFix->coordBuff); + else + lf_free_align(lfFix->coordBuff); + + lfFix->mod->Destroy(); + delete lfFix->lens; +} + +void test_mod_subpix(lfFixture *lfFix, gconstpointer data) +{ + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * 3 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplySubpixelDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} + +#ifdef _OPENMP +void test_mod_subpix_parallel(lfFixture *lfFix, gconstpointer data) +{ + #pragma omp parallel for schedule(static) + for(size_t y = 0; y < lfFix->img_height; y++) + { + float *coordData = (float *)lfFix->coordBuff + (size_t)2 * 3 * y * lfFix->img_width; + + g_assert_true( + lfFix->mod->ApplySubpixelDistortion(0.0, y, lfFix->img_width, 1, coordData) + ); + } +} +#endif + +gchar *describe(lfTestParams *p, const char *prefix) +{ + gchar alignment[32] = ""; + g_snprintf(alignment, sizeof(alignment), "%lu-byte", p->alignment); + + return g_strdup_printf( + "/%s/%s/%s/%s", + prefix, + p->reverse ? "UnTCA" : "TCA", + p->tcaModel, + p->alignment == 0 ? "unaligned" : alignment + ); +} + +void add_set_item(lfTestParams *p) +{ + gchar *desc = NULL; + + desc = describe(p, "modifier/subpix/serialFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_subpix, mod_teardown); + g_free(desc); + desc = NULL; + +#ifdef _OPENMP + desc = describe(p, "modifier/subpix/parallelFor"); + g_test_add(desc, lfFixture, p, mod_setup, test_mod_subpix_parallel, mod_teardown); + g_free(desc); + desc = NULL; +#endif +} + +void free_params(gpointer mem) +{ + lfTestParams *p = (lfTestParams *)mem; + + g_free(p->tcaModel); + g_free(mem); +} + +int main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + g_test_init(&argc, &argv, NULL); + + GSList *slist = NULL; + + std::vector reverse; + reverse.push_back(false); + reverse.push_back(true); + + for(std::vector::iterator it_reverse = reverse.begin(); it_reverse != reverse.end(); ++it_reverse) + { + std::map tcaCalib; + // ??? + Nikon AF-S DX Nikkor 35mm f/1.8G + tcaCalib["LF_TCA_MODEL_LINEAR"] = (lfLensCalibTCA) + { + LF_TCA_MODEL_LINEAR, 35.0f, {1.0003, 1.0003} + }; + // Canon EOS 5D Mark III + Canon EF 24-70mm f/2.8L II USM + tcaCalib["LF_TCA_MODEL_POLY3"] = (lfLensCalibTCA) + { + LF_TCA_MODEL_POLY3, 24.0f, {1.0002104, 1.0000529, 0.0f, 0.0f, -0.0000220, -0.0000000} + }; + + for(std::map::iterator it_tcaCalib = tcaCalib.begin(); it_tcaCalib != tcaCalib.end(); ++it_tcaCalib) + { + std::vector align; + align.push_back(0); + align.push_back(4 * sizeof(float)); // SSE + //align.push_back(8 * sizeof(float)); // AVX + //align.push_back(16 * sizeof(float)); // AVX512 + + for(std::vector::iterator it_align = align.begin(); it_align != align.end(); ++it_align) + { + lfTestParams *p = (lfTestParams *)g_malloc(sizeof(lfTestParams)); + + p->reverse = *it_reverse; + p->tcaModel = g_strdup(it_tcaCalib->first.c_str()); + p->calib = it_tcaCalib->second; + p->alignment = *it_align; + + add_set_item(p); + + slist = g_slist_append(slist, p); + } + } + } + + const int res = g_test_run(); + + g_slist_free_full(slist, (GDestroyNotify)free_params); + + return res; +}