void gimp_channel_select_channel (GimpChannel *channel, const gchar *undo_desc, GimpChannel *add_on, gint offset_x, gint offset_y, GimpChannelOps op, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); g_return_if_fail (undo_desc != NULL); g_return_if_fail (GIMP_IS_CHANNEL (add_on)); gimp_channel_push_undo (channel, undo_desc); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); if (feather || op == GIMP_CHANNEL_OP_INTERSECT) { GimpItem *item = GIMP_ITEM (channel); GimpChannel *add_on2; add_on2 = gimp_channel_new_mask (gimp_item_get_image (item), gimp_item_width (item), gimp_item_height (item)); gimp_channel_combine_mask (add_on2, add_on, GIMP_CHANNEL_OP_ADD, offset_x, offset_y); if (feather) gimp_channel_feather (add_on2, feather_radius_x, feather_radius_y, FALSE /* no undo */); gimp_channel_combine_mask (channel, add_on2, op, 0, 0); g_object_unref (add_on2); } else { gimp_channel_combine_mask (channel, add_on, op, offset_x, offset_y); } }
static GValueArray * channel_combine_masks_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GValueArray *args) { gboolean success = TRUE; GimpChannel *channel1; GimpChannel *channel2; gint32 operation; gint32 offx; gint32 offy; channel1 = gimp_value_get_channel (&args->values[0], gimp); channel2 = gimp_value_get_channel (&args->values[1], gimp); operation = g_value_get_enum (&args->values[2]); offx = g_value_get_int (&args->values[3]); offy = g_value_get_int (&args->values[4]); if (success) { gimp_channel_push_undo (channel1, _("Combine Masks")); gimp_channel_combine_mask (channel1, channel2, operation, offx, offy); } return gimp_procedure_get_return_values (procedure, success); }
static GimpValueArray * channel_combine_masks_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GimpValueArray *args, GError **error) { gboolean success = TRUE; GimpChannel *channel1; GimpChannel *channel2; gint32 operation; gint32 offx; gint32 offy; channel1 = gimp_value_get_channel (gimp_value_array_index (args, 0), gimp); channel2 = gimp_value_get_channel (gimp_value_array_index (args, 1), gimp); operation = g_value_get_enum (gimp_value_array_index (args, 2)); offx = g_value_get_int (gimp_value_array_index (args, 3)); offy = g_value_get_int (gimp_value_array_index (args, 4)); if (success) { gimp_channel_push_undo (channel1, _("Combine Masks")); gimp_channel_combine_mask (channel1, channel2, operation, offx, offy); } return gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); }
void gimp_channel_select_round_rect (GimpChannel *channel, gint x, gint y, gint w, gint h, gdouble corner_radius_x, gdouble corner_radius_y, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y, gboolean push_undo) { g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); if (push_undo) gimp_channel_push_undo (channel, Q_("command|Rounded Rectangle Select")); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); /* if feathering for rect, make a new mask with the * rectangle and feather that with the old mask */ if (feather || op == GIMP_CHANNEL_OP_INTERSECT) { GimpItem *item = GIMP_ITEM (channel); GimpChannel *add_on; add_on = gimp_channel_new_mask (gimp_item_get_image (item), gimp_item_width (item), gimp_item_height (item)); gimp_channel_combine_ellipse_rect (add_on, GIMP_CHANNEL_OP_ADD, x, y, w, h, corner_radius_x, corner_radius_y, antialias); if (feather) gimp_channel_feather (add_on, feather_radius_x, feather_radius_y, FALSE /* no undo */); gimp_channel_combine_mask (channel, add_on, op, 0, 0); g_object_unref (add_on); } else { gimp_channel_combine_ellipse_rect (channel, op, x, y, w, h, corner_radius_x, corner_radius_y, antialias); } }
void gimp_channel_select_scan_convert (GimpChannel *channel, const gchar *undo_desc, GimpScanConvert *scan_convert, gint offset_x, gint offset_y, GimpChannelOps op, gboolean antialias, gboolean feather, gdouble feather_radius_x, gdouble feather_radius_y, gboolean push_undo) { GimpItem *item; GimpChannel *add_on; g_return_if_fail (GIMP_IS_CHANNEL (channel)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (channel))); g_return_if_fail (undo_desc != NULL); g_return_if_fail (scan_convert != NULL); if (push_undo) gimp_channel_push_undo (channel, undo_desc); /* if applicable, replace the current selection */ if (op == GIMP_CHANNEL_OP_REPLACE) gimp_channel_clear (channel, NULL, FALSE); item = GIMP_ITEM (channel); add_on = gimp_channel_new_mask (gimp_item_get_image (item), gimp_item_width (item), gimp_item_height (item)); gimp_scan_convert_render (scan_convert, gimp_drawable_get_tiles (GIMP_DRAWABLE (add_on)), offset_x, offset_y, antialias); if (feather) gimp_channel_feather (add_on, feather_radius_x, feather_radius_y, FALSE /* no undo */); gimp_channel_combine_mask (channel, add_on, op, 0, 0); g_object_unref (add_on); }
void gimp_drawable_bucket_fill_full (GimpDrawable *drawable, GimpBucketFillMode fill_mode, gint paint_mode, gdouble opacity, gboolean do_seed_fill, gboolean fill_transparent, GimpSelectCriterion fill_criterion, gdouble threshold, gboolean sample_merged, gdouble x, gdouble y, const GimpRGB *color, GimpPattern *pattern) { GimpImage *image; TileManager *buf_tiles; PixelRegion bufPR, maskPR; GimpChannel *mask = NULL; gint bytes; gint x1, y1, x2, y2; guchar col[MAX_CHANNELS]; TempBuf *pat_buf = NULL; gboolean new_buf = FALSE; gboolean selection; g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); g_return_if_fail (fill_mode != GIMP_PATTERN_BUCKET_FILL || GIMP_IS_PATTERN (pattern)); g_return_if_fail (fill_mode == GIMP_PATTERN_BUCKET_FILL || color != NULL); image = gimp_item_get_image (GIMP_ITEM (drawable)); bytes = gimp_drawable_bytes (drawable); selection = gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2); if ((x1 == x2) || (y1 == y2)) return; if (fill_mode == GIMP_FG_BUCKET_FILL || fill_mode == GIMP_BG_BUCKET_FILL) { guchar tmp_col[MAX_CHANNELS]; gimp_rgb_get_uchar (color, &tmp_col[RED], &tmp_col[GREEN], &tmp_col[BLUE]); gimp_image_transform_color (image, gimp_drawable_type (drawable), col, GIMP_RGB, tmp_col); col[gimp_drawable_bytes_with_alpha (drawable) - 1] = OPAQUE_OPACITY; } else if (fill_mode == GIMP_PATTERN_BUCKET_FILL) { pat_buf = gimp_image_transform_temp_buf (image, gimp_drawable_type (drawable), pattern->mask, &new_buf); } else { g_warning ("%s: invalid fill_mode passed", G_STRFUNC); return; } gimp_set_busy (image->gimp); /* Do a seed bucket fill...To do this, calculate a new * contiguous region. If there is a selection, calculate the * intersection of this region with the existing selection. */ if (do_seed_fill) { mask = gimp_image_contiguous_region_by_seed (image, drawable, sample_merged, TRUE, (gint) threshold, fill_transparent, fill_criterion, (gint) x, (gint) y); if (selection) { gint off_x = 0; gint off_y = 0; if (! sample_merged) gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); gimp_channel_combine_mask (mask, gimp_image_get_mask (image), GIMP_CHANNEL_OP_INTERSECT, -off_x, -off_y); } gimp_channel_bounds (mask, &x1, &y1, &x2, &y2); /* make sure we handle the mask correctly if it was sample-merged */ if (sample_merged) { GimpItem *item; gint off_x, off_y; item = GIMP_ITEM (drawable); /* Limit the channel bounds to the drawable's extents */ gimp_item_get_offset (item, &off_x, &off_y); x1 = CLAMP (x1, off_x, (off_x + gimp_item_get_width (item))); y1 = CLAMP (y1, off_y, (off_y + gimp_item_get_height (item))); x2 = CLAMP (x2, off_x, (off_x + gimp_item_get_width (item))); y2 = CLAMP (y2, off_y, (off_y + gimp_item_get_height (item))); pixel_region_init (&maskPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)), x1, y1, (x2 - x1), (y2 - y1), TRUE); /* translate mask bounds to drawable coords */ x1 -= off_x; y1 -= off_y; x2 -= off_x; y2 -= off_y; } else { pixel_region_init (&maskPR, gimp_drawable_get_tiles (GIMP_DRAWABLE (mask)), x1, y1, (x2 - x1), (y2 - y1), TRUE); } /* if the image doesn't have an alpha channel, make sure that * the buf_tiles have. We need the alpha channel to fill with * the region calculated above */ if (! gimp_drawable_has_alpha (drawable)) bytes++; } else if (fill_mode == GIMP_PATTERN_BUCKET_FILL && (pat_buf->bytes == 2 || pat_buf->bytes == 4)) { /* If pattern being applied has an alpha channel, add one to the * buf_tiles. */ if (! gimp_drawable_has_alpha (drawable)) bytes++; } buf_tiles = tile_manager_new ((x2 - x1), (y2 - y1), bytes); pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), TRUE); switch (fill_mode) { case GIMP_FG_BUCKET_FILL: case GIMP_BG_BUCKET_FILL: if (mask) color_region_mask (&bufPR, &maskPR, col); else color_region (&bufPR, col); break; case GIMP_PATTERN_BUCKET_FILL: if (mask) pattern_region (&bufPR, &maskPR, pat_buf, x1, y1); else pattern_region (&bufPR, NULL, pat_buf, x1, y1); break; } /* Apply it to the image */ pixel_region_init (&bufPR, buf_tiles, 0, 0, (x2 - x1), (y2 - y1), FALSE); gimp_drawable_apply_region (drawable, &bufPR, TRUE, C_("undo-type", "Bucket Fill"), opacity, paint_mode, NULL, NULL, x1, y1); tile_manager_unref (buf_tiles); /* update the image */ gimp_drawable_update (drawable, x1, y1, x2 - x1, y2 - y1); /* free the mask */ if (mask) g_object_unref (mask); if (new_buf) temp_buf_free (pat_buf); gimp_unset_busy (image->gimp); }