static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err; gint j; cl_int cl_err; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE, GEGL_ABYSS_NONE); gint read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_NONE); gint aux = gegl_buffer_cl_iterator_add_2 (i, NULL, result, in_format, GEGL_CL_BUFFER_AUX, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err)) { if (err) return FALSE; for (j=0; j < i->n; j++) { cl_err = cl_edge_laplace(i->tex[read][j], i->tex[aux][j], i->tex[0][j], &i->roi[read][j], &i->roi[0][j], LAPLACE_RADIUS); if (cl_err != CL_SUCCESS) { g_warning("[OpenCL] Error in gegl:edge-laplace: %s", gegl_cl_errstring(cl_err)); return FALSE; } } } return TRUE; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err; gint j; cl_int cl_err; GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE, GEGL_ABYSS_NONE); gint read = gegl_buffer_cl_iterator_add (i, input, result, in_format, GEGL_CL_BUFFER_READ, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err)) { if (err) return FALSE; for (j=0; j < i->n; j++) { cl_err = cl_mono_mixer(i->tex[read][j], i->tex[0][j], i->size[0][j], &i->roi[0][j], o->red ,o->green , o->blue); if (cl_err != CL_SUCCESS) { g_warning("[OpenCL] Error in gegl:mono-mixer: %s", gegl_cl_errstring(cl_err)); return FALSE; } } } return TRUE; }
static gboolean gegl_operation_point_filter_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); GeglOperationPointFilterClass *point_filter_class; point_filter_class = GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation); if ((result->width > 0) && (result->height > 0)) { { GeglBufferIterator *i = gegl_buffer_iterator_new (output, result, out_format, GEGL_BUFFER_WRITE); gint read = /*output == input ? 0 :*/ gegl_buffer_iterator_add (i, input, result, in_format, GEGL_BUFFER_READ); /* using separate read and write iterators for in-place ideally a single * readwrite indice would be sufficient */ while (gegl_buffer_iterator_next (i)) point_filter_class->process (operation, i->data[read], i->data[0], i->length, &i->roi[0]); } } return TRUE; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err; gint j; cl_int cl_err; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE, GEGL_ABYSS_NONE); gint read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err)) { if (err) return FALSE; for (j=0; j < i->n; j++) { cl_err = cl_bilateral_filter(i->tex[read][j], i->tex[0][j], i->size[0][j], &i->roi[0][j], ceil(o->blur_radius), o->edge_preservation); if (cl_err != CL_SUCCESS) { g_warning("[OpenCL] Error in gegl:bilateral-filter: %s", gegl_cl_errstring(cl_err)); return FALSE; } } } return TRUE; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); gint read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_NONE); gint aux = gegl_buffer_cl_iterator_add_2 (i, NULL, result, in_format, GEGL_CL_BUFFER_AUX, 0, 0, op_area->top, op_area->bottom, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err)) { if (err) return FALSE; err = cl_box_max(i->tex[read], i->tex[aux], i->tex[0], i->size[0], &i->roi[0], ceil (o->radius)); if (err) return FALSE; } return TRUE; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err = 0; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglProperties *o = GEGL_PROPERTIES (operation); GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); gint read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_CLAMP); gint aux = gegl_buffer_cl_iterator_add_aux (i, result, in_format, 0, 0, op_area->top, op_area->bottom); while (gegl_buffer_cl_iterator_next (i, &err) && !err) { err = cl_box_blur (i->tex[read], i->tex[aux], i->tex[0], i->size[0], &i->roi[0], o->radius); if (err) { gegl_buffer_cl_iterator_stop (i); break; } } return !err; }
static void prepare_cl (GeglOperation *operation) { GeglOperationAreaFilter* op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglChantO* o = GEGL_CHANT_PROPERTIES (operation); gdouble theta = o->angle * G_PI / 180.0; gdouble offset_x = fabs(o->length * cos(theta)); gdouble offset_y = fabs(o->length * sin(theta)); op_area->left = op_area->right = (gint)ceil(0.5 * offset_x); op_area->top = op_area->bottom = (gint)ceil(0.5 * offset_y); GeglNode * self; GeglPad *pad; Babl * format=babl_format ("RaGaBaA float"); self=gegl_operation_get_source_node(operation,"input"); while(self) { if(strcmp(gegl_node_get_operation(self),"gimp:tilemanager-source")==0) { format=gegl_operation_get_format(self->operation,"output"); break; } self=gegl_operation_get_source_node(self->operation,"input"); } gegl_operation_set_format (operation, "output", format); }
static gboolean process (GeglOperation *operation, void *in_buf, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "input"); memcpy (out_buf, in_buf, n_pixels * babl_format_get_bytes_per_pixel (format)); if (o->cache != (void *) operation->node->cache) { if (o->cache) { g_object_unref (o->cache); o->cache = NULL; } if (operation->node->cache) o->cache = g_object_ref (operation->node->cache); } return TRUE; }
static gboolean gimp_operation_tile_source_process (GeglOperation *operation, GeglBuffer *output, const GeglRectangle *result) { GimpOperationTileSource *self = GIMP_OPERATION_TILE_SOURCE (operation); const Babl *format; PixelRegion srcPR; gpointer pr; if (! self->tile_manager) return FALSE; format = gegl_operation_get_format (operation, "output"); pixel_region_init (&srcPR, self->tile_manager, result->x, result->y, result->width, result->height, FALSE); for (pr = pixel_regions_register (1, &srcPR); pr; pr = pixel_regions_process (pr)) { GeglRectangle rect = { srcPR.x, srcPR.y, srcPR.w, srcPR.h }; gegl_buffer_set (output, &rect, 1, format, srcPR.data, srcPR.rowstride); } return TRUE; }
static gboolean bilateral_cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint s_sigma, gfloat r_sigma) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err = 0; GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); gint read = gegl_buffer_cl_iterator_add (i, input, result, in_format, GEGL_CL_BUFFER_READ, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err) && !err) { err = cl_bilateral (i->tex[read], i->tex[0], &i->roi[0], &i->roi[read], s_sigma, r_sigma); if (err) { gegl_buffer_cl_iterator_stop (i); break; } } return !err; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, const GeglRectangle *src_rect) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint err; gint j; cl_int cl_err; GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); gdouble theta = o->angle * G_PI / 180.0; gfloat offset_x = (gfloat)(o->length * cos(theta)); gfloat offset_y = (gfloat)(o->length * sin(theta)); gint num_steps = (gint)ceil(o->length) + 1; GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE, GEGL_ABYSS_NONE); gint read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ, op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err)) { if (err) return FALSE; for (j=0; j < i->n; j++) { cl_err = cl_motion_blur(i->tex[read][j], i->tex[0][j], i->size[0][j], &i->roi[0][j], &i->roi[read][j], num_steps, offset_x, offset_y); if (cl_err != CL_SUCCESS) { g_warning("[OpenCL] Error in gegl:motion-blur: %s", gegl_cl_errstring(cl_err)); return FALSE; } } } return TRUE; }
static gboolean gegl_gblur_1d_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "output"); GeglGblur1dFilter filter; GeglAbyssPolicy abyss_policy = to_gegl_policy (o->abyss_policy); filter = filter_disambiguation (o->filter, o->std_dev); if (filter == GEGL_GBLUR_1D_IIR) { gdouble b[4], m[3][3]; iir_young_find_constants (o->std_dev, b, m); if (o->orientation == GEGL_ORIENTATION_HORIZONTAL) iir_young_hor_blur (input, result, output, b, m, abyss_policy, format); else iir_young_ver_blur (input, result, output, b, m, abyss_policy, format); } else { gfloat *cmatrix; gint clen; clen = fir_gen_convolve_matrix (o->std_dev, &cmatrix); /* FIXME: implement others format cases */ if (gegl_operation_use_opencl (operation) && format == babl_format ("RaGaBaA float")) if (fir_cl_process(input, output, result, format, cmatrix, clen, o->orientation, abyss_policy)) return TRUE; if (o->orientation == GEGL_ORIENTATION_HORIZONTAL) fir_hor_blur (input, result, output, cmatrix, clen, abyss_policy, format); else fir_ver_blur (input, result, output, cmatrix, clen, abyss_policy, format); gegl_free (cmatrix); } return TRUE; }
gboolean gegl_can_do_inplace_processing (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result) { if (!input) return FALSE; if (gegl_object_get_has_forked (G_OBJECT (input))) return FALSE; if (gegl_buffer_get_format (input) == gegl_operation_get_format (operation, "output") && gegl_rectangle_contains (gegl_buffer_get_extent (input), result)) return TRUE; return FALSE; }
static gboolean checkerboard_cl_process (GeglOperation *operation, cl_mem out_tex, size_t global_worksize, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *out_format = gegl_operation_get_format (operation, "output"); const size_t gbl_size[2] = {roi->width, roi->height}; const size_t gbl_offs[2] = {roi->x, roi->y}; cl_int cl_err = 0; float color1[4]; float color2[4]; if (!cl_data) { const char *kernel_name[] = {"kernel_checkerboard", NULL}; cl_data = gegl_cl_compile_and_build (checkerboard_cl_source, kernel_name); if (!cl_data) return TRUE; } gegl_color_get_pixel (o->color1, out_format, color1); gegl_color_get_pixel (o->color2, out_format, color2); cl_err = gegl_cl_set_kernel_args (cl_data->kernel[0], sizeof(cl_mem), &out_tex, sizeof(color1), &color1, sizeof(color2), &color2, sizeof(cl_int), &o->x, sizeof(cl_int), &o->y, sizeof(cl_int), &o->x_offset, sizeof(cl_int), &o->y_offset, NULL); CL_CHECK; cl_err = gegl_clEnqueueNDRangeKernel (gegl_cl_get_command_queue (), cl_data->kernel[0], 2, gbl_offs, gbl_size, NULL, 0, NULL, NULL); CL_CHECK; return FALSE; error: return TRUE; }
static gboolean operation_source_process (GeglOperation *operation, GeglBuffer *output, const GeglRectangle *result, gint level) { const Babl *out_format = gegl_operation_get_format (operation, "output"); if ((result->width > 0) && (result->height > 0)) { GeglBufferIterator *iter; if (gegl_operation_use_opencl (operation) && babl_format_get_n_components (out_format) == 4 && babl_format_get_type (out_format, 0) == babl_type ("float")) { GeglBufferClIterator *cl_iter; gboolean err; GEGL_NOTE (GEGL_DEBUG_OPENCL, "GEGL_OPERATION_POINT_RENDER: %s", GEGL_OPERATION_GET_CLASS (operation)->name); cl_iter = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); while (gegl_buffer_cl_iterator_next (cl_iter, &err) && !err) { err = checkerboard_cl_process (operation, cl_iter->tex[0], cl_iter->size[0], &cl_iter->roi[0], level); if (err) { gegl_buffer_cl_iterator_stop (cl_iter); break; } } if (err) GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", GEGL_OPERATION_GET_CLASS (operation)->name); else return TRUE; } iter = gegl_buffer_iterator_new (output, result, level, out_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) checkerboard_process (operation, iter->data[0], iter->length, &iter->roi[0], level); } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *out_buf, const GeglRectangle *roi, gint level) { GeglBufferIterator *iter; const Babl *out_format = gegl_operation_get_format (operation, "output"); if (gegl_operation_use_opencl (operation)) { GeglBufferClIterator *cl_iter; gboolean err; GEGL_NOTE (GEGL_DEBUG_OPENCL, "GEGL_OPERATION_POINT_RENDER: %s", GEGL_OPERATION_GET_CLASS (operation)->name); cl_iter = gegl_buffer_cl_iterator_new (out_buf, roi, out_format, GEGL_CL_BUFFER_WRITE); while (gegl_buffer_cl_iterator_next (cl_iter, &err) && !err) { err = cl_process (operation, cl_iter->tex[0], cl_iter->roi); if (err) { gegl_buffer_cl_iterator_stop (cl_iter); break; } } if (err) GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", GEGL_OPERATION_GET_CLASS (operation)->name); else return TRUE; } iter = gegl_buffer_iterator_new (out_buf, roi, level, out_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) c_process (operation, iter->data[0], &iter->roi[0]); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "output"); gint radius = ceil (o->radius); if (o->orientation == GEGL_ORIENTATION_HORIZONTAL) wav_hor_blur (input, output, result, radius, format); else wav_ver_blur (input, output, result, radius, format); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); GeglRectangle compute; gboolean has_alpha; compute = gegl_operation_get_required_for_output (operation, "input", result); has_alpha = babl_format_has_alpha (gegl_operation_get_format (operation, "output")); if (gegl_operation_use_opencl (operation)) if (cl_process (operation, input, output, result, has_alpha)) return TRUE; edge_sobel (input, &compute, output, result, o->horizontal, o->vertical, o->keep_signal, has_alpha); return TRUE; }
static gboolean checkerboard_process (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint pixel_size = babl_format_get_bytes_per_pixel (out_format); guchar *out_pixel = out_buf; void *color1 = alloca(pixel_size); void *color2 = alloca(pixel_size); gint y; const gint x_min = roi->x - o->x_offset; const gint y_min = roi->y - o->y_offset; const gint x_max = roi->x + roi->width - o->x_offset; const gint y_max = roi->y + roi->height - o->y_offset; const gint square_width = o->x; const gint square_height = o->y; if (level) return checkerboard_process_simple (operation, out_buf, n_pixels, roi, level); gegl_color_get_pixel (o->color1, out_format, color1); gegl_color_get_pixel (o->color2, out_format, color2); for (y = y_min; y < y_max; y++) { gint x = x_min; void *cur_color; /* Figure out which box we're in */ gint tilex = TILE_INDEX (x, square_width); gint tiley = TILE_INDEX (y, square_height); if ((tilex + tiley) % 2 == 0) cur_color = color1; else cur_color = color2; while (x < x_max) { /* Figure out how long this stripe is */ gint count; gint stripe_end = (TILE_INDEX (x, square_width) + 1) * square_width; stripe_end = stripe_end > x_max ? x_max : stripe_end; count = stripe_end - x; gegl_memset_pattern (out_pixel, cur_color, pixel_size, count); out_pixel += count * pixel_size; x = stripe_end; if (cur_color == color1) cur_color = color2; else cur_color = color1; } } return TRUE; }
static gboolean checkerboard_process_simple (GeglOperation *operation, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { gint factor = 1 << level; GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *out_format = gegl_operation_get_format (operation, "output"); gint pixel_size = babl_format_get_bytes_per_pixel (out_format); guchar *out_pixel = out_buf; void *color1 = alloca(pixel_size); void *color2 = alloca(pixel_size); gint x = roi->x; /* initial x */ gint y = roi->y; /* and y coordinates */ gegl_color_get_pixel (o->color1, out_format, color1); gegl_color_get_pixel (o->color2, out_format, color2); while (n_pixels--) { gint nx,ny; if ((x - o->x_offset) < 0) { nx = div (x - o->x_offset + 1, o->x / factor).quot; } else { nx = div (x - o->x_offset, o->x / factor).quot; } if ((y - o->y_offset) < 0) { ny = div (y - o->y_offset + 1, o->y / factor).quot; } else { ny = div (y - o->y_offset, o->y / factor).quot; } /* shift negative cell indices */ nx -= (x - o->x_offset) < 0 ? 1 : 0; ny -= (y - o->y_offset) < 0 ? 1 : 0; if ( (nx+ny) % 2 == 0) memcpy (out_pixel, color1, pixel_size); else memcpy (out_pixel, color2, pixel_size); out_pixel += pixel_size; /* update x and y coordinates */ x++; if (x>=roi->x + roi->width) { x=roi->x; y++; } } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "output"); gint components = babl_format_get_n_components (format); gboolean has_alpha = babl_format_has_alpha (format); gfloat *src_buff; gfloat *dst_buff; GeglRectangle rect; gint x, y, ix, iy, b, idx; rect = gegl_operation_get_required_for_output (operation, "input", roi); src_buff = g_new (gfloat, rect.width * rect.height * components); dst_buff = g_new0 (gfloat, roi->width * roi->height * components); gegl_buffer_get (input, &rect, 1.0, format, src_buff, GEGL_AUTO_ROWSTRIDE, o->border_behavior); for (y = 0; y < roi->height; y++) { iy = y + 1; for (x = 0; x < roi->width; x++) { ix = x + 1; for (b = 0; b < 3; b++) { #define SRCPIX(X,Y,B) src_buff[((X) + (Y) * rect.width) * components + B] gfloat window[9]; window[0] = SRCPIX(ix - 1, iy - 1, b); window[1] = SRCPIX(ix, iy - 1, b); window[2] = SRCPIX(ix + 1, iy - 1, b); window[3] = SRCPIX(ix - 1, iy, b); window[4] = SRCPIX(ix, iy, b); window[5] = SRCPIX(ix + 1, iy, b); window[6] = SRCPIX(ix - 1, iy + 1, b); window[7] = SRCPIX(ix, iy + 1, b); window[8] = SRCPIX(ix + 1, iy + 1, b); idx = (x + y * roi->width) * components + b; switch (o->algorithm) { default: case GEGL_EDGE_SOBEL: dst_buff[idx] = edge_sobel (window, o->amount); break; case GEGL_EDGE_PREWITT: dst_buff[idx] = edge_prewitt (window, o->amount); break; case GEGL_EDGE_GRADIENT: dst_buff[idx] = edge_gradient (window, o->amount); break; case GEGL_EDGE_ROBERTS: dst_buff[idx] = edge_roberts (window, o->amount); break; case GEGL_EDGE_DIFFERENTIAL: dst_buff[idx] = edge_differential (window, o->amount); break; case GEGL_EDGE_LAPLACE: dst_buff[idx] = edge_laplace (window, o->amount); break; } } if (has_alpha) dst_buff[idx + 1] = SRCPIX(ix, iy, 3); } #undef SRCPIX } gegl_buffer_set (output, roi, level, format, dst_buff, GEGL_AUTO_ROWSTRIDE); g_free (src_buff); g_free (dst_buff); return TRUE; }
GeglBuffer * gegl_operation_context_get_target (GeglOperationContext *context, const gchar *padname) { GeglBuffer *output; const GeglRectangle *result; const Babl *format; GeglNode *node; GeglOperation *operation; #if 0 g_return_val_if_fail (GEGL_IS_OPERATION_CONTEXT (context), NULL); #endif operation = context->operation; node = operation->node; /* <ick */ format = gegl_operation_get_format (operation, padname); if (format == NULL) { g_warning ("no format for %s presuming RGBA float\n", gegl_node_get_debug_name (node)); format = babl_format ("RGBA float"); } g_assert (format != NULL); g_assert (!strcmp (padname, "output")); result = &context->result_rect; if (result->width == 0 || result->height == 0) { output = g_object_ref (emptybuf()); } else if (node->dont_cache == FALSE && ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache) { GeglBuffer *cache; cache = GEGL_BUFFER (gegl_node_get_cache (node)); /* Only use the cache if the result is within the cache * extent. This is certainly not optimal. My gut feeling is that * the current caching mechanism needs to be redesigned */ if (gegl_rectangle_contains (gegl_buffer_get_extent (cache), result)) { output = g_object_ref (cache); } else { output = gegl_buffer_new_ram (result, format); } } else { output = gegl_buffer_new_ram (result, format); } gegl_operation_context_take_object (context, padname, G_OBJECT (output)); return output; }
static gboolean process (GeglOperation *operation, void *in_buf, void *out_buf, glong samples, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "input"); gfloat *in = in_buf; gfloat *out = out_buf; gint component_index; gint n_components; gdouble min = 0.0; gdouble max = 1.0; n_components = babl_format_get_n_components (format); switch (o->component) { case GEGL_COMPONENT_EXTRACT_RGB_RED: case GEGL_COMPONENT_EXTRACT_HUE: case GEGL_COMPONENT_EXTRACT_CMYK_CYAN: case GEGL_COMPONENT_EXTRACT_YCBCR_Y: case GEGL_COMPONENT_EXTRACT_LAB_L: { component_index = 0; if (o->component == GEGL_COMPONENT_EXTRACT_LAB_L) { max = 100.0; } } break; case GEGL_COMPONENT_EXTRACT_RGB_GREEN: case GEGL_COMPONENT_EXTRACT_HSV_SATURATION: case GEGL_COMPONENT_EXTRACT_HSL_SATURATION: case GEGL_COMPONENT_EXTRACT_CMYK_MAGENTA: case GEGL_COMPONENT_EXTRACT_YCBCR_CB: case GEGL_COMPONENT_EXTRACT_LAB_A: case GEGL_COMPONENT_EXTRACT_ALPHA: { component_index = 1; if (o->component == GEGL_COMPONENT_EXTRACT_YCBCR_CB) { min = -0.5; max = 0.5; } else if (o->component == GEGL_COMPONENT_EXTRACT_LAB_A) { min = -128.0; max = 127; } } break; case GEGL_COMPONENT_EXTRACT_RGB_BLUE: case GEGL_COMPONENT_EXTRACT_HSV_VALUE: case GEGL_COMPONENT_EXTRACT_HSL_LIGHTNESS: case GEGL_COMPONENT_EXTRACT_CMYK_YELLOW: case GEGL_COMPONENT_EXTRACT_YCBCR_CR: case GEGL_COMPONENT_EXTRACT_LAB_B: { component_index = 2; if (o->component == GEGL_COMPONENT_EXTRACT_YCBCR_CR) { min = -0.5; max = 0.5; } else if (o->component == GEGL_COMPONENT_EXTRACT_LAB_B) { min = -128.0; max = 127; } } break; case GEGL_COMPONENT_EXTRACT_CMYK_KEY: { component_index = 3; } break; } while (samples--) { gdouble value = in[component_index]; if (min != 0.0 || max != 1.0) { gdouble scale = 1.0 / (max - min); gdouble offset = -min; value = CLAMP ((value + offset) * scale, 0.0, 1.0); } if (o->invert) out[0] = 1.0 - value; else out[0] = value; in += n_components; out += 1; } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { gint components; gint col, c; gfloat *rowbefore; gfloat *rowthis; gfloat *rowafter; gfloat *dest; gfloat *ninepix; gboolean has_alpha; guint alpha; const Babl *format = gegl_operation_get_format (operation, "input"); /* The rectangle of the current row we are working on */ GeglRectangle rowrect; /* The rectangle of the sample we are going to take for the * next line (this does include the interpolation distance!) */ GeglRectangle rownext_bufrect; components = babl_format_get_n_components (format); has_alpha = babl_format_has_alpha (format); alpha = components - 1; /* The original algorithm that appeared in GIMP did a manual clamping * of samples outside the input rectangle, by always allocating a * buffer which is 1-pixel wider than necessary, and then filling the * edges of the buffer with repetitions of the edges. * We don't need this complexity here thanks to the CLAMP abyss policy * which is implemented by GEGL. We still allocate buffers which are * larger, but we let GEGL fill the edges with the clamped values. */ rowbefore = g_new (gfloat, (roi->width + 2) * components); rowthis = g_new (gfloat, (roi->width + 2) * components); rowafter = g_new (gfloat, (roi->width + 2) * components); dest = g_new (gfloat, roi->width * components); ninepix = g_new (gfloat, 9 * components); gegl_rectangle_set (&rowrect, roi->x, roi->y, roi->width, 1); gegl_rectangle_set (&rownext_bufrect, roi->x - 1, roi->y - 1, roi->width + 2, 1); gegl_buffer_get (input, &rownext_bufrect, 1.0, format, rowbefore, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); ++rownext_bufrect.y; gegl_buffer_get (input, &rownext_bufrect, 1.0, format, rowthis, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); ++rownext_bufrect.y; gegl_buffer_get (input, &rownext_bufrect, 1.0, format, rowafter, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); ++rownext_bufrect.y; for (rowrect.y = roi->y; rowrect.y < (roi->y + roi->height); ++rowrect.y) { gfloat *tmp; /* this macro returns the current pixel if it has some opacity. Otherwise * it returns the center pixel of the current 3x3 area. */ #define USE_IF_ALPHA(p) (((!has_alpha) || *((p)+alpha)) ? (p) : &rowthis[(col+1) * components]) for (col = 0; col < roi->width; ++col) { /* do 9x extrapolation pass */ if (((!has_alpha) || (rowthis[(col + 1) * components + alpha] > 0)) && extrapolate9 (components, &ninepix[0 * components], &ninepix[1 * components], &ninepix[2 * components], &ninepix[3 * components], &ninepix[4 * components], &ninepix[5 * components], &ninepix[6 * components], &ninepix[7 * components], &ninepix[8 * components], USE_IF_ALPHA (&rowbefore[(col + 0) * components]), USE_IF_ALPHA (&rowbefore[(col + 1) * components]), USE_IF_ALPHA (&rowbefore[(col + 2) * components]), USE_IF_ALPHA (&rowthis [(col + 0) * components]), &rowthis [(col + 1) * components], USE_IF_ALPHA (&rowthis [(col + 2) * components]), USE_IF_ALPHA (&rowafter [(col + 0) * components]), USE_IF_ALPHA (&rowafter [(col + 1) * components]), USE_IF_ALPHA (&rowafter [(col + 2) * components]) )) { /* subsample results and put into dest */ for (c = 0; c < components; ++c) { #define NINEPIX(index, c) ninepix[(index) * components + (c)] dest[(col * components) + c] = (3 * NINEPIX(0, c) + 5 * NINEPIX(1, c) + 3 * NINEPIX(2, c) + 5 * NINEPIX(3, c) + 6 * NINEPIX(4, c) + 5 * NINEPIX(5, c) + 3 * NINEPIX(6, c) + 5 * NINEPIX(7, c) + 3 * NINEPIX(8, c) /* The GIMP implementation added 19 (out of 255) here before * normalizing (dividing by 38), which is equivalent to a * call to "ceil". We don't need this since we are working * with floating point numbers... */ ) / 38; #undef NINEPIX } } else { memcpy (&dest[col * components], &rowthis[(col + 1) * components], components * sizeof(gfloat)); } } #undef USE_IF_ALPHA /* write result row to dest */ gegl_buffer_set (output, &rowrect, 0, format, &dest[0], GEGL_AUTO_ROWSTRIDE); /* rotate pointers */ tmp = rowbefore; rowbefore = rowthis; rowthis = rowafter; rowafter = tmp; /* populate new after-row */ gegl_buffer_get (input, &rownext_bufrect, 1.0, format, rowafter, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); ++rownext_bufrect.y; } g_free (rowbefore); g_free (rowthis); g_free (rowafter); g_free (dest); g_free (ninepix); return TRUE; }
static gboolean cl_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result) { const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *out_format = gegl_operation_get_format (operation, "output"); gfloat min[] = {1.0f, 1.0f, 1.0f, 1.0f}; gfloat max[] = {0.0f, 0.0f, 0.0f, 0.0f}; gfloat i_min[4], i_max[4], diff[4]; cl_int err = 0; gint read, c; GeglBufferClIterator *i; GeglProperties *o; cl_float4 cl_min, cl_diff; o = GEGL_PROPERTIES (operation); if (cl_build_kernels ()) return FALSE; i = gegl_buffer_cl_iterator_new (input, result, in_format, GEGL_CL_BUFFER_READ); while (gegl_buffer_cl_iterator_next (i, &err) && !err) { err = cl_buffer_get_min_max (i->tex[0], i->size[0], &i->roi[0], i_min, i_max); if (err) { gegl_buffer_cl_iterator_stop (i); break; } for (c = 0; c < 3; c++) { if (i_min[c] < min[c]) min[c] = i_min[c]; if (i_max[c] > max[c]) max[c] = i_max[c]; } } if (err) return FALSE; if (o->keep_colors) reduce_min_max_global (min, max); for (c = 0; c < 3; c ++) { diff[c] = max[c] - min[c]; /* Avoid a divide by zero error if the image is a solid color */ if (diff[c] < 1e-3) { min[c] = 0.0; diff[c] = 1.0; } } cl_diff.x = diff[0]; cl_diff.y = diff[1]; cl_diff.z = diff[2]; cl_diff.w = 1.0; cl_min.x = min[0]; cl_min.y = min[1]; cl_min.z = min[2]; cl_min.w = 0.0; i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE); read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ, 0, 0, 0, 0, GEGL_ABYSS_NONE); while (gegl_buffer_cl_iterator_next (i, &err) && !err) { err = cl_stretch_contrast (i->tex[read], i->tex[0], i->size[0], &i->roi[0], cl_min, cl_diff); if (err) { gegl_buffer_cl_iterator_stop (i); break; } } return !err; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "input"); gint n_components = babl_format_get_n_components (format); gboolean has_alpha = babl_format_has_alpha (format); gfloat *src_buf; gfloat *dst_buf; gint n_pixels; GeglRectangle src_rect; Histogram *hist; Direction dir; gint src_x, src_y; gint dst_x, dst_y; gint dst_idx, src_idx; gint xmin, ymin, xmax, ymax; src_rect = gegl_operation_get_required_for_output (operation, "input", roi); n_pixels = roi->width * roi->height; dst_buf = g_new0 (gfloat, n_pixels * n_components); src_buf = g_new0 (gfloat, src_rect.width * src_rect.height * n_components); gegl_buffer_get (input, &src_rect, 1.0, format, src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); hist = g_slice_new0 (Histogram); dst_x = 0; dst_y = 0; src_x = o->radius; src_y = o->radius; /* compute the first window */ hist->xmin = src_x - o->radius; hist->ymin = src_y - o->radius; hist->xmax = src_x + o->radius; hist->ymax = src_y + o->radius; histogram_add_vals (hist, src_buf, &src_rect, n_components, hist->xmin, hist->ymin, hist->xmax, hist->ymax); dst_idx = (dst_x + dst_y * roi->width) * n_components; dst_buf[dst_idx] = histogram_get_median (hist, 0); dst_buf[dst_idx + 1] = histogram_get_median (hist, 1); dst_buf[dst_idx + 2] = histogram_get_median (hist, 2); if (has_alpha) { src_idx = (src_x + src_y * src_rect.width) * n_components; dst_buf[dst_idx + 3] = src_buf[src_idx + 3]; } n_pixels--; dir = LEFT_TO_RIGHT; while (n_pixels--) { /* move the src coords based on current direction and positions */ if (dir == LEFT_TO_RIGHT) { if (dst_x != roi->width - 1) { src_x++; dst_x++; } else { src_y++; dst_y++; dir = TOP_TO_BOTTOM; } } else if (dir == TOP_TO_BOTTOM) { if (dst_x == 0) { src_x++; dst_x++; dir = LEFT_TO_RIGHT; } else { src_x--; dst_x--; dir = RIGHT_TO_LEFT; } } else if (dir == RIGHT_TO_LEFT) { if (dst_x != 0) { src_x--; dst_x--; } else { src_y++; dst_y++; dir = TOP_TO_BOTTOM; } } xmin = src_x - o->radius; ymin = src_y - o->radius; xmax = src_x + o->radius; ymax = src_y + o->radius; histogram_update (hist, src_buf, &src_rect, n_components, xmin, ymin, xmax, ymax, dir); dst_idx = (dst_x + dst_y * roi->width) * n_components; dst_buf[dst_idx] = histogram_get_median (hist, 0); dst_buf[dst_idx + 1] = histogram_get_median (hist, 1); dst_buf[dst_idx + 2] = histogram_get_median (hist, 2); if (has_alpha) { src_idx = (src_x + src_y * src_rect.width) * n_components; dst_buf[dst_idx + 3] = src_buf[src_idx + 3]; } } gegl_buffer_set (output, roi, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); g_slice_free (Histogram, hist); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *src_format = gegl_operation_get_source_format (operation, "input"); const Babl *dst_format = gegl_operation_get_format (operation, "output"); gint src_components = babl_format_get_n_components (src_format); gint dst_components = babl_format_get_n_components (dst_format); gint width, height; gint row_size; gint y; gdouble *top_row = NULL; gdouble *dst_row = NULL; gdouble *src_row = NULL; gdouble *p_top = NULL; gdouble *p_dst = NULL; width = gegl_buffer_get_width (input); height = gegl_buffer_get_height (input); row_size = width + 1; top_row = g_new0 (gdouble, row_size * dst_components); dst_row = g_new0 (gdouble, row_size * dst_components); src_row = g_new (gdouble, row_size * src_components); p_top = top_row; p_dst = dst_row; for (y = 0; y < height; y++) { GeglRectangle row_rect = {-1, y, width + 1, 1}; gegl_buffer_get (input, &row_rect, 1.0, src_format, src_row, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); compute_row_integral (src_row + src_components, p_top + dst_components, p_dst + dst_components, width, src_components, o->squared); gegl_buffer_set (output, &row_rect, 0, dst_format, p_dst, GEGL_AUTO_ROWSTRIDE); p_top = p_dst; if (p_dst == top_row) p_dst = dst_row; else p_dst = top_row; } g_free (top_row); g_free (dst_row); g_free (src_row); return TRUE; }
static gboolean process (GeglOperation *operation, void *in_buf, void *out_buf, glong n_pixels, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "input"); gboolean has_alpha = babl_format_has_alpha (format); gint n_components = has_alpha ? 4 : 3; gfloat *input = in_buf; gfloat *output = out_buf; if (o->clip_low && o->clip_high) { while (n_pixels--) { output[0] = CLAMP (input[0], o->low_limit, o->high_limit); output[1] = CLAMP (input[1], o->low_limit, o->high_limit); output[2] = CLAMP (input[2], o->low_limit, o->high_limit); if (has_alpha) output[3] = input[3]; input += n_components; output += n_components; } } else if (o->clip_high) { while (n_pixels--) { output[0] = input[0] > o->high_limit ? o->high_limit : input[0]; output[1] = input[1] > o->high_limit ? o->high_limit : input[1]; output[2] = input[2] > o->high_limit ? o->high_limit : input[2]; if (has_alpha) output[3] = input[3]; input += n_components; output += n_components; } } else if (o->clip_low) { while (n_pixels--) { output[0] = input[0] < o->low_limit ? o->low_limit : input[0]; output[1] = input[1] < o->low_limit ? o->low_limit : input[1]; output[2] = input[2] < o->low_limit ? o->low_limit : input[2]; if (has_alpha) output[3] = input[3]; input += n_components; output += n_components; } } return TRUE; }
static gboolean gegl_operation_point_composer3_process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *aux, GeglBuffer *aux2, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglOperationPointComposer3Class *point_composer3_class = GEGL_OPERATION_POINT_COMPOSER3_GET_CLASS (operation); const Babl *in_format = gegl_operation_get_format (operation, "input"); const Babl *aux_format = gegl_operation_get_format (operation, "aux"); const Babl *aux2_format = gegl_operation_get_format (operation, "aux2"); const Babl *out_format = gegl_operation_get_format (operation, "output"); if ((result->width > 0) && (result->height > 0)) { GeglBufferIterator *i = gegl_buffer_iterator_new (output, result, level, out_format, GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); gint read = gegl_buffer_iterator_add (i, input, result, level, in_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); if (aux) { gint foo = gegl_buffer_iterator_add (i, aux, result, level, aux_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); if (aux2) { gint bar = gegl_buffer_iterator_add (i, aux2, result, level, aux2_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (i)) { point_composer3_class->process (operation, i->data[read], i->data[foo], i->data[bar], i->data[0], i->length, &(i->roi[0]), level); } } else { while (gegl_buffer_iterator_next (i)) { point_composer3_class->process (operation, i->data[read], i->data[foo], NULL, i->data[0], i->length, &(i->roi[0]), level); } } } else { if (aux2) { gint bar = gegl_buffer_iterator_add (i, aux2, result, level, aux2_format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (i)) { point_composer3_class->process (operation, i->data[read], NULL, i->data[bar], i->data[0], i->length, &(i->roi[0]), level); } } else { while (gegl_buffer_iterator_next (i)) { point_composer3_class->process (operation, i->data[read], NULL, NULL, i->data[0], i->length, &(i->roi[0]), level); } } } return TRUE; } return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); gdouble percentile = o->percentile / 100.0; gdouble alpha_percentile = o->alpha_percentile / 100.0; const gint *neighborhood_outline = o->user_data; const Babl *format = gegl_operation_get_format (operation, "input"); gint n_components = babl_format_get_n_components (format); gboolean has_alpha = babl_format_has_alpha (format); G_STATIC_ASSERT (sizeof (gint32) == sizeof (gfloat)); gint32 *src_buf; gfloat *dst_buf; GeglRectangle src_rect; gint src_stride; gint dst_stride; gint n_pixels; Histogram *hist; const gint32 *src; gfloat *dst; gint dst_x, dst_y; Direction dir; gint i; gint c; src_rect = gegl_operation_get_required_for_output (operation, "input", roi); src_stride = src_rect.width * n_components; dst_stride = roi->width * n_components; n_pixels = roi->width * roi->height; dst_buf = g_new0 (gfloat, n_pixels * n_components); src_buf = g_new0 (gint32, src_rect.width * src_rect.height * n_components); gegl_buffer_get (input, &src_rect, 1.0, format, src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); convert_values_to_bins (src_buf, n_components, has_alpha, src_rect.width * src_rect.height); hist = g_slice_new0 (Histogram); src = src_buf + o->radius * (src_rect.width + 1) * n_components; dst = dst_buf; /* compute the first window */ for (i = -o->radius; i <= o->radius; i++) { histogram_modify_vals (hist, src, n_components, src_stride, has_alpha, i, -neighborhood_outline[abs (i)], i, +neighborhood_outline[abs (i)], +1); hist->size += 2 * neighborhood_outline[abs (i)] + 1; } for (c = 0; c < 3; c++) dst[c] = histogram_get_median (hist, c, percentile); if (has_alpha) dst[3] = histogram_get_median (hist, 3, alpha_percentile); dst_x = 0; dst_y = 0; n_pixels--; dir = LEFT_TO_RIGHT; while (n_pixels--) { /* move the src coords based on current direction and positions */ if (dir == LEFT_TO_RIGHT) { if (dst_x != roi->width - 1) { dst_x++; src += n_components; dst += n_components; } else { dst_y++; src += src_stride; dst += dst_stride; dir = TOP_TO_BOTTOM; } } else if (dir == TOP_TO_BOTTOM) { if (dst_x == 0) { dst_x++; src += n_components; dst += n_components; dir = LEFT_TO_RIGHT; } else { dst_x--; src -= n_components; dst -= n_components; dir = RIGHT_TO_LEFT; } } else if (dir == RIGHT_TO_LEFT) { if (dst_x != 0) { dst_x--; src -= n_components; dst -= n_components; } else { dst_y++; src += src_stride; dst += dst_stride; dir = TOP_TO_BOTTOM; } } histogram_update (hist, src, n_components, src_stride, has_alpha, o->neighborhood, o->radius, neighborhood_outline, dir); for (c = 0; c < 3; c++) dst[c] = histogram_get_median (hist, c, percentile); if (has_alpha) dst[3] = histogram_get_median (hist, 3, alpha_percentile); } gegl_buffer_set (output, roi, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); g_slice_free (Histogram, hist); g_free (dst_buf); g_free (src_buf); return TRUE; }