void gimp_paint_core_validate_saved_proj_tiles (GimpPaintCore *core, GimpPickable *pickable, gint x, gint y, gint w, gint h) { gint i, j; g_return_if_fail (GIMP_IS_PAINT_CORE (core)); g_return_if_fail (GIMP_IS_PICKABLE (pickable)); g_return_if_fail (core->saved_proj_tiles != NULL); for (i = y; i < (y + h); i += (TILE_HEIGHT - (i % TILE_HEIGHT))) { for (j = x; j < (x + w); j += (TILE_WIDTH - (j % TILE_WIDTH))) { Tile *dest_tile = tile_manager_get_tile (core->saved_proj_tiles, j, i, FALSE, FALSE); if (! tile_is_valid (dest_tile)) { Tile *src_tile = tile_manager_get_tile (gimp_pickable_get_tiles (pickable), j, i, TRUE, FALSE); tile_manager_map_tile (core->saved_proj_tiles, j, i, src_tile); tile_release (src_tile, FALSE); } } } }
void gimp_pickable_srgb_to_pixel (GimpPickable *pickable, const GimpRGB *color, const Babl *format, gpointer pixel) { GimpPickableInterface *pickable_iface; g_return_if_fail (GIMP_IS_PICKABLE (pickable)); g_return_if_fail (color != NULL); g_return_if_fail (pixel != NULL); if (! format) format = gimp_pickable_get_format (pickable); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->srgb_to_pixel) { pickable_iface->srgb_to_pixel (pickable, color, format, pixel); } else { gimp_rgba_get_pixel (color, format, pixel); } }
gboolean gimp_pickable_pick_color (GimpPickable *pickable, gint x, gint y, gboolean sample_average, gdouble average_radius, gpointer pixel, GimpRGB *color) { const Babl *format; gdouble sample[4]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); format = gimp_pickable_get_format (pickable); if (! gimp_pickable_get_pixel_at (pickable, x, y, format, sample)) return FALSE; gimp_pickable_pixel_to_srgb (pickable, format, sample, color); if (pixel) memcpy (pixel, sample, babl_format_get_bytes_per_pixel (format)); if (sample_average) { gint count = 0; gdouble color_avg[4] = { 0.0, 0.0, 0.0, 0.0 }; gint radius = (gint) average_radius; gint i, j; format = babl_format ("RaGaBaA double"); for (i = x - radius; i <= x + radius; i++) for (j = y - radius; j <= y + radius; j++) if (gimp_pickable_get_pixel_at (pickable, i, j, format, sample)) { count++; color_avg[RED] += sample[RED]; color_avg[GREEN] += sample[GREEN]; color_avg[BLUE] += sample[BLUE]; color_avg[ALPHA] += sample[ALPHA]; } sample[RED] = color_avg[RED] / count; sample[GREEN] = color_avg[GREEN] / count; sample[BLUE] = color_avg[BLUE] / count; sample[ALPHA] = color_avg[ALPHA] / count; gimp_pickable_pixel_to_srgb (pickable, format, sample, color); } return TRUE; }
void gimp_pickable_flush (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_if_fail (GIMP_IS_PICKABLE (pickable)); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->flush) pickable_iface->flush (pickable); }
TileManager * gimp_pickable_get_tiles (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_tiles) return pickable_iface->get_tiles (pickable); return NULL; }
gint gimp_pickable_get_bytes (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), 0); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_bytes) return pickable_iface->get_bytes (pickable); return 0; }
const Babl * gimp_pickable_get_format (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_format) return pickable_iface->get_format (pickable); return NULL; }
GimpImage * gimp_pickable_get_image (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_image) return pickable_iface->get_image (pickable); return NULL; }
GeglBuffer * gimp_pickable_get_buffer (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_buffer) return pickable_iface->get_buffer (pickable); return NULL; }
void gimp_pickable_srgb_to_image_color (GimpPickable *pickable, const GimpRGB *color, GimpRGB *image_color) { g_return_if_fail (GIMP_IS_PICKABLE (pickable)); g_return_if_fail (color != NULL); g_return_if_fail (image_color != NULL); gimp_pickable_srgb_to_pixel (pickable, color, babl_format ("R'G'B'A double"), image_color); }
GimpImageType gimp_pickable_get_image_type (GimpPickable *pickable) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), -1); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_image_type) return pickable_iface->get_image_type (pickable); return -1; }
gdouble gimp_pickable_get_opacity_at (GimpPickable *pickable, gint x, gint y) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), GIMP_OPACITY_TRANSPARENT); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_opacity_at) return pickable_iface->get_opacity_at (pickable, x, y); return GIMP_OPACITY_TRANSPARENT; }
gint gimp_pickable_get_opacity_at (GimpPickable *pickable, gint x, gint y) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), 0); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_opacity_at) return pickable_iface->get_opacity_at (pickable, x, y); return 0; }
gboolean gimp_pickable_get_pixel_at (GimpPickable *pickable, gint x, gint y, guchar *pixel) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); g_return_val_if_fail (pixel != NULL, FALSE); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_pixel_at) return pickable_iface->get_pixel_at (pickable, x, y, pixel); return FALSE; }
gboolean gimp_pickable_get_color_at (GimpPickable *pickable, gint x, gint y, GimpRGB *color) { guchar pixel[32]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); g_return_val_if_fail (color != NULL, FALSE); if (! gimp_pickable_get_pixel_at (pickable, x, y, NULL, pixel)) return FALSE; gimp_rgba_set_pixel (color, gimp_pickable_get_format (pickable), pixel); return TRUE; }
gboolean gimp_pickable_get_pixel_at (GimpPickable *pickable, gint x, gint y, const Babl *format, gpointer pixel) { GimpPickableInterface *pickable_iface; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); g_return_val_if_fail (pixel != NULL, FALSE); if (! format) format = gimp_pickable_get_format (pickable); pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable); if (pickable_iface->get_pixel_at) return pickable_iface->get_pixel_at (pickable, x, y, format, pixel); return FALSE; }
gboolean gimp_pickable_get_color_at (GimpPickable *pickable, gint x, gint y, GimpRGB *color) { guchar pixel[4]; guchar col[4]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); g_return_val_if_fail (color != NULL, FALSE); if (! gimp_pickable_get_pixel_at (pickable, x, y, pixel)) return FALSE; gimp_image_get_color (gimp_pickable_get_image (pickable), gimp_pickable_get_image_type (pickable), pixel, col); gimp_rgba_set_uchar (color, col[0], col[1], col[2], col[3]); return TRUE; }
GeglBuffer * gimp_pickable_contiguous_region_by_color (GimpPickable *pickable, gboolean antialias, gfloat threshold, gboolean select_transparent, GimpSelectCriterion select_criterion, const GimpRGB *color) { /* Scan over the pickable's active layer, finding pixels within the * specified threshold from the given R, G, & B values. If * antialiasing is on, use the same antialiasing scheme as in * fuzzy_select. Modify the pickable's mask to reflect the * additional selection */ GeglBufferIterator *iter; GeglBuffer *src_buffer; GeglBuffer *mask_buffer; const Babl *format; gint n_components; gboolean has_alpha; gfloat start_col[MAX_CHANNELS]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); g_return_val_if_fail (color != NULL, NULL); gimp_pickable_flush (pickable); src_buffer = gimp_pickable_get_buffer (pickable); format = choose_format (src_buffer, select_criterion, &n_components, &has_alpha); gimp_rgba_get_pixel (color, format, start_col); if (has_alpha) { if (select_transparent) { /* don't select transparancy if "color" isn't fully transparent */ if (start_col[n_components - 1] > 0.0) select_transparent = FALSE; } } else { select_transparent = FALSE; } mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), babl_format ("Y float")); iter = gegl_buffer_iterator_new (src_buffer, NULL, 0, format, GEGL_ACCESS_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, mask_buffer, NULL, 0, babl_format ("Y float"), GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { const gfloat *src = iter->data[0]; gfloat *dest = iter->data[1]; gint count = iter->length; while (count--) { /* Find how closely the colors match */ *dest = pixel_difference (start_col, src, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); src += n_components; dest += 1; } } return mask_buffer; }
gboolean gimp_pickable_pick_color (GimpPickable *pickable, gint x, gint y, gboolean sample_average, gdouble average_radius, GimpRGB *color, gint *color_index) { const Babl *format; gdouble pixel[4]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); format = babl_format ("RGBA double"); if (! gimp_pickable_get_pixel_at (pickable, x, y, format, pixel)) return FALSE; if (sample_average) { gint count = 0; gdouble color_avg[4] = { 0.0, 0.0, 0.0, 0.0 }; gint radius = (gint) average_radius; gint i, j; for (i = x - radius; i <= x + radius; i++) for (j = y - radius; j <= y + radius; j++) if (gimp_pickable_get_pixel_at (pickable, i, j, format, pixel)) { count++; color_avg[RED] += pixel[RED]; color_avg[GREEN] += pixel[GREEN]; color_avg[BLUE] += pixel[BLUE]; color_avg[ALPHA] += pixel[ALPHA]; } pixel[RED] = color_avg[RED] / count; pixel[GREEN] = color_avg[GREEN] / count; pixel[BLUE] = color_avg[BLUE] / count; pixel[ALPHA] = color_avg[ALPHA] / count; } gimp_rgba_set_pixel (color, format, pixel); if (color_index) { format = gimp_pickable_get_format (pickable); if (babl_format_is_palette (format) && ! sample_average) { guchar indexed_pixel[4]; gimp_pickable_get_pixel_at (pickable, x, y, format, indexed_pixel); *color_index = indexed_pixel[0]; } else { *color_index = -1; } } return TRUE; }
GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, gboolean antialias, gfloat threshold, gboolean select_transparent, GimpSelectCriterion select_criterion, gboolean diagonal_neighbors, gint x, gint y) { GeglBuffer *src_buffer; GeglBuffer *mask_buffer; const Babl *format; GeglRectangle extent; gint n_components; gboolean has_alpha; gfloat start_col[MAX_CHANNELS]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); gimp_pickable_flush (pickable); src_buffer = gimp_pickable_get_buffer (pickable); format = choose_format (src_buffer, select_criterion, &n_components, &has_alpha); gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); if (has_alpha) { if (select_transparent) { /* don't select transparent regions if the start pixel isn't * fully transparent */ if (start_col[n_components - 1] > 0) select_transparent = FALSE; } } else { select_transparent = FALSE; } extent = *gegl_buffer_get_extent (src_buffer); mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float")); if (x >= extent.x && x < (extent.x + extent.width) && y >= extent.y && y < (extent.y + extent.height)) { GIMP_TIMER_START(); find_contiguous_region (src_buffer, mask_buffer, format, n_components, has_alpha, select_transparent, select_criterion, antialias, threshold, diagonal_neighbors, x, y, start_col); GIMP_TIMER_END("foo"); } return mask_buffer; }
TempBuf * gimp_paint_core_get_orig_proj (GimpPaintCore *core, GimpPickable *pickable, gint x, gint y, gint width, gint height) { TileManager *src_tiles; PixelRegion srcPR; PixelRegion destPR; Tile *saved_tile; gboolean release_tile; gint h; gint pixelwidth; gint pickable_width; gint pickable_height; const guchar *s; guchar *d; gpointer pr; g_return_val_if_fail (GIMP_IS_PAINT_CORE (core), NULL); g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL); g_return_val_if_fail (core->saved_proj_tiles != NULL, NULL); core->orig_proj_buf = temp_buf_resize (core->orig_proj_buf, gimp_pickable_get_bytes (pickable), x, y, width, height); src_tiles = gimp_pickable_get_tiles (pickable); pickable_width = tile_manager_width (src_tiles); pickable_height = tile_manager_height (src_tiles); gimp_rectangle_intersect (x, y, width, height, 0, 0, pickable_width, pickable_height, &x, &y, &width, &height); /* configure the pixel regions */ pixel_region_init (&srcPR, src_tiles, x, y, width, height, FALSE); pixel_region_init_temp_buf (&destPR, core->orig_proj_buf, x - core->orig_proj_buf->x, y - core->orig_proj_buf->y, width, height); for (pr = pixel_regions_register (2, &srcPR, &destPR); pr != NULL; pr = pixel_regions_process (pr)) { /* If the saved tile corresponding to this location is valid, use it */ saved_tile = tile_manager_get_tile (core->saved_proj_tiles, srcPR.x, srcPR.y, FALSE, FALSE); if (tile_is_valid (saved_tile)) { release_tile = TRUE; saved_tile = tile_manager_get_tile (core->saved_proj_tiles, srcPR.x, srcPR.y, TRUE, FALSE); s = tile_data_pointer (saved_tile, srcPR.x, srcPR.y); } else { release_tile = FALSE; s = srcPR.data; } d = destPR.data; pixelwidth = srcPR.w * srcPR.bytes; h = srcPR.h; while (h --) { memcpy (d, s, pixelwidth); s += srcPR.rowstride; d += destPR.rowstride; } if (release_tile) tile_release (saved_tile, FALSE); } return core->orig_proj_buf; }
gboolean gimp_pickable_pick_color (GimpPickable *pickable, gint x, gint y, gboolean sample_average, gdouble average_radius, GimpRGB *color, gint *color_index) { GimpImage *image; GimpImageType type; guchar pixel[4]; guchar col[4]; g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE); if (! gimp_pickable_get_pixel_at (pickable, x, y, pixel)) return FALSE; image = gimp_pickable_get_image (pickable); type = gimp_pickable_get_image_type (pickable); if (sample_average) { gint count = 0; gint color_avg[4] = { 0, 0, 0, 0 }; gint radius = (gint) average_radius; gint i, j; for (i = x - radius; i <= x + radius; i++) for (j = y - radius; j <= y + radius; j++) if (gimp_pickable_get_pixel_at (pickable, i, j, pixel)) { count++; gimp_image_get_color (image, type, pixel, col); color_avg[RED] += col[RED]; color_avg[GREEN] += col[GREEN]; color_avg[BLUE] += col[BLUE]; color_avg[ALPHA] += col[ALPHA]; } col[RED] = (guchar) ((color_avg[RED] + count / 2) / count); col[GREEN] = (guchar) ((color_avg[GREEN] + count / 2) / count); col[BLUE] = (guchar) ((color_avg[BLUE] + count / 2) / count); col[ALPHA] = (guchar) ((color_avg[ALPHA] + count / 2) / count); } else { gimp_image_get_color (image, type, pixel, col); } gimp_rgba_set_uchar (color, col[RED], col[GREEN], col[BLUE], col[ALPHA]); if (color_index) { if (GIMP_IMAGE_TYPE_IS_INDEXED (type) && ! sample_average) *color_index = pixel[0]; else *color_index = -1; } return TRUE; }