Hello again!

I hope this is the right list to discuss such questions here; if not I
beg pardon in advance and would kindly ask to redirect me to a more
appropriate place for technical discussions.

I finished a draft of the interface (just the interface... the
implementation is in a quite early development) for a lens database
library. I have attached it to this message. I would gladly
listen to any comments on it, since on this list there are people good
both at theory and practice.

At a second thought I decided that a universal library should provide
support for multiple lens models... otherwise it won't be universal :-)
So I decided to include all lens models that (IMHO of course) can have
practical application.

I've included the 3rd and 5th order polynomial models as well as the
1st order Field-of-view model (used in Picture Window Pro), the PTLens
model for rectilinear and fish-eye lenses. I hope this complexity could
be hidden somehow in user interface to not make users mad :-)

By the way, here's what the author of Imatest says about the PTLens
model:

------8<------8<------8<------
This equation drives me nuts! rsrc and rdest are reversed from
the equations on this page; it only goes up to fourth power (when you
include rdest outside the parentheses; third power if you don't); and
it has even order terms (a and c) when the theory implies that
distortion can be modeled with odd terms only. Give me a higher order
term (h * rdest4 ) and dump a * rdest3 and c * rdest. But nonetheless
it works pretty well.
------>8------>8------>8------

:-)

For lateral chromatic aberrations I decided to include for now only the
linear model (e.g. rd = ru * k) since I experimented a little with the
GIMP Fix-CA plug-in (http://kcd.sourceforge.net/fix-ca.php) and found
it to work pretty well for all images I had at hand (including some
images taken with a fisheye with severe TCA) despite the simplistic
(linear) model used. Also several papers I found on Internet state that
a linear model for TCAs is enough. So for now I'm not sure there are
reasons for a more sophisticated TCA model, but if somebody knows
some, don't hesitate to tell me :)

-- 
Andrew
/*
 * LensFun - a library for maintaining a database of photographical lenses,
 * and providing the means to correct some of the typical lens distortions.
 *
 * /LGPL here/
 */

#ifndef __LENSFUN_H__
#define __LENSFUN_H__

/* Private lens database fields */
typedef struct _lfDatabasePrivate lfDatabasePrivate;

/**
 * A lens database object.
 */
typedef struct
{
    /* Private fields */
    lfDatabasePrivate *Private;
} lfDatabase;

/* Private camera-related fields */
typedef struct _lfCameraPrivate lfCameraPrivate;

/**
 * Camera data.
 * Unknown fields are set to NULL.
 */
typedef struct
{
    /** Camera maker (ex: "Rollei") */
    const char *Maker;
    /** Model name ("Rolleiflex SL35") */
    const char *Name;
    /** Camera mount type (ex: "QBM") */
    const char *Mount;
    /** Camera crop factor (ex: 1.0). Must be defined. */
    float CropFactor;
    /* Additional private data */
    lfCameraPrivate *Private;
} lfCamera;

/**
 * The lensdb library implements several lens distortion models.
 * This enum lists them. Distortion usually heavily depends on the
 * focal distance, but do not depend on the aperture.
 *
 * For a popular explanation of lens distortion see
 * http://www.vanwalree.com/optics/distortion.html
 */
typedef enum
{
    /** Distortion parameters are unknown */
    LDB_DIST_MODEL_NONE,
    /**
     * 3rd order polynomial model:
     * ru = rd * (1 + k1 * r^2)
     * Ref: http://www.imatest.com/docs/distortion.html
     */
    LDB_DIST_MODEL_POLY3,
    /**
     * 5th order polynomial model:
     * ru = rd * (1 + k1 * r^2 + k2 * r^4)
     */
    LDB_DIST_MODEL_POLY5,
    /**
     *
     * ru = tg (rd * w) / (2 * tg (w/2))
     * Ref: ftp://ftp-sop.inria.fr/chir/publis/devernay-faugeras:01.pdf
     */
    LDB_DIST_MODEL_FOV1,
    /**
     * PTLens rectilinear:
     * ru = rd * (a * rd^3 + b * rd^2 + c * rd + 1)
     */
    LDB_DIST_MODEL_PTLENS_RECT,
    /**
     * PTLens fisheye model.
     * ru = rd * (a * rd^3 + b * rd^2 + c * rd + 1)
     * Ref: http://wiki.panotools.org/Lens_correction_model
     */
    LDB_DIST_MODEL_PTLENS_FISHEYE
} lfDistortionModel;

/**
 * The lensdb library supports several models for lens lateral
 * chromatic aberrations (also called transversal chromatic
 * aberrations, TCA). TCAs depend on focal distance, but do not
 * depend of the aperture.
 *
 * For a popular explanation of chromatic aberrations see
 * http://www.vanwalree.com/optics/chromatic.html
 */
typedef enum
{
    /** No TCA correction data is known */
    LDB_TCA_MODEL_NONE,
    /**
     * Linear lateral chromatic abberations model:
     * rd = ru * k
     * Ref: http://cipa.icomos.org/fileadmin/papers/Torino2005/403.pdf?PHPSESSID=8f5fa7da0b8aef1558792c10425086e2
     */
    LDB_TCA_MODEL_LINEAR
} lfTCAModel;

/**
 * The lensdb library supports several models for lens vignetting
 * correction. We focus on optical and natural vignetting since they
 * can be generalized for all lenses of a certain type; mechanical
 * vignetting is out of the scope of this library.
 *
 * Vignetting is dependent on both focal distance and aperture.
 *
 * For a popular explanation of vignetting see
 * http://www.vanwalree.com/optics/vignetting.html
 */
typedef enum
{
    /** No vignetting correction data is known */
    LDB_VIGNETTING_MODEL_NONE,
    /**
     * Pablo D'Angelo vignetting model
     * (which is a more general variant of the cos^4 law):
     * c = 1 + k1 * r^2 + k2 * r^4 + k3 * r^6
     * Ref: http://hugin.sourceforge.net/tech/
     */
    LDB_VIGNETTING_PA
} lfVignettingModel;

/**
 * Lens calibration data. This data describes optical lens
 * properties at certain fixed conditions: at some focal length
 * and/or aperture. The library will interpolate the actual
 * requested values if the exact focal/aperture match is not
 * available.
 */
typedef struct
{
    /** Focal distance at which this calibration data was taken (0 - unspecified) */
    float Focal;
    /** Aperture at which this calibration data was taken (0 - unspecified) */
    float Aperture;
    /** The type of distortion model used */
    lfDistortionModel DistModel;
    /** Distortion coefficients, dependent on model */
    float DistCoeff [3];
    /** The lateral chromatic aberration model used */
    lfTCAModel TCAModel;
    /** The coefficients for TCA, dependent on model */
    float TCACoeff [1];
    /** The lens vignetting model used */
    lfVignettingModel VignettingModel;
    /** Lens vignetting model coefficients (depending on model) */
    float VignettingCoeff [3];
} lfLensCalibration;

/* Private lens-related fields  */
typedef struct _lfLensPrivate lfLensPrivate;

/**
 * Lens data.
 * Unknown fields are set to NULL or 0.
 */
typedef struct _lfLens
{
    /** Lens maker (ex: "Rollei") */
    const char *Maker;
    /** Lens model (ex: "Zoom-Rolleinar") */
    const char *Model;
    /**
     * A pointer to other lens, which this is a clone of. This is useful
     * for lenses that were released under several names. If this field is
     * non-NULL, all following fields are unused.
     */
    struct _lfLens *Clone;
    /** Minimum focal distance, mm (ex: 35). Must be defined. */
    float MinFocal;
    /** Maximum focal distance, mm (ex: 105). If 0, same as MinFocal. */
    float MaxFocal;
    /** Aperture at minimum focal distance (ex: 3.5). Must be defined. */
    float MinAperture;
    /** Aperture at maximum focal distance (ex: 4.3). If 0, same as MinAperture. */
    float MaxAperture;
    /** Available mounts (NULL-terminated list) (ex: { "QBM", NULL }) */
    const char **Mounts;
    /** The horizontal shift of all lens distortions in range -1..+1 */
    float CenterDX;
    /** The vertical shift of all lens distortions; (0,0) for geometric center */
    float CenterDY;
    /** Lens calibration data, NULL-terminated (unsorted) */
    lfLensCalibration **Calibration;
    /* Additional private data */
    lfLensPrivate *Private;
} lfLens;

/** A opaque data structure used while correcting images */
typedef struct _lfImageCorrector lfImageCorrector;

/** liblensdb error codes: negative codes are -errno, positive are here */
typedef enum
{
    /** No error occured */
    LDB_NO_ERROR = 0,
    /** Wrong XML data format */
    LDB_WRONG_FORMAT
} lfError;

/** A list of bitmask flags used for ordering various image corrections */
enum
{
    /** Apply all possible corrections */
    LF_CORRECT_ALL  = 0xffffffff,
    /** Correct lens distortion */
    LF_CORRECT_DIST = 0x00000001,
    /** Correct lens transversal chromatic aberrations */
    LF_CORRECT_TCA  = 0x00000002,
    /** Correct lens vignetting */
    LF_CORRECT_VIGN = 0x00000004
};

/**
 * The basics of memory allocation: never free objects allocated by the
 * library yourselves, instead use this function. It is a direct
 * equivalent of standard C free(), however you should not use free()
 * in the event that the library uses a separate heap.
 * @param data
 *     A pointer to memory to be freed.
 */
void lf_free (void *data);

/**
 * Create a new empty database object.
 */
lfDatabase *lf_db_new (void);

/**
 * Create a new database object and load the whole lens database.
 * Usually the application will want to do this at startup.
 * This calls lf_load_file() for all XML files found in usual places
 * (first /usr/share/lensdb/ then ~/.lensdb/).
 */
lfDatabase *lf_db_load (void);

/**
 * Destroy the database object.
 * @param db
 *     The database to destroy.
 */
void lf_db_destroy (lfDatabase *db);

/**
 * Load just a specific XML file. If the loaded file contains the
 * specification of a camera/lens that's already in memory, it
 * overrides that data.
 * @param db
 *     The database to add the camera/lens data to.
 * @param filename
 *     The name of a XML file to load. Note that lensdb does not support
 *     the full XML specification as it uses the glib's simple XML parser,
 *     so advanced XML features are not available.
 * @return
 *     LDB_NO_ERROR or a error code.
 */
lfError lf_db_load_file (lfDatabase *db, const char *filename);

/**
 * Load a set of camera/lenses from a memory array.
 * This is the lowest-level loading function.
 * @param db
 *     The database to add the camera/lens data to.
 * @param data
 *     The XML data.
 * @return
 *     LDB_NO_ERROR or a error code.
 */
lfError lf_load (lfDatabase *db, const char *data);

/**
 * Save a set of camera and lens descriptions to a file.
 * @param filename
 *     The file name to write the lenses to.
 * @param cameras
 *     A list of cameras to be written to the file. Can be NULL.
 * @param lenses
 *     A list of lenses to be written to the file. Can be NULL.
 * @return
 *     LDB_NO_ERROR or a error code.
 */
lfError lf_save_file (const char *filename, const lfCamera **cameras,
                      const lfLens **lenses);

/**
 * Save a set of camera and lens descriptions into a memory array.
 * @param cameras
 *     A list of cameras to be written to the file. Can be NULL.
 * @param lenses
 *     A list of lenses to be written to the file. Can be NULL.
 * @param output
 *     This variable is set to point to a newly-allocated memory area.
 *     Like usually, it must be freed with lf_free().
 * @return
 *     LDB_NO_ERROR or a error code.
 */
lfError lf_save (const lfCamera **cameras, const lfLens **lenses,
                 char **output);

/**
 * Parse a human-level lens description (ex: "smc PENTAX-F 35-105mm F4-5.6
 * or SIGMA AF 28-300 F3.5-5.6 DL IF") and return a set of lfLens'es which
 * are matching this description. Multiple lenses may be listed using the
 * "or" glueword, also multiple lenses may be returned if only a part of
 * the lens specification is provided (e.g. "Pentax SMC").
 *
 * The matching algorithm works as follows: both user's description and the
 * actual lens description are split into words. Words containing numbers
 * are tried to be interpreted as either focal distance ranges or aperture
 * ranges. After that word matching is done; a lens matches the description
 * ONLY IF it contains all the words found in the description (including
 * buzzwords e.g. IF AL LD DI USM SDM etc). Order of the words does not
 * matter. An additional check is done on the focal/aperture ranges, they
 * must exactly match if they are specified.
 * @param db
 *     The database where to search for lenses.
 * @param camera
 *     The camera (can be NULL if camera is unknown, or just certain
 *     fields in structure can be NULL).
 * @param lens
 *     A human description of the lens(-es).
 * @return
 *     A list of lenses parsed from user description or NULL.
 *     Release memory with lf_free(). The list is ordered in the
 *     most-likely to least-likely order, e.g. the first returned
 *     value is the most likely match.
 */
const lfLens **lf_find_lenses_hd (lfDatabase *db, const lfCamera *camera,
                                  const char *lens);

/**
 * Find a set of lenses that fit certain criteria.
 *
 * If both camera and lens are NULLs, the whole database is returned.
 * @param db
 *     The database where to search for lenses.
 * @param camera
 *     The camera (can be NULL if camera is unknown, or just certain
 *     fields in structure can be NULL).
 * @param lens
 *     The candidate lense. Uncertain fields may be NULL. If this
 *     parameter is NULL, all lenses fitting the specified camera
 *     are returned.
 * @return
 *     A list of lenses matching the search criteria or NULL if none.
 *     Release memory with lf_free(). The list is ordered in the
 *     most-likely to least-likely order, e.g. the first returned
 *     value is the most likely match.
 */
const lfLens **lf_find_lenses (lfDatabase *db, const lfCamera *camera,
                               lfLens *lens);

/**
 * Initialize the process of correcting abberations in a image.
 * You must provide the original image width/height even if you
 * plan to correct just a part of the image.
 *
 * The corrector object will be set up to rectify all aberrations
 * found in the lens description. Make sure the focal length and aperture
 * value are correct, otherwise the corrector may pick up wrong model
 * parameters!
 * @param lens
 *     The lens which abberations you want to correct in a image.
 * @param width
 *     The width of the image you want to correct.
 * @param height
 *     The height of the image you want to correct.
 * @param focal
 *     The focal length at which the image was taken.
 * @param aperture
 *     The aperture at which the image was taken.
 * @param flags
 *     A set of flags (se LF_CORRECT_XXX) telling which distortions you want
 *     corrected. A value of LF_CORRECT_ALL orders correction of everything
 *     possible.
 * @return
 *     A new image corrector object.
 */
lfImageCorrector *lf_corrector_new (const lfLens *lens, int width, int height,
                                    float focal, float aperture, int flags);

/**
 * Destroy the corrector object.
 * @param corrector
 *     The corrector object to destroy.
 */
void lf_corrector_destroy (lfImageCorrector *corrector);

/**
 * Apply the reverse distortion transforms on a pixel coordinate.
 * Returns the corrected coordinates separately for R/G/B channels.
 * @param xu
 *     The pixel X coordinate in undistorted image.
 * @param yu
 *     The pixel Y coordinate in undistorted image.
 * @param xd
 *     A pointer to an array of 3 floats receiving the X coordinate of the
 *     distorted pixel for the R, G and B channels.
 * @param yd
 *     A pointer to an array of 3 floats receiving the Y coordinate of the
 *     distorted pixel for the R, G and B channels.
 */
void lf_corrector_apply (float xu, float yu, float *xd, float *yd);

#endif /* __LENSFUN_H__ */

Attachment: signature.asc
Description: PGP signature

_______________________________________________
CREATE mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/create

Reply via email to