static void gegl_buffer_dispose (GObject *object) { GeglBuffer *buffer = GEGL_BUFFER (object); GeglTileHandler *handler = GEGL_TILE_HANDLER (object); gegl_buffer_sample_cleanup (buffer); if (gegl_cl_is_accelerated ()) gegl_buffer_cl_cache_invalidate (GEGL_BUFFER (object), NULL); if (handler->source && GEGL_IS_TILE_STORAGE (handler->source)) { GeglTileBackend *backend = gegl_buffer_backend (buffer); /* only flush non-internal backends,. */ if (!(GEGL_IS_TILE_BACKEND_FILE (backend) || GEGL_IS_TILE_BACKEND_RAM (backend) || GEGL_IS_TILE_BACKEND_TILE_DIR (backend))) gegl_buffer_flush (buffer); gegl_tile_source_reinit (GEGL_TILE_SOURCE (handler->source)); #if 0 g_object_unref (handler->source); handler->source = NULL; /* this might be a dangerous way of marking that we have already voided */ #endif } _gegl_buffer_drop_hot_tile (buffer); G_OBJECT_CLASS (parent_class)->dispose (object); }
static void apply_whirl_pinch (gdouble whirl, gdouble pinch, gdouble radius, gdouble cen_x, gdouble cen_y, Babl *format, GeglBuffer *src, GeglRectangle *in_boundary, GeglBuffer *dst, GeglRectangle *boundary, const GeglRectangle *roi) { gfloat *dst_buf; gint row, col; gdouble scale_x, scale_y; gdouble cx, cy; /* Get buffer in which to place dst pixels. */ dst_buf = g_new0 (gfloat, roi->width * roi->height * 4); whirl = whirl * G_PI / 180; scale_x = 1.0; scale_y = roi->width / (gdouble) roi->height; for (row = 0; row < roi->height; row++) { for (col = 0; col < roi->width; col++) { calc_undistorted_coords (roi->x + col, roi->y + row, cen_x, cen_y, scale_x, scale_y, whirl, pinch, radius, &cx, &cy); gegl_buffer_sample (src, cx, cy, 1.0, &dst_buf[(row * roi->width + col) * 4], format, GEGL_INTERPOLATION_LINEAR); } /* for */ } /* for */ gegl_buffer_sample_cleanup (src); /* Store dst pixels. */ gegl_buffer_set (dst, roi, format, dst_buf, GEGL_AUTO_ROWSTRIDE); gegl_buffer_flush(dst); g_free (dst_buf); }
/* Apply the actual transform */ static void apply_spread (gint x_amount, gint y_amount, gint img_width, gint img_height, const Babl *format, GeglBuffer *src, GeglBuffer *dst, const GeglRectangle *roi) { gfloat *dst_buf; gint x1, y1; // Noise image gdouble x, y; // Source Image GRand *gr = g_rand_new (); /* Get buffer in which to place dst pixels. */ dst_buf = g_new0 (gfloat, roi->width * roi->height * 4); for (y1 = 0; y1 < roi->height; y1++) { for (x1 = 0; x1 < roi->width; x1++) { calc_sample_coords (x1, y1, x_amount, y_amount, gr, &x, &y); /* Only displace the pixel if it's within the bounds of the image. */ if (x >= 0 && x < img_width && y >= 0 && y < img_height) gegl_buffer_sample (src, x, y, NULL, &dst_buf[(y1 * roi->width + x1) * 4], format, GEGL_SAMPLER_LINEAR, GEGL_ABYSS_NONE); else /* Else just copy it */ gegl_buffer_sample (src, x1, y1, NULL, &dst_buf[(y1 * roi->width + x1) * 4], format, GEGL_SAMPLER_LINEAR, GEGL_ABYSS_NONE); } /* for */ } /* for */ gegl_buffer_sample_cleanup (src); /* Store dst pixels. */ gegl_buffer_set (dst, roi, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); gegl_buffer_flush(dst); g_free (dst_buf); g_rand_free (gr); }
/* Create a layer with the provided image data and add it to the image */ gboolean create_layer(gint32 image_ID, uint8_t *layer_data, gint32 position, gchar *name, gint width, gint height, gint32 offsetx, gint32 offsety) { gint32 layer_ID; #ifdef GIMP_2_9 GeglBuffer *geglbuffer; GeglRectangle extent; #else GimpDrawable *drawable; GimpPixelRgn region; #endif layer_ID = gimp_layer_new(image_ID, name, width, height, GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE); #ifdef GIMP_2_9 /* Retrieve the buffer for the layer */ geglbuffer = gimp_drawable_get_buffer(layer_ID); /* Copy the image data to the region */ gegl_rectangle_set(&extent, 0, 0, width, height); gegl_buffer_set(geglbuffer, &extent, 0, NULL, layer_data, GEGL_AUTO_ROWSTRIDE); /* Flush the drawable and detach */ gegl_buffer_flush(geglbuffer); g_object_unref(geglbuffer); #else /* Retrieve the drawable for the layer */ drawable = gimp_drawable_get(layer_ID); /* Get a pixel region from the layer */ gimp_pixel_rgn_init(®ion, drawable, 0, 0, width, height, FALSE, FALSE); /* Copy the image data to the region */ gimp_pixel_rgn_set_rect(®ion, layer_data, 0, 0, width, height); /* Flush the drawable and detach */ gimp_drawable_flush(drawable); gimp_drawable_detach(drawable); #endif /* Add the new layer to the image */ gimp_image_insert_layer(image_ID, layer_ID, -1, position); /* If layer offsets were provided, use them to position the image */ if (offsetx || offsety) { gimp_layer_set_offsets(layer_ID, offsetx, offsety); } /* TODO: fix this */ return TRUE; }
static void do_zcrop (gint32 drawable_id, gint32 image_id) { GeglBuffer *drawable_buffer; GeglBuffer *shadow_buffer; gfloat *linear_buf; const Babl *format; gint x, y, width, height; gint components; gint8 *killrows; gint8 *killcols; gint32 livingrows, livingcols, destrow, destcol; gint32 selection_copy_id; gboolean has_alpha; drawable_buffer = gimp_drawable_get_buffer (drawable_id); shadow_buffer = gimp_drawable_get_shadow_buffer (drawable_id); width = gegl_buffer_get_width (drawable_buffer); height = gegl_buffer_get_height (drawable_buffer); has_alpha = gimp_drawable_has_alpha (drawable_id); if (has_alpha) format = babl_format ("R'G'B'A float"); else format = babl_format ("R'G'B' float"); components = babl_format_get_n_components (format); killrows = g_new (gint8, height); killcols = g_new (gint8, width); linear_buf = g_new (gfloat, (width > height ? width : height) * components); /* search which rows to remove */ livingrows = 0; for (y = 0; y < height; y++) { gegl_buffer_get (drawable_buffer, GEGL_RECTANGLE (0, y, width, 1), 1.0, format, linear_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); killrows[y] = TRUE; for (x = components; x < width * components; x += components) { if (! colors_equal (linear_buf, &linear_buf[x], components, has_alpha)) { livingrows++; killrows[y] = FALSE; break; } } } gimp_progress_update (0.25); /* search which columns to remove */ livingcols = 0; for (x = 0; x < width; x++) { gegl_buffer_get (drawable_buffer, GEGL_RECTANGLE (x, 0, 1, height), 1.0, format, linear_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); killcols[x] = TRUE; for (y = components; y < height * components; y += components) { if (! colors_equal (linear_buf, &linear_buf[y], components, has_alpha)) { livingcols++; killcols[x] = FALSE; break; } } } gimp_progress_update (0.5); if ((livingcols == 0 || livingrows == 0) || (livingcols == width && livingrows == height)) { g_message (_("Nothing to crop.")); g_free (linear_buf); g_free (killrows); g_free (killcols); return; } /* restitute living rows */ destrow = 0; for (y = 0; y < height; y++) { if (!killrows[y]) { gegl_buffer_copy (drawable_buffer, GEGL_RECTANGLE (0, y, width, 1), GEGL_ABYSS_NONE, shadow_buffer, GEGL_RECTANGLE (0, destrow, width, 1)); destrow++; } } gimp_progress_update (0.75); /* restitute living columns */ destcol = 0; for (x = 0; x < width; x++) { if (!killcols[x]) { gegl_buffer_copy (shadow_buffer, GEGL_RECTANGLE (x, 0, 1, height), GEGL_ABYSS_NONE, shadow_buffer, GEGL_RECTANGLE (destcol, 0, 1, height)); destcol++; } } gimp_progress_update (1.00); gimp_image_undo_group_start (image_id); selection_copy_id = gimp_selection_save (image_id); gimp_selection_none (image_id); gegl_buffer_flush (shadow_buffer); gimp_drawable_merge_shadow (drawable_id, TRUE); gegl_buffer_flush (drawable_buffer); gimp_image_select_item (image_id, GIMP_CHANNEL_OP_REPLACE, selection_copy_id); gimp_image_remove_channel (image_id, selection_copy_id); gimp_image_crop (image_id, livingcols, livingrows, 0, 0); gimp_image_undo_group_end (image_id); g_object_unref (shadow_buffer); g_object_unref (drawable_buffer); g_free (linear_buf); g_free (killrows); g_free (killcols); }
static gboolean test_buffer_change_extent (void) { gboolean result = TRUE; gchar *tmpdir = NULL; gchar *buf_a_path = NULL; GeglBuffer *buf_a = NULL; const Babl *format = babl_format ("R'G'B'A u8"); GeglRectangle roi = {0, 0, 128, 128}; GeglRectangle roi2 = {0, 0, 64, 64}; tmpdir = g_dir_make_tmp ("test-backend-file-XXXXXX", NULL); g_return_val_if_fail (tmpdir, FALSE); buf_a_path = g_build_filename (tmpdir, "buf_a.gegl", NULL); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", format, "path", buf_a_path, "x", roi.x, "y", roi.y, "width", roi.width, "height", roi.height, NULL); gegl_buffer_flush (buf_a); g_object_unref (buf_a); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", babl_format ("RGBA u16"), "path", buf_a_path, NULL); if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi)) { printf ("Extent does not match:\n"); gegl_rectangle_dump (gegl_buffer_get_extent (buf_a)); gegl_rectangle_dump (&roi); result = FALSE; } gegl_buffer_set_extent (buf_a, &roi2); gegl_buffer_flush (buf_a); g_object_unref (buf_a); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", babl_format ("RGBA u16"), "path", buf_a_path, NULL); if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi2)) { printf ("Extent does not match:\n"); gegl_rectangle_dump (gegl_buffer_get_extent (buf_a)); gegl_rectangle_dump (&roi2); result = FALSE; } g_object_unref (buf_a); g_unlink (buf_a_path); g_remove (tmpdir); g_free (tmpdir); g_free (buf_a_path); return result; }
static gboolean test_buffer_same_path (void) { gboolean result = TRUE; gchar *tmpdir = NULL; gchar *buf_a_path = NULL; GeglBuffer *buf_a = NULL; const Babl *format = babl_format ("R'G'B'A u8"); GeglRectangle roi = {0, 0, 128, 128}; tmpdir = g_dir_make_tmp ("test-backend-file-XXXXXX", NULL); g_return_val_if_fail (tmpdir, FALSE); buf_a_path = g_build_filename (tmpdir, "buf_a.gegl", NULL); buf_a = g_object_new (GEGL_TYPE_BUFFER, "format", format, "path", buf_a_path, "x", roi.x, "y", roi.y, "width", roi.width, "height", roi.height, NULL); gegl_buffer_flush (buf_a); g_object_unref (buf_a); buf_a = g_object_new (GEGL_TYPE_BUFFER, /* FIXME: Currently the buffer must always have a format specified */ "format", babl_format ("RGBA u16"), "path", buf_a_path, NULL); if (!GEGL_IS_BUFFER (buf_a)) { printf ("Failed to load file:%s\n", buf_a_path); result = FALSE; } if (!gegl_rectangle_equal (gegl_buffer_get_extent (buf_a), &roi)) { printf ("Extent does not match:\n"); gegl_rectangle_dump (gegl_buffer_get_extent (buf_a)); gegl_rectangle_dump (&roi); result = FALSE; } if (gegl_buffer_get_format (buf_a) != format) { printf ("Formats do not match:\n%s\n%s\n", babl_get_name (gegl_buffer_get_format (buf_a)), babl_get_name (format)); result = FALSE; } g_object_unref (buf_a); g_unlink (buf_a_path); g_remove (tmpdir); g_free (tmpdir); g_free (buf_a_path); return result; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, const GeglRectangle *result, gint level) { GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); if (o->buffer) { GeglBuffer *output = GEGL_BUFFER (o->buffer); const Babl *in_format = gegl_buffer_get_format (input); const Babl *out_format = gegl_buffer_get_format (output); if (gegl_operation_use_opencl (operation) && gegl_cl_color_supported (in_format, out_format) == GEGL_CL_COLOR_CONVERT) { size_t size; gboolean err; cl_int cl_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, out_format, GEGL_CL_BUFFER_READ, GEGL_ABYSS_NONE); gegl_cl_color_babl (out_format, &size); GEGL_NOTE (GEGL_DEBUG_OPENCL, "write-buffer: " "%p %p %s %s {%d %d %d %d}", input, output, babl_get_name (in_format), babl_get_name (out_format), result->x, result->y, result->width, result->height); while (gegl_buffer_cl_iterator_next (i, &err)) { if (err) break; cl_err = gegl_clEnqueueCopyBuffer (gegl_cl_get_command_queue (), i->tex[read], i->tex[0], 0, 0, i->size[0] * size, 0, NULL, NULL); if (cl_err != CL_SUCCESS) { GEGL_NOTE (GEGL_DEBUG_OPENCL, "Error: %s", gegl_cl_errstring (cl_err)); break; } } if (cl_err || err) gegl_buffer_copy (input, result, output, result); } else gegl_buffer_copy (input, result, output, result); gegl_buffer_flush (output); } return TRUE; }