1 /* queryfeature.c
2 Feature querying functionality
3 See queryfeature.h
4 */
5 #include <assert.h>
6 #include <stdio.h>
7 #include <string.h>
8
9 #include "version.h"
10 #include "queryfeature.h"
11 #include "filter.h"
12
13 typedef struct {char* name; int value;} TIntFeature;
14 typedef struct {char* name; double value;} TDoubleFeature;
15 typedef struct {char* name; char* value;} TStringFeature;
16
17 // Fulvio Senore June.2004 changed the check to work with microsoft compiler
18 #ifdef _MSC_VER
19 //#ifdef MSVS
20 #define snprintf _snprintf
21 #endif
22
23 /***************** Feature tables: *************************/
24 TIntFeature intFeatures[] ={
25 {"CPErrorIsDistSphere",1}, // optimizer reports angular control point errors
26 {"NumLensTypes",5}, // source lens types 0..4
27 {"NumPanoTypes",8}, // pano lens types 0..7
28 {"CanCropOutside",1},
29 {"CanHaveNegativeCP",1},
30 {"AntiAliasingFilter",1},
31 {"NumFilter",24},
32 {"SetProgressFcn",1} // setProgressFcn and setInfoDlgFcn are available
33 };
34
35 TDoubleFeature doubleFeatures[] ={
36 {"MaxFFOV",MAX_FISHEYE_FOV}
37 };
38
39 TStringFeature stringFeatures[]={
40 // Version info:
41 {PTVERSION_NAME_FILEVERSION,PTVERSION_FILEVERSION}, // "FileVersion"
42 {PTVERSION_NAME_LONG,LONGVERSION}, // "LongVersion"
43 {PTVERSION_NAME_LEGALCOPYRIGHT,PTVERSION_LEGALCOPYRIGHT}, // "LegalCopyright"
44 {PTVERSION_NAME_COMMENT,PTVERSION_COMMENT}, // "Comments"
45 // Source lens type names
46 // If a lens type is unavailable, set its name to ""
47 {"LensType0","Normal (rectilinear)"},
48 {"LensType1","Cylindrical"},
49 {"LensType2","Fisheye Equidistance Circular"},
50 {"LensType3","Fisheye Equidistance Full Frame"},
51 {"LensType4","Equirectangular"},
52 {"LensType5",""},//"_spherical_cp"},
53 {"LensType6",""},//"_spherical_tp"},
54 {"LensType7","Mirror"},
55 {"LensType8","Fisheye Orthographic"},
56 {"LensType9",""},//"_cubic"},
57 {"LensType10","Fisheye Stereographic"}, // fisheye stereographic
58 {"LensType11",""},//"_mercator"},
59 {"LensType12",""},//"_trans_mercator"},
60 {"LensType13",""},//"_trans_panorama"},
61 {"LensType14",""},//"_sinusoidal"},
62 {"LensType15",""},//"_lambert"},
63 {"LensType16",""},//"_lambertazimuthal"},
64 {"LensType17",""},//"_albersequalareaconic"},
65 {"LensType18",""},//"_millercylindrical"},
66 {"LensType19","Fisheye Equisolid"},
67
68 // Source lens type crop format (C)ircle or (R)ectangle:
69 {"LensMask0","R"},
70 {"LensMask1","R"},
71 {"LensMask2","C"},
72 {"LensMask3","R"},
73 {"LensMask4","R"},
74 {"LensMask7","C"},
75 {"LensMask8","C"},
76 {"LensMask10","C"},
77 {"LensMask19","C"},
78 // Pano lens type names
79 // If a lens type is unavailable, set its name to ""
80 {"PanoType0","Normal (rectilinear)"},
81 {"PanoType1","Cylindrical"},
82 {"PanoType2","Equirectangular"},
83 {"PanoType3","Full Frame"},
84 {"PanoType4","Stereographic"},
85 {"PanoType5","Mercator"},
86 {"PanoType6","Transverse mercator"},
87 {"PanoType7","Sinusoidal"},
88 {"PanoType8","Lambert Cylindrical Equal Area"},
89 {"PanoType9","Lambert Azimuthal Equal Area"},
90 {"PanoType10","Albers Conical Equal Area"},
91 {"PanoType11","Miller Cylindrical"},
92 {"PanoType12","Panini"},
93 {"PanoType13","Architectural"},
94 {"PanoType14","Orthographic"},
95 {"PanoType15","Equisolid"},
96 {"PanoType16","Equirectangular Panini"},
97 {"PanoType17","Biplane"},
98 {"PanoType18","Triplane"},
99 {"PanoType19","Panini General"},
100 {"PanoType20", "Thoby Projection"},
101 {"PanoType21", "Hammer-Aitoff Equal Area"},
102
103 // Filter Types
104
105 // fix: Fixed Windowsize
106 // aa: Antialiasing filter with adaptive filter size
107 // Filter Names
108 {"FilterType0","fix"},
109 {"FilterName0","Poly3"},
110 {"FilterType1","fix"},
111 {"FilterName1","Spline16"},
112 {"FilterType2","fix"},
113 {"FilterName2","Spline36"},
114 {"FilterType2","fix"},
115 {"FilterName3","Sinc256"},
116 {"FilterType4","fix"},
117 {"FilterName4","Spline64"},
118 {"FilterType5","fix"},
119 {"FilterName5","Bilinear"},
120 {"FilterType6","fix"},
121 {"FilterName6","Nearest neighbor"},
122 {"FilterType7","fix"},
123 {"FilterName7","Sinc1024"},
124 {"FilterType8","aa"},
125 {"FilterName8","Box"},
126 {"FilterType9","aa"},
127 {"FilterName9","Bartlett/Triangle"},
128 {"FilterType10","aa"},
129 {"FilterName10","Hermite"},
130 {"FilterType11","aa"},
131 {"FilterName11","Hanning"},
132 {"FilterType12","aa"},
133 {"FilterName12","Hamming"},
134 {"FilterType13","aa"},
135 {"FilterName13","Blackmann"},
136 {"FilterType14","aa"},
137 {"FilterName14","Gaussian 1/sqrt(2)"},
138 {"FilterType15","aa"},
139 {"FilterName15","Gaussian 1/2"},
140 {"FilterType16","aa"},
141 {"FilterName16","Quadardic"},
142 {"FilterType17","aa"},
143 {"FilterName17","Cubic"},
144 {"FilterType18","aa"},
145 {"FilterName18","Catmull-Rom"},
146 {"FilterType19","aa"},
147 {"FilterName19","Mitchell"},
148 {"FilterType20","aa"},
149 {"FilterName20","Lanczos2"},
150 {"FilterType21","aa"},
151 {"FilterName21","Lanczos3"},
152 {"FilterType22","aa"},
153 {"FilterName22","Blackman/Bessel"},
154 {"FilterType23","aa"},
155 {"FilterName23","Blackman/sinc"},
156 #if 0
157 // WE NO longer support need to list them. It should be enough to list the version
158
159 // Patches that have been applied
160 {"Patch200510a", "Rob Platt, Do not process unchanged color channels for CA correction"},
161 {"BMPrev", "Jim Watters, correctly open BMP files created with rows in reverse order"},
162 {"Tiff32", "Thomas Rauscher, Load and save TIFF 32-bit with IEEE floats, http://www.pano2qtvr.com/dll_patch/"},
163 {"AntiAliasing", "Thomas Rauscher, New antialiasing filter for adjust, http://www.pano2qtvr.com/dll_patch/"},
164 {"HDRFile", "Thomas Rauscher, Load and save Radiance HDR files, http://www.pano2qtvr.com/dll_patch/"},
165 {"Patch200505", "Douglas Wilkins, Correct behaviour when mode = _usedata"},
166 #ifdef HasJava
167 {"Patch200504a", "Douglas Wilkins, Java support enabled"},
168 #else
169 {"Patch200504a", "Douglas Wilkins, Java support disabled"},
170 #endif
171 {"Patch200502a", "Joost Nieuwenhuijse, Crop outside of image, http://www.ptgui.com"},
172 {"Patch200410a", "Jim Watters, JPEG optimization, http://photocreations.ca/panotools"},
173 {"FastTransform01", "Fulvio Senore, Fast transform, http://www.fsoft.it/panorama/pano12.htm"},
174 {"Patch200407a", "Rik Littlefield, Kevin Kratzke, & Jim Watters, Fix multiple bugs - PSD, 16bit"},
175 {"MaskFromFocus_001", "Rik Littlefield, added mask-from-focus, http://www.janrik.net/ptools/"},
176 {"Patch200405a", "Rik Littlefield, Improved optimizer, http://www.janrik.net/ptools/"},
177 {"Patch200403a", "Kevin Kratzke, Radial Shift fix, http://www.kekus.com"},
178 {"Patch200312a", "Jim Watters, Updated PSD format, http://photocreations.ca/panotools"},
179 {"Patch200309a", "Jim Watters, Allowed linking of y, p, & r values, http://photocreations.ca/panotools"},
180 {"Patch200308a", "Jim Watters, Improved Radial Luminance, http://photocreations.ca/panotools"}
181 #endif
182 };
183 /***************** end feature tables **********************/
184
185
queryFeatureInt(const char * name,int * result)186 int queryFeatureInt(const char *name, int *result)
187 {
188 int i;
189 int count = sizeof( intFeatures ) / sizeof( intFeatures[0] );
190 for(i=0; i < count; i++)
191 {
192 if(strcmp(name,intFeatures[i].name)==0)
193 {
194 *result=intFeatures[i].value;
195 return 1;
196 }
197 }
198 return 0;
199 }
200
queryFeatureDouble(const char * name,double * result)201 int queryFeatureDouble(const char *name, double *result)
202 {
203 int i;
204 int count = sizeof( doubleFeatures ) / sizeof( doubleFeatures[0] );
205 for(i=0; i < count; i++)
206 {
207 if(strcmp(name,doubleFeatures[i].name)==0)
208 {
209 *result=doubleFeatures[i].value;
210 return 1;
211 }
212 }
213 return 0;
214 }
215
queryFeatureString(const char * name,char * result,const int bufsize)216 int queryFeatureString(const char *name,char *result, const int bufsize)
217 {
218 int intvalue;
219 double doublevalue;
220 size_t i, length=0, count = (sizeof( stringFeatures ) / sizeof( stringFeatures[0] ));
221 const size_t tmp_len=200;
222
223 // Fulvio Senore, August 2004
224 // allocates a dummy buffer for the calls to snprintf
225 // the original code passed NULL to snprintf() but it caused problems (asserts) when compiling
226 // with the microsoft compiler that links with the debug libraries to avoid crashes
227 char *cpTmp = malloc( tmp_len + 1 );
228 cpTmp[tmp_len] = '\0';
229
230 for(i=0; i < count; i++)
231 {
232 if(strcmp(name,stringFeatures[i].name)==0)
233 {
234 if(result != NULL)
235 {
236 strncpy(result, stringFeatures[i].value, (size_t)bufsize);
237 }
238 length=strlen(stringFeatures[i].value);
239 break;
240 }
241 }
242 if(length <= 0)
243 {
244 // there's no string value with the specified name
245 // Let's check the int values too:
246 for(i=0; i < sizeof( intFeatures ) / sizeof( intFeatures[0] ); i++)
247 {
248 if(queryFeatureInt(name, &intvalue))
249 {
250 // length=snprintf(NULL,0,"%d",intvalue);
251 length=snprintf(cpTmp,tmp_len,"%d",intvalue);
252 if(result != NULL)
253 {
254 snprintf(result,(size_t)bufsize,"%d",intvalue);
255 }
256 break;
257 }
258 }
259 }
260 if(length <= 0)
261 {
262 // Let's check the double values too:
263 for(i=0; i < sizeof( doubleFeatures ) / sizeof( doubleFeatures[0] ); i++)
264 {
265 if(queryFeatureDouble(name, &doublevalue))
266 {
267 // length=snprintf(NULL,0,"%0.f",doublevalue);
268 length=snprintf(cpTmp,tmp_len,"%0.f",doublevalue);
269 if(result != NULL)
270 {
271 snprintf(result,(size_t)bufsize,"%0.f",doublevalue);
272 }
273 break;
274 }
275 }
276 }
277 // make sure that the copied string always is NULL terminated, even if truncated
278 // (except if the buffer holds only zero bytes):
279 if( result && ((int)length >= bufsize) && (bufsize > 0) )
280 {
281 result[bufsize-1]=0;
282 }
283 free( cpTmp );
284 return length;
285 }
286
queryFeatureCount()287 int queryFeatureCount()
288 {
289 return sizeof( intFeatures ) / sizeof( intFeatures[0] )+
290 sizeof( doubleFeatures ) / sizeof( doubleFeatures[0] ) +
291 sizeof( stringFeatures ) / sizeof( stringFeatures[0] );
292 }
293
queryFeatures(int index,char ** name,Tp12FeatureType * type)294 void queryFeatures(int index,char** name,Tp12FeatureType* type)
295 {
296 if(index < (sizeof( intFeatures ) / sizeof( intFeatures[0] )))
297 {
298 if(name) *name=intFeatures[index].name;
299 if(type) *type=p12FeatureInt;
300 }
301 else
302 {
303 index -= sizeof( intFeatures ) / sizeof( intFeatures[0] );
304 if(index < sizeof( doubleFeatures ) / sizeof( doubleFeatures[0] ))
305 {
306 if(name) *name=doubleFeatures[index].name;
307 if(type) *type=p12FeatureDouble;
308 }
309 else
310 {
311 index -= sizeof( doubleFeatures ) / sizeof( doubleFeatures[0] );
312 if(index < sizeof( stringFeatures ) / sizeof( stringFeatures[0] ))
313 {
314 if(name) *name=stringFeatures[index].name;
315 if(type) *type=p12FeatureString;
316 }
317 else
318 {
319 if(type) *type=p12FeatureUnknown;
320 }
321 }
322 }
323 }
324
325 //////////////////////////////////////////////////////////////////////
326
327
328 char *panoFormatNames[] = {
329 "Rectilinear",
330 "Cylindrical",
331 "Equirectangular",
332 "Fisheye",
333 "Stereographic",
334 "Mercator",
335 "Trans Mercator",
336 "Sinusoidal",
337 "Lambert Cylindrical Equal Area",
338 "Lambert Equal Area Azimuthal",
339 "Albers Equal Area Conic",
340 "Miller Cylindrical",
341 "Panini",
342 "Architectural",
343 "Orthographic",
344 "Equisolid",
345 "Equirectangular Panini",
346 "Biplane",
347 "Triplane",
348 "Panini General",
349 "Thoby Projection",
350 "Hammer-Aitoff Equal Area",
351 };
352
353 static int panoFormatID[] = {
354 _rectilinear,
355 _panorama,
356 _equirectangular,
357 _fisheye_ff,
358 _stereographic,
359 _mercator,
360 _trans_mercator,
361 _sinusoidal,
362 _lambert,
363 _lambertazimuthal,
364 _albersequalareaconic,
365 _millercylindrical,
366 _panini,
367 _architectural,
368 _orthographic,
369 _equisolid,
370 _equipanini,
371 _biplane,
372 _triplane,
373 _panini_general,
374 _thoby,
375 _hammer,
376 };
377
378
panoProjectionFormatCount(void)379 int panoProjectionFormatCount(void)
380 {
381 // Return the number of Projection formats available in the library
382 assert(sizeof(panoFormatNames) == PANO_FORMAT_COUNT * sizeof(typeof (panoFormatNames[0])));
383 return PANO_FORMAT_COUNT;
384 }
385
panoProjectionFeaturesQuery(int projection,pano_projection_features * features)386 int panoProjectionFeaturesQuery(int projection, pano_projection_features *features)
387 {
388 // Return static information on the characteristics of each of the projections
389 // in the library. This now includes min, max and defualt parameter values.
390 // All data are zero by default.
391
392 int i;
393
394 assert(features != NULL);
395 assert(sizeof(panoFormatNames) == PANO_FORMAT_COUNT * sizeof(char*));
396
397
398 if (projection < 0 || projection >= PANO_FORMAT_COUNT)
399 return 0;
400
401
402 // Set defaults
403 bzero(features, sizeof (*features));
404
405 features->projection = projection;
406 features->internalFormat = panoFormatID[projection];
407 features->maxHFOV = 360;
408 features->maxVFOV = 180;
409 features->name = panoFormatNames[projection];
410 switch (projection) {
411 case PANO_FORMAT_RECTILINEAR:
412 features->maxVFOV = 179;
413 features->maxHFOV = 179;
414 break;
415 case PANO_FORMAT_PANORAMA:
416 features->maxVFOV = 179;
417 break;
418 case PANO_FORMAT_EQUIRECTANGULAR:
419 case PANO_FORMAT_MILLER_CYLINDRICAL:
420 case PANO_FORMAT_ARCHITECTURAL:
421 break;
422 case PANO_FORMAT_PANINI:
423 features->maxVFOV = 179;
424 features->maxHFOV = 359;
425 break;
426 case PANO_FORMAT_EQUI_PANINI:
427 features->maxVFOV = 179;
428 features->maxHFOV = 359;
429 break;
430 case PANO_FORMAT_PANINI_GENERAL:
431 features->maxVFOV = 160;
432 features->maxHFOV = 320;
433 features->numberOfParameters = 3;
434 features->parm[0].name = "Cmpr";
435 features->parm[1].name = "Tops";
436 features->parm[2].name = "Bots";
437 features->parm[0].minValue = 0;
438 features->parm[0].maxValue = 150;
439 features->parm[0].defValue = 100;
440 features->parm[1].minValue = -100;
441 features->parm[1].maxValue = 100;
442 features->parm[2].minValue = -100;
443 features->parm[2].maxValue = 100;
444
445 break;
446 case PANO_FORMAT_FISHEYE_FF:
447 case PANO_FORMAT_THOBY:
448 features->maxVFOV = 360;
449 features->maxHFOV = 360;
450 break;
451 case PANO_FORMAT_ORTHOGRAPHIC:
452 features->maxVFOV = 180;
453 features->maxHFOV = 180;
454 break;
455 case PANO_FORMAT_EQUISOLID:
456 features->maxVFOV = 360;
457 features->maxHFOV = 360;
458 break;
459 case PANO_FORMAT_STEREOGRAPHIC:
460 features->maxHFOV = 359;
461 features->maxVFOV = 359;
462 break;
463 case PANO_FORMAT_MERCATOR:
464 features->maxVFOV = 179;
465 break;
466 case PANO_FORMAT_TRANS_MERCATOR:
467 features->maxHFOV = 179;
468 features->maxVFOV = 360;
469 break;
470 case PANO_FORMAT_SINUSOIDAL:
471 case PANO_FORMAT_LAMBERT_EQUAL_AREA_CONIC:
472 case PANO_FORMAT_LAMBERT_AZIMUTHAL:
473 case PANO_FORMAT_HAMMER:
474 break;
475 case PANO_FORMAT_ALBERS_EQUAL_AREA_CONIC:
476 features->numberOfParameters = 2;
477 features->parm[0].name = "phi1";
478 features->parm[1].name = "phi2";
479 for (i=0;i<2;i++) {
480 features->parm[i].minValue = -90;
481 features->parm[i].maxValue = +90;
482 }
483 features->parm[0].defValue = 0;
484 features->parm[1].defValue = 60;
485
486 break;
487 case PANO_FORMAT_BIPLANE:
488 features->maxVFOV = 179;
489 features->maxHFOV = 359;
490 features->numberOfParameters = 2;
491 features->parm[0].name = "alpha";
492 features->parm[0].minValue=1;
493 features->parm[0].maxValue=179;
494 features->parm[0].defValue=45;
495 features->parm[1].name = "corners";
496 features->parm[1].minValue = 0;
497 features->parm[1].maxValue = 1;
498 features->parm[1].defValue = 0;
499 break;
500 case PANO_FORMAT_TRIPLANE:
501 features->maxVFOV = 179;
502 features->maxHFOV = 359;
503 features->numberOfParameters = 1;
504 features->parm[0].name = "alpha";
505 features->parm[0].minValue=1;
506 features->parm[0].maxValue=120;
507 features->parm[0].defValue=60;
508 break;
509 default:
510 assert(0); // A projection is missing!
511 return 0;
512 }
513 return 1;
514 }
515
queryFOVLimits(int projection,double * params,double * lims)516 int queryFOVLimits( int projection, /* projection index */
517 double * params, /* length depends on projection */
518 double * lims /* [0] = maxhfov, [1] = maxvfov */
519 )
520 {
521 pano_projection_features pf;
522 int ok = panoProjectionFeaturesQuery(projection, &pf);
523 lims[0] = lims[1] = 0;
524 if( !ok ) return 0;
525 // default fixed values
526 lims[0] = pf.maxHFOV;
527 lims[1] = pf.maxVFOV;
528 // compute dynamic values
529 switch (projection) {
530 default:
531 break;
532 case PANO_FORMAT_PANINI_GENERAL:
533 maxFOVs_panini_general (params, lims );
534 break;
535 case PANO_FORMAT_BIPLANE:
536 lims[0] = params[0] + 179;
537 break;
538 case PANO_FORMAT_TRIPLANE:
539 lims[0] = 2 * params[0] + 179;
540 break;
541 case PANO_FORMAT_ALBERS_EQUAL_AREA_CONIC:
542 break;
543 }
544
545 return 1;
546 }
547
548
549
550