|
Packit Service |
2781ba |
/* This file is an image processing operation for GEGL
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* GEGL is free software; you can redistribute it and/or
|
|
Packit Service |
2781ba |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit Service |
2781ba |
* License as published by the Free Software Foundation; either
|
|
Packit Service |
2781ba |
* version 3 of the License, or (at your option) any later version.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* GEGL is distributed in the hope that it will be useful,
|
|
Packit Service |
2781ba |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
2781ba |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
2781ba |
* Lesser General Public License for more details.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
2781ba |
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Copyright 2006 Øyvind Kolås <pippin@gimp.org>
|
|
Packit Service |
2781ba |
* Copyright 2008 Bradley Broom <bmbroom@gmail.com>
|
|
Packit Service |
2781ba |
* Copyright 2011 Robert Sasu <sasu.robert@gmail.com>
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "config.h"
|
|
Packit Service |
2781ba |
#include <lensfun.h>
|
|
Packit Service |
2781ba |
#include <glib/gi18n-lib.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#ifdef GEGL_CHANT_PROPERTIES
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_chant_string (maker, _("Maker:"),"none",
|
|
Packit Service |
2781ba |
_("Write lens maker correctly"))
|
|
Packit Service |
2781ba |
gegl_chant_string (Camera, _("Camera:"),"none",
|
|
Packit Service |
2781ba |
_("Write camera name correctly"))
|
|
Packit Service |
2781ba |
gegl_chant_string (Lens, _("Lens:"),"none",
|
|
Packit Service |
2781ba |
_("Write your lens model with majuscules"))
|
|
Packit Service |
2781ba |
gegl_chant_double (focal, _("Focal of the camera"), 0.0, 300.0, 20.0,
|
|
Packit Service |
2781ba |
_("Calculate b value from focal"))
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_chant_boolean (center, _("Center"), TRUE,
|
|
Packit Service |
2781ba |
_("If you want center"))
|
|
Packit Service |
2781ba |
gegl_chant_int (cx, _("Lens center x"), -G_MAXINT, G_MAXINT, 0,
|
|
Packit Service |
2781ba |
_("Coordinates of lens center"))
|
|
Packit Service |
2781ba |
gegl_chant_int (cy, _("Lens center y"), -G_MAXINT, G_MAXINT, 0,
|
|
Packit Service |
2781ba |
_("Coordinates of lens center"))
|
|
Packit Service |
2781ba |
gegl_chant_double (rscale, _("Scale"), 0.001, 10.0, 0.5,
|
|
Packit Service |
2781ba |
_("Scale of the image"))
|
|
Packit Service |
2781ba |
gegl_chant_boolean (correct, _("Autocorrect d values"), TRUE,
|
|
Packit Service |
2781ba |
_("Autocorrect D values for lens correction models."))
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_chant_double (red_a, _("Model red a:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (red_b, _("Model red b:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (red_c, _("Model red c:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (red_d, _("Model red d:"), 0.0, 2.0, 1.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_chant_double (green_a, _("Model green a:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (green_b, _("Model green b:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (green_c, _("Model green c:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (green_d, _("Model green d:"), 0.0, 2.0, 1.00,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_chant_double (blue_a, _("Model blue a:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (blue_b, _("Model blue b:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (blue_c, _("Model blue c:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (blue_d, _("Model blue d:"), 0.0, 2.0, 1.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for each color channel"))
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_chant_double (alpha_a, _("Model alpha a:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for alpha channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (alpha_b, _("Model alpha b:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for alpha channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (alpha_c, _("Model alpha c:"), -1.0, 1.0, 0.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for alpha channel"))
|
|
Packit Service |
2781ba |
gegl_chant_double (alpha_d, _("Model alpha d:"), 0.0, 2.0, 1.0,
|
|
Packit Service |
2781ba |
_("Correction parameters for alpha channel"))
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#else
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#define GEGL_CHANT_TYPE_FILTER
|
|
Packit Service |
2781ba |
#define GEGL_CHANT_C_FILE "lens-correct.c"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "gegl-chant.h"
|
|
Packit Service |
2781ba |
#include <math.h>
|
|
Packit Service |
2781ba |
#include <stdio.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* Struct containing the correction parameters a,b,c,d for a lens color
|
|
Packit Service |
2781ba |
* channel. These parameters as the same as used in the Panotools
|
|
Packit Service |
2781ba |
* system. For a detailed explanation, please consult
|
|
Packit Service |
2781ba |
* http://wiki.panotools.org/Lens_correction_model
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Normally a, b, and c are close to zero, and d is close to one. Note
|
|
Packit Service |
2781ba |
* that d is the parameter that's approximately equal to 1 - a - b - c,
|
|
Packit Service |
2781ba |
* NOT one of the image shift parameters as used in some GUIs.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
typedef struct {
|
|
Packit Service |
2781ba |
gfloat a, b, c, d;
|
|
Packit Service |
2781ba |
} ChannelCorrectionModel;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* Struct containing all the information required for lens correction.
|
|
Packit Service |
2781ba |
* It includes the total size of the image plus the correction
|
|
Packit Service |
2781ba |
* parameters for each color channel.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
typedef struct {
|
|
Packit Service |
2781ba |
GeglRectangle BB; /* Bounding box of the imaged area. */
|
|
Packit Service |
2781ba |
gfloat cx, cy; /* Coordinates of lens center within the imaged area. */
|
|
Packit Service |
2781ba |
gfloat rscale; /* Scale of the image (1/2 of the shortest side). */
|
|
Packit Service |
2781ba |
ChannelCorrectionModel red, green, blue, alpha; /* Correction parameters for each color channel. */
|
|
Packit Service |
2781ba |
} LensCorrectionModel;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
make_lens (LensCorrectionModel *lens,
|
|
Packit Service |
2781ba |
GeglChantO *o,
|
|
Packit Service |
2781ba |
GeglRectangle boundary)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
lens->BB.x = boundary.x;
|
|
Packit Service |
2781ba |
lens->BB.y = boundary.y;
|
|
Packit Service |
2781ba |
lens->BB.width = boundary.width;
|
|
Packit Service |
2781ba |
lens->BB.height = boundary.height;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->center)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
o->cx = (boundary.x + boundary.width) / 2;
|
|
Packit Service |
2781ba |
o->cy = (boundary.y + boundary.height) / 2;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->cx = o->cx;
|
|
Packit Service |
2781ba |
lens->cy = o->cy;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->rscale = o->rscale;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->red.a = o->red_a;
|
|
Packit Service |
2781ba |
lens->red.b = o->red_b;
|
|
Packit Service |
2781ba |
lens->red.c = o->red_c;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->correct)
|
|
Packit Service |
2781ba |
lens->red.d = 1 - o->red_a - o->red_b - o->red_c;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
lens->red.d = o->red_d;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->green.a = o->green_a;
|
|
Packit Service |
2781ba |
lens->green.b = o->green_b;
|
|
Packit Service |
2781ba |
lens->green.c = o->green_c;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->correct)
|
|
Packit Service |
2781ba |
lens->green.d = 1 - o->green_a - o->green_b - o->green_c;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
lens->green.d = o->green_d;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->blue.a = o->blue_a;
|
|
Packit Service |
2781ba |
lens->blue.b = o->blue_b;
|
|
Packit Service |
2781ba |
lens->blue.c = o->blue_c;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->correct)
|
|
Packit Service |
2781ba |
lens->blue.d = 1 - o->blue_a - o->blue_b - o->blue_c;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
lens->blue.d = o->blue_d;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->alpha.a = o->alpha_a;
|
|
Packit Service |
2781ba |
lens->alpha.b = o->alpha_b;
|
|
Packit Service |
2781ba |
lens->alpha.c = o->alpha_c;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->correct)
|
|
Packit Service |
2781ba |
lens->alpha.d = 1 - o->alpha_a - o->alpha_b - o->alpha_c;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
lens->alpha.d = o->red_d;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->focal!=0.0)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gdouble f = o->focal;
|
|
Packit Service |
2781ba |
lens->red.b = lens->green.b = lens->blue.b = lens->alpha.b
|
|
Packit Service |
2781ba |
= 0.000005142 * f*f*f - 0.000380839 * f*f + 0.009606325 * f - 0.075316854;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static gboolean
|
|
Packit Service |
2781ba |
find_make_lens(LensCorrectionModel *lens,
|
|
Packit Service |
2781ba |
GeglChantO *o,
|
|
Packit Service |
2781ba |
GeglRectangle boundary)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
struct lfDatabase *ldb;
|
|
Packit Service |
2781ba |
const lfCamera **cameras;
|
|
Packit Service |
2781ba |
const lfLens **lenses;
|
|
Packit Service |
2781ba |
const lfCamera *camera;
|
|
Packit Service |
2781ba |
const lfLens *onelen;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
struct lfLensCalibDistortion **dist;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gint i, j=0;
|
|
Packit Service |
2781ba |
gfloat aux = G_MAXINT;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->BB.x = boundary.x;
|
|
Packit Service |
2781ba |
lens->BB.y = boundary.y;
|
|
Packit Service |
2781ba |
lens->BB.width = boundary.width;
|
|
Packit Service |
2781ba |
lens->BB.height = boundary.height;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (o->center)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
o->cx = (boundary.x + boundary.width) / 2;
|
|
Packit Service |
2781ba |
o->cy = (boundary.y + boundary.height) / 2;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->cx = o->cx;
|
|
Packit Service |
2781ba |
lens->cy = o->cy;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->rscale = o->rscale;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
ldb = lf_db_new ();
|
|
Packit Service |
2781ba |
if (!ldb)
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lf_db_load (ldb);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
cameras = lf_db_find_cameras (ldb, o->maker, o->Camera);
|
|
Packit Service |
2781ba |
if (!cameras)
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
camera = cameras[0];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lf_free (cameras);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lenses = lf_db_find_lenses_hd (ldb, camera, o->maker, o->Lens, 0);
|
|
Packit Service |
2781ba |
if (!lenses)
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
onelen = lenses[0];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
dist = onelen->CalibDistortion;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (i=0; lenses[i]; i++)
|
|
Packit Service |
2781ba |
if (lenses[i]->MinFocal < o->focal && o->focal < lenses[i]->MaxFocal)
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
dist = lenses[i]->CalibDistortion;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (!dist)
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (i=0; dist[i]; i++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (dist[i]->Focal == o->focal)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
lens->red.a = lens->green.a = lens->blue.a = lens->alpha.a
|
|
Packit Service |
2781ba |
= dist[i]->Terms[0];
|
|
Packit Service |
2781ba |
lens->red.b = lens->green.b = lens->blue.b = lens->alpha.b
|
|
Packit Service |
2781ba |
= dist[i]->Terms[1];
|
|
Packit Service |
2781ba |
lens->red.c = lens->green.c = lens->blue.c = lens->alpha.c
|
|
Packit Service |
2781ba |
= dist[i]->Terms[2];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->red.d = 1 - lens->red.a - lens->red.b - lens->red.c;
|
|
Packit Service |
2781ba |
lens->green.d = 1 - lens->green.a - lens->green.b - lens->green.c;
|
|
Packit Service |
2781ba |
lens->blue.d = 1 - lens->blue.a - lens->blue.b - lens->blue.c;
|
|
Packit Service |
2781ba |
lens->alpha.d = 1 - lens->alpha.a - lens->alpha.b - lens->alpha.c;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
aux = -G_MAXINT;
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if (i > 0)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (aux > fabs (dist[i]->Focal - o->focal
|
|
Packit Service |
2781ba |
+ dist[i-1]->Focal - o->focal))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
aux = fabs (dist[i]->Focal + dist[i-1]->Focal - 2 * o->focal);
|
|
Packit Service |
2781ba |
j = i;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
lf_free (lenses);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (aux != -G_MAXINT)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gfloat aux[3];
|
|
Packit Service |
2781ba |
for (i=0; i<3; i++)
|
|
Packit Service |
2781ba |
aux[i] = (dist[j]->Terms[i] - dist[j-1]->Terms[i]) / 2.0;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->red.a = lens->green.a = lens->blue.a = lens->alpha.a
|
|
Packit Service |
2781ba |
= aux[0];
|
|
Packit Service |
2781ba |
lens->red.b = lens->green.b = lens->blue.b = lens->alpha.b
|
|
Packit Service |
2781ba |
= aux[1];
|
|
Packit Service |
2781ba |
lens->red.c = lens->green.c = lens->blue.c = lens->alpha.c
|
|
Packit Service |
2781ba |
= aux[2];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
lens->red.d = 1 - lens->red.a - lens->red.b - lens->red.c;
|
|
Packit Service |
2781ba |
lens->green.d = 1 - lens->green.a - lens->green.b - lens->green.c;
|
|
Packit Service |
2781ba |
lens->blue.d = 1 - lens->blue.a - lens->blue.b - lens->blue.c;
|
|
Packit Service |
2781ba |
lens->alpha.d = 1 - lens->alpha.a - lens->alpha.b - lens->alpha.c;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return TRUE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static GeglRectangle
|
|
Packit Service |
2781ba |
get_bounding_box (GeglOperation *operation)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRectangle result = {0,0,0,0};
|
|
Packit Service |
2781ba |
GeglRectangle *in_rect;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
in_rect = gegl_operation_source_get_bounding_box (operation, "input");
|
|
Packit Service |
2781ba |
if (!in_rect)
|
|
Packit Service |
2781ba |
return result;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return *in_rect;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static GeglRectangle
|
|
Packit Service |
2781ba |
get_required_for_output (GeglOperation *operation,
|
|
Packit Service |
2781ba |
const gchar *input_pad,
|
|
Packit Service |
2781ba |
const GeglRectangle *roi)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
return get_bounding_box (operation);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
prepare (GeglOperation *operation)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gegl_operation_set_format (operation, "input", babl_format ("RGBA float"));
|
|
Packit Service |
2781ba |
gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
find_src_pixel (LensCorrectionModel *lcip, ChannelCorrectionModel *pp,
|
|
Packit Service |
2781ba |
gfloat x, gfloat y, gfloat *srcx, gfloat *srcy)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gdouble r, radj;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
r = hypot (x - lcip->cx, y - lcip->cy) / lcip->rscale;
|
|
Packit Service |
2781ba |
radj = (((pp->a*r+pp->b)*r+pp->c)*r+pp->d);
|
|
Packit Service |
2781ba |
*srcx = (x - lcip->cx) * radj + lcip->cx;
|
|
Packit Service |
2781ba |
*srcy = (y - lcip->cy) * radj + lcip->cy;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
lens_distort_newl (gfloat *src_buf,
|
|
Packit Service |
2781ba |
gfloat *dst_buf,
|
|
Packit Service |
2781ba |
const GeglRectangle *extended,
|
|
Packit Service |
2781ba |
const GeglRectangle *result,
|
|
Packit Service |
2781ba |
const GeglRectangle *boundary,
|
|
Packit Service |
2781ba |
LensCorrectionModel *lens,
|
|
Packit Service |
2781ba |
gint xx,
|
|
Packit Service |
2781ba |
gint yy,
|
|
Packit Service |
2781ba |
GeglBuffer *input)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gfloat temp[4];
|
|
Packit Service |
2781ba |
gint tmpx, tmpy, x, y, rgb;
|
|
Packit Service |
2781ba |
gint offset;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
ChannelCorrectionModel ccm[4];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* Compute each dst pixel in turn and store into dst buffer. */
|
|
Packit Service |
2781ba |
ccm[0] = lens->red;
|
|
Packit Service |
2781ba |
ccm[1] = lens->green;
|
|
Packit Service |
2781ba |
ccm[2] = lens->blue;
|
|
Packit Service |
2781ba |
ccm[3] = lens->alpha;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (rgb = 0; rgb < 4; rgb++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gfloat gx, gy;
|
|
Packit Service |
2781ba |
gfloat val = 0.0;
|
|
Packit Service |
2781ba |
gfloat wx[2], wy[2], wt = 0.0;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
find_src_pixel (lens, &ccm[rgb], (gfloat)xx, (gfloat)yy, &gx, &gy;;
|
|
Packit Service |
2781ba |
tmpx = (gint) gx;
|
|
Packit Service |
2781ba |
tmpy = (gint) gy;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
wx[1] = gx - tmpx;
|
|
Packit Service |
2781ba |
wx[0] = 1.0 - wx[1];
|
|
Packit Service |
2781ba |
wy[1] = gy - tmpy;
|
|
Packit Service |
2781ba |
wy[0] = 1.0 - wy[1];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (x = 0; x < 2; x++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
for (y = 0; y < 2; y++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (tmpx+x >= extended->x && tmpx+x < extended->x + extended->width
|
|
Packit Service |
2781ba |
&& tmpy+y >= extended->y && tmpy+y < extended->y + extended->height)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
offset = (tmpy + y - extended->y) * extended->width * 4 +
|
|
Packit Service |
2781ba |
(tmpx + x - extended->x) * 4 + rgb;
|
|
Packit Service |
2781ba |
val += src_buf[offset] * wx[x] * wy[y];
|
|
Packit Service |
2781ba |
wt += wx[x] * wy[y];
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if (tmpx+x >= boundary->x &&
|
|
Packit Service |
2781ba |
tmpx+x < boundary->x + boundary->width &&
|
|
Packit Service |
2781ba |
tmpy+y >= boundary->y &&
|
|
Packit Service |
2781ba |
tmpy+y < boundary->y + boundary->height)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gfloat color[4];
|
|
Packit Service |
2781ba |
gegl_buffer_sample (input, tmpx+x, tmpy+y, NULL, color,
|
|
Packit Service |
2781ba |
babl_format ("RGBA float"),
|
|
Packit Service |
2781ba |
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
|
|
Packit Service |
2781ba |
val += color[rgb] * wx[x] * wy[y];
|
|
Packit Service |
2781ba |
wt += wx[x] * wy[y];
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
if (wt <= 0)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
temp [rgb] = 0.0;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
temp [rgb] = val / wt;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
offset = (yy - result->y) * result->width * 4 + (xx - result->x) * 4;
|
|
Packit Service |
2781ba |
for (x=0; x<4; x++)
|
|
Packit Service |
2781ba |
dst_buf[offset++] = temp[x];
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static gboolean
|
|
Packit Service |
2781ba |
process (GeglOperation *operation,
|
|
Packit Service |
2781ba |
GeglBuffer *input,
|
|
Packit Service |
2781ba |
GeglBuffer *output,
|
|
Packit Service |
2781ba |
const GeglRectangle *result,
|
|
Packit Service |
2781ba |
gint level)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit Service |
2781ba |
LensCorrectionModel lens = { { 0, }, };
|
|
Packit Service |
2781ba |
GeglRectangle boundary = *gegl_operation_source_get_bounding_box
|
|
Packit Service |
2781ba |
(operation, "input");
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gint x, y, found = FALSE;
|
|
Packit Service |
2781ba |
gfloat *src_buf, *dst_buf;
|
|
Packit Service |
2781ba |
src_buf = g_new0 (gfloat, result->width * result->height * 4);
|
|
Packit Service |
2781ba |
dst_buf = g_new0 (gfloat, result->width * result->height * 4);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
found = find_make_lens (&lens, o, boundary);
|
|
Packit Service |
2781ba |
if (!found) make_lens (&lens, o, boundary);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_buffer_get (input, result, 1.0, babl_format ("RGBA float"),
|
|
Packit Service |
2781ba |
src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (y = result->y; y < result->y + result->height; y++)
|
|
Packit Service |
2781ba |
for (x = result->x; x < result->x + result->width; x++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
lens_distort_newl (src_buf, dst_buf, result,
|
|
Packit Service |
2781ba |
result, &boundary, &lens, x, y, input);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_buffer_set (output, result, 0, babl_format ("RGBA float"),
|
|
Packit Service |
2781ba |
dst_buf, GEGL_AUTO_ROWSTRIDE);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_free (dst_buf);
|
|
Packit Service |
2781ba |
g_free (src_buf);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return TRUE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
gegl_chant_class_init (GeglChantClass *klass)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglOperationClass *operation_class;
|
|
Packit Service |
2781ba |
GeglOperationFilterClass *filter_class;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
operation_class = GEGL_OPERATION_CLASS (klass);
|
|
Packit Service |
2781ba |
filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
filter_class->process = process;
|
|
Packit Service |
2781ba |
operation_class->prepare = prepare;
|
|
Packit Service |
2781ba |
operation_class->get_bounding_box = get_bounding_box;
|
|
Packit Service |
2781ba |
operation_class->get_required_for_output = get_required_for_output;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_operation_class_set_keys (operation_class,
|
|
Packit Service |
2781ba |
"name" , "gegl:lens-correct",
|
|
Packit Service |
2781ba |
"categories" , "blur",
|
|
Packit Service |
2781ba |
"description",
|
|
Packit Service |
2781ba |
_("Copies image performing lens distortion correction."),
|
|
Packit Service |
2781ba |
NULL);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#endif
|