static GimpTempBuf * gimp_pattern_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpPattern *pattern = GIMP_PATTERN (viewable); GimpTempBuf *temp_buf; GeglBuffer *src_buffer; GeglBuffer *dest_buffer; gint copy_width; gint copy_height; copy_width = MIN (width, gimp_temp_buf_get_width (pattern->mask)); copy_height = MIN (height, gimp_temp_buf_get_height (pattern->mask)); temp_buf = gimp_temp_buf_new (copy_width, copy_height, gimp_temp_buf_get_format (pattern->mask)); src_buffer = gimp_temp_buf_create_buffer (pattern->mask); dest_buffer = gimp_temp_buf_create_buffer (temp_buf); gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (0, 0, copy_width, copy_height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); g_object_unref (src_buffer); g_object_unref (dest_buffer); return temp_buf; }
void paint_mask_to_paint_buffer (const GimpTempBuf *paint_mask, gint mask_x_offset, gint mask_y_offset, GimpTempBuf *paint_buf, gfloat paint_opacity) { gint width = gimp_temp_buf_get_width (paint_buf); gint height = gimp_temp_buf_get_height (paint_buf); const gint mask_stride = gimp_temp_buf_get_width (paint_mask); const gint mask_start_offset = mask_y_offset * mask_stride + mask_x_offset; const Babl *mask_format = gimp_temp_buf_get_format (paint_mask); int iy, ix; gfloat *paint_pixel = (gfloat *)gimp_temp_buf_get_data (paint_buf); /* Validate that the paint buffer is withing the bounds of the paint mask */ g_return_if_fail (width <= gimp_temp_buf_get_width (paint_mask) - mask_x_offset); g_return_if_fail (height <= gimp_temp_buf_get_height (paint_mask) - mask_y_offset); if (mask_format == babl_format ("Y u8")) { const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask); mask_data += mask_start_offset; for (iy = 0; iy < height; iy++) { int mask_offset = iy * mask_stride; const guint8 *mask_pixel = &mask_data[mask_offset]; for (ix = 0; ix < width; ix++) { paint_pixel[3] *= (((gfloat)*mask_pixel) / 255.0f) * paint_opacity; mask_pixel += 1; paint_pixel += 4; } } } else if (mask_format == babl_format ("Y float")) { const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask); mask_data += mask_start_offset; for (iy = 0; iy < height; iy++) { int mask_offset = iy * mask_stride; const gfloat *mask_pixel = &mask_data[mask_offset]; for (ix = 0; ix < width; ix++) { paint_pixel[3] *= (*mask_pixel) * paint_opacity; mask_pixel += 1; paint_pixel += 4; } } } }
GimpTempBuf * gimp_image_get_new_preview (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpImage *image = GIMP_IMAGE (viewable); const Babl *format; gboolean linear; GimpTempBuf *buf; gdouble scale_x; gdouble scale_y; scale_x = (gdouble) width / (gdouble) gimp_image_get_width (image); scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image); format = gimp_projectable_get_format (GIMP_PROJECTABLE (image)); linear = gimp_babl_format_get_linear (format); format = gimp_babl_format (gimp_babl_format_get_base_type (format), gimp_babl_precision (GIMP_COMPONENT_TYPE_U8, linear), babl_format_has_alpha (format)); buf = gimp_temp_buf_new (width, height, format); gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)), GEGL_RECTANGLE (0, 0, width, height), MIN (scale_x, scale_y), gimp_temp_buf_get_format (buf), gimp_temp_buf_get_data (buf), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); return buf; }
static GimpValueArray * patterns_get_pattern_data_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GimpValueArray *args, GError **error) { gboolean success = TRUE; GimpValueArray *return_vals; const gchar *name; gchar *actual_name = NULL; gint32 width = 0; gint32 height = 0; gint32 mask_bpp = 0; gint32 length = 0; guint8 *mask_data = NULL; name = g_value_get_string (gimp_value_array_index (args, 0)); if (success) { GimpPattern *pattern; if (name && strlen (name)) pattern = gimp_pdb_get_pattern (gimp, name, error); else pattern = gimp_context_get_pattern (context); if (pattern) { actual_name = g_strdup (gimp_object_get_name (pattern)); width = gimp_temp_buf_get_width (pattern->mask); height = gimp_temp_buf_get_height (pattern->mask); mask_bpp = babl_format_get_bytes_per_pixel (gimp_temp_buf_get_format (pattern->mask)); length = gimp_temp_buf_get_data_size (pattern->mask); mask_data = g_memdup (gimp_temp_buf_get_data (pattern->mask), length); } else success = FALSE; } return_vals = gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); if (success) { g_value_take_string (gimp_value_array_index (return_vals, 1), actual_name); g_value_set_int (gimp_value_array_index (return_vals, 2), width); g_value_set_int (gimp_value_array_index (return_vals, 3), height); g_value_set_int (gimp_value_array_index (return_vals, 4), mask_bpp); g_value_set_int (gimp_value_array_index (return_vals, 5), length); gimp_value_take_int8array (gimp_value_array_index (return_vals, 6), mask_data, length); } return return_vals; }
GimpTempBuf * gimp_drawable_get_sub_preview (GimpDrawable *drawable, gint src_x, gint src_y, gint src_width, gint src_height, gint dest_width, gint dest_height) { GimpItem *item; GimpImage *image; GeglBuffer *buffer; GimpTempBuf *preview; gdouble scale; gint scaled_x; gint scaled_y; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (src_x >= 0, NULL); g_return_val_if_fail (src_y >= 0, NULL); g_return_val_if_fail (src_width > 0, NULL); g_return_val_if_fail (src_height > 0, NULL); g_return_val_if_fail (dest_width > 0, NULL); g_return_val_if_fail (dest_height > 0, NULL); item = GIMP_ITEM (drawable); g_return_val_if_fail ((src_x + src_width) <= gimp_item_get_width (item), NULL); g_return_val_if_fail ((src_y + src_height) <= gimp_item_get_height (item), NULL); image = gimp_item_get_image (item); if (! image->gimp->config->layer_previews) return NULL; buffer = gimp_drawable_get_buffer (drawable); preview = gimp_temp_buf_new (dest_width, dest_height, gimp_drawable_get_preview_format (drawable)); scale = MIN ((gdouble) dest_width / (gdouble) src_width, (gdouble) dest_height / (gdouble) src_height); scaled_x = RINT ((gdouble) src_x * scale); scaled_y = RINT ((gdouble) src_y * scale); gegl_buffer_get (buffer, GEGL_RECTANGLE (scaled_x, scaled_y, dest_width, dest_height), scale, gimp_temp_buf_get_format (preview), gimp_temp_buf_get_data (preview), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); return preview; }
static gboolean gimp_drawable_edit_can_fill_direct (GimpDrawable *drawable, GimpFillOptions *options) { GimpImage *image; GimpContext *context; gdouble opacity; GimpComponentMask affect; GimpLayerMode mode; GimpLayerCompositeMode composite_mode; GimpLayerCompositeRegion composite_region; image = gimp_item_get_image (GIMP_ITEM (drawable)); context = GIMP_CONTEXT (options); opacity = gimp_context_get_opacity (context); affect = gimp_drawable_get_active_mask (drawable); mode = gimp_context_get_paint_mode (context); composite_mode = gimp_layer_mode_get_paint_composite_mode (mode); composite_region = gimp_layer_mode_get_included_region (mode, composite_mode); if (gimp_channel_is_empty (gimp_image_get_mask (image)) && opacity == GIMP_OPACITY_OPAQUE && affect == GIMP_COMPONENT_MASK_ALL && gimp_layer_mode_is_trivial (mode) && (! gimp_layer_mode_is_subtractive (mode) ^ ! (composite_region & GIMP_LAYER_COMPOSITE_REGION_SOURCE))) { switch (gimp_fill_options_get_style (options)) { case GIMP_FILL_STYLE_SOLID: return TRUE; case GIMP_FILL_STYLE_PATTERN: { GimpPattern *pattern; GimpTempBuf *mask; const Babl *format; pattern = gimp_context_get_pattern (context); mask = gimp_pattern_get_mask (pattern); format = gimp_temp_buf_get_format (mask); return ! babl_format_has_alpha (format); } } } return FALSE; }
static GdkPixbuf * gimp_buffer_get_new_pixbuf (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpBuffer *buffer = GIMP_BUFFER (viewable); GdkPixbuf *pixbuf; gdouble scale; pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); scale = MIN ((gdouble) width / (gdouble) gimp_buffer_get_width (buffer), (gdouble) height / (gdouble) gimp_buffer_get_height (buffer)); if (buffer->color_profile) { GimpColorProfile *srgb_profile; GimpTempBuf *temp_buf; GeglBuffer *src_buf; GeglBuffer *dest_buf; srgb_profile = gimp_color_profile_new_rgb_srgb (); temp_buf = gimp_temp_buf_new (width, height, gimp_buffer_get_format (buffer)); gegl_buffer_get (buffer->buffer, GEGL_RECTANGLE (0, 0, width, height), scale, gimp_temp_buf_get_format (temp_buf), gimp_temp_buf_get_data (temp_buf), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); src_buf = gimp_temp_buf_create_buffer (temp_buf); dest_buf = gimp_pixbuf_create_buffer (pixbuf); gimp_temp_buf_unref (temp_buf); gimp_gegl_convert_color_profile (src_buf, GEGL_RECTANGLE (0, 0, width, height), buffer->color_profile, dest_buf, GEGL_RECTANGLE (0, 0, 0, 0), srgb_profile, GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, TRUE, NULL); g_object_unref (src_buf); g_object_unref (dest_buf); g_object_unref (srgb_profile); } else { gegl_buffer_get (buffer->buffer, GEGL_RECTANGLE (0, 0, width, height), scale, gimp_pixbuf_get_format (pixbuf), gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_rowstride (pixbuf), GEGL_ABYSS_CLAMP); } return pixbuf; }
void gimp_edit_fill (GimpImage *image, GimpDrawable *drawable, GimpFillOptions *options, const gchar *undo_desc) { GeglBuffer *dest_buffer; GimpPattern *pattern = NULL; GimpRGB color; const Babl *format; gint x, y, width, height; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (GIMP_IS_FILL_OPTIONS (options)); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height)) return; /* nothing to do, but the fill succeeded */ switch (gimp_fill_options_get_style (options)) { case GIMP_FILL_STYLE_SOLID: gimp_context_get_foreground (GIMP_CONTEXT (options), &color); break; case GIMP_FILL_STYLE_PATTERN: pattern = gimp_context_get_pattern (GIMP_CONTEXT (options)); break; } if (pattern && babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) && ! gimp_drawable_has_alpha (drawable)) { format = gimp_drawable_get_format_with_alpha (drawable); } else { format = gimp_drawable_get_format (drawable); } dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), format); if (pattern) { GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern); gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0); g_object_unref (src_buffer); } else { GeglColor *gegl_color = gimp_gegl_color_new (&color); gegl_buffer_set_color (dest_buffer, NULL, gegl_color); g_object_unref (gegl_color); } if (! undo_desc) undo_desc = gimp_fill_options_get_undo_desc (options); gimp_drawable_apply_buffer (drawable, dest_buffer, GEGL_RECTANGLE (0, 0, width, height), TRUE, undo_desc, gimp_context_get_opacity (GIMP_CONTEXT (options)), gimp_context_get_paint_mode (GIMP_CONTEXT (options)), NULL, x, y); g_object_unref (dest_buffer); gimp_drawable_update (drawable, x, y, width, height); }
GdkPixbuf * gimp_drawable_get_sub_pixbuf (GimpDrawable *drawable, gint src_x, gint src_y, gint src_width, gint src_height, gint dest_width, gint dest_height) { GimpItem *item; GimpImage *image; GeglBuffer *buffer; GdkPixbuf *pixbuf; gdouble scale; gint scaled_x; gint scaled_y; GimpColorTransform *transform; g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (src_x >= 0, NULL); g_return_val_if_fail (src_y >= 0, NULL); g_return_val_if_fail (src_width > 0, NULL); g_return_val_if_fail (src_height > 0, NULL); g_return_val_if_fail (dest_width > 0, NULL); g_return_val_if_fail (dest_height > 0, NULL); item = GIMP_ITEM (drawable); g_return_val_if_fail ((src_x + src_width) <= gimp_item_get_width (item), NULL); g_return_val_if_fail ((src_y + src_height) <= gimp_item_get_height (item), NULL); image = gimp_item_get_image (item); if (! image->gimp->config->layer_previews) return NULL; buffer = gimp_drawable_get_buffer (drawable); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, dest_width, dest_height); scale = MIN ((gdouble) dest_width / (gdouble) src_width, (gdouble) dest_height / (gdouble) src_height); scaled_x = RINT ((gdouble) src_x * scale); scaled_y = RINT ((gdouble) src_y * scale); transform = gimp_image_get_color_transform_to_srgb_u8 (image); if (transform) { GimpTempBuf *temp_buf; GeglBuffer *src_buf; GeglBuffer *dest_buf; temp_buf = gimp_temp_buf_new (dest_width, dest_height, gimp_drawable_get_format (drawable)); gegl_buffer_get (buffer, GEGL_RECTANGLE (scaled_x, scaled_y, dest_width, dest_height), scale, gimp_temp_buf_get_format (temp_buf), gimp_temp_buf_get_data (temp_buf), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); src_buf = gimp_temp_buf_create_buffer (temp_buf); dest_buf = gimp_pixbuf_create_buffer (pixbuf); gimp_temp_buf_unref (temp_buf); gimp_color_transform_process_buffer (transform, src_buf, GEGL_RECTANGLE (0, 0, dest_width, dest_height), dest_buf, GEGL_RECTANGLE (0, 0, 0, 0)); g_object_unref (src_buf); g_object_unref (dest_buf); } else { gegl_buffer_get (buffer, GEGL_RECTANGLE (scaled_x, scaled_y, dest_width, dest_height), scale, gimp_pixbuf_get_format (pixbuf), gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_rowstride (pixbuf), GEGL_ABYSS_CLAMP); } return pixbuf; }
void combine_paint_mask_to_canvas_mask (const GimpTempBuf *paint_mask, gint mask_x_offset, gint mask_y_offset, GeglBuffer *canvas_buffer, gint x_offset, gint y_offset, gfloat opacity, gboolean stipple) { GeglRectangle roi; GeglBufferIterator *iter; const gint mask_stride = gimp_temp_buf_get_width (paint_mask); const gint mask_start_offset = mask_y_offset * mask_stride + mask_x_offset; const Babl *mask_format = gimp_temp_buf_get_format (paint_mask); roi.x = x_offset; roi.y = y_offset; roi.width = gimp_temp_buf_get_width (paint_mask) - mask_x_offset; roi.height = gimp_temp_buf_get_height (paint_mask) - mask_y_offset; iter = gegl_buffer_iterator_new (canvas_buffer, &roi, 0, babl_format ("Y float"), GEGL_ACCESS_READWRITE, GEGL_ABYSS_NONE); if (stipple) { if (mask_format == babl_format ("Y u8")) { const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask); mask_data += mask_start_offset; while (gegl_buffer_iterator_next (iter)) { gfloat *out_pixel = (gfloat *)iter->data[0]; int iy, ix; for (iy = 0; iy < iter->roi[0].height; iy++) { int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x; const guint8 *mask_pixel = &mask_data[mask_offset]; for (ix = 0; ix < iter->roi[0].width; ix++) { out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity; mask_pixel += 1; out_pixel += 1; } } } } else if (mask_format == babl_format ("Y float")) { const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask); mask_data += mask_start_offset; while (gegl_buffer_iterator_next (iter)) { gfloat *out_pixel = (gfloat *)iter->data[0]; int iy, ix; for (iy = 0; iy < iter->roi[0].height; iy++) { int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x; const gfloat *mask_pixel = &mask_data[mask_offset]; for (ix = 0; ix < iter->roi[0].width; ix++) { out_pixel[0] += (1.0 - out_pixel[0]) * (*mask_pixel) * opacity; mask_pixel += 1; out_pixel += 1; } } } } else { g_warning("Mask format not supported: %s", babl_get_name (mask_format)); } } else { if (mask_format == babl_format ("Y u8")) { const guint8 *mask_data = (const guint8 *) gimp_temp_buf_get_data (paint_mask); mask_data += mask_start_offset; while (gegl_buffer_iterator_next (iter)) { gfloat *out_pixel = (gfloat *)iter->data[0]; int iy, ix; for (iy = 0; iy < iter->roi[0].height; iy++) { int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x; const guint8 *mask_pixel = &mask_data[mask_offset]; for (ix = 0; ix < iter->roi[0].width; ix++) { if (opacity > out_pixel[0]) out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel / 255.0f) * opacity; mask_pixel += 1; out_pixel += 1; } } } } else if (mask_format == babl_format ("Y float")) { const gfloat *mask_data = (const gfloat *) gimp_temp_buf_get_data (paint_mask); mask_data += mask_start_offset; while (gegl_buffer_iterator_next (iter)) { gfloat *out_pixel = (gfloat *)iter->data[0]; int iy, ix; for (iy = 0; iy < iter->roi[0].height; iy++) { int mask_offset = (iy + iter->roi[0].y - roi.y) * mask_stride + iter->roi[0].x - roi.x; const gfloat *mask_pixel = &mask_data[mask_offset]; for (ix = 0; ix < iter->roi[0].width; ix++) { if (opacity > out_pixel[0]) out_pixel[0] += (opacity - out_pixel[0]) * (*mask_pixel) * opacity; mask_pixel += 1; out_pixel += 1; } } } } else { g_warning("Mask format not supported: %s", babl_get_name (mask_format)); } } }
void do_layer_blend (GeglBuffer *src_buffer, GeglBuffer *dst_buffer, GimpTempBuf *paint_buf, GeglBuffer *mask_buffer, gfloat opacity, gint x_offset, gint y_offset, gint mask_x_offset, gint mask_y_offset, gboolean linear_mode, GimpLayerModeEffects paint_mode) { GeglRectangle roi; GeglRectangle mask_roi; GeglRectangle process_roi; const Babl *iterator_format; GeglBufferIterator *iter; const guint paint_stride = gimp_temp_buf_get_width (paint_buf); gfloat *paint_data = (gfloat *) gimp_temp_buf_get_data (paint_buf); GimpLayerModeFunction apply_func = get_layer_mode_function (paint_mode, linear_mode); if (linear_mode) iterator_format = babl_format ("RGBA float"); else iterator_format = babl_format ("R'G'B'A float"); roi.x = x_offset; roi.y = y_offset; roi.width = gimp_temp_buf_get_width (paint_buf); roi.height = gimp_temp_buf_get_height (paint_buf); mask_roi.x = roi.x - mask_x_offset; mask_roi.y = roi.y - mask_y_offset; mask_roi.width = roi.width; mask_roi.height = roi.height; g_return_if_fail (gimp_temp_buf_get_format (paint_buf) == iterator_format); iter = gegl_buffer_iterator_new (dst_buffer, &roi, 0, iterator_format, GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, src_buffer, &roi, 0, iterator_format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); if (mask_buffer) { gegl_buffer_iterator_add (iter, mask_buffer, &mask_roi, 0, babl_format ("Y float"), GEGL_ACCESS_READ, GEGL_ABYSS_NONE); } while (gegl_buffer_iterator_next (iter)) { gfloat *out_pixel = (gfloat *)iter->data[0]; gfloat *in_pixel = (gfloat *)iter->data[1]; gfloat *mask_pixel = NULL; gfloat *paint_pixel = paint_data + ((iter->roi[0].y - roi.y) * paint_stride + iter->roi[0].x - roi.x) * 4; int iy; if (mask_buffer) mask_pixel = (gfloat *)iter->data[2]; process_roi.x = iter->roi[0].x; process_roi.width = iter->roi[0].width; process_roi.height = 1; for (iy = 0; iy < iter->roi[0].height; iy++) { process_roi.y = iter->roi[0].y + iy; (*apply_func) (in_pixel, paint_pixel, mask_pixel, out_pixel, opacity, iter->roi[0].width, &process_roi, 0); in_pixel += iter->roi[0].width * 4; out_pixel += iter->roi[0].width * 4; if (mask_buffer) mask_pixel += iter->roi[0].width; paint_pixel += paint_stride * 4; } } }
gboolean gimp_edit_fill_full (GimpImage *image, GimpDrawable *drawable, const GimpRGB *color, GimpPattern *pattern, gdouble opacity, GimpLayerModeEffects paint_mode, const gchar *undo_desc) { GeglBuffer *dest_buffer; const Babl *format; gint x, y, width, height; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), FALSE); g_return_val_if_fail (color != NULL || pattern != NULL, FALSE); if (! gimp_item_mask_intersect (GIMP_ITEM (drawable), &x, &y, &width, &height)) return TRUE; /* nothing to do, but the fill succeeded */ if (pattern && babl_format_has_alpha (gimp_temp_buf_get_format (pattern->mask)) && ! gimp_drawable_has_alpha (drawable)) { format = gimp_drawable_get_format_with_alpha (drawable); } else { format = gimp_drawable_get_format (drawable); } dest_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), format); if (pattern) { GeglBuffer *src_buffer = gimp_pattern_create_buffer (pattern); gegl_buffer_set_pattern (dest_buffer, NULL, src_buffer, 0, 0); g_object_unref (src_buffer); } else { GeglColor *gegl_color = gimp_gegl_color_new (color); gegl_buffer_set_color (dest_buffer, NULL, gegl_color); g_object_unref (gegl_color); } gimp_drawable_apply_buffer (drawable, dest_buffer, GEGL_RECTANGLE (0, 0, width, height), TRUE, undo_desc, opacity, paint_mode, NULL, x, y); g_object_unref (dest_buffer); gimp_drawable_update (drawable, x, y, width, height); return TRUE; }
GdkPixbuf * gimp_image_get_new_pixbuf (GimpViewable *viewable, GimpContext *context, gint width, gint height) { GimpImage *image = GIMP_IMAGE (viewable); GdkPixbuf *pixbuf; gdouble scale_x; gdouble scale_y; GimpColorTransform *transform; scale_x = (gdouble) width / (gdouble) gimp_image_get_width (image); scale_y = (gdouble) height / (gdouble) gimp_image_get_height (image); pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); transform = gimp_image_get_color_transform_to_srgb_u8 (image); if (transform) { GimpTempBuf *temp_buf; GeglBuffer *src_buf; GeglBuffer *dest_buf; temp_buf = gimp_temp_buf_new (width, height, gimp_pickable_get_format (GIMP_PICKABLE (image))); gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)), GEGL_RECTANGLE (0, 0, width, height), MIN (scale_x, scale_y), gimp_temp_buf_get_format (temp_buf), gimp_temp_buf_get_data (temp_buf), GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); src_buf = gimp_temp_buf_create_buffer (temp_buf); dest_buf = gimp_pixbuf_create_buffer (pixbuf); gimp_temp_buf_unref (temp_buf); gimp_color_transform_process_buffer (transform, src_buf, GEGL_RECTANGLE (0, 0, width, height), dest_buf, GEGL_RECTANGLE (0, 0, 0, 0)); g_object_unref (src_buf); g_object_unref (dest_buf); } else { gegl_buffer_get (gimp_pickable_get_buffer (GIMP_PICKABLE (image)), GEGL_RECTANGLE (0, 0, width, height), MIN (scale_x, scale_y), gimp_pixbuf_get_format (pixbuf), gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_rowstride (pixbuf), GEGL_ABYSS_CLAMP); } return pixbuf; }
static GimpValueArray * gimp_pattern_select_run_callback (GimpPdbDialog *dialog, GimpObject *object, gboolean closing, GError **error) { GimpPattern *pattern = GIMP_PATTERN (object); GimpArray *array; GimpValueArray *return_vals; array = gimp_array_new (gimp_temp_buf_get_data (pattern->mask), gimp_temp_buf_get_data_size (pattern->mask), TRUE); return_vals = gimp_pdb_execute_procedure_by_name (dialog->pdb, dialog->caller_context, NULL, error, dialog->callback_name, G_TYPE_STRING, gimp_object_get_name (object), GIMP_TYPE_INT32, gimp_temp_buf_get_width (pattern->mask), GIMP_TYPE_INT32, gimp_temp_buf_get_height (pattern->mask), GIMP_TYPE_INT32, babl_format_get_bytes_per_pixel (gimp_temp_buf_get_format (pattern->mask)), GIMP_TYPE_INT32, array->length, GIMP_TYPE_INT8_ARRAY, array, GIMP_TYPE_INT32, closing, G_TYPE_NONE); gimp_array_free (array); return return_vals; }
static void gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer, GtkWidget *widget, GimpTempBuf *temp_buf, gint temp_buf_x, gint temp_buf_y, gint channel, GimpViewBG inside_bg, GimpViewBG outside_bg, cairo_surface_t *surface, gint surface_width, gint surface_height) { cairo_t *cr; gint x, y; gint width, height; const Babl *temp_buf_format; gint temp_buf_width; gint temp_buf_height; g_return_if_fail (temp_buf != NULL); g_return_if_fail (surface != NULL); temp_buf_format = gimp_temp_buf_get_format (temp_buf); temp_buf_width = gimp_temp_buf_get_width (temp_buf); temp_buf_height = gimp_temp_buf_get_height (temp_buf); /* Here are the different cases this functions handles correctly: * 1) Offset temp_buf which does not necessarily cover full image area * 2) Color conversion of temp_buf if it is gray and image is color * 3) Background check buffer for transparent temp_bufs * 4) Using the optional "channel" argument, one channel can be extracted * from a multi-channel temp_buf and composited as a grayscale * Prereqs: * 1) Grayscale temp_bufs have bytes == {1, 2} * 2) Color temp_bufs have bytes == {3, 4} * 3) If image is gray, then temp_buf should have bytes == {1, 2} */ cr = cairo_create (surface); if (outside_bg == GIMP_VIEW_BG_CHECKS || inside_bg == GIMP_VIEW_BG_CHECKS) { if (! renderer->pattern) renderer->pattern = gimp_cairo_checkerboard_create (cr, GIMP_CHECK_SIZE_SM, gimp_render_light_check_color (), gimp_render_dark_check_color ()); } switch (outside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_paint (cr); if (! gimp_rectangle_intersect (0, 0, surface_width, surface_height, temp_buf_x, temp_buf_y, temp_buf_width, temp_buf_height, &x, &y, &width, &height)) { cairo_destroy (cr); return; } if (inside_bg != outside_bg && babl_format_has_alpha (temp_buf_format) && channel == -1) { cairo_rectangle (cr, x, y, width, height); switch (inside_bg) { case GIMP_VIEW_BG_CHECKS: cairo_set_source (cr, renderer->pattern); break; case GIMP_VIEW_BG_WHITE: cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); break; } cairo_fill (cr); } if (babl_format_has_alpha (temp_buf_format) && channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_t *alpha_surface; alpha_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (alpha_surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (0, 0, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (alpha_surface); cairo_translate (cr, x, y); cairo_rectangle (cr, 0, 0, width, height); cairo_set_source_surface (cr, alpha_surface, 0, 0); cairo_fill (cr); cairo_surface_destroy (alpha_surface); } else if (channel == -1) { GeglBuffer *src_buffer; GeglBuffer *dest_buffer; cairo_surface_flush (surface); src_buffer = gimp_temp_buf_create_buffer (temp_buf); dest_buffer = gimp_cairo_surface_create_buffer (surface); if (! renderer->profile_transform) gimp_view_renderer_transform_create (renderer, widget, src_buffer, dest_buffer); if (renderer->profile_transform) { gimp_gegl_convert_color_transform (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), renderer->profile_src_format, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0), renderer->profile_dest_format, renderer->profile_transform); } else { gegl_buffer_copy (src_buffer, GEGL_RECTANGLE (x - temp_buf_x, y - temp_buf_y, width, height), GEGL_ABYSS_NONE, dest_buffer, GEGL_RECTANGLE (x, y, 0, 0)); } g_object_unref (src_buffer); g_object_unref (dest_buffer); cairo_surface_mark_dirty (surface); } else { const Babl *fish; const guchar *src; guchar *dest; gint dest_stride; gint bytes; gint rowstride; gint i; cairo_surface_flush (surface); bytes = babl_format_get_bytes_per_pixel (temp_buf_format); rowstride = temp_buf_width * bytes; src = gimp_temp_buf_get_data (temp_buf) + ((y - temp_buf_y) * rowstride + (x - temp_buf_x) * bytes); dest = cairo_image_surface_get_data (surface); dest_stride = cairo_image_surface_get_stride (surface); dest += y * dest_stride + x * 4; fish = babl_fish (temp_buf_format, babl_format ("cairo-RGB24")); for (i = y; i < (y + height); i++) { const guchar *s = src; guchar *d = dest; gint j; for (j = x; j < (x + width); j++, d += 4, s += bytes) { if (bytes > 2) { guchar pixel[4] = { s[channel], s[channel], s[channel], 255 }; babl_process (fish, pixel, d, 1); } else { guchar pixel[2] = { s[channel], 255 }; babl_process (fish, pixel, d, 1); } } src += rowstride; dest += dest_stride; } cairo_surface_mark_dirty (surface); } cairo_destroy (cr); }