/* FIXME: not 100% bullet proof */ static GeglRectangle get_required (GeglRectangle *boundary, const GeglRectangle *roi, GeglOperation *operation) { GeglChantO *o; GeglRectangle area; LensValues lens; gdouble x1, y1, x2, y2, x3, y3, x4, y4, mag; gint x, y, width, height; o = GEGL_CHANT_PROPERTIES (operation); lens = lens_setup_calc (o, *boundary); x = roi->x; y = roi->y; width = roi->width; height = roi->height; lens_get_source_coord (x, y, &x1, &y1, &mag, &lens); lens_get_source_coord (x + width, y, &x2, &y2, &mag, &lens); lens_get_source_coord (x, y + height, &x3, &y3, &mag, &lens); lens_get_source_coord (x + width, y + height, &x4, &y4, &mag, &lens); /* This is ugly, and happens * with a crazy set of parameters */ reorder (&x1, &x2); reorder (&x3, &x4); reorder (&y1, &y3); reorder (&y2, &y4); if (lens.centre_y > y && lens.centre_y < y + height) { gdouble x5, y5, x6, y6; lens_get_source_coord (x, lens.centre_y, &x5, &y5, &mag, &lens); lens_get_source_coord (x + width, lens.centre_y, &x6, &y6, &mag, &lens); reorder (&x5, &x6); area.x = floor (MIN3 (x1, x3, x5)) - 1; area.width = ceil (MAX3 (x2, x4, x6)) + 3 - area.x; } else { area.x = floor (MIN (x1, x3)) - 1; area.width = ceil (MAX (x2, x4)) + 3 - area.x; } if (lens.centre_x > x && lens.centre_x < x + width) { gdouble x5, y5, x6, y6; lens_get_source_coord (lens.centre_x, y, &x5, &y5, &mag, &lens); lens_get_source_coord (lens.centre_x, y + height, &x6, &y6, &mag, &lens); reorder (&y5, &y6); area.y = floor (MIN3 (y1, y2, y5)) - 1; area.height = ceil (MAX3 (y3, y4, y6)) + 3 - area.y; } else { area.y = floor (MIN (y1, y2)) - 1; area.height = ceil (MAX (y3, y4)) + 3 - area.y; } return area; }
static void lens_distort_func (gfloat *src_buf, gfloat *dst_buf, const GeglRectangle *extended, const GeglRectangle *result, const GeglRectangle *boundary, LensValues *lens, gint xx, gint yy, GeglBuffer *input, gfloat *background) { gdouble sx, sy, mag; gdouble brighten; gfloat pixel_buffer [16 * 4], temp[4]; gdouble dx, dy; gint x_int, y_int, x = 0, y = 0, offset = 0; temp[0] = temp[1] = temp[2] = temp[3] = 0.0; lens_get_source_coord ((gdouble) xx, (gdouble) yy, &sx, &sy, &mag, lens); /* pseudo gamma transformation, since the input is scRGB */ brighten = pow (MAX (1.0 + mag * lens->brighten, 0.0), 2.4); x_int = floor (sx); dx = sx - x_int; y_int = floor (sy); dy = sy - y_int; for (y = y_int - 1; y <= y_int + 2; y++) { for (x = x_int - 1; x <= x_int + 2; x++) { gint b; if (x < boundary->x || x >= (boundary->x + boundary->width) || y < boundary->y || y >= (boundary->y + boundary->height)) { for (b = 0; b < 4; b++) pixel_buffer[offset++] = background[b]; } else { if (x >= extended->x && x < (extended->x + extended->width) && y >= extended->y && y < (extended->y + extended->height)) { gint src_off; src_off = (y - extended->y) * extended->width * 4 + (x - extended->x) * 4; for (b = 0; b < 4; b++) temp[b] = src_buf[src_off++]; } else { gegl_buffer_sample (input, x, y, NULL, temp, babl_format ("RGBA float"), GEGL_SAMPLER_LINEAR, GEGL_ABYSS_CLAMP); } for (b = 0; b < 4; b++) pixel_buffer[offset++] = temp[b]; } } } lens_cubic_interpolate (pixel_buffer, temp, dx, dy, brighten); offset = (yy - result->y) * result->width * 4 + (xx - result->x) * 4; for (x = 0; x < 4; x++) dst_buf[offset++] = temp[x]; }
static void lens_distort_func (gfloat *src_buf, gfloat *dst_buf, const GeglRectangle *extended, const GeglRectangle *result, const GeglRectangle *boundary, LensDistortion old, gint xx, gint yy, GeglBuffer *input) { gdouble sx, sy, mag; gdouble brighten; gfloat pixel_buffer [16 * 4], temp[4]; gdouble dx, dy; gint x_int, y_int, x = 0, y = 0, offset = 0; temp[0] = temp[1] = temp[2] = temp[3] = 0.0; lens_get_source_coord ((gdouble)xx, (gdouble)yy, &sx, &sy, &mag, &old); brighten = 1.0 + mag * old.brighten; x_int = floor (sx); dx = sx - x_int; y_int = floor (sy); dy = sy - y_int; for (y = y_int - 1; y <= y_int + 2; y++) { for (x = x_int - 1; x <= x_int + 2; x++) { gint b; if (x >= extended->x && x<(extended->x + extended->width) && y >= extended->y && y < (extended->y + extended->height)) { gint src_off; src_off = (y - extended->y) * extended->width * 4 + (x - extended->x) * 4; for (b=0; b<4; b++) temp[b] = src_buf[src_off++]; } else if (x >= boundary->x && x < boundary->x + boundary->width && y >= boundary->y && y < boundary->y + boundary->height) { gegl_buffer_sample (input, x, y, NULL, temp, babl_format ("RGBA float"), GEGL_SAMPLER_CUBIC, GEGL_ABYSS_NONE); } else { for (b=0; b<4; b++) temp[b] = 0.0; } for (b=0; b<4; b++) pixel_buffer[offset++] = temp[b]; } } lens_cubic_interpolate (pixel_buffer, temp, dx, dy, brighten); offset = (yy - result->y) * result->width * 4 + (xx - result->x) * 4; for (x=0; x<4; x++) dst_buf[offset++] = temp[x]; }