static void prepare (GeglOperation *operation) { GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle *whole_region; gdouble angle = o->angle * G_PI / 180.0; while (angle < 0.0) angle += 2 * G_PI; whole_region = gegl_operation_source_get_bounding_box (operation, "input"); if (whole_region != NULL) { gdouble center_x = gegl_coordinate_relative_to_pixel (o->center_x, whole_region->width); gdouble center_y = gegl_coordinate_relative_to_pixel (o->center_y, whole_region->height); gdouble maxr_x = MAX (fabs (center_x - whole_region->x), fabs (center_x - whole_region->x - whole_region->width)); gdouble maxr_y = MAX (fabs (center_y - whole_region->y), fabs (center_y - whole_region->y - whole_region->height)); if (angle >= G_PI) angle = G_PI; op_area->left = op_area->right = ceil (maxr_y * sin (angle / 2.0)) + 1; op_area->top = op_area->bottom = ceil (maxr_x * sin (angle / 2.0)) + 1; } else { op_area->left = op_area->right = op_area->top = op_area->bottom = 0; } gegl_operation_set_format (operation, "input", babl_format ("RaGaBaA float")); gegl_operation_set_format (operation, "output", babl_format ("RaGaBaA float")); }
static void prepare (GeglOperation *operation) { GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle *whole_region; whole_region = gegl_operation_source_get_bounding_box (operation, "input"); if (whole_region != NULL) { gdouble center_x, center_y; center_x = gegl_coordinate_relative_to_pixel ( o->center_x, whole_region->width); center_y = gegl_coordinate_relative_to_pixel ( o->center_y, whole_region->height); op_area->left = op_area->right = MAX (fabs (whole_region->x - center_x), fabs (whole_region->width + whole_region->x - center_x)) * fabs (o->factor) +1; op_area->top = op_area->bottom = MAX (fabs (whole_region->y - center_y), fabs (whole_region->height + whole_region->y - center_y)) * fabs (o->factor) +1; } else { op_area->left = op_area->right = op_area->top = op_area->bottom = 0; } gegl_operation_set_format (operation, "input", babl_format ("RaGaBaA float")); gegl_operation_set_format (operation, "output", babl_format ("RaGaBaA float")); }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); gfloat *in_buf, *out_buf, *out_pixel; gint x, y; GeglRectangle src_rect; GeglRectangle *whole_region; gdouble center_x, center_y; whole_region = gegl_operation_source_get_bounding_box (operation, "input"); center_x = gegl_coordinate_relative_to_pixel ( o->center_x, whole_region->width); center_y = gegl_coordinate_relative_to_pixel ( o->center_y, whole_region->height); src_rect = *roi; src_rect.x -= op_area->left; src_rect.y -= op_area->top; src_rect.width += op_area->left + op_area->right; src_rect.height += op_area->top + op_area->bottom; in_buf = g_new (gfloat, src_rect.width * src_rect.height * 4); out_buf = g_new0 (gfloat, roi->width * roi->height * 4); out_pixel = out_buf; gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RaGaBaA float"), in_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); for (y = roi->y; y < roi->height + roi->y; ++y) { for (x = roi->x; x < roi->width + roi->x; ++x) { gint c, i; gfloat dxx, dyy, ix, iy, inv_xy_len; gfloat sum[] = {0, 0, 0, 0}; gfloat x_start = x; gfloat y_start = y; gfloat x_end = x + (center_x - (gfloat) x) * o->factor; gfloat y_end = y + (center_y - (gfloat) y) * o->factor; gint dist = ceil (sqrt (SQR (x_end - x_start) + SQR (y_end - y_start)) +1); /* ensure quality when near the center or with small factor */ gint xy_len = MAX (dist, 3); /* performance concern */ if (xy_len > NOMINAL_NUM_IT) xy_len = MIN (NOMINAL_NUM_IT + (gint) sqrt (xy_len - NOMINAL_NUM_IT), MAX_NUM_IT); inv_xy_len = 1.0 / (gfloat) xy_len; dxx = (x_end - x_start) * inv_xy_len; dyy = (y_end - y_start) * inv_xy_len; ix = x_start; iy = y_start; for (i = 0; i < xy_len; i++) { gfloat dx = ix - floor (ix); gfloat dy = iy - floor (iy); /* do bilinear interpolation to get a nice smooth result */ gfloat *pix0, *pix1, *pix2, *pix3; gfloat mixy0[4]; gfloat mixy1[4]; pix0 = get_pixel_color (in_buf, &src_rect, ix, iy); pix1 = get_pixel_color (in_buf, &src_rect, ix+1, iy); pix2 = get_pixel_color (in_buf, &src_rect, ix, iy+1); pix3 = get_pixel_color (in_buf, &src_rect, ix+1, iy+1); for (c = 0; c < 4; ++c) { mixy0[c] = dy * (pix2[c] - pix0[c]) + pix0[c]; mixy1[c] = dy * (pix3[c] - pix1[c]) + pix1[c]; sum[c] += dx * (mixy1[c] - mixy0[c]) + mixy0[c]; } ix += dxx; iy += dyy; } for (c = 0; c < 4; ++c) *out_pixel++ = sum[c] * inv_xy_len; } } gegl_buffer_set (output, roi, 0, babl_format ("RaGaBaA float"), out_buf, GEGL_AUTO_ROWSTRIDE); g_free (in_buf); g_free (out_buf); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglSampler *sampler = gegl_buffer_sampler_new_at_level (input, babl_format ("RGBA float"), o->sampler_type, level); GeglRectangle *in_extent = gegl_operation_source_get_bounding_box (operation, "input"); GeglBufferIterator *iter; GeglAbyssPolicy abyss = o->clamp ? GEGL_ABYSS_CLAMP : GEGL_ABYSS_NONE; gdouble px_x = gegl_coordinate_relative_to_pixel (o->x, in_extent->width); gdouble px_y = gegl_coordinate_relative_to_pixel (o->y, in_extent->height); 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; } iter = gegl_buffer_iterator_new (output, result, 0, babl_format ("RGBA float"), GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { gint x = result->x; gint y = result->y; gfloat *out_pixel = iter->data[0]; for (y = iter->roi[0].y; y < iter->roi[0].y + iter->roi[0].height; ++y) for (x = iter->roi[0].x; x < iter->roi[0].x + iter->roi[0].width; ++x) { gdouble radius; gdouble shift; gdouble dx; gdouble dy; gdouble ux; gdouble uy; dx = (x - px_x) * scalex; dy = (y - px_y) * scaley; if (!dx && !dy) radius = 0.000001; else 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; } } g_object_unref (sampler); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); gfloat *in_buf, *out_buf, *out_pixel; gint x, y; GeglRectangle src_rect; GeglRectangle *whole_region; gdouble angle; gdouble center_x, center_y; whole_region = gegl_operation_source_get_bounding_box (operation, "input"); center_x = gegl_coordinate_relative_to_pixel ( o->center_x, whole_region->width); center_y = gegl_coordinate_relative_to_pixel ( o->center_y, whole_region->height); src_rect = *roi; src_rect.x -= op_area->left; src_rect.y -= op_area->top; src_rect.width += op_area->left + op_area->right; src_rect.height += op_area->top + op_area->bottom; in_buf = g_new (gfloat, src_rect.width * src_rect.height * 4); out_buf = g_new0 (gfloat, roi->width * roi->height * 4); out_pixel = out_buf; gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RaGaBaA float"), in_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); angle = o->angle * G_PI / 180.0; while (angle < 0.0) angle += 2 * G_PI; for (y = roi->y; y < roi->height + roi->y; ++y) { for (x = roi->x; x < roi->width + roi->x; ++x) { gint c, i; gdouble phi_base, phi_start, phi_step; gfloat sum[] = {0, 0, 0, 0}; gint count = 0; gdouble xr = x - center_x; gdouble yr = y - center_y; gdouble radius = sqrt (SQR (xr) + SQR (yr)); /* This is not the "real" length, a bit shorter */ gdouble arc_length = radius * angle * SQRT_2; /* ensure quality with small angles */ gint n = MAX (ceil (arc_length), 3); /* performance concern */ if (n > NOMINAL_NUM_IT) n = NOMINAL_NUM_IT + (gint) sqrt (n - NOMINAL_NUM_IT); phi_base = compute_phi (xr, yr); phi_start = phi_base + angle / 2.0; phi_step = angle / (gdouble) n; /* Iterate other the arc */ for (i = 0; i < n; i++) { gfloat s_val = sin (phi_start - i * phi_step); gfloat c_val = cos (phi_start - i * phi_step); gfloat ix = center_x + radius * c_val; gfloat iy = center_y + radius * s_val; if (ix >= whole_region->x && ix < whole_region->x + whole_region->width && iy >= whole_region->y && iy < whole_region->y + whole_region->height) { /* do bilinear interpolation to get a nice smooth result */ gfloat dx = ix - floor (ix); gfloat dy = iy - floor (iy); gfloat *pix0, *pix1, *pix2, *pix3; gfloat mixy0[4]; gfloat mixy1[4]; pix0 = get_pixel_color (in_buf, &src_rect, ix, iy); pix1 = get_pixel_color (in_buf, &src_rect, ix+1, iy); pix2 = get_pixel_color (in_buf, &src_rect, ix, iy+1); pix3 = get_pixel_color (in_buf, &src_rect, ix+1, iy+1); for (c = 0; c < 4; ++c) { mixy0[c] = dy * (pix2[c] - pix0[c]) + pix0[c]; mixy1[c] = dy * (pix3[c] - pix1[c]) + pix1[c]; sum[c] += dx * (mixy1[c] - mixy0[c]) + mixy0[c]; } count++; } } if (count == 0) { gfloat *pix = get_pixel_color (in_buf, &src_rect, x, y); for (c = 0; c < 4; ++c) *out_pixel++ = pix[c]; } else { for (c = 0; c < 4; ++c) *out_pixel++ = sum[c] / (gfloat) count; } } } gegl_buffer_set (output, roi, 0, babl_format ("RaGaBaA float"), out_buf, GEGL_AUTO_ROWSTRIDE); g_free (in_buf); g_free (out_buf); return TRUE; }