static void median (GeglBuffer *src, GeglBuffer *dst, gint radius, gdouble rank) { RankList list = {0}; gint x,y; gint offset; gfloat *src_buf; gfloat *dst_buf; src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4); dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 4); gegl_buffer_get (src, NULL, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); offset = 0; for (y=0; y<gegl_buffer_get_height (dst); y++) for (x=0; x<gegl_buffer_get_width (dst); x++) { gint u,v; gfloat *median_pix; list_clear (&list); for (v=y-radius;v<=y+radius;v++) for (u=x-radius;u<=x+radius;u++) { gint ru, rv; ru = (x-u)*(x-u); rv = (y-v)*(y-v); if (u >= 0 && u < gegl_buffer_get_width (dst) && v >= 0 && v < gegl_buffer_get_height (dst) && (ru+rv) < radius* radius ) { gfloat *src_pix = src_buf + (u+(v * gegl_buffer_get_width (src))) * 4; gfloat luma = (src_pix[0] * 0.212671 + src_pix[1] * 0.715160 + src_pix[2] * 0.072169); list_add (&list, luma, src_pix); } } median_pix = list_percentile (&list, rank); for (u=0; u<4;u++) dst_buf[offset*4+u] = median_pix[u]; offset++; } gegl_buffer_set (dst, NULL, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *aux, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglBuffer *temp_in; GeglBuffer *temp_aux; /* FIXME: just pass the originals buffers if the result rectangle does not * include both input buffers */ temp_in = gegl_buffer_create_sub_buffer (input, result); temp_aux = gegl_buffer_create_sub_buffer (aux, result); { gfloat *buf = g_new0 (gfloat, result->width * result->height * 4); gfloat *bufB = g_new0 (gfloat, result->width * result->height * 4); gegl_buffer_get (temp_in, NULL, 1.0, babl_format ("RGBA float"), buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gegl_buffer_get (temp_aux, NULL, 1.0, babl_format ("RGBA float"), bufB, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); { gint offset=0; gint x,y; for (y=0;y<gegl_buffer_get_height (output);y++) for (x=0;x<gegl_buffer_get_width (output);x++) { if (x + result->x >= gegl_buffer_get_width (input)) { buf[offset+0]=bufB[offset+0]; buf[offset+1]=bufB[offset+1]; buf[offset+2]=bufB[offset+2]; buf[offset+3]=bufB[offset+3]; } offset+=4; } } gegl_buffer_set (output, NULL, 0, babl_format ("RGBA float"), buf, GEGL_AUTO_ROWSTRIDE); g_free (buf); g_free (bufB); } g_object_unref (temp_in); g_object_unref (temp_aux); return TRUE; }
gint gimp_buffer_get_width (const GimpBuffer *buffer) { g_return_val_if_fail (GIMP_IS_BUFFER (buffer), 0); return gegl_buffer_get_width (buffer->buffer); }
TileManager * gimp_buffer_to_tiles (GeglBuffer *buffer) { const Babl *format = gegl_buffer_get_format (buffer); TileManager *new_tiles = NULL; GeglNode *source = NULL; GeglNode *sink = NULL; g_return_val_if_fail (buffer != NULL, NULL); /* Setup and process the graph */ new_tiles = tile_manager_new (gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), gimp_babl_format_to_legacy_bpp (format)); source = gegl_node_new_child (NULL, "operation", "gegl:buffer-source", "buffer", buffer, NULL); sink = gegl_node_new_child (NULL, "operation", "gimp:tilemanager-sink", "tile-manager", new_tiles, NULL); gegl_node_link_many (source, sink, NULL); gegl_node_process (sink); /* Clenaup */ g_object_unref (sink); g_object_unref (source); return new_tiles; }
void gimp_create_image_from_buffer (Gimp *gimp, GeglBuffer *buffer) { GimpImage *image; GimpLayer *layer; const Babl *format; g_return_if_fail (GIMP_IS_GIMP (gimp)); g_return_if_fail (GEGL_IS_BUFFER (buffer)); format = gegl_buffer_get_format (buffer); image = gimp_create_image (gimp, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), gimp_babl_format_get_base_type (format), gimp_babl_format_get_precision (format), FALSE); layer = gimp_layer_new_from_buffer (buffer, image, format, "Debug Image", GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE); gimp_image_add_layer (image, layer, NULL, -1, FALSE); gimp_create_display (gimp, image, GIMP_UNIT_PIXEL, 1.0); }
void gimp_channel_combine_buffer (GimpChannel *mask, GeglBuffer *add_on_buffer, GimpChannelOps op, gint off_x, gint off_y) { GeglBuffer *buffer; gint x, y, w, h; g_return_if_fail (GIMP_IS_CHANNEL (mask)); g_return_if_fail (GEGL_IS_BUFFER (add_on_buffer)); buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); if (! gimp_gegl_mask_combine_buffer (buffer, add_on_buffer, op, off_x, off_y)) return; gimp_rectangle_intersect (off_x, off_y, gegl_buffer_get_width (add_on_buffer), gegl_buffer_get_height (add_on_buffer), 0, 0, gimp_item_get_width (GIMP_ITEM (mask)), gimp_item_get_height (GIMP_ITEM (mask)), &x, &y, &w, &h); mask->bounds_known = FALSE; gimp_drawable_update (GIMP_DRAWABLE (mask), x, y, w, h); }
void gimp_channel_combine_buffer (GimpChannel *mask, GeglBuffer *add_on_buffer, GimpChannelOps op, gint off_x, gint off_y) { GimpChannelCombineData data; g_return_if_fail (GIMP_IS_CHANNEL (mask)); g_return_if_fail (GEGL_IS_BUFFER (add_on_buffer)); if (gimp_channel_combine_start (mask, op, GEGL_RECTANGLE ( off_x, off_y, gegl_buffer_get_width (add_on_buffer), gegl_buffer_get_height (add_on_buffer)), FALSE, FALSE, &data)) { GeglBuffer *buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask)); gimp_gegl_mask_combine_buffer (buffer, add_on_buffer, op, off_x, off_y); } gimp_channel_combine_end (mask, &data); }
/** * gimp_layer_new_from_gegl_buffer: * @buffer: The buffer to make the new layer from. * @dest_image: The image the new layer will be added to. * @format: The #Babl format of the new layer. * @name: The new layer's name. * @opacity: The new layer's opacity. * @mode: The new layer's mode. * * Copies %buffer to a layer taking into consideration the * possibility of transforming the contents to meet the requirements * of the target image type * * Return value: The new layer. **/ GimpLayer * gimp_layer_new_from_gegl_buffer (GeglBuffer *buffer, GimpImage *dest_image, const Babl *format, const gchar *name, gdouble opacity, GimpLayerModeEffects mode, GimpColorProfile *buffer_profile) { GimpLayer *layer; g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL); g_return_val_if_fail (format != NULL, NULL); g_return_val_if_fail (buffer_profile == NULL || GIMP_IS_COLOR_PROFILE (buffer_profile), NULL); /* do *not* use the buffer's format because this function gets * buffers of any format passed, and converts them */ layer = gimp_layer_new (dest_image, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), format, name, opacity, mode); gimp_layer_new_convert_buffer (layer, buffer, buffer_profile, NULL); return layer; }
static GimpBezierDesc * gimp_brush_transform_boundary_exact (GimpBrush *brush, gdouble scale, gdouble aspect_ratio, gdouble angle, gdouble hardness) { const GimpTempBuf *mask; mask = gimp_brush_transform_mask (brush, NULL, scale, aspect_ratio, angle, hardness); if (mask) { GeglBuffer *buffer; GimpBoundSeg *bound_segs; gint n_bound_segs; buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) mask); bound_segs = gimp_boundary_find (buffer, NULL, babl_format ("Y float"), GIMP_BOUNDARY_WITHIN_BOUNDS, 0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), 0.0, &n_bound_segs); g_object_unref (buffer); if (bound_segs) { GimpBoundSeg *stroke_segs; gint n_stroke_groups; stroke_segs = gimp_boundary_sort (bound_segs, n_bound_segs, &n_stroke_groups); g_free (bound_segs); if (stroke_segs) { GimpBezierDesc *path; path = gimp_bezier_desc_new_from_bound_segs (stroke_segs, n_bound_segs, n_stroke_groups); g_free (stroke_segs); return path; } } } return NULL; }
static gboolean debug_show_image_graph (GimpImage *source_image) { Gimp *gimp = source_image->gimp; GimpProjectable *projectable = GIMP_PROJECTABLE (source_image); GeglNode *image_graph = gimp_projectable_get_graph (projectable); GeglNode *output_node = gegl_node_get_output_proxy (image_graph, "output"); GimpImage *new_image = NULL; GimpLayer *layer = NULL; GeglNode *introspect = NULL; GeglNode *sink = NULL; GeglBuffer *buffer = NULL; gchar *new_name = NULL; /* Setup and process the introspection graph */ introspect = gegl_node_new_child (NULL, "operation", "gegl:introspect", "node", output_node, NULL); sink = gegl_node_new_child (NULL, "operation", "gegl:buffer-sink", "buffer", &buffer, NULL); gegl_node_link_many (introspect, sink, NULL); gegl_node_process (sink); /* Create a new image of the result */ new_name = g_strdup_printf ("%s GEGL graph", gimp_image_get_display_name (source_image)); new_image = gimp_create_image (gimp, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), GIMP_RGB, GIMP_PRECISION_U8, FALSE); gimp_image_set_uri (new_image, new_name); layer = gimp_layer_new_from_buffer (buffer, new_image, gimp_image_get_layer_format (new_image, TRUE), new_name, 1.0, GIMP_NORMAL_MODE); gimp_image_add_layer (new_image, layer, NULL, 0, FALSE); gimp_create_display (gimp, new_image, GIMP_UNIT_PIXEL, 1.0); /* Cleanup */ g_object_unref (new_image); g_free (new_name); g_object_unref (buffer); g_object_unref (sink); g_object_unref (introspect); g_object_unref (source_image); return FALSE; }
static void gimp_smudge_accumulator_coords (GimpPaintCore *paint_core, const GimpCoords *coords, gint *x, gint *y) { GimpSmudge *smudge = GIMP_SMUDGE (paint_core); *x = (gint) coords->x - gegl_buffer_get_width (smudge->accum_buffer) / 2; *y = (gint) coords->y - gegl_buffer_get_height (smudge->accum_buffer) / 2; }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglProperties *o = GEGL_PROPERTIES (operation); GeglRectangle result = {0,0,0,0}; load_buffer (o); result.width = gegl_buffer_get_width (GEGL_BUFFER (o->user_data)); result.height = gegl_buffer_get_height (GEGL_BUFFER (o->user_data)); return result; }
void gimp_applicator_apply (GimpApplicator *applicator, GeglBuffer *src_buffer, GeglBuffer *apply_buffer, gint apply_buffer_x, gint apply_buffer_y, gdouble opacity, GimpLayerModeEffects paint_mode) { gint width = gegl_buffer_get_width (apply_buffer); gint height = gegl_buffer_get_height (apply_buffer); if (applicator->src_buffer != src_buffer) { applicator->src_buffer = src_buffer; gegl_node_set (applicator->src_node, "buffer", src_buffer, NULL); } if (applicator->apply_buffer != apply_buffer) { applicator->apply_buffer = apply_buffer; gegl_node_set (applicator->apply_src_node, "buffer", apply_buffer, NULL); } gegl_node_set (applicator->apply_offset_node, "x", (gdouble) apply_buffer_x, "y", (gdouble) apply_buffer_y, NULL); if ((applicator->opacity != opacity) || (applicator->paint_mode != paint_mode)) { applicator->opacity = opacity; applicator->paint_mode = paint_mode; gimp_gegl_mode_node_set (applicator->mode_node, paint_mode, opacity, FALSE); } gegl_processor_set_rectangle (applicator->processor, GEGL_RECTANGLE (apply_buffer_x, apply_buffer_y, width, height)); while (gegl_processor_work (applicator->processor, NULL)); }
gint64 gimp_gegl_buffer_get_memsize (GeglBuffer *buffer) { if (buffer) { const Babl *format = gegl_buffer_get_format (buffer); return (babl_format_get_bytes_per_pixel (format) * gegl_buffer_get_width (buffer) * gegl_buffer_get_height (buffer) + gimp_g_object_get_memsize (G_OBJECT (buffer))); } return 0; }
static GeglRectangle get_bounding_box (GeglOperation *operation) { GeglRectangle result = {0,0,0,0}; GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); load_buffer (o); if (o->chant_data) { result.width = gegl_buffer_get_width (GEGL_BUFFER (o->chant_data)); result.height = gegl_buffer_get_height (GEGL_BUFFER (o->chant_data)); } return result; }
gint64 gimp_gegl_pyramid_get_memsize (GeglBuffer *buffer) { if (buffer) { const Babl *format = gegl_buffer_get_format (buffer); /* The pyramid levels constitute a geometric sum with a ratio of 1/4. */ return ((gint64) babl_format_get_bytes_per_pixel (format) * (gint64) gegl_buffer_get_width (buffer) * (gint64) gegl_buffer_get_height (buffer) * 1.33 + gimp_g_object_get_memsize (G_OBJECT (buffer))); } return 0; }
static gdouble gradient_calc_shapeburst_dimpled_factor (GeglBuffer *dist_buffer, gdouble x, gdouble y) { gint ix = CLAMP (x, 0.0, gegl_buffer_get_width (dist_buffer) - 0.7); gint iy = CLAMP (y, 0.0, gegl_buffer_get_height (dist_buffer) - 0.7); gfloat value; gegl_buffer_get (dist_buffer, GEGL_RECTANGLE (ix, iy, 1, 1), 1.0, NULL, &value, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); value = cos (0.5 * G_PI * value); return value; }
gboolean gimp_edit_fade (GimpImage *image, GimpContext *context) { GimpDrawableUndo *undo; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (GIMP_IS_CONTEXT (context), FALSE); undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image)); if (undo && undo->applied_buffer) { GimpDrawable *drawable; GeglBuffer *buffer; drawable = GIMP_DRAWABLE (GIMP_ITEM_UNDO (undo)->item); g_object_ref (undo); buffer = g_object_ref (undo->applied_buffer); gimp_image_undo (image); gimp_drawable_apply_buffer (drawable, buffer, GEGL_RECTANGLE (0, 0, gegl_buffer_get_width (undo->buffer), gegl_buffer_get_height (undo->buffer)), TRUE, gimp_object_get_name (undo), gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), GIMP_LAYER_COLOR_SPACE_AUTO, GIMP_LAYER_COLOR_SPACE_AUTO, GIMP_LAYER_COMPOSITE_AUTO, NULL, undo->x, undo->y); g_object_unref (buffer); g_object_unref (undo); return TRUE; } return FALSE; }
static gboolean gimp_projection_get_pixel_at (GimpPickable *pickable, gint x, gint y, const Babl *format, gpointer pixel) { GeglBuffer *buffer = gimp_projection_get_buffer (pickable); if (x < 0 || y < 0 || x >= gegl_buffer_get_width (buffer) || y >= gegl_buffer_get_height (buffer)) return FALSE; gegl_buffer_sample (buffer, x, y, NULL, pixel, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); return TRUE; }
/** * gimp_seamless_clone_tool_start: * @sc: The GimpSeamlessCloneTool to initialize for usage on the given * display * @display: The display to initialize the tool for * * A utility function to initialize a tool for working on a given * display. At the beginning of each function, we can check if the event's * display is the same as the tool's one, and if not call this. This is * not required by the gimptool interface or anything like that, but * this is a convenient way to do all the initialization work in one * place, and this is how the base class (GimpDrawTool) does that */ static void gimp_seamless_clone_tool_start (GimpSeamlessCloneTool *sc, GimpDisplay *display) { GimpTool *tool = GIMP_TOOL (sc); GimpImage *image = gimp_display_get_image (display); GimpDrawable *drawable = gimp_image_get_active_drawable (image); /* First handle the paste - we need to make sure we have one in order * to do anything else. */ if (sc->paste == NULL) { GimpBuffer *buffer = gimp_clipboard_get_buffer (tool->tool_info->gimp); if (! buffer) { gimp_tool_push_status (tool, display, "%s", _("There is no image data in the clipboard to paste.")); return; } sc->paste = gegl_buffer_dup (gimp_buffer_get_buffer (buffer)); g_object_unref (buffer); sc->width = gegl_buffer_get_width (sc->paste); sc->height = gegl_buffer_get_height (sc->paste); } /* Free resources which are relevant only for the previous display */ gimp_seamless_clone_tool_stop (sc, TRUE); tool->display = display; gimp_seamless_clone_tool_create_filter (sc, drawable); gimp_draw_tool_start (GIMP_DRAW_TOOL (sc), display); sc->tool_state = SC_STATE_RENDER_WAIT; }
GimpLayerMask * gimp_layer_mask_new_from_buffer (GeglBuffer *buffer, GimpImage *image, const gchar *name, const GimpRGB *color) { GimpLayerMask *layer_mask; GeglBuffer *dest; g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); layer_mask = gimp_layer_mask_new (image, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), name, color); dest = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer_mask)); gegl_buffer_copy (buffer, NULL, dest, NULL); return layer_mask; }
static void gimp_n_point_deformation_tool_apply_deformation (GimpNPointDeformationTool *npd_tool) { GimpTool *tool = GIMP_TOOL (npd_tool); GimpNPointDeformationOptions *npd_options; GeglBuffer *buffer; GimpImage *image; gint width, height, prev; npd_options = GIMP_N_POINT_DEFORMATION_TOOL_GET_OPTIONS (npd_tool); image = gimp_display_get_image (tool->display); buffer = gimp_drawable_get_buffer (tool->drawable); width = gegl_buffer_get_width (buffer); height = gegl_buffer_get_height (buffer); prev = npd_options->rigidity; npd_options->rigidity = 0; gimp_n_point_deformation_tool_set_options (npd_tool, npd_options); npd_options->rigidity = prev; gimp_drawable_push_undo (tool->drawable, _("N-Point Deformation"), NULL, 0, 0, width, height); gimp_gegl_apply_operation (NULL, NULL, _("N-Point Deformation"), npd_tool->npd_node, gimp_drawable_get_buffer (tool->drawable), NULL); gimp_drawable_update (tool->drawable, 0, 0, width, height); gimp_projection_flush (gimp_image_get_projection (image)); }
void gimp_paint_core_paste (GimpPaintCore *core, const GimpTempBuf *paint_mask, gint paint_mask_offset_x, gint paint_mask_offset_y, GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, GimpLayerModeEffects paint_mode, GimpPaintApplicationMode mode) { gint width = gegl_buffer_get_width (core->paint_buffer); gint height = gegl_buffer_get_height (core->paint_buffer); if (core->applicator) { /* If the mode is CONSTANT: * combine the canvas buf, the paint mask to the canvas buffer */ if (mode == GIMP_PAINT_CONSTANT) { /* Some tools (ink) paint the mask to paint_core->canvas_buffer * directly. Don't need to copy it in this case. */ if (paint_mask != NULL) { GeglBuffer *paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); gimp_gegl_combine_mask_weird (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height), core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), paint_opacity, GIMP_IS_AIRBRUSH (core)); g_object_unref (paint_mask_buffer); } gimp_gegl_apply_mask (core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0); gimp_applicator_set_src_buffer (core->applicator, core->undo_buffer); } /* Otherwise: * combine the canvas buf and the paint mask to the canvas buf */ else { GeglBuffer *paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); gimp_gegl_apply_mask (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height), core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), paint_opacity); g_object_unref (paint_mask_buffer); gimp_applicator_set_src_buffer (core->applicator, gimp_drawable_get_buffer (drawable)); } gimp_applicator_set_apply_buffer (core->applicator, core->paint_buffer); gimp_applicator_set_apply_offset (core->applicator, core->paint_buffer_x, core->paint_buffer_y); gimp_applicator_set_mode (core->applicator, image_opacity, paint_mode); /* apply the paint area to the image */ gimp_applicator_blit (core->applicator, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height)); } else { GimpTempBuf *paint_buf = gimp_gegl_buffer_get_temp_buf (core->paint_buffer); GeglBuffer *dest_buffer; GeglBuffer *src_buffer; if (! paint_buf) return; if (core->comp_buffer) dest_buffer = core->comp_buffer; else dest_buffer = gimp_drawable_get_buffer (drawable); if (mode == GIMP_PAINT_CONSTANT) { /* This step is skipped by the ink tool, which writes * directly to canvas_buffer */ if (paint_mask != NULL) { /* Mix paint mask and canvas_buffer */ combine_paint_mask_to_canvas_mask (paint_mask, paint_mask_offset_x, paint_mask_offset_y, core->canvas_buffer, core->paint_buffer_x, core->paint_buffer_y, paint_opacity, GIMP_IS_AIRBRUSH (core)); } /* Write canvas_buffer to paint_buf */ canvas_buffer_to_paint_buf_alpha (paint_buf, core->canvas_buffer, core->paint_buffer_x, core->paint_buffer_y); /* undo buf -> paint_buf -> dest_buffer */ src_buffer = core->undo_buffer; } else { g_return_if_fail (paint_mask); /* Write paint_mask to paint_buf, does not modify canvas_buffer */ paint_mask_to_paint_buffer (paint_mask, paint_mask_offset_x, paint_mask_offset_y, paint_buf, paint_opacity); /* dest_buffer -> paint_buf -> dest_buffer */ src_buffer = dest_buffer; } do_layer_blend (src_buffer, dest_buffer, paint_buf, core->mask_buffer, image_opacity, core->paint_buffer_x, core->paint_buffer_y, core->mask_x_offset, core->mask_y_offset, core->linear_mode, paint_mode); if (core->comp_buffer) { mask_components_onto (src_buffer, core->comp_buffer, gimp_drawable_get_buffer (drawable), GEGL_RECTANGLE(core->paint_buffer_x, core->paint_buffer_y, width, height), gimp_drawable_get_active_mask (drawable), core->linear_mode); } } /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y); core->x2 = MAX (core->x2, core->paint_buffer_x + width); core->y2 = MAX (core->y2, core->paint_buffer_y + height); /* Update the drawable */ gimp_drawable_update (drawable, core->paint_buffer_x, core->paint_buffer_y, width, height); }
static void gimp_image_convert_profile_rgb (GimpImage *image, GimpColorProfile *src_profile, GimpColorProfile *dest_profile, GimpColorRenderingIntent intent, gboolean bpc, GimpProgress *progress) { GList *layers; GList *list; gint n_drawables; gint nth_drawable; layers = gimp_image_get_layer_list (image); n_drawables = g_list_length (layers); for (list = layers, nth_drawable = 0; list; list = g_list_next (list), nth_drawable++) { GimpDrawable *drawable = list->data; cmsHPROFILE src_lcms; cmsHPROFILE dest_lcms; const Babl *iter_format; cmsUInt32Number lcms_format; cmsUInt32Number flags; cmsHTRANSFORM transform; if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))) continue; src_lcms = gimp_color_profile_get_lcms_profile (src_profile); dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile); iter_format = gimp_color_profile_get_format (gimp_drawable_get_format (drawable), &lcms_format); flags = cmsFLAGS_NOOPTIMIZE; if (bpc) flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; transform = cmsCreateTransform (src_lcms, lcms_format, dest_lcms, lcms_format, intent, flags); if (transform) { GeglBuffer *buffer; GeglBufferIterator *iter; buffer = gimp_drawable_get_buffer (drawable); gimp_drawable_push_undo (drawable, NULL, NULL, 0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)); iter = gegl_buffer_iterator_new (buffer, NULL, 0, iter_format, GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { cmsDoTransform (transform, iter->data[0], iter->data[0], iter->length); } gimp_drawable_update (drawable, 0, 0, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer)); cmsDeleteTransform (transform); } if (progress) gimp_progress_set_value (progress, (gdouble) nth_drawable / (gdouble) n_drawables); } g_list_free (layers); }
static void snn_percentile (GeglBuffer *src, GeglBuffer *dst, gdouble radius, gdouble percentile, gint pairs) { gint x, y; gint offset; gfloat *src_buf; gfloat *dst_buf; RankList list = {0}; src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4); dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 4); gegl_buffer_get (src, 1.0, NULL, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE); offset = 0; percentile/= 100.0; for (y=0; y<gegl_buffer_get_height (dst); y++) for (x=0; x<gegl_buffer_get_width (dst); x++) { gint u,v; gfloat *center_pix = src_buf + offset * 4; list_clear (&list); /* iterate through the upper left quater of pixels */ for (v=-radius; v<=0; v++) for (u=-radius; u<= (pairs==1?radius:0); u++) { gfloat *selected_pix = center_pix; gfloat best_diff = 1000.0; gint i; /* skip computations for the center pixel */ if (u != 0 && v != 0) { /* compute the coordinates of the symmetric pairs for * this locaiton in the quadrant */ gint xs[4] = {x+u, x-u, x-u, x+u}; gint ys[4] = {y+v, y-v, y+v, y-v}; /* check which member of the symmetric quadruple to use */ for (i=0; i<pairs*2; i++) { if (xs[i] >= 0 && xs[i] < gegl_buffer_get_width (src) && ys[i] >= 0 && ys[i] < gegl_buffer_get_height (src)) { gfloat *tpix = src_buf + (xs[i]+ys[i]*gegl_buffer_get_width (src))*4; gfloat diff = colordiff (tpix, center_pix); if (diff < best_diff) { best_diff = diff; selected_pix = tpix; } } } } list_add (&list, rgb2luminance(selected_pix), selected_pix); if (u==0 && v==0) break; /* to avoid doubly processing when using only 1 pair */ } { gfloat *result = list_percentile (&list, percentile); for (u=0; u<4; u++) dst_buf[offset*4+u] = result[u]; } offset++; } gegl_buffer_set (dst, NULL, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); }
static GeglBuffer * gimp_source_core_real_get_source (GimpSourceCore *source_core, GimpDrawable *drawable, GimpPaintOptions *paint_options, GimpPickable *src_pickable, gint src_offset_x, gint src_offset_y, GeglBuffer *paint_buffer, gint paint_buffer_x, gint paint_buffer_y, gint *paint_area_offset_x, gint *paint_area_offset_y, gint *paint_area_width, gint *paint_area_height, GeglRectangle *src_rect) { GimpSourceOptions *options = GIMP_SOURCE_OPTIONS (paint_options); GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable)); GimpImage *src_image = gimp_pickable_get_image (src_pickable); GeglBuffer *src_buffer = gimp_pickable_get_buffer (src_pickable); GeglBuffer *dest_buffer; gint x, y; gint width, height; if (! gimp_rectangle_intersect (paint_buffer_x + src_offset_x, paint_buffer_y + src_offset_y, gegl_buffer_get_width (paint_buffer), gegl_buffer_get_height (paint_buffer), 0, 0, gegl_buffer_get_width (src_buffer), gegl_buffer_get_height (src_buffer), &x, &y, &width, &height)) { return FALSE; } /* If the source image is different from the destination, * then we should copy straight from the source image * to the canvas. * Otherwise, we need a call to get_orig_image to make sure * we get a copy of the unblemished (offset) image */ if (( options->sample_merged && (src_image != image)) || (! options->sample_merged && (source_core->src_drawable != drawable))) { dest_buffer = src_buffer; } else { /* get the original image */ if (options->sample_merged) dest_buffer = gimp_paint_core_get_orig_proj (GIMP_PAINT_CORE (source_core)); else dest_buffer = gimp_paint_core_get_orig_image (GIMP_PAINT_CORE (source_core)); } *paint_area_offset_x = x - (paint_buffer_x + src_offset_x); *paint_area_offset_y = y - (paint_buffer_y + src_offset_y); *paint_area_width = width; *paint_area_height = height; *src_rect = *GEGL_RECTANGLE (x, y, width, height); return g_object_ref (dest_buffer); }
/** * gimp_color_transform_process_buffer: * @transform: * @src_format: * @src_rect: * @dest_format: * @dest_rect: * * This function transforms buffer into another buffer. * * Since: 2.10 **/ void gimp_color_transform_process_buffer (GimpColorTransform *transform, GeglBuffer *src_buffer, const GeglRectangle *src_rect, GeglBuffer *dest_buffer, const GeglRectangle *dest_rect) { GimpColorTransformPrivate *priv; GeglBufferIterator *iter; gint total_pixels; gint done_pixels = 0; g_return_if_fail (GIMP_IS_COLOR_TRANSFORM (transform)); g_return_if_fail (GEGL_IS_BUFFER (src_buffer)); g_return_if_fail (GEGL_IS_BUFFER (dest_buffer)); priv = transform->priv; if (src_rect) { total_pixels = src_rect->width * src_rect->height; } else { total_pixels = (gegl_buffer_get_width (src_buffer) * gegl_buffer_get_height (src_buffer)); } if (src_buffer != dest_buffer) { const Babl *fish = NULL; if (babl_format_has_alpha (priv->dest_format)) fish = babl_fish (priv->src_format, priv->dest_format); iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0, priv->src_format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, dest_buffer, dest_rect, 0, priv->dest_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { /* make sure the alpha channel is copied too, lcms doesn't copy it */ if (fish) babl_process (fish, iter->data[0], iter->data[1], iter->length); cmsDoTransform (priv->transform, iter->data[0], iter->data[1], iter->length); done_pixels += iter->roi[0].width * iter->roi[0].height; g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0, (gdouble) done_pixels / (gdouble) total_pixels); } } else { iter = gegl_buffer_iterator_new (src_buffer, src_rect, 0, priv->src_format, GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { cmsDoTransform (priv->transform, iter->data[0], iter->data[0], iter->length); done_pixels += iter->roi[0].width * iter->roi[0].height; g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0, (gdouble) done_pixels / (gdouble) total_pixels); } } g_signal_emit (transform, gimp_color_transform_signals[PROGRESS], 0, 1.0); }
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; }
/* This works similarly to gimp_paint_core_paste. However, instead of * combining the canvas to the paint core drawable using one of the * combination modes, it uses a "replace" mode (i.e. transparent * pixels in the canvas erase the paint core drawable). * When not drawing on alpha-enabled images, it just paints using * NORMAL mode. */ void gimp_paint_core_replace (GimpPaintCore *core, const GimpTempBuf *paint_mask, gint paint_mask_offset_x, gint paint_mask_offset_y, GimpDrawable *drawable, gdouble paint_opacity, gdouble image_opacity, GimpPaintApplicationMode mode) { GeglRectangle mask_rect; GeglBuffer *paint_mask_buffer; gint width, height; if (! gimp_drawable_has_alpha (drawable)) { gimp_paint_core_paste (core, paint_mask, paint_mask_offset_x, paint_mask_offset_y, drawable, paint_opacity, image_opacity, GIMP_NORMAL_MODE, mode); return; } width = gegl_buffer_get_width (core->paint_buffer); height = gegl_buffer_get_height (core->paint_buffer); if (mode == GIMP_PAINT_CONSTANT && /* Some tools (ink) paint the mask to paint_core->canvas_buffer * directly. Don't need to copy it in this case. */ paint_mask != NULL) { if (core->applicator) { paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); /* combine the paint mask and the canvas buffer */ gimp_gegl_combine_mask_weird (paint_mask_buffer, GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height), core->canvas_buffer, GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height), paint_opacity, GIMP_IS_AIRBRUSH (core)); g_object_unref (paint_mask_buffer); } else { /* Mix paint mask and canvas_buffer */ combine_paint_mask_to_canvas_mask (paint_mask, paint_mask_offset_x, paint_mask_offset_y, core->canvas_buffer, core->paint_buffer_x, core->paint_buffer_y, paint_opacity, GIMP_IS_AIRBRUSH (core)); } /* initialize the maskPR from the canvas buffer */ paint_mask_buffer = g_object_ref (core->canvas_buffer); mask_rect = *GEGL_RECTANGLE (core->paint_buffer_x, core->paint_buffer_y, width, height); } else { paint_mask_buffer = gimp_temp_buf_create_buffer ((GimpTempBuf *) paint_mask); mask_rect = *GEGL_RECTANGLE (paint_mask_offset_x, paint_mask_offset_y, width, height); } /* apply the paint area to the image */ gimp_drawable_replace_buffer (drawable, core->paint_buffer, GEGL_RECTANGLE (0, 0, width, height), FALSE, NULL, image_opacity, paint_mask_buffer, &mask_rect, core->paint_buffer_x, core->paint_buffer_y); g_object_unref (paint_mask_buffer); /* Update the undo extents */ core->x1 = MIN (core->x1, core->paint_buffer_x); core->y1 = MIN (core->y1, core->paint_buffer_y); core->x2 = MAX (core->x2, core->paint_buffer_x + width); core->y2 = MAX (core->y2, core->paint_buffer_y + height); /* Update the drawable */ gimp_drawable_update (drawable, core->paint_buffer_x, core->paint_buffer_y, width, height); }
static void kuwahara (GeglBuffer *src, GeglBuffer *dst, gint radius) { gint u,v; gint offset; gfloat *src_buf; gfloat *dst_buf; src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4); dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 4); gegl_buffer_get (src, NULL, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); offset = 0; for (v=0; v<gegl_buffer_get_height (dst); v++) for (u=0; u<gegl_buffer_get_width (dst); u++) { gint component; for (component=0; component<3; component++) { gfloat value=0.0; gfloat best=1000000.0; gfloat mean = 0.0; gfloat variance = 0.0; compute_rectangle (src_buf, gegl_buffer_get_width (src), gegl_buffer_get_height (src), u - radius - 1, v - radius - 1, 1 + radius, 1 + radius, component, NULL, /* min */ NULL, /* max */ &mean, &variance); if (variance<best) { best = variance; value = mean; } compute_rectangle (src_buf, gegl_buffer_get_width (src), gegl_buffer_get_height (src), u, v - radius - 1, 1 + radius, 1 + radius, component, NULL, /* min */ NULL, /* max */ &mean, &variance); if (variance<best) { best = variance; value = mean; } compute_rectangle (src_buf, gegl_buffer_get_width (src), gegl_buffer_get_height (src), u - radius - 1, v, 1 + radius, 1 + radius, component, NULL, /* min */ NULL, /* max */ &mean, &variance); if (variance<best) { best = variance; value = mean; } compute_rectangle (src_buf, gegl_buffer_get_width (src), gegl_buffer_get_height (src), u, v, 1 + radius, 1 + radius, component, NULL, /* min */ NULL, /* max */ &mean, &variance); if (variance<best) { best = variance; value = mean; } dst_buf [offset++] = value; } dst_buf [offset] = src_buf[offset]; offset++; } gegl_buffer_set (dst, NULL, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); }