/*
Internal library functions and definitions
Copyright (C) 2007 by Andrew Zabolotny
*/
#ifndef __LENSFUNPRV_H__
#define __LENSFUNPRV_H__
#include <glib.h>
#include <string.h>
#define MEMBER_OFFSET(s,f) ((unsigned int)(char *)&((s *)0)->f)
#define ARRAY_LEN(a) (sizeof (a) / sizeof (a [0]))
#define cbool int
// This epsilon is in image coordinate space, where 1.0 is
// half of the smallest image dimension (width or height)
// adjusted for the lens calibration data/camera crop factors.
#define NEWTON_EPS 0.00001
class lfFuzzyStrCmp;
/**
* @brief Return the absolute value of a number.
* @param x
* A number
* @return
* The absolute value of x
*/
template<typename T> static inline T absolute (T x)
{
return (x < 0) ? -x : x;
}
/**
* @brief Return the square of the argument.
* @param x
* A floating-point number.
*/
template<typename T> static inline T square (T x)
{
return x * x;
}
/**
* @brief Clamp a double value between 0 and max, then convert to given type.
* @param x
* The number to clamp.
* @param min
* The minimal value.
* @param max
* The maximal value. If equal to 0, no clamping by upper boundary is done.
* @return
* The clamped value.
*/
template<typename T> static inline T clampd (double x, double min, double max)
{
if (x < min)
return static_cast<T> (min);
else if (max != 0.0 && x > max)
return static_cast<T> (max);
return static_cast<T> (x);
}
/**
* @brief Free a list of pointers.
* @param list
* A NULL-terminated list of pointers
*/
extern void _lf_list_free (void **list);
/**
* @brief Make a copy of given value into given variable using g_strdup,
* freeing the old value if defined.
* @param var
* The variable to copy value into
* @param val
* The value to assign to the variable
*/
extern void _lf_setstr (gchar **var, const gchar *val);
/**
* @brief Add a string to the end of a string list.
* @param var
* A pointer to an array of strings.
* @param val
* The value to be added to the array.
*/
extern void _lf_addstr (gchar ***var, const gchar *val);
/**
* @brief Insert a item into a GPtrArray, keeping the array sorted.
*
* This method assumes that the array is already sorted, so
* function uses a binary search algorithm.
* Returns the index at which the item as inserted.
* @param array
* The array of pointers to similar items.
* @param item
* The item to insert into the array.
* @param compare
* The function to compare two items.
* @return
* The index at which the item was inserted.
*/
extern int _lf_ptr_array_insert_sorted (
GPtrArray *array, void *item, GCompareFunc compare);
/**
* @brief Insert a item into a GPtrArray, keeping the array sorted. If array
* contains a item equal to the inserted one, the new item overrides the old.
* @param array
* The array of pointers to similar items.
* @param item
* The item to insert into the array.
* @param compare
* The function to compare two items.
* @param dest
* The function to destroy old duplicate item (if found).
* @return
* The index at which the item was inserted.
*/
extern int _lf_ptr_array_insert_unique (
GPtrArray *array, void *item, GCompareFunc compare, GDestroyNotify dest);
/**
* @brief Find a item in a sorted array.
*
* The function uses a binary search algorithm.
* @param array
* The array of pointers to similar items.
* @param item
* The item to search for.
* @return
* The index where the item was found or -1 if not found.
*/
extern int _lf_ptr_array_find_sorted (
const GPtrArray *array, void *item, GCompareFunc compare);
/**
* @brief Add a object to a list of objects.
*
* Accepts an optional pointer to
* a function that compares two values from the list, if function
* returns true the existing object is replaced with the new one.
* @param var
* A pointer to an array of objects.
* @param val
* The value to be added to the array.
* @param val_size
* The size of the value in bytes.
* @param cmpf
* An auxiliary function which, if not NULL, should return
* true if two objects are similar or false if not.
*/
extern void _lf_addobj (void ***var, const void *val, size_t val_size,
bool (*cmpf) (const void *, const void *));
/**
* @brief Remove an object from a list of objects, freeing memory which was
* allocated by _lf_addobj().
* @param var
* A pointer to an array of objects.
* @param idx
* The index of the object to remove (zero-based).
* @return
* false if idx is out of range.
*/
extern bool _lf_delobj (void ***var, int idx);
/**
* @brief Appends a formatted string to a dynamically-growing string
* using g_markup_printf_escaped() internally.
* @param output
* The output array.
* @param format
* The format string.
*/
extern void _lf_xml_printf (GString *output, const char *format, ...);
/**
* @brief Output a multi-language value to output string.
*
* Outputs a number of lines which looks like:
*
* \Verbatim
* ${prefix}<${element}>${val}</${element}>
* ${prefix}<${element} lang="xxx">${val[xxx]}</${element}>
* ...
* \EndVerbatim
* @param output
* The output array.
* @param prefix
* The prefix at the start of every line of output.
* @param element
* The name of the element to output.
* @param val
* The value of the multi-language string.
*/
extern void _lf_xml_printf_mlstr (GString *output, const char *prefix,
const char *element, const lfMLstr val);
/**
* @brief Get the XML id of the given distortion model
* @param model
* The model.
*/
extern const char *_lf_get_distortion_model_id (lfDistortionModel model);
/**
* @brief Something like a very advanced strcmp().
*
* It doesn't segfault if one or both strings are NULL:
* NULL is considered to be less than any string.
* Actually this function does a fuzzy comparison of the strings,
* ignoring spaces at both ends of the string, compressing multiple
* spaces into one and ignoring character case.
*/
extern int _lf_strcmp (const char *s1, const char *s2);
/**
* @brief Same as _lf_strcmp(), but compares a string with a multi-language
* string.
*
* If it equals any of the translations, 0 is returned, otherwise
* the result of strcmp() with the first (default) string is returned.
*/
extern int _lf_mlstrcmp (const char *s1, const lfMLstr s2);
/**
* @brief Comparison function for mount sorting and finding.
*
* Since this function is used when reading the database, it effectively
* enforces the primary key for mounts, which is their Name.
* @param a
* A pointer to first lfMount object.
* @param b
* A pointer to second lfMount object.
* @return
* Positive if a > b, negative if a < b, zero if they are equal.
*/
extern gint _lf_mount_compare (gconstpointer a, gconstpointer b);
/**
* @brief Comparison function for camera sorting and finding.
*
* Since this function is used when reading the database, it effectively
* enforces the primary key for cameras, which is the combination of the
* attributes Maker, Model, and Variant.
* @param a
* A pointer to first lfCamera object.
* @param b
* A pointer to second lfCamera object.
* @return
* Positive if a > b, negative if a < b, zero if they are equal.
*/
extern gint _lf_camera_compare (gconstpointer a, gconstpointer b);
/**
* @brief Comparison helper function for lens sorting and finding.
*
* This function compares the numerical parameters of the lenses: MinFocal,
* MaxFocal, and MinAperture, in this order. Since it is not meant to be used
* as a sorting key function directly, it doesn't take generic pointers as
* parameters. Instead, it is supposed to be used by such sorting key
* functions like _lf_lens_compare.
* @param i1
* A pointer to first lfLens object.
* @param i2
* A pointer to second lfLens object.
* @return
* Positive if i1 > i2, negative if i1 < i2, zero if they are equal.
*/
extern gint _lf_lens_parameters_compare (const lfLens *i1, const lfLens *i2);
/**
* @brief Comparison helper function for lens sorting and finding.
*
* This function compares the names of the lenses: Maker and Model, in this
* order. Since it is not meant to be used as a sorting key function directly,
* it doesn't take generic pointers as parameters. Instead, it is supposed to
* be used by such sorting key functions like _lf_lens_compare.
* @param i1
* A pointer to first lfLens object.
* @param i2
* A pointer to second lfLens object.
* @return
* Positive if i1 > i2, negative if i1 < i2, zero if they are equal.
*/
extern gint _lf_lens_name_compare (const lfLens *i1, const lfLens *i2);
/**
* @brief Comparison function for lens sorting and finding.
*
* Since this function is used when reading the database, it effectively
* enforces the primary key for lenses, which is the combination of the
* attributes Maker, Model, and CropFactor.
* @param a
* A pointer to first lfLens object.
* @param b
* A pointer to second lfLens object.
* @return
* Positive if a > b, negative if a < b, zero if they are equal.
*/
extern gint _lf_lens_compare (gconstpointer a, gconstpointer b);
/**
* @brief Get an interpolated value.
*
* Currently this uses a kind of Catmull-Rom splines with linear
* interpolation at the ends, allowing for non-evenly spaced values
* and handling the extreme cases correctly (the one at the start
* of spline and at the end of spline). The region of interest is
* from y2 to y3, selected by values of t from 0.0 to 1.0.
* @param y1
* The Y coordinate of the first spline point.
* If equal to FLT_MAX, the first point is considered non-existent.
* @param y2
* The Y coordinate of the second spline point.
* @param y3
* The Y coordinate of the third spline point.
* @param y4
* The Y coordinate of the fourth spline point.
* If equal to FLT_MAX, the fourth point is considered non-existent.
* @param t
* Value from 0.0 to 1.0 selects a point on spline on the interval
* between points 2 and 3.
*/
extern float _lf_interpolate (float y1, float y2, float y3, float y4, float t);
/**
* @brief Scans for the timestamp of a Lensfun database.
*
* "database" means here a directory containing XML files. If it also contains
* a file timestamp.txt, its content is interpreted as a string-encoded
* floating point value, representing the timestamp in seconds since the Epoch
* (UNIX time). If it is not present, 0 is returned. If the directory is not
* found or empty, a negative value is returned.
* @param dirname
* the name of the directory containing a Lensfun database; the "version_x"
* suffix is implicitly appended
* @return
* the number of seconds since the Epoch when this database was last
* updated.
*/
extern long int _lf_read_database_timestamp(const gchar *dirname);
/**
* @brief Compare a lens with a pattern and return a matching score.
*
* The comparison is quasi-intelligent: the order of words in a name
* does not matter; the more words from match are present in the pattern,
* the higher is score. Numeric parameters have to coincide or not be specified
* at all, otherwise the score drops to zero (well, a 1% tolerance is allowed
* for rounding errors etc).
* @param pattern
* A pattern to compare against. Unsure fields should be set to NULL.
* It is generally a good idea to call GuessParameters() first since
* that may give additional info for quicker comparison.
* @param match
* The object to match against.
* @param fuzzycmp
* A fuzzy comparator initialized with pattern->Model
* @param compat_mounts
* An additional list of compatible mounts, can be NULL.
* This does not include the mounts from pattern->Mounts.
* @return
* A numeric score in the range 0 to 100, where 100 means that
* every field matches and 0 means that at least one field is
* fundamentally different.
*/
extern int _lf_lens_compare_score (const lfLens *pattern, const lfLens *match,
lfFuzzyStrCmp *fuzzycmp, const char **compat_mounts);
enum
{
LF_CPU_FLAG_MMX = 0x00000001,
LF_CPU_FLAG_SSE = 0x00000002,
LF_CPU_FLAG_CMOV = 0x00000004,
LF_CPU_FLAG_3DNOW = 0x00000008,
LF_CPU_FLAG_3DNOW_EXT = 0x00000010,
LF_CPU_FLAG_AMD_ISSE = 0x00000020,
LF_CPU_FLAG_SSE2 = 0x00000040,
LF_CPU_FLAG_SSE3 = 0x00000080,
LF_CPU_FLAG_SSSE3 = 0x00000100,
LF_CPU_FLAG_SSE4_1 = 0x00000200,
LF_CPU_FLAG_SSE4_2 = 0x00000400
};
/**
* @brief Detect supported CPU features (used for runtime selection of accelerated
* functions for specific architecture extensions).
*/
extern guint _lf_detect_cpu_features ();
/**
* @brief Google-in-your-pocket: a fuzzy string comparator.
*
* This has been designed for comparing lens and camera model names.
* At construction the pattern is split into words and then the component
* words from target are matched against them.
*/
class lfFuzzyStrCmp
{
GPtrArray *pattern_words;
GPtrArray *match_words;
bool match_all_words;
void Split (const char *str, GPtrArray *dest);
void Free (GPtrArray *dest);
public:
/**
* @param pattern
* The pattern which will be compared against a number of strings.
* This is typically what was found in the EXIF data.
* @param allwords
* If true, all words of the pattern must be present in the
* target string. If not, a looser result will be accepted,
* although this will be reflected in the match score.
*/
lfFuzzyStrCmp (const char *pattern, bool allwords);
~lfFuzzyStrCmp ();
/**
* @brief Fuzzy compare the pattern with a string.
* @param match
* The string to match against. This is typically taken from the
* Lensfun database.
* @return
* Returns a score in range 0-100. If the match succedes, this score
* is the number of matched words divided by the mean word count of
* pattern and string, given as a percentage. If it fails, it is 0.
* It fails if no words could be matched, of if allwords was set to
* true and one word in pattern could not be found in match.
*/
int Compare (const char *match);
/**
* @brief Compares the pattern with a multi-language string.
*
* This function returns the largest score as compared against
* every of the translated strings.
* @param match
* The multi-language string to match against. This is typically taken
* from the Lensfun database.
* @return
* Returns the maximal score in range 0-100. For every component of
* the multi-language string, a score is computed: If the match
* succedes, the score is the number of matched words divided by the
* mean word count of pattern and string, given as a percentage. If it
* fails, it is 0. It fails if no words could be matched, of if
* allwords was set to true and one word in pattern could not be found
* in match.
*/
int Compare (const lfMLstr match);
};
/// Subpixel distortion callback
struct lfSubpixelCallbackData : public lfCallbackData
{
lfSubpixelCoordFunc callback;
};
/// A single pixel coordinate modifier callback.
struct lfCoordCallbackData : public lfCallbackData
{
lfModifyCoordFunc callback;
};
/// A single pixel color modifier callback.
struct lfColorCallbackData : public lfCallbackData
{
lfModifyColorFunc callback;
};
#endif /* __LENSFUNPRV_H__ */