1 #include <string>
2 #include <limits>
3 #include <map>
4 #include <cmath>
5 
6 #include "lensfun.h"
7 #include "../libs/lensfun/lensfunprv.h"
8 
9 
10 typedef struct
11 {
12   lfDatabase *db;
13   size_t img_height;
14   size_t img_width;
15 } lfFixture;
16 
17 // setup a standard lens
mod_setup(lfFixture * lfFix,gconstpointer data)18 void mod_setup (lfFixture *lfFix, gconstpointer data)
19 {
20 
21     lfFix->db = new lfDatabase ();
22     lfFix->db->LoadDirectory("data/db");
23 
24     lfFix->img_height = 1000;
25     lfFix->img_width  = 1500;
26 }
27 
mod_teardown(lfFixture * lfFix,gconstpointer data)28 void mod_teardown (lfFixture *lfFix, gconstpointer data)
29 {
30     lfFix->db->Destroy();
31 }
32 
test_verify_dist_poly3(lfFixture * lfFix,gconstpointer data)33 void test_verify_dist_poly3 (lfFixture *lfFix, gconstpointer data)
34 {
35     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "pEntax 50-200 ED");
36     g_assert_nonnull(lenses);
37     g_assert_cmpstr(lenses[0]->Model, ==, "smc Pentax-DA 50-200mm f/4-5.6 DA ED");
38 
39     lfModifier* mod = lfModifier::Create (lenses[0], 1.534f, lfFix->img_width, lfFix->img_height);
40 
41     mod->Initialize(lenses[0], LF_PF_F32, 80.89f, 5.6f, 1000.0f, 1.0f, LF_RECTILINEAR,
42                            LF_MODIFY_DISTORTION, false);
43 
44     float x[] = {0, 751, 810, 1270};
45     float y[] = {0, 497, 937, 100};
46 
47     float expected_x[] = {-14.03764153, 751.00000000, 810.27246094, 1275.17346191};
48     float expected_y[] = {-9.35532570, 497.00000000, 938.97027588, 96.02919769};
49 
50     float coords [2];
51     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
52     {
53         g_assert_true(mod->ApplyGeometryDistortion (x[i], y[i], 1, 1, coords));
54         //g_print("\n%.8f, %.8f\n", coords[0], coords[1]);
55         g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, 1e-3);
56         g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, 1e-3);
57     }
58 
59     mod->Destroy();
60     lf_free (lenses);
61 }
62 
test_verify_dist_poly5(lfFixture * lfFix,gconstpointer data)63 void test_verify_dist_poly5 (lfFixture *lfFix, gconstpointer data)
64 {
65     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "Canon PowerShot G12");
66     g_assert_nonnull(lenses);
67     g_assert_cmpstr(lenses[0]->Model, ==, "Canon PowerShot G12 & compatibles (Standard)");
68 
69     g_print(lenses[0]->Model);
70 
71     lfModifier* mod = lfModifier::Create (lenses[0], 4.6f, lfFix->img_width, lfFix->img_height);
72 
73     mod->Initialize(lenses[0], LF_PF_F32, 10.89f, 5.6f, 1000.0f, 1.0f, LF_RECTILINEAR,
74                            LF_MODIFY_DISTORTION, false);
75 
76     float x[] = {0, 751, 810, 1270};
77     float y[] = {0, 497, 937, 100};
78 
79     float expected_x[] = {28.85699272, 751.00000000, 809.50451660, 1260.12316895};
80     float expected_y[] = {19.23155594, 497.00000000, 933.41711426, 107.58076477};
81 
82     float coords [2];
83     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
84     {
85         g_assert_true(mod->ApplyGeometryDistortion (x[i], y[i], 1, 1, coords));
86         //g_print("\n%.8f, %.8f\n", coords[0], coords[1]);
87         g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, 1e-3);
88         g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, 1e-3);
89     }
90 
91     mod->Destroy();
92     lf_free (lenses);
93 }
94 
test_verify_dist_ptlens(lfFixture * lfFix,gconstpointer data)95 void test_verify_dist_ptlens (lfFixture *lfFix, gconstpointer data)
96 {
97     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "PENTAX-F 28-80mm");
98     g_assert_nonnull(lenses);
99     g_assert_cmpstr(lenses[0]->Model, ==, "Pentax-F 28-80mm f/3.5-4.5");
100 
101     lfModifier* mod = lfModifier::Create (lenses[0], 1.534f, lfFix->img_width, lfFix->img_height);
102 
103     mod->Initialize(lenses[0], LF_PF_F32, 30.89f, 5.6f, 1000.0f, 1.0f, LF_RECTILINEAR,
104                            LF_MODIFY_DISTORTION, false);
105 
106     float x[] = {0, 751, 810, 1270};
107     float y[] = {0, 497, 937, 100};
108 
109     float expected_x[] = {29.04440117, 750.99969482, 808.74157715, 1255.12915039};
110     float expected_y[] = {19.35648155, 497.00045776, 927.89971924, 111.41387939};
111 
112     float coords [2];
113     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
114     {
115         g_assert_true(mod->ApplyGeometryDistortion (x[i], y[i], 1, 1, coords));
116         //g_print("\n%.8f, %.8f\n", coords[0], coords[1]);
117         g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, 1e-3);
118         g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, 1e-3);
119     }
120 
121     mod->Destroy();
122     lf_free (lenses);
123 }
124 
test_verify_vignetting_pa(lfFixture * lfFix,gconstpointer data)125 void test_verify_vignetting_pa (lfFixture *lfFix, gconstpointer data)
126 {
127     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "Olympus ED 14-42mm");
128     g_assert_nonnull(lenses);
129     g_assert_cmpstr(lenses[0]->Model, ==, "Olympus Zuiko Digital ED 14-42mm f/3.5-5.6");
130 
131     lfModifier* mod = lfModifier::Create (lenses[0], 2.0f, lfFix->img_width, lfFix->img_height);
132 
133     mod->Initialize(lenses[0], LF_PF_U16, 17.89f, 5.0f, 1000.0f, 1.0f, LF_RECTILINEAR,
134                            LF_MODIFY_VIGNETTING, false);
135 
136     float x[] = {0, 751, 810, 1270};
137     float y[] = {0, 497, 937, 100};
138 
139     lf_u16 expected[] = {22422, 22422, 24174, 28848};
140 
141     lf_u16 coords [3] = {16000, 16000, 16000};
142     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
143     {
144         g_assert_true(mod->ApplyColorModification(&coords[0], x[i], y[i], 1, 1, LF_CR_3(RED,GREEN,BLUE), 0));
145         //g_print("\n%d, %d, %d\n", coords[0], coords[1], coords[2]);
146         g_assert_cmpfloat (fabs (coords [0] - expected [i]), <=, 1e-3);
147         g_assert_cmpfloat (fabs (coords [1] - expected [i]), <=, 1e-3);
148         g_assert_cmpfloat (fabs (coords [2] - expected [i]), <=, 1e-3);
149     }
150 
151     mod->Destroy();
152     lf_free (lenses);
153 }
154 
test_verify_subpix_linear(lfFixture * lfFix,gconstpointer data)155 void test_verify_subpix_linear (lfFixture *lfFix, gconstpointer data)
156 {
157     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "Olympus ED 14-42mm");
158     g_assert_nonnull(lenses);
159     g_assert_cmpstr(lenses[0]->Model, ==, "Olympus Zuiko Digital ED 14-42mm f/3.5-5.6");
160 
161     lfModifier* mod = lfModifier::Create (lenses[0], 2.0f, lfFix->img_width, lfFix->img_height);
162 
163     mod->Initialize(lenses[0], LF_PF_U16, 17.89f, 5.0f, 1000.0f, 1.0f, LF_RECTILINEAR,
164                            LF_MODIFY_TCA, false);
165 
166     float x[] = {0, 751, 810, 1270};
167     float y[] = {0, 497, 937, 100};
168 
169     float expected[][6] = {
170         {-0.08681729, -0.05789410, 0.00002450, -0.00001032, -0.02400517, -0.01601936},
171         {751.00061035, 496.99899292, 751.00000000, 497.00000000, 751.00000000, 497.00000000},
172         {810.01995850, 937.14440918, 810.00000000, 937.00000000, 810.00042725, 937.00305176},
173         {1270.12915039, 99.90086365, 1270.00000000, 100.00000763, 1270.00854492, 99.99343872}
174     };
175 
176     float coords [6];
177     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
178     {
179         g_assert_true(mod->ApplySubpixelDistortion(x[i], y[i], 1, 1, coords));
180         //g_print("{%.8f, %.8f, %.8f, %.8f, %.8f, %.8f},\n", coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
181         for (int j = 0; j < 6; j++)
182             g_assert_cmpfloat (fabs (coords [j] - expected [i][j]), <=, 1e-3);
183     }
184 
185     mod->Destroy();
186     lf_free (lenses);
187 }
188 
test_verify_subpix_poly3(lfFixture * lfFix,gconstpointer data)189 void test_verify_subpix_poly3 (lfFixture *lfFix, gconstpointer data)
190 {
191     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "Olympus ED 14-42mm");
192     g_assert_nonnull(lenses);
193     g_assert_cmpstr(lenses[0]->Model, ==, "Olympus Zuiko Digital ED 14-42mm f/3.5-5.6");
194 
195     lfModifier* mod = lfModifier::Create (lenses[0], 2.0f, lfFix->img_width, lfFix->img_height);
196 
197     mod->Initialize(lenses[0], LF_PF_U16, 26.89f, 5.0f, 1000.0f, 1.0f, LF_RECTILINEAR,
198                            LF_MODIFY_TCA, false);
199 
200     float x[] = {0, 751, 810, 1270};
201     float y[] = {0, 497, 937, 100};
202 
203     float expected[][6] = {
204         {-0.05537901, -0.03692452, 0.00002450, -0.00001032, 0.01445518, 0.00962087},
205         {751.00061035, 496.99902344, 751.00000000, 497.00000000, 750.99981689, 497.00030518},
206         {810.01898193, 937.13732910, 810.00000000, 937.00000000, 809.99389648, 936.95599365},
207         {1270.11572266, 99.91123199, 1270.00000000, 100.00000763, 1269.96374512, 100.02780914}
208     };
209 
210     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
211     {
212         float coords [6];
213         g_assert_true(mod->ApplySubpixelDistortion (x[i], y[i], 1, 1, coords));
214         //g_print("{%.8f, %.8f, %.8f, %.8f, %.8f, %.8f},\n", coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
215         for (int j = 0; j < 6; j++)
216             g_assert_cmpfloat (fabs (coords [j] - expected [i][j]), <=, 1e-3);
217     }
218 
219     mod->Destroy();
220     lf_free (lenses);
221 }
222 
test_verify_geom_fisheye_rectlinear(lfFixture * lfFix,gconstpointer data)223 void test_verify_geom_fisheye_rectlinear (lfFixture *lfFix, gconstpointer data)
224 {
225     // select a lens from database
226     const lfLens** lenses = lfFix->db->FindLenses (NULL, NULL, "M.Zuiko Digital ED 8mm f/1.8 Fisheye");
227     g_assert_nonnull(lenses);
228     g_assert_cmpstr(lenses[0]->Model, ==, "Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro");
229 
230     lfModifier* mod = lfModifier::Create (lenses[0], 2.0f, lfFix->img_width, lfFix->img_height);
231 
232     mod->Initialize(lenses[0], LF_PF_U16, 8.0f, 5.0f, 1000.0f, 1.0f, LF_RECTILINEAR,
233                            LF_MODIFY_GEOMETRY, false);
234 
235     float x[] = {0, 751, 810, 1270};
236     float y[] = {0, 497, 937, 100};
237 
238     float expected_x[] = {248.98896790, 751.00000000, 802.23010254, 1151.07922363};
239     float expected_y[] = {165.93727112, 497.00000000, 880.81262207, 191.27542114};
240 
241     float coords [2];
242     for (int i = 0; i < sizeof(x) / sizeof(float); i++)
243     {
244         g_assert_true(mod->ApplyGeometryDistortion (x[i], y[i], 1, 1, coords));
245         //g_print("\n%.8f, %.8f\n", coords[0], coords[1]);
246         g_assert_cmpfloat (fabs (coords [0] - expected_x [i]), <=, 1e-1);
247         g_assert_cmpfloat (fabs (coords [1] - expected_y [i]), <=, 1e-1);
248     }
249 
250     mod->Destroy();
251     lf_free (lenses);
252 }
253 
main(int argc,char ** argv)254 int main (int argc, char **argv)
255 {
256   setlocale (LC_ALL, "");
257   setlocale(LC_NUMERIC, "C");
258 
259   g_test_init (&argc, &argv, NULL);
260 
261   g_test_add ("/modifier/coord/dist/verify_poly3", lfFixture, NULL,
262               mod_setup, test_verify_dist_poly3, mod_teardown);
263 
264   g_test_add ("/modifier/coord/dist/verify_ptlens", lfFixture, NULL,
265               mod_setup, test_verify_dist_ptlens, mod_teardown);
266 
267   g_test_add ("/modifier/coord/dist/verify_poly5", lfFixture, NULL,
268               mod_setup, test_verify_dist_poly5, mod_teardown);
269 
270   g_test_add ("/modifier/coord/geom/verify_equisolid_linrect", lfFixture, NULL,
271               mod_setup, test_verify_geom_fisheye_rectlinear, mod_teardown);
272 
273   g_test_add ("/modifier/color/vignetting/verify_pa", lfFixture, NULL,
274               mod_setup, test_verify_vignetting_pa, mod_teardown);
275 
276   g_test_add ("/modifier/subpix/TCA/verify_linear", lfFixture, NULL,
277               mod_setup, test_verify_subpix_linear, mod_teardown);
278 
279   g_test_add ("/modifier/subpix/TCA/verify_poly3", lfFixture, NULL,
280               mod_setup, test_verify_subpix_poly3, mod_teardown);
281 
282   return g_test_run();
283 }
284