Commit c33fb451 authored by Marek Dvoroznak's avatar Marek Dvoroznak Committed by Mikael Magnusson

npd: NPD operation uses GEGL sampler and operates in RGBA float

parent ace20153
......@@ -54,7 +54,7 @@ npd_bilinear_color_interpolation (NPDColor *I0,
out->a = npd_bilinear_interpolation (I0->a, I1->a, I2->a, I3->a, dx, dy);
}
static gfloat
gfloat
npd_blend_band (gfloat src,
gfloat dst,
gfloat src_alpha,
......@@ -70,24 +70,60 @@ npd_blend_colors (NPDColor *src,
NPDColor *dst,
NPDColor *out_color)
{
#ifdef NPD_RGBA_FLOAT
gfloat src_A = src->a,
dst_A = dst->a;
#else
gfloat src_A = src->a / 255.0,
dst_A = dst->a / 255.0;
#endif
gfloat out_alpha = src_A + dst_A * (1 - src_A);
gfloat out_alpha_recip = 1 / out_alpha;
out_color->r = npd_blend_band (src->r, dst->r, src_A, dst_A, out_alpha_recip);
out_color->g = npd_blend_band (src->g, dst->g, src_A, dst_A, out_alpha_recip);
out_color->b = npd_blend_band (src->b, dst->b, src_A, dst_A, out_alpha_recip);
#ifdef NPD_RGBA_FLOAT
out_color->a = out_alpha;
#else
out_color->a = out_alpha * 255;
#endif
}
void
npd_process_pixel_bilinear (NPDImage *input_image,
gfloat ix,
gfloat iy,
NPDImage *output_image,
gfloat ox,
gfloat oy,
NPDSettings settings)
{
gint fx, fy;
gfloat dx, dy;
NPDColor I0, interpolated, *final_color;
fx = floor (ix);
fy = floor (iy);
npd_get_pixel_color (input_image, fx, fy, &I0);
final_color = &I0;
/* bilinear interpolation */
if (settings & NPD_BILINEAR_INTERPOLATION)
{
NPDColor I1, I2, I3;
dx = ix - fx;
dy = iy - fy;
npd_get_pixel_color (input_image, fx + 1, fy, &I1);
npd_get_pixel_color (input_image, fx, fy + 1, &I2);
npd_get_pixel_color (input_image, fx + 1, fy + 1, &I3);
npd_bilinear_color_interpolation (&I0, &I1, &I2, &I3, dx, dy, &interpolated);
final_color = &interpolated;
}
/* alpha blending */
if (settings & NPD_ALPHA_BLENDING)
{
NPDColor dest;
npd_get_pixel_color (output_image, ox, oy, &dest);
npd_blend_colors (final_color, &dest, final_color);
}
npd_set_pixel_color (output_image, ox, oy, final_color);
}
static void
......@@ -99,47 +135,18 @@ npd_draw_texture_line (gint x1,
NPDImage *output_image,
NPDSettings settings)
{
gint x, fx, fy;
gfloat dx, dy;
gint x;
for (x = x1; x <= x2; x++)
{
NPDPoint p, q;
NPDColor I0, interpolated, *final;
q.x = x; q.y = y;
npd_apply_transformation (A, &q, &p);
fx = floor (p.x);
fy = floor (p.y);
npd_get_pixel_color (input_image, fx, fy, &I0);
final = &I0;
/* bilinear interpolation */
if (settings & NPD_BILINEAR_INTERPOLATION)
{
NPDColor I1, I2, I3;
dx = p.x - fx;
dy = p.y - fy;
npd_get_pixel_color (input_image, fx + 1, fy, &I1);
npd_get_pixel_color (input_image, fx, fy + 1, &I2);
npd_get_pixel_color (input_image, fx + 1, fy + 1, &I3);
npd_bilinear_color_interpolation (&I0, &I1, &I2, &I3, dx, dy, &interpolated);
final = &interpolated;
}
/* alpha blending */
if (settings & NPD_ALPHA_BLENDING)
{
NPDColor dest;
npd_get_pixel_color (output_image, x, y, &dest);
npd_blend_colors (final, &dest, final);
}
npd_set_pixel_color (output_image, x, y, final);
npd_process_pixel (input_image, p.x, p.y,
output_image, x, y,
settings);
}
}
......@@ -354,7 +361,7 @@ npd_create_mesh (NPDModel *model,
gint square_size = model->mesh_square_size;
NPDImage *image = model->reference_image;
gint i, cy, cx, y, x, r, c, ow, oh;
NPDColor pixel_color = { 0, 0, 0, 0 };
NPDColor pixel_color;
GArray *squares;
gint *sq2id;
gboolean *empty_squares;
......@@ -549,7 +556,6 @@ npd_create_model_from_image (NPDModel *model,
npd_create_mesh (model, width, height, position_x, position_y);
}
void
npd_draw_mesh (NPDModel *model,
NPDDisplay *display)
......@@ -572,3 +578,8 @@ npd_draw_mesh (NPDModel *model,
npd_draw_line (display, p1->x, p1->y, first->x, first->y);
}
}
void (*npd_process_pixel) (NPDImage*, gfloat, gfloat, NPDImage*, gfloat, gfloat, NPDSettings) = NULL;
void (*npd_draw_line) (NPDDisplay*, gfloat, gfloat, gfloat, gfloat) = NULL;
void (*npd_get_pixel_color) (NPDImage*, gint, gint, NPDColor*) = NULL;
void (*npd_set_pixel_color) (NPDImage*, gint, gint, NPDColor*) = NULL;
......@@ -24,20 +24,17 @@
#include "npd_common.h"
//#define NPD_RGBA_FLOAT
struct _NPDColor {
#ifdef NPD_RGBA_FLOAT
gfloat r;
gfloat g;
gfloat b;
gfloat a;
#else
guint8 r;
guint8 g;
guint8 b;
guint8 a;
#endif
struct _NPDColor
{
union {
guint32 color;
struct {
guint8 r;
guint8 g;
guint8 b;
guint8 a;
};
};
};
typedef enum
......@@ -46,30 +43,49 @@ typedef enum
NPD_ALPHA_BLENDING = 1 << 1
} NPDSettings;
void npd_create_model_from_image (NPDModel *model,
NPDImage *image,
gint width,
gint height,
gint position_x,
gint position_y,
gint square_size);
void npd_draw_model_into_image (NPDModel *model,
NPDImage *image);
void npd_draw_mesh (NPDModel *model,
NPDDisplay *display);
gboolean npd_is_color_transparent (NPDColor *color);
void (*npd_draw_line) (NPDDisplay *display,
gfloat x0,
gfloat y0,
gfloat x1,
gfloat y1);
void (*npd_get_pixel_color) (NPDImage *image,
gint x,
gint y,
NPDColor *color);
void (*npd_set_pixel_color) (NPDImage *image,
gint x,
gint y,
NPDColor *color);
void npd_create_model_from_image (NPDModel *model,
NPDImage *image,
gint width,
gint height,
gint position_x,
gint position_y,
gint square_size);
void npd_draw_model_into_image (NPDModel *model,
NPDImage *image);
void npd_draw_mesh (NPDModel *model,
NPDDisplay *display);
gboolean npd_is_color_transparent (NPDColor *color);
gfloat npd_blend_band (gfloat src,
gfloat dst,
gfloat src_alpha,
gfloat dst_alpha,
gfloat out_alpha_recip);
extern void (*npd_draw_line) (NPDDisplay *display,
gfloat x0,
gfloat y0,
gfloat x1,
gfloat y1);
extern void (*npd_process_pixel) (NPDImage *input_image,
gfloat ix,
gfloat iy,
NPDImage *output_image,
gfloat ox,
gfloat oy,
NPDSettings settings);
void npd_process_pixel_bilinear (NPDImage *input_image,
gfloat ix,
gfloat iy,
NPDImage *output_image,
gfloat ox,
gfloat oy,
NPDSettings settings);
extern void (*npd_get_pixel_color) (NPDImage *image,
gint x,
gint y,
NPDColor *color);
extern void (*npd_set_pixel_color) (NPDImage *image,
gint x,
gint y,
NPDColor *color);
#endif /*__NPD_GRAPHICS_H__ */
......@@ -94,9 +94,10 @@ typedef struct
} NPDModel;
#define npd_init(set_pixel, get_pixel, \
draw_line) \
process_pixel, draw_line) \
npd_set_pixel_color = set_pixel; \
npd_get_pixel_color = get_pixel; \
npd_process_pixel = process_pixel; \
npd_draw_line = draw_line;
void npd_init_model (NPDModel *model);
......
......@@ -65,7 +65,7 @@ npd_gegl_set_pixel_color (NPDImage *image,
if (x > -1 && x < image->width &&
y > -1 && y < image->height)
{
gint position = y * image->rowstride + 4 * x;
gint position = 4 * (y * image->width + x);
image->buffer[position + 0] = color->r;
image->buffer[position + 1] = color->g;
......@@ -83,7 +83,7 @@ npd_gegl_get_pixel_color (NPDImage *image,
if (x > -1 && x < image->width &&
y > -1 && y < image->height)
{
gint position = y * image->rowstride + 4 * x;
gint position = 4 * (y * image->width + x);
color->r = image->buffer[position + 0];
color->g = image->buffer[position + 1];
......@@ -116,6 +116,9 @@ npd_gegl_init_image (NPDImage *image,
image->gegl_buffer = gegl_buffer;
image->width = gegl_buffer_get_width (gegl_buffer);
image->rowstride = image->width * babl_format_get_bytes_per_pixel (format);
image->length = babl_format_get_n_components (format) * gegl_buffer_get_pixel_count (gegl_buffer);
image->height = gegl_buffer_get_height (gegl_buffer);
image->format = format;
image->buffer = NULL;
image->buffer_f = NULL;
}
......@@ -32,22 +32,24 @@ struct _NPDImage
gint height;
NPDPoint position;
gint rowstride;
gint length;
GeglBuffer *gegl_buffer;
guchar *buffer;
gfloat *buffer_f;
const Babl *format;
GeglSamplerType sampler_type;
};
void npd_gegl_set_pixel_color (NPDImage *image,
gint x,
gint y,
NPDColor *color);
void npd_gegl_get_pixel_color (NPDImage *image,
gint x,
gint y,
NPDColor *color);
void npd_gegl_open_buffer (NPDImage *image);
void npd_gegl_close_buffer (NPDImage *image);
void npd_gegl_set_pixel_color (NPDImage *image,
gint x,
gint y,
NPDColor *color);
void npd_gegl_get_pixel_color (NPDImage *image,
gint x,
gint y,
NPDColor *color);
void npd_gegl_open_buffer (NPDImage *image);
void npd_gegl_close_buffer (NPDImage *image);
void npd_gegl_init_image (NPDImage *image,
GeglBuffer *gegl_buffer,
const Babl *format);
......
......@@ -41,7 +41,7 @@ gfloat
npd_SED (NPDPoint *p1,
NPDPoint *p2)
{
gint dx = p1->x - p2->x;
gint dy = p1->y - p2->y;
gfloat dx = p1->x - p2->x;
gfloat dy = p1->y - p2->y;
return dx * dx + dy * dy;
}
......@@ -39,12 +39,12 @@ void npd_compute_affinity (NPDPoint *p11,
void npd_apply_transformation (NPDMatrix *T,
NPDPoint *src,
NPDPoint *dest);
gboolean npd_equal_floats_epsilon (gfloat a,
gfloat b,
gfloat epsilon);
gboolean npd_equal_floats (gfloat a,
gfloat b);
gfloat npd_SED (NPDPoint *p1,
NPDPoint *p2);
gboolean npd_equal_floats_epsilon (gfloat a,
gfloat b,
gfloat epsilon);
gboolean npd_equal_floats (gfloat a,
gfloat b);
gfloat npd_SED (NPDPoint *p1,
NPDPoint *p2);
#endif /* __NPD_MATH_H__ */
......@@ -42,6 +42,15 @@ gegl_chant_boolean (MLS_weights, _("MLS weights"),
gegl_chant_double (MLS_weights_alpha, _("MLS weights alpha"),
0.1, 2.0, 1.0,
_("Alpha parameter of MLS weights"))
gegl_chant_boolean (preserve_model, _("preserve model"),
FALSE,
_("When TRUE the model will not be freed"))
gegl_chant_enum (sampler_type, _("Sampler"),
GeglSamplerType, gegl_sampler_type,
GEGL_SAMPLER_CUBIC,
_("Sampler used internally"))
#else
#define GEGL_CHANT_TYPE_FILTER
......@@ -61,7 +70,7 @@ struct _NPDDisplay
typedef struct
{
gboolean first_run;
NPDModel model;
NPDModel *model;
} NPDProperties;
static void
......@@ -69,18 +78,45 @@ prepare (GeglOperation *operation)
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
NPDProperties *props;
if (o->chant_data == NULL)
{
props = g_new (NPDProperties, 1);
props->first_run = TRUE;
o->chant_data = props;
props->first_run = TRUE;
props->model = o->model;
o->chant_data = props;
}
gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
}
static void
npd_gegl_process_pixel (NPDImage *input_image,
gfloat ix,
gfloat iy,
NPDImage *output_image,
gfloat ox,
gfloat oy,
NPDSettings settings)
{
if (ox > -1 && ox < output_image->width &&
oy > -1 && oy < output_image->height)
{
gint position = 4 * (((gint) oy) * output_image->width + ((gint) ox));
gegl_buffer_sample (input_image->gegl_buffer, ix, iy, NULL,
&output_image->buffer_f[position], output_image->format,
output_image->sampler_type, GEGL_ABYSS_NONE);
}
}
gegl_operation_set_format (operation, "input",
babl_format ("RGBA float"));
gegl_operation_set_format (operation, "output",
babl_format ("RGBA float"));
static void
npd_gegl_get_pixel_color_f (NPDImage *image,
gint x,
gint y,
NPDColor *color)
{
gegl_buffer_sample (image->gegl_buffer, x, y, NULL,
&color->color, babl_format ("RGBA u8"),
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
}
static gboolean
......@@ -90,41 +126,48 @@ process (GeglOperation *operation,
const GeglRectangle *roi,
gint level)
{
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
const Babl *format = babl_format ("RGBA u8");
NPDProperties *props = o->chant_data;
NPDModel *model = &props->model;
gint length = gegl_buffer_get_pixel_count (input) * 4;
NPDDisplay *display = model->display;
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
const Babl *format_f = babl_format ("RGBA float");
NPDProperties *props = o->chant_data;
NPDModel *model = props->model;
gboolean have_model = model != NULL;
NPDDisplay *display = NULL;
if (props->first_run)
{
NPDImage *input_image = g_new (NPDImage, 1);
display = g_new (NPDDisplay, 1);
npd_init (npd_gegl_set_pixel_color,
npd_gegl_get_pixel_color,
NULL);
npd_init (NULL,
npd_gegl_get_pixel_color_f,
npd_gegl_process_pixel, NULL);
npd_gegl_init_image (input_image, input, format);
input_image->buffer = g_new0 (guchar, gegl_buffer_get_pixel_count (input) * 4);
gegl_buffer_get (input, NULL, 1.0, format, input_image->buffer,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
npd_gegl_init_image (&display->image, output, format_f);
display->image.sampler_type = o->sampler_type;
npd_gegl_init_image (input_image, input, gegl_buffer_get_format (output));
npd_gegl_init_image (&display->image, output, format);
npd_gegl_open_buffer (&display->image);
if (!have_model)
{
model = props->model = o->model = g_new (NPDModel, 1);
gegl_buffer_copy (input, NULL, output, NULL);
display->image.buffer_f = (gfloat*) gegl_buffer_linear_open (display->image.gegl_buffer,
NULL,
&display->image.rowstride,
format_f);
npd_create_model_from_image (model, input_image,
input_image->width, input_image->height,
0, 0, o->square_size);
}
model->reference_image = input_image;
model->display = display;
npd_create_model_from_image (model, input_image,
input_image->width, input_image->height,
0, 0, o->square_size);
o->model = model;
memcpy (display->image.buffer, input_image->buffer, length);
props->first_run = FALSE;
}
else
if (have_model)
{
display = model->display;
npd_set_deformation_type (model, o->ASAP_deformation, o->MLS_weights);
if (o->MLS_weights &&
......@@ -134,13 +177,17 @@ process (GeglOperation *operation,
npd_compute_MLS_weights (model);
}
npd_gegl_open_buffer (&display->image);
memset (display->image.buffer, 0, length);
gegl_buffer_clear (display->image.gegl_buffer, NULL);
display->image.buffer_f = (gfloat*) gegl_buffer_linear_open (display->image.gegl_buffer,
NULL,
&display->image.rowstride,
format_f);
npd_deform_model (model, o->rigidity);
npd_draw_model_into_image (model, &display->image);
}
npd_gegl_close_buffer (&display->image);
gegl_buffer_linear_close (display->image.gegl_buffer, display->image.buffer_f);
return TRUE;
}
......@@ -152,14 +199,17 @@ finalize (GObject *object)
if (o->chant_data)
{
NPDProperties *props = o->chant_data;
NPDModel *model = &props->model;
NPDDisplay *display = model->display;
NPDProperties *props = o->chant_data;
NPDModel *model = props->model;
NPDDisplay *display = model->display;
g_free (model->reference_image->buffer);
g_free (model->reference_image);
g_free (display);
npd_destroy_model (model);
g_free (model->reference_image);
if (!o->preserve_model)
{
npd_destroy_model (model);
g_free (model);
}
o->chant_data = NULL;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment