static GeglRectangle gegl_affine_get_bounding_box (GeglOperation *op) { OpAffine *affine = OP_AFFINE (op); GeglMatrix3 matrix; GeglRectangle in_rect = {0,0,0,0}, have_rect; gdouble have_points [8]; gint i; GeglRectangle context_rect; GeglSampler *sampler; sampler = gegl_buffer_sampler_new (NULL, babl_format("RaGaBaA float"), gegl_sampler_type_from_string (affine->filter)); context_rect = *gegl_sampler_get_context_rect (sampler); g_object_unref (sampler); if (gegl_operation_source_get_bounding_box (op, "input")) in_rect = *gegl_operation_source_get_bounding_box (op, "input"); gegl_affine_create_composite_matrix (affine, &matrix); if (gegl_affine_is_intermediate_node (affine) || gegl_matrix3_is_identity (&matrix)) { return in_rect; } in_rect.x += context_rect.x; in_rect.y += context_rect.y; in_rect.width += context_rect.width; in_rect.height += context_rect.height; have_points [0] = in_rect.x; have_points [1] = in_rect.y; have_points [2] = in_rect.x + in_rect.width ; have_points [3] = in_rect.y; have_points [4] = in_rect.x + in_rect.width ; have_points [5] = in_rect.y + in_rect.height ; have_points [6] = in_rect.x; have_points [7] = in_rect.y + in_rect.height ; for (i = 0; i < 8; i += 2) gegl_matrix3_transform_point (&matrix, have_points + i, have_points + i + 1); gegl_affine_bounding_box (have_points, 4, &have_rect); return have_rect; }
static GeglRectangle gegl_affine_get_required_for_output (GeglOperation *op, const gchar *input_pad, const GeglRectangle *region) { OpAffine *affine = OP_AFFINE (op); GeglMatrix3 inverse; GeglRectangle requested_rect, need_rect; GeglRectangle context_rect; GeglSampler *sampler; gdouble need_points [8]; gint i; requested_rect = *region; sampler = gegl_buffer_sampler_new (NULL, babl_format("RaGaBaA float"), gegl_sampler_type_from_string (affine->filter)); context_rect = *gegl_sampler_get_context_rect (sampler); g_object_unref (sampler); gegl_affine_create_composite_matrix (affine, &inverse); gegl_matrix3_invert (&inverse); if (gegl_affine_is_intermediate_node (affine) || gegl_matrix3_is_identity (&inverse)) { return requested_rect; } need_points [0] = requested_rect.x; need_points [1] = requested_rect.y; need_points [2] = requested_rect.x + requested_rect.width ; need_points [3] = requested_rect.y; need_points [4] = requested_rect.x + requested_rect.width ; need_points [5] = requested_rect.y + requested_rect.height ; need_points [6] = requested_rect.x; need_points [7] = requested_rect.y + requested_rect.height ; for (i = 0; i < 8; i += 2) gegl_matrix3_transform_point (&inverse, need_points + i, need_points + i + 1); gegl_affine_bounding_box (need_points, 4, &need_rect); need_rect.x += context_rect.x; need_rect.y += context_rect.y; need_rect.width += context_rect.width; need_rect.height += context_rect.height; return need_rect; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gint x = result->x; /* initial x */ gint y = result->y; /* and y coordinates */ gfloat *dst_buf = g_slice_alloc (result->width * result->height * 4 * sizeof (float)); gfloat *out_pixel = dst_buf; GeglSampler *sampler = gegl_buffer_sampler_new (input, babl_format ("RGBA float"), o->sampler_type); gint n_pixels = result->width * result->height; while (n_pixels--) { gegl_sampler_get (sampler, x, y, NULL, out_pixel, GEGL_ABYSS_NONE); out_pixel += 4; /* update x and y coordinates */ x++; if (x>=result->x + result->width) { x=result->x; y++; } } gegl_buffer_set (output, result, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_slice_free1 (result->width * result->height * 4 * sizeof(gfloat), dst_buf); g_object_unref (sampler); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gint x = result->x; /* initial x */ gint y = result->y; /* and y coordinates */ gfloat *dst_buf = g_slice_alloc (result->width * result->height * 4 * sizeof(gfloat)); gfloat *out_pixel = dst_buf; GeglSampler *sampler = gegl_buffer_sampler_new (input, babl_format ("RGBA float"), o->sampler_type); gint n_pixels = result->width * result->height; while (n_pixels--) { gdouble shift; gdouble coordsx; gdouble coordsy; gdouble lambda; gdouble angle_rad = o->angle / 180.0 * G_PI; gdouble nx = x * cos (angle_rad) + y * sin (angle_rad); switch (o->wave_type) { case GEGl_RIPPLE_WAVE_TYPE_SAWTOOTH: lambda = div (nx,o->period).rem - o->phi * o->period; if (lambda < 0) lambda += o->period; shift = o->amplitude * (fabs (((lambda / o->period) * 4) - 2) - 1); break; case GEGl_RIPPLE_WAVE_TYPE_SINE: default: shift = o->amplitude * sin (2.0 * G_PI * nx / o->period + 2.0 * G_PI * o->phi); break; } coordsx = x + shift * sin (angle_rad); coordsy = y + shift * cos (angle_rad); gegl_sampler_get (sampler, coordsx, coordsy, NULL, out_pixel); out_pixel += 4; /* update x and y coordinates */ x++; if (x>=result->x + result->width) { x=result->x; y++; } } gegl_buffer_set (output, result, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_slice_free1 (result->width * result->height * 4 * sizeof(gfloat), dst_buf); g_object_unref (sampler); return TRUE; }
static gboolean gegl_affine_process (GeglOperation *operation, GeglOperationContext *context, const gchar *output_prop, const GeglRectangle *result) { GeglBuffer *input; GeglBuffer *output; GeglMatrix3 matrix; OpAffine *affine = (OpAffine *) operation; gegl_affine_create_composite_matrix (affine, &matrix); if (gegl_affine_is_intermediate_node (affine) || gegl_matrix3_is_identity (&matrix)) { /* passing straight through (like gegl:nop) */ input = gegl_operation_context_get_source (context, "input"); if (!input) { g_warning ("transform received NULL input"); return FALSE; } gegl_operation_context_take_object (context, "output", G_OBJECT (input)); } else if (gegl_affine_matrix3_allow_fast_translate (&matrix) || (gegl_matrix3_is_translate (&matrix) && ! strcmp (affine->filter, "nearest"))) { /* doing a buffer shifting trick, (enhanced nop) */ input = gegl_operation_context_get_source (context, "input"); output = g_object_new (GEGL_TYPE_BUFFER, "source", input, "shift-x", (int)-matrix.coeff[0][2], "shift-y", (int)-matrix.coeff[1][2], "abyss-width", -1, /* turn of abyss (relying on abyss of source) */ NULL); if (gegl_object_get_has_forked (input)) gegl_object_set_has_forked (output); gegl_operation_context_take_object (context, "output", G_OBJECT (output)); if (input != NULL) g_object_unref (input); } else if (gegl_affine_matrix3_allow_fast_reflect_x (&matrix)) { GeglRectangle src_rect; GeglSampler *sampler; GeglRectangle context_rect; input = gegl_operation_context_get_source (context, "input"); if (!input) { g_warning ("transform received NULL input"); return FALSE; } output = gegl_operation_context_get_target (context, "output"); src_rect = gegl_operation_get_required_for_output (operation, "output", result); src_rect.y += 1; sampler = gegl_buffer_sampler_new (input, babl_format("RaGaBaA float"), gegl_sampler_type_from_string (affine->filter)); context_rect = *gegl_sampler_get_context_rect (sampler); src_rect.width -= context_rect.width; src_rect.height -= context_rect.height; gegl_affine_fast_reflect_x (output, input, result, &src_rect); g_object_unref (sampler); if (input != NULL) g_object_unref (input); } else if (gegl_affine_matrix3_allow_fast_reflect_y (&matrix)) { GeglRectangle src_rect; GeglSampler *sampler; GeglRectangle context_rect; input = gegl_operation_context_get_source (context, "input"); if (!input) { g_warning ("transform received NULL input"); return FALSE; } output = gegl_operation_context_get_target (context, "output"); src_rect = gegl_operation_get_required_for_output (operation, "output", result); src_rect.x += 1; sampler = gegl_buffer_sampler_new (input, babl_format("RaGaBaA float"), gegl_sampler_type_from_string (affine->filter)); context_rect = *gegl_sampler_get_context_rect (sampler); src_rect.width -= context_rect.width; src_rect.height -= context_rect.height; gegl_affine_fast_reflect_y (output, input, result, &src_rect); g_object_unref (sampler); if (input != NULL) g_object_unref (input); } else { /* for all other cases, do a proper resampling */ GeglSampler *sampler; input = gegl_operation_context_get_source (context, "input"); output = gegl_operation_context_get_target (context, "output"); sampler = gegl_buffer_sampler_new (input, babl_format("RaGaBaA float"), gegl_sampler_type_from_string (affine->filter)); affine_generic (output, input, &matrix, sampler); g_object_unref (sampler); if (input != NULL) g_object_unref (input); } return TRUE; }
static GeglRectangle gegl_affine_get_invalidated_by_change (GeglOperation *op, const gchar *input_pad, const GeglRectangle *input_region) { OpAffine *affine = OP_AFFINE (op); GeglMatrix3 matrix; GeglRectangle affected_rect; GeglRectangle context_rect; GeglSampler *sampler; gdouble affected_points [8]; gint i; GeglRectangle region = *input_region; sampler = gegl_buffer_sampler_new (NULL, babl_format("RaGaBaA float"), gegl_sampler_type_from_string (affine->filter)); context_rect = *gegl_sampler_get_context_rect (sampler); g_object_unref (sampler); gegl_affine_create_matrix (affine, &matrix); if (affine->origin_x || affine->origin_y) gegl_matrix3_originate (&matrix, affine->origin_x, affine->origin_y); if (gegl_affine_is_composite_node (affine)) { GeglMatrix3 source; gegl_affine_get_source_matrix (affine, &source); gegl_matrix3_multiply (&source, &matrix, &matrix); } if (gegl_affine_is_intermediate_node (affine) || gegl_matrix3_is_identity (&matrix)) { return region; } region.x += context_rect.x; region.y += context_rect.y; region.width += context_rect.width; region.height += context_rect.height; affected_points [0] = region.x; affected_points [1] = region.y; affected_points [2] = region.x + region.width ; affected_points [3] = region.y; affected_points [4] = region.x + region.width ; affected_points [5] = region.y + region.height ; affected_points [6] = region.x; affected_points [7] = region.y + region.height ; for (i = 0; i < 8; i += 2) gegl_matrix3_transform_point (&matrix, affected_points + i, affected_points + i + 1); gegl_affine_bounding_box (affected_points, 4, &affected_rect); return affected_rect; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gint x = result->x; /* initial x */ gint y = result->y; /* and y coordinates */ gfloat *dst_buf = g_slice_alloc (result->width * result->height * 4 * sizeof (gfloat)); gfloat *out_pixel = dst_buf; GeglSampler *sampler = gegl_buffer_sampler_new (input, babl_format ("RGBA float"), o->sampler_type); gint n_pixels = result->width * result->height; GeglAbyssPolicy abyss = o->clamp ? GEGL_ABYSS_CLAMP : GEGL_ABYSS_NONE; gdouble scalex; gdouble scaley; if (o->aspect > 1.0) { scalex = 1.0; scaley = o->aspect; } else if (o->aspect < 1.0) { scalex = 1.0 / o->aspect; scaley = 1.0; } else { scalex = 1.0; scaley = 1.0; } while (n_pixels--) { gdouble radius; gdouble shift; gdouble dx; gdouble dy; gdouble ux; gdouble uy; dx = (x - o->x) * scalex; dy = (y - o->y) * scaley; radius = sqrt (dx * dx + dy * dy); shift = o->amplitude * sin (2.0 * G_PI * radius / o->period + 2.0 * G_PI * o->phi); ux = dx / radius; uy = dy / radius; gegl_sampler_get (sampler, x + (shift + ux) / scalex, y + (shift + uy) / scaley, NULL, out_pixel, abyss); out_pixel += 4; /* update x and y coordinates */ x++; if (x >= result->x + result->width) { x = result->x; y++; } } gegl_buffer_set (output, result, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_slice_free1 (result->width * result->height * 4 * sizeof (gfloat), dst_buf); g_object_unref (sampler); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gint x = result->x; /* initial x */ gint y = result->y; /* and y coordinates */ gfloat *dst_buf = g_slice_alloc (result->width * result->height * 4 * sizeof(gfloat)); gfloat *out_pixel = dst_buf; GeglSampler *sampler = gegl_buffer_sampler_new (input, babl_format ("RGBA float"), o->sampler_type); gint n_pixels = result->width * result->height; while (n_pixels--) { gdouble coordsx = 0.0; gdouble coordsy = 0.0; gdouble radius = 0.0; gdouble shift = 0.0; gdouble ux = 0.0; /* unit vector of the radius */ gdouble uy = 0.0; gdouble vx = 0.0; /* orthogonal vector of u */ gdouble vy = 0.0; gdouble dx = 0.0; gdouble dy = 0.0; dx = (gdouble)x-o->x; dy = (gdouble)y-o->y; radius = sqrt( dx * dx + dy * dy ); shift = o->amplitude * sin(2.0 * G_PI * radius / o->period + 2.0 * G_PI * o->phi); ux = dx / radius; uy = dy / radius; vx = -uy; vy = ux; coordsx = x + shift * vx; coordsy = y + shift * vy; gegl_sampler_get (sampler, coordsx, coordsy, NULL, out_pixel); out_pixel += 4; /* update x and y coordinates */ x++; if (x>=result->x + result->width) { x=result->x; y++; } } gegl_buffer_set (output, result, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_slice_free1 (result->width * result->height * 4 * sizeof(gfloat), dst_buf); g_object_unref (sampler); return TRUE; }