static void transfer_registration_color (const guchar *src, gint bpp, gint numpix, guchar **dst, gint num_channels) { register const guchar *rgb_src = src; guchar *dsts[4]; register gint count = numpix; gint channel; GimpRGB color; guchar red, green, blue; gimp_context_get_foreground (&color); gimp_rgb_get_uchar (&color, &red, &green, &blue); for (channel = 0; channel < num_channels; channel++) dsts[channel] = dst[channel]; while (count-- > 0) { if (rgb_src[0] == red && rgb_src[1] == green && rgb_src[2] == blue) for (channel = 0; channel < num_channels; channel++) *(dsts[channel]++) = 255; else for (channel = 0; channel < num_channels; channel++) dsts[channel]++; rgb_src += bpp; } }
static guchar best_cmap_match (const guchar *cmap, gint ncolors, const GimpRGB *color) { guchar cmap_index = 0; gint max = MAXDIFF; gint i, diff, sum; guchar r, g, b; gimp_rgb_get_uchar (color, &r, &g, &b); for (i = 0; i < ncolors; i++) { diff = r - *cmap++; sum = SQR (diff); diff = g - *cmap++; sum += SQR (diff); diff = b - *cmap++; sum += SQR (diff); if (sum < max) { cmap_index = i; max = sum; } } return cmap_index; }
/** * gimp_color_hex_entry_set_color: * @entry: a #GimpColorHexEntry widget * @color: pointer to a #GimpRGB * * Sets the color displayed by a #GimpColorHexEntry. If the new color * is different to the previously set color, the "color-changed" * signal is emitted. * * Since: GIMP 2.2 **/ void gimp_color_hex_entry_set_color (GimpColorHexEntry *entry, const GimpRGB *color) { g_return_if_fail (GIMP_IS_COLOR_HEX_ENTRY (entry)); g_return_if_fail (color != NULL); if (gimp_rgb_distance (&entry->color, color) > 0.0) { gchar buffer[8]; guchar r, g, b; gimp_rgb_set (&entry->color, color->r, color->g, color->b); gimp_rgb_clamp (&entry->color); gimp_rgb_get_uchar (&entry->color, &r, &g, &b); g_snprintf (buffer, sizeof (buffer), "%.2x%.2x%.2x", r, g, b); gtk_entry_set_text (GTK_ENTRY (entry), buffer); /* move cursor to the end */ gtk_editable_set_position (GTK_EDITABLE (entry), -1); g_signal_emit (entry, entry_signals[COLOR_CHANGED], 0); } }
GtkTextTag * gimp_text_buffer_get_color_tag (GimpTextBuffer *buffer, const GimpRGB *color) { GList *list; GtkTextTag *tag; gchar name[256]; GdkColor gdk_color; guchar r, g, b; gimp_rgb_get_uchar (color, &r, &g, &b); for (list = buffer->color_tags; list; list = g_list_next (list)) { GimpRGB tag_color; guchar tag_r, tag_g, tag_b; tag = list->data; gimp_text_tag_get_color (tag, &tag_color); gimp_rgb_get_uchar (&tag_color, &tag_r, &tag_g, &tag_b); /* Do not compare the alpha channel, since it's unused */ if (tag_r == r && tag_g == g && tag_b == b) { return tag; } } g_snprintf (name, sizeof (name), "color-#%02x%02x%02x", r, g, b); gimp_rgb_get_gdk_color (color, &gdk_color); tag = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (buffer), name, "foreground-gdk", &gdk_color, "foreground-set", TRUE, NULL); buffer->color_tags = g_list_prepend (buffer->color_tags, tag); return tag; }
static gboolean gimp_color_hex_entry_events (GtkWidget *widget, GdkEvent *event) { GimpColorHexEntry *entry = GIMP_COLOR_HEX_ENTRY (widget); switch (event->type) { case GDK_KEY_PRESS: { GdkEventKey *kevent = (GdkEventKey *) event; if (kevent->keyval != GDK_KEY_Return && kevent->keyval != GDK_KEY_KP_Enter && kevent->keyval != GDK_KEY_ISO_Enter) break; /* else fall through */ } case GDK_FOCUS_CHANGE: { const gchar *text; gchar buffer[8]; guchar r, g, b; text = gtk_entry_get_text (GTK_ENTRY (widget)); gimp_rgb_get_uchar (&entry->color, &r, &g, &b); g_snprintf (buffer, sizeof (buffer), "%.2x%.2x%.2x", r, g, b); if (g_ascii_strcasecmp (buffer, text) != 0) { GimpRGB color; gsize len = strlen (text); if (len > 0 && (gimp_rgb_parse_hex (&color, text, len) || gimp_rgb_parse_name (&color, text, -1))) { gimp_color_hex_entry_set_color (entry, &color); } else { gtk_entry_set_text (GTK_ENTRY (entry), buffer); } } } break; default: /* do nothing */ break; } return FALSE; }
static VALUE rb_gimp_rgb_get_uchar (VALUE self) { Get_TypedStruct(self, GimpRGB, color); guchar r, g, b; gimp_rgb_get_uchar(color, &r, &g, &b); return rb_ary_new3(3, INT2FIX(r), INT2FIX(g), INT2FIX(b)); }
void get_colors (GimpDrawable *drawable, guint8 *fg, guint8 *bg) { GimpRGB foreground; GimpRGB background; gimp_context_get_foreground (&foreground); gimp_context_get_background (&background); fg[0] = fg[1] = fg[2] = fg[3] = 255; bg[0] = bg[1] = bg[2] = bg[3] = 255; switch (gimp_drawable_type (drawable->drawable_id)) { case GIMP_RGB_IMAGE: case GIMP_RGBA_IMAGE: gimp_rgb_get_uchar (&foreground, &fg[0], &fg[1], &fg[2]); gimp_rgb_get_uchar (&background, &bg[0], &bg[1], &bg[2]); break; case GIMP_GRAYA_IMAGE: case GIMP_GRAY_IMAGE: fg[0] = gimp_rgb_luminance_uchar (&foreground); bg[0] = gimp_rgb_luminance_uchar (&background); break; case GIMP_INDEXEDA_IMAGE: case GIMP_INDEXED_IMAGE: /* FIXME: Should use current fg/bg colors. */ g_warning("maze: get_colors: Indexed image. Using colors 15 and 0.\n"); fg[0] = 15; /* As a plugin, I protest. *I* shouldn't be the */ bg[0] = 0; /* one who has to deal with this colormapcrap. */ break; default: break; } }
static void transform (guchar *r, guchar *g, guchar *b) { switch (wvals.colormodel) { case HSL_MODEL: { GimpHSL hsl; GimpRGB rgb; gimp_rgb_set_uchar (&rgb, *r, *g, *b); gimp_rgb_to_hsl (&rgb, &hsl); if (wvals.redmode) hsl.h = 0.5 * (1.0 + sin (((2 * hsl.h - 1.0) * wvals.redfrequency + wvals.redangle / 180.0) * G_PI)); if (wvals.greenmode) hsl.s = 0.5 * (1.0 + sin (((2 * hsl.s - 1.0) * wvals.greenfrequency + wvals.greenangle / 180.0) * G_PI)); if (wvals.bluemode) hsl.l = 0.5 * (1.0 + sin (((2 * hsl.l - 1.0) * wvals.bluefrequency + wvals.blueangle / 180.0) * G_PI)); gimp_hsl_to_rgb (&hsl, &rgb); gimp_rgb_get_uchar (&rgb, r, g, b); } break; case RGB_MODEL: if (wvals.redmode) *r = ROUND (127.5 * (1.0 + sin (((*r / 127.5 - 1.0) * wvals.redfrequency + wvals.redangle / 180.0) * G_PI))); if (wvals.greenmode) *g = ROUND (127.5 * (1.0 + sin (((*g / 127.5 - 1.0) * wvals.greenfrequency + wvals.greenangle / 180.0) * G_PI))); if (wvals.bluemode) *b = ROUND (127.5 * (1.0 + sin (((*b / 127.5 - 1.0) * wvals.bluefrequency + wvals.blueangle / 180.0) * G_PI))); break; } }
/* Returns: %TRUE if the XOR color is not white */ static gboolean gimp_canvas_get_xor_color (GimpCanvas *canvas, GdkColor *color) { GimpDisplayConfig *config = GIMP_DISPLAY_CONFIG (canvas->gimp->config); guchar r, g, b; gimp_rgb_get_uchar (&config->xor_color, &r, &g, &b); color->red = (r << 8) | r; color->green = (g << 8) | g; color->blue = (b << 8) | b; return (r != 255 || g != 255 || b != 255); }
/** * gimp_rgb_get_gdk_color: * @rgb: the source color as #GimpRGB * @gdk_color: pointer to a #GdkColor * * Initializes @gdk_color from a #GimpRGB. This function does not * allocate the color for you. Depending on how you want to use it, * you may have to call gdk_colormap_alloc_color(). **/ void gimp_rgb_get_gdk_color (const GimpRGB *rgb, GdkColor *gdk_color) { guchar r, g, b; g_return_if_fail (rgb != NULL); g_return_if_fail (gdk_color != NULL); gimp_rgb_get_uchar (rgb, &r, &g, &b); gdk_color->red = (r << 8) | r; gdk_color->green = (g << 8) | g; gdk_color->blue = (b << 8) | b; }
gboolean gimp_palette_save (GimpData *data, GOutputStream *output, GError **error) { GimpPalette *palette = GIMP_PALETTE (data); GString *string; GList *list; gsize bytes_written; string = g_string_new ("GIMP Palette\n"); g_string_append_printf (string, "Name: %s\n" "Columns: %d\n" "#\n", gimp_object_get_name (palette), CLAMP (gimp_palette_get_columns (palette), 0, 256)); for (list = gimp_palette_get_colors (palette); list; list = g_list_next (list)) { GimpPaletteEntry *entry = list->data; guchar r, g, b; gimp_rgb_get_uchar (&entry->color, &r, &g, &b); g_string_append_printf (string, "%3d %3d %3d\t%s\n", r, g, b, entry->name); } if (! g_output_stream_write_all (output, string->str, string->len, &bytes_written, NULL, error) || bytes_written != string->len) { g_string_free (string, TRUE); return FALSE; } g_string_free (string, TRUE); return TRUE; }
static void initialize_background (GimpImageType image_type, gint channels, guchar *here, guchar *best, void **tmp) { GimpRGB background; guchar *ch; if (*tmp == NULL) { *tmp = (void *) g_new (guchar, 3); ch = (guchar *)*tmp; gimp_context_get_background (&background); gimp_rgb_get_uchar (&background, &ch[0], &ch[1], &ch[2]); } }
void gimp_image_add_colormap_entry (GimpImage *image, const GimpRGB *color) { g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (image->colormap != NULL); g_return_if_fail (image->n_colors < 256); g_return_if_fail (color != NULL); gimp_image_undo_push_image_colormap (image, _("Add Color to Colormap")); gimp_rgb_get_uchar (color, &image->colormap[image->n_colors * 3], &image->colormap[image->n_colors * 3 + 1], &image->colormap[image->n_colors * 3 + 2]); image->n_colors++; gimp_image_colormap_changed (image, -1); }
gboolean gimp_palette_save (GimpData *data, GError **error) { GimpPalette *palette = GIMP_PALETTE (data); GList *list; FILE *file; file = g_fopen (gimp_data_get_filename (data), "wb"); if (! file) { g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_OPEN, _("Could not open '%s' for writing: %s"), gimp_filename_to_utf8 (gimp_data_get_filename (data)), g_strerror (errno)); return FALSE; } fprintf (file, "GIMP Palette\n"); fprintf (file, "Name: %s\n", gimp_object_get_name (palette)); fprintf (file, "Columns: %d\n#\n", CLAMP (gimp_palette_get_columns (palette), 0, 256)); for (list = gimp_palette_get_colors (palette); list; list = g_list_next (list)) { GimpPaletteEntry *entry = list->data; guchar r, g, b; gimp_rgb_get_uchar (&entry->color, &r, &g, &b); fprintf (file, "%3d %3d %3d\t%s\n", r, g, b, entry->name); } fclose (file); return TRUE; }
void gimp_image_set_colormap_entry (GimpImage *image, gint color_index, const GimpRGB *color, gboolean push_undo) { g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (image->colormap != NULL); g_return_if_fail (color_index >= 0 && color_index < image->n_colors); g_return_if_fail (color != NULL); if (push_undo) gimp_image_undo_push_image_colormap (image, _("Change Colormap entry")); gimp_rgb_get_uchar (color, &image->colormap[color_index * 3], &image->colormap[color_index * 3 + 1], &image->colormap[color_index * 3 + 2]); gimp_image_colormap_changed (image, color_index); }
void gimp_drawable_get_color_uchar (gint32 drawable_ID, const GimpRGB *color, guchar *color_uchar) { g_return_if_fail (color != NULL); g_return_if_fail (color_uchar != NULL); switch (gimp_drawable_type (drawable_ID)) { case GIMP_RGB_IMAGE: gimp_rgb_get_uchar (color, &color_uchar[0], &color_uchar[1], &color_uchar[2]); color_uchar[3] = 255; break; case GIMP_RGBA_IMAGE: gimp_rgba_get_uchar (color, &color_uchar[0], &color_uchar[1], &color_uchar[2], &color_uchar[3]); break; case GIMP_GRAY_IMAGE: color_uchar[0] = gimp_rgb_luminance_uchar (color); color_uchar[1] = 255; break; case GIMP_GRAYA_IMAGE: color_uchar[0] = gimp_rgb_luminance_uchar (color); gimp_rgba_get_uchar (color, NULL, NULL, NULL, &color_uchar[1]); break; default: break; } }
void compute_preview (gint x, gint y, gint w, gint h, gint pw, gint ph) { gdouble xpostab[PREVIEW_WIDTH]; gdouble ypostab[PREVIEW_HEIGHT]; gdouble realw; gdouble realh; GimpVector3 p1, p2; GimpRGB color; GimpRGB lightcheck, darkcheck; gint xcnt, ycnt, f1, f2; glong index = 0; init_compute (); p1 = int_to_pos (x, y); p2 = int_to_pos (x + w, y + h); /* First, compute the linear mapping (x,y,x+w,y+h) to (0,0,pw,ph) */ /* ============================================================== */ realw = (p2.x - p1.x); realh = (p2.y - p1.y); for (xcnt = 0; xcnt < pw; xcnt++) xpostab[xcnt] = p1.x + realw * ((gdouble) xcnt / (gdouble) pw); for (ycnt = 0; ycnt < ph; ycnt++) ypostab[ycnt] = p1.y + realh * ((gdouble) ycnt / (gdouble) ph); /* Compute preview using the offset tables */ /* ======================================= */ if (mapvals.transparent_background == TRUE) { gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0); } else { gimp_context_get_background (&background); gimp_rgb_set_alpha (&background, 1.0); } gimp_rgba_set (&lightcheck, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0); gimp_rgba_set (&darkcheck, GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0); gimp_vector3_set (&p2, -1.0, -1.0, 0.0); for (ycnt = 0; ycnt < ph; ycnt++) { for (xcnt = 0; xcnt < pw; xcnt++) { p1.x = xpostab[xcnt]; p1.y = ypostab[ycnt]; p2 = p1; color = (* get_ray_color) (&p1); if (color.a < 1.0) { f1 = ((xcnt % 32) < 16); f2 = ((ycnt % 32) < 16); f1 = f1 ^ f2; if (f1) { if (color.a == 0.0) color = lightcheck; else gimp_rgb_composite (&color, &lightcheck, GIMP_RGB_COMPOSITE_BEHIND); } else { if (color.a == 0.0) color = darkcheck; else gimp_rgb_composite (&color, &darkcheck, GIMP_RGB_COMPOSITE_BEHIND); } } gimp_rgb_get_uchar (&color, preview_rgb_data + index, preview_rgb_data + index + 1, preview_rgb_data + index + 2); index += 3; } } }
static void value_propagate_body (GimpDrawable *drawable, GimpPreview *preview) { GimpImageType dtype; ModeParam operation; GimpPixelRgn srcRgn, destRgn; guchar *here, *best, *dest; guchar *dest_row, *prev_row, *cur_row, *next_row; guchar *pr, *cr, *nr, *swap; gint width, height, bytes, index; gint begx, begy, endx, endy, x, y, dx; gint left_index, right_index, up_index, down_index; gpointer tmp; GimpRGB foreground; /* calculate neighbors' indexes */ left_index = (vpvals.direction_mask & (1 << Left2Right)) ? -1 : 0; right_index = (vpvals.direction_mask & (1 << Right2Left)) ? 1 : 0; up_index = (vpvals.direction_mask & (1 << Top2Bottom)) ? -1 : 0; down_index = (vpvals.direction_mask & (1 << Bottom2Top)) ? 1 : 0; operation = modes[vpvals.propagate_mode]; tmp = NULL; dtype = gimp_drawable_type (drawable->drawable_id); bytes = drawable->bpp; /* Here I use the algorithm of blur.c */ if (preview) { gimp_preview_get_position (preview, &begx, &begy); gimp_preview_get_size (preview, &width, &height); endx = begx + width; endy = begy + height; } else { if (! gimp_drawable_mask_intersect (drawable->drawable_id, &begx, &begy, &width, &height)) return; endx = begx + width; endy = begy + height; } gimp_tile_cache_ntiles (2 * ((width) / gimp_tile_width () + 1)); prev_row = g_new (guchar, (width + 2) * bytes); cur_row = g_new (guchar, (width + 2) * bytes); next_row = g_new (guchar, (width + 2) * bytes); dest_row = g_new (guchar, width * bytes); gimp_pixel_rgn_init (&srcRgn, drawable, begx, begy, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&destRgn, drawable, begx, begy, width, height, (preview == NULL), TRUE); pr = prev_row + bytes; cr = cur_row + bytes; nr = next_row + bytes; prepare_row (&srcRgn, pr, begx, (0 < begy) ? begy : begy - 1, endx-begx); prepare_row (&srcRgn, cr, begx, begy, endx-begx); best = g_new (guchar, bytes); if (!preview) gimp_progress_init (_("Value Propagate")); gimp_context_get_foreground (&foreground); gimp_rgb_get_uchar (&foreground, fore+0, fore+1, fore+2); /* start real job */ for (y = begy ; y < endy ; y++) { prepare_row (&srcRgn, nr, begx, ((y+1) < endy) ? y+1 : endy, endx-begx); for (index = 0; index < (endx - begx) * bytes; index++) dest_row[index] = cr[index]; for (x = 0 ; x < endx - begx; x++) { dest = dest_row + (x * bytes); here = cr + (x * bytes); /* *** copy source value to best value holder *** */ memcpy (best, here, bytes); if (operation.initializer) (* operation.initializer)(dtype, bytes, best, here, &tmp); /* *** gather neighbors' values: loop-unfolded version *** */ if (up_index == -1) for (dx = left_index ; dx <= right_index ; dx++) (* operation.updater)(dtype, bytes, here, pr+((x+dx)*bytes), best, tmp); for (dx = left_index ; dx <= right_index ; dx++) if (dx != 0) (* operation.updater)(dtype, bytes, here, cr+((x+dx)*bytes), best, tmp); if (down_index == 1) for (dx = left_index ; dx <= right_index ; dx++) (* operation.updater)(dtype, bytes, here, nr+((x+dx)*bytes), best, tmp); /* *** store it to dest_row*** */ (* operation.finalizer)(dtype, bytes, best, here, dest, tmp); } /* now store destline to destRgn */ gimp_pixel_rgn_set_row (&destRgn, dest_row, begx, y, endx - begx); /* shift the row pointers */ swap = pr; pr = cr; cr = nr; nr = swap; if (((y % 16) == 0) && !preview) gimp_progress_update ((gdouble) y / (gdouble) (endy - begy)); } if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &destRgn); } else { /* update the region */ gimp_progress_update (1.0); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, begx, begy, endx-begx, endy-begy); } }
GimpColorTransform * gimp_widget_get_color_transform (GtkWidget *widget, GimpColorConfig *config, GimpColorProfile *src_profile, const Babl *src_format, const Babl *dest_format) { static gboolean initialized = FALSE; GimpColorProfile *dest_profile = NULL; GimpColorProfile *proof_profile = NULL; TransformCache *cache; g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile), NULL); g_return_val_if_fail (src_format != NULL, NULL); g_return_val_if_fail (dest_format != NULL, NULL); if (G_UNLIKELY (! initialized)) { initialized = TRUE; debug_cache = g_getenv ("GIMP_DEBUG_TRANSFORM_CACHE") != NULL; } switch (gimp_color_config_get_mode (config)) { case GIMP_COLOR_MANAGEMENT_OFF: return NULL; case GIMP_COLOR_MANAGEMENT_SOFTPROOF: proof_profile = gimp_color_config_get_simulation_color_profile (config, NULL); /* fallthru */ case GIMP_COLOR_MANAGEMENT_DISPLAY: dest_profile = get_display_profile (widget, config); break; } cache = transform_cache_get (config, src_profile, src_format, dest_profile, dest_format, proof_profile); if (cache) { g_object_unref (dest_profile); if (proof_profile) g_object_unref (proof_profile); if (cache->transform) return g_object_ref (cache->transform); return NULL; } if (! proof_profile && gimp_color_profile_is_equal (src_profile, dest_profile)) { g_object_unref (dest_profile); return NULL; } cache = g_new0 (TransformCache, 1); if (debug_cache) g_printerr ("creating cache %p\n", cache); cache->config = g_object_ref (config); cache->src_profile = g_object_ref (src_profile); cache->src_format = src_format; cache->dest_profile = dest_profile; cache->dest_format = dest_format; cache->proof_profile = proof_profile; cache->notify_id = g_signal_connect (cache->config, "notify", G_CALLBACK (transform_cache_config_notify), cache); transform_caches = g_list_prepend (transform_caches, cache); if (cache->proof_profile) { GimpColorTransformFlags flags = 0; if (gimp_color_config_get_simulation_bpc (config)) flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION; if (! gimp_color_config_get_simulation_optimize (config)) flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE; if (gimp_color_config_get_simulation_gamut_check (config)) { cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = { 0, }; guchar r, g, b; flags |= GIMP_COLOR_TRANSFORM_FLAGS_GAMUT_CHECK; gimp_rgb_get_uchar (&config->out_of_gamut_color, &r, &g, &b); alarmCodes[0] = (cmsUInt16Number) r * 256; alarmCodes[1] = (cmsUInt16Number) g * 256; alarmCodes[2] = (cmsUInt16Number) b * 256; cmsSetAlarmCodes (alarmCodes); } cache->transform = gimp_color_transform_new_proofing (cache->src_profile, cache->src_format, cache->dest_profile, cache->dest_format, cache->proof_profile, gimp_color_config_get_simulation_intent (config), gimp_color_config_get_display_intent (config), flags); } else { GimpColorTransformFlags flags = 0; if (gimp_color_config_get_display_bpc (config)) flags |= GIMP_COLOR_TRANSFORM_FLAGS_BLACK_POINT_COMPENSATION; if (! gimp_color_config_get_display_optimize (config)) flags |= GIMP_COLOR_TRANSFORM_FLAGS_NOOPTIMIZE; cache->transform = gimp_color_transform_new (cache->src_profile, cache->src_format, cache->dest_profile, cache->dest_format, gimp_color_config_get_display_intent (config), flags); } if (cache->transform) return g_object_ref (cache->transform); return NULL; }
static void cdisplay_lcms_changed (GimpColorDisplay *display) { CdisplayLcms *lcms = CDISPLAY_LCMS (display); GimpColorConfig *config = gimp_color_display_get_config (display); cmsHPROFILE src_profile = NULL; cmsHPROFILE dest_profile = NULL; cmsHPROFILE proof_profile = NULL; cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = { 0, }; if (lcms->transform) { cmsDeleteTransform (lcms->transform); lcms->transform = NULL; } if (! config) return; switch (config->mode) { case GIMP_COLOR_MANAGEMENT_OFF: return; case GIMP_COLOR_MANAGEMENT_SOFTPROOF: proof_profile = cdisplay_lcms_get_printer_profile (lcms); /* fallthru */ case GIMP_COLOR_MANAGEMENT_DISPLAY: src_profile = cdisplay_lcms_get_rgb_profile (lcms); dest_profile = cdisplay_lcms_get_display_profile (lcms); break; } if (proof_profile) { cmsUInt32Number softproof_flags = 0; if (! src_profile) src_profile = gimp_lcms_create_srgb_profile (); if (! dest_profile) dest_profile = gimp_lcms_create_srgb_profile (); softproof_flags |= cmsFLAGS_SOFTPROOFING; if (config->simulation_use_black_point_compensation) { softproof_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } if (config->simulation_gamut_check) { guchar r, g, b; softproof_flags |= cmsFLAGS_GAMUTCHECK; gimp_rgb_get_uchar (&config->out_of_gamut_color, &r, &g, &b); alarmCodes[0] = (cmsUInt16Number) r * 256; alarmCodes[1] = (cmsUInt16Number) g * 256; alarmCodes[2] = (cmsUInt16Number) b * 256; cmsSetAlarmCodes (alarmCodes); } lcms->transform = cmsCreateProofingTransform (src_profile, TYPE_RGBA_FLT, dest_profile, TYPE_RGBA_FLT, proof_profile, config->simulation_intent, config->display_intent, softproof_flags); cmsCloseProfile (proof_profile); } else if (src_profile || dest_profile) { cmsUInt32Number display_flags = 0; if (! src_profile) src_profile = gimp_lcms_create_srgb_profile (); if (! dest_profile) dest_profile = gimp_lcms_create_srgb_profile (); if (config->display_use_black_point_compensation) { display_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } lcms->transform = cmsCreateTransform (src_profile, TYPE_RGBA_FLT, dest_profile, TYPE_RGBA_FLT, config->display_intent, display_flags); } if (dest_profile) cmsCloseProfile (dest_profile); if (src_profile) cmsCloseProfile (src_profile); }
static void gimp_view_renderer_palette_render (GimpViewRenderer *renderer, GtkWidget *widget) { GimpViewRendererPalette *renderpal = GIMP_VIEW_RENDERER_PALETTE (renderer); GimpPalette *palette; guchar *row; guchar *dest; GList *list; gdouble cell_width; gint grid_width; gint dest_stride; gint y; palette = GIMP_PALETTE (renderer->viewable); if (palette->n_colors < 1) return; grid_width = renderpal->draw_grid ? 1 : 0; if (renderpal->cell_size > 0) { if (palette->n_columns > 0) cell_width = MAX ((gdouble) renderpal->cell_size, (gdouble) (renderer->width - grid_width) / (gdouble) palette->n_columns); else cell_width = renderpal->cell_size; } else { if (palette->n_columns > 0) cell_width = ((gdouble) (renderer->width - grid_width) / (gdouble) palette->n_columns); else cell_width = (gdouble) (renderer->width - grid_width) / 16.0; } cell_width = MAX (4.0, cell_width); renderpal->cell_width = cell_width; renderpal->columns = (gdouble) (renderer->width - grid_width) / cell_width; renderpal->rows = palette->n_colors / renderpal->columns; if (palette->n_colors % renderpal->columns) renderpal->rows += 1; renderpal->cell_height = MAX (4, ((renderer->height - grid_width) / renderpal->rows)); if (! renderpal->draw_grid) renderpal->cell_height = MIN (renderpal->cell_height, renderpal->cell_width); list = palette->colors; if (! renderer->surface) renderer->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, renderer->width, renderer->height); cairo_surface_flush (renderer->surface); row = g_new (guchar, renderer->width * 4); dest = cairo_image_surface_get_data (renderer->surface); dest_stride = cairo_image_surface_get_stride (renderer->surface); for (y = 0; y < renderer->height; y++) { if ((y % renderpal->cell_height) == 0) { guchar r, g, b; gint x; gint n = 0; guchar *d = row; memset (row, renderpal->draw_grid ? 0 : 255, renderer->width * 4); r = g = b = (renderpal->draw_grid ? 0 : 255); for (x = 0; x < renderer->width; x++, d += 4) { if ((x % renderpal->cell_width) == 0) { if (list && n < renderpal->columns && renderer->width - x >= renderpal->cell_width) { GimpPaletteEntry *entry = list->data; list = g_list_next (list); n++; gimp_rgb_get_uchar (&entry->color, &r, &g, &b); } else { r = g = b = (renderpal->draw_grid ? 0 : 255); } } if (renderpal->draw_grid && (x % renderpal->cell_width) == 0) { GIMP_CAIRO_RGB24_SET_PIXEL (d, 0, 0, 0); } else { GIMP_CAIRO_RGB24_SET_PIXEL (d, r, g, b); } } } if (renderpal->draw_grid && (y % renderpal->cell_height) == 0) { memset (dest, 0, renderer->width * 4); } else { memcpy (dest, row, renderer->width * 4); } dest += dest_stride; } g_free (row); cairo_surface_mark_dirty (renderer->surface); renderer->needs_render = FALSE; }
static void compute_preview (gint startx, gint starty, gint w, gint h) { gint xcnt, ycnt, f1, f2; gdouble imagex, imagey; gint32 index = 0; GimpRGB color; GimpRGB lightcheck, darkcheck; GimpVector3 pos; get_ray_func ray_func; if (xpostab_size != w) { if (xpostab) { g_free (xpostab); xpostab = NULL; } } if (!xpostab) { xpostab = g_new (gdouble, w); xpostab_size = w; } if (ypostab_size != h) { if (ypostab) { g_free (ypostab); ypostab = NULL; } } if (!ypostab) { ypostab = g_new (gdouble, h); ypostab_size = h; } for (xcnt = 0; xcnt < w; xcnt++) xpostab[xcnt] = (gdouble) width *((gdouble) xcnt / (gdouble) w); for (ycnt = 0; ycnt < h; ycnt++) ypostab[ycnt] = (gdouble) height *((gdouble) ycnt / (gdouble) h); precompute_init (width, height); gimp_rgba_set (&lightcheck, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0); gimp_rgba_set (&darkcheck, GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0); if (mapvals.bump_mapped == TRUE && mapvals.bumpmap_id != -1) { gimp_pixel_rgn_init (&bump_region, gimp_drawable_get (mapvals.bumpmap_id), 0, 0, width, height, FALSE, FALSE); } imagey = 0; if (mapvals.previewquality) ray_func = get_ray_color; else ray_func = get_ray_color_no_bilinear; if (mapvals.env_mapped == TRUE && mapvals.envmap_id != -1) { env_width = gimp_drawable_width (mapvals.envmap_id); env_height = gimp_drawable_height (mapvals.envmap_id); gimp_pixel_rgn_init (&env_region, gimp_drawable_get (mapvals.envmap_id), 0, 0, env_width, env_height, FALSE, FALSE); if (mapvals.previewquality) ray_func = get_ray_color_ref; else ray_func = get_ray_color_no_bilinear_ref; } for (ycnt = 0; ycnt < PREVIEW_HEIGHT; ycnt++) { for (xcnt = 0; xcnt < PREVIEW_WIDTH; xcnt++) { if ((ycnt >= starty && ycnt < (starty + h)) && (xcnt >= startx && xcnt < (startx + w))) { imagex = xpostab[xcnt - startx]; imagey = ypostab[ycnt - starty]; pos = int_to_posf (imagex, imagey); if (mapvals.bump_mapped == TRUE && mapvals.bumpmap_id != -1 && xcnt == startx) { pos_to_float (pos.x, pos.y, &imagex, &imagey); precompute_normals (0, width, RINT (imagey)); } color = (*ray_func) (&pos); if (color.a < 1.0) { f1 = ((xcnt % 32) < 16); f2 = ((ycnt % 32) < 16); f1 = f1 ^ f2; if (f1) { if (color.a == 0.0) color = lightcheck; else gimp_rgb_composite (&color, &lightcheck, GIMP_RGB_COMPOSITE_BEHIND); } else { if (color.a == 0.0) color = darkcheck; else gimp_rgb_composite (&color, &darkcheck, GIMP_RGB_COMPOSITE_BEHIND); } } gimp_rgb_get_uchar (&color, preview_rgb_data + index, preview_rgb_data + index + 1, preview_rgb_data + index + 2); index += 3; imagex++; } else { preview_rgb_data[index++] = 200; preview_rgb_data[index++] = 200; preview_rgb_data[index++] = 200; } } } }
static void gimp_drawable_stroke_scan_convert (GimpDrawable *drawable, GimpStrokeOptions *options, GimpScanConvert *scan_convert) { GimpContext *context = GIMP_CONTEXT (options); GimpImage *image; gdouble width; TileManager *base; TileManager *mask; gint x, y, w, h; gint bytes; gint off_x, off_y; guchar bg[1] = { 0, }; PixelRegion maskPR, basePR; image = gimp_item_get_image (GIMP_ITEM (drawable)); /* must call gimp_channel_is_empty() instead of relying on * gimp_drawable_mask_intersect() because the selection pretends to * be empty while it is being stroked, to prevent masking itself. */ if (gimp_channel_is_empty (gimp_image_get_mask (image))) { x = 0; y = 0; w = gimp_item_width (GIMP_ITEM (drawable)); h = gimp_item_height (GIMP_ITEM (drawable)); } else if (! gimp_drawable_mask_intersect (drawable, &x, &y, &w, &h)) { return; } gimp_item_offsets (GIMP_ITEM (drawable), &off_x, &off_y); width = options->width; if (options->unit != GIMP_UNIT_PIXEL) { gimp_scan_convert_set_pixel_ratio (scan_convert, image->yresolution / image->xresolution); width *= (image->yresolution / _gimp_unit_get_factor (image->gimp, options->unit)); } gimp_scan_convert_stroke (scan_convert, width, options->join_style, options->cap_style, options->miter_limit, options->dash_offset, options->dash_info); /* fill a 1-bpp Tilemanager with black, this will describe the shape * of the stroke. */ mask = tile_manager_new (w, h, 1); pixel_region_init (&maskPR, mask, 0, 0, w, h, TRUE); color_region (&maskPR, bg); /* render the stroke into it */ gimp_scan_convert_render (scan_convert, mask, x + off_x, y + off_y, options->antialias); bytes = gimp_drawable_bytes_with_alpha (drawable); base = tile_manager_new (w, h, bytes); pixel_region_init (&basePR, base, 0, 0, w, h, TRUE); pixel_region_init (&maskPR, mask, 0, 0, w, h, FALSE); switch (options->style) { case GIMP_STROKE_STYLE_SOLID: { guchar tmp_col[MAX_CHANNELS] = { 0, }; guchar col[MAX_CHANNELS] = { 0, }; gimp_rgb_get_uchar (&context->foreground, &tmp_col[RED_PIX], &tmp_col[GREEN_PIX], &tmp_col[BLUE_PIX]); gimp_image_transform_color (image, gimp_drawable_type (drawable), col, GIMP_RGB, tmp_col); col[bytes - 1] = OPAQUE_OPACITY; color_region_mask (&basePR, &maskPR, col); } break; case GIMP_STROKE_STYLE_PATTERN: { GimpPattern *pattern; TempBuf *pat_buf; gboolean new_buf; pattern = gimp_context_get_pattern (context); pat_buf = gimp_image_transform_temp_buf (image, gimp_drawable_type (drawable), pattern->mask, &new_buf); pattern_region (&basePR, &maskPR, pat_buf, x, y); if (new_buf) temp_buf_free (pat_buf); } break; } /* Apply to drawable */ pixel_region_init (&basePR, base, 0, 0, w, h, FALSE); gimp_drawable_apply_region (drawable, &basePR, TRUE, _("Render Stroke"), gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), NULL, x, y); tile_manager_unref (mask); tile_manager_unref (base); gimp_drawable_update (drawable, x, y, w, h); }
/* do the exchanging */ static void exchange (GimpDrawable *drawable, GimpPreview *preview) { GimpPixelRgn srcPR, destPR; guchar min_red, min_green, min_blue; guchar max_red, max_green, max_blue; guchar from_red, from_green, from_blue; guchar to_red, to_green, to_blue; guchar *src_row, *dest_row; gint x, y, bpp = drawable->bpp; gboolean has_alpha; gint x1, y1, y2; gint width, height; GimpRGB min; GimpRGB max; if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); } else if (! gimp_drawable_mask_intersect (drawable->drawable_id, &x1, &y1, &width, &height)) { return; } y2 = y1 + height; has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); /* allocate memory */ src_row = g_new (guchar, drawable->width * bpp); gimp_rgb_get_uchar (&xargs.from, &from_red, &from_green, &from_blue); gimp_rgb_get_uchar (&xargs.to, &to_red, &to_green, &to_blue); /* get boundary values */ min = xargs.from; gimp_rgb_subtract (&min, &xargs.threshold); gimp_rgb_clamp (&min); gimp_rgb_get_uchar (&min, &min_red, &min_green, &min_blue); max = xargs.from; gimp_rgb_add (&max, &xargs.threshold); gimp_rgb_clamp (&max); gimp_rgb_get_uchar (&max, &max_red, &max_green, &max_blue); dest_row = g_new (guchar, drawable->width * bpp); gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&destPR, drawable, x1, y1, width, height, (preview == NULL), TRUE); for (y = y1; y < y2; y++) { gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y, width); for (x = 0; x < width; x++) { guchar pixel_red, pixel_green, pixel_blue; guchar new_red, new_green, new_blue; guint idx; /* get current pixel-values */ pixel_red = src_row[x * bpp]; pixel_green = src_row[x * bpp + 1]; pixel_blue = src_row[x * bpp + 2]; idx = x * bpp; /* want this pixel? */ if (pixel_red >= min_red && pixel_red <= max_red && pixel_green >= min_green && pixel_green <= max_green && pixel_blue >= min_blue && pixel_blue <= max_blue) { guchar red_delta, green_delta, blue_delta; red_delta = pixel_red > from_red ? pixel_red - from_red : from_red - pixel_red; green_delta = pixel_green > from_green ? pixel_green - from_green : from_green - pixel_green; blue_delta = pixel_blue > from_blue ? pixel_blue - from_blue : from_blue - pixel_blue; new_red = CLAMP (to_red + red_delta, 0, 255); new_green = CLAMP (to_green + green_delta, 0, 255); new_blue = CLAMP (to_blue + blue_delta, 0, 255); } else { new_red = pixel_red; new_green = pixel_green; new_blue = pixel_blue; } /* fill buffer */ dest_row[idx + 0] = new_red; dest_row[idx + 1] = new_green; dest_row[idx + 2] = new_blue; /* copy alpha-channel */ if (has_alpha) dest_row[idx + 3] = src_row[x * bpp + 3]; } /* store the dest */ gimp_pixel_rgn_set_row (&destPR, dest_row, x1, y, width); /* and tell the user what we're doing */ if (!preview && (y % 10) == 0) gimp_progress_update ((gdouble) y / (gdouble) height); } g_free (src_row); g_free (dest_row); if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &destPR); } else { gimp_progress_update (1.0); /* update the processed region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } }
void _gimp_color_area_render_buf (GtkWidget *widget, gboolean insensitive, GimpColorAreaType type, guchar *buf, guint width, guint height, guint rowstride, GimpRGB *color) { guint x, y; guint check_size = 0; guchar light[3]; guchar dark[3]; guchar opaque[3]; guchar insens[3]; guchar *p; gdouble frac; g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (buf != NULL); g_return_if_fail (color != NULL); switch (type) { case GIMP_COLOR_AREA_FLAT: check_size = 0; break; case GIMP_COLOR_AREA_SMALL_CHECKS: check_size = GIMP_CHECK_SIZE_SM; break; case GIMP_COLOR_AREA_LARGE_CHECKS: check_size = GIMP_CHECK_SIZE; break; } gimp_rgb_get_uchar (color, opaque, opaque + 1, opaque + 2); insens[0] = widget->style->bg[GTK_STATE_INSENSITIVE].red >> 8; insens[1] = widget->style->bg[GTK_STATE_INSENSITIVE].green >> 8; insens[2] = widget->style->bg[GTK_STATE_INSENSITIVE].blue >> 8; if (insensitive || check_size == 0 || color->a == 1.0) { for (y = 0; y < height; y++) { p = buf + y * rowstride; for (x = 0; x < width; x++) { if (insensitive && ((x + y) % 2)) { *p++ = insens[0]; *p++ = insens[1]; *p++ = insens[2]; } else { *p++ = opaque[0]; *p++ = opaque[1]; *p++ = opaque[2]; } } } return; } light[0] = (GIMP_CHECK_LIGHT + (color->r - GIMP_CHECK_LIGHT) * color->a) * 255.999; light[1] = (GIMP_CHECK_LIGHT + (color->g - GIMP_CHECK_LIGHT) * color->a) * 255.999; light[2] = (GIMP_CHECK_LIGHT + (color->b - GIMP_CHECK_LIGHT) * color->a) * 255.999; dark[0] = (GIMP_CHECK_DARK + (color->r - GIMP_CHECK_DARK) * color->a) * 255.999; dark[1] = (GIMP_CHECK_DARK + (color->g - GIMP_CHECK_DARK) * color->a) * 255.999; dark[2] = (GIMP_CHECK_DARK + (color->b - GIMP_CHECK_DARK) * color->a) * 255.999; for (y = 0; y < height; y++) { p = buf + y * rowstride; for (x = 0; x < width; x++) { if ((width - x) * height > y * width) { *p++ = opaque[0]; *p++ = opaque[1]; *p++ = opaque[2]; continue; } frac = y - (gdouble) ((width - x) * height) / (gdouble) width; if (((x / check_size) ^ (y / check_size)) & 1) { if ((gint) frac) { *p++ = light[0]; *p++ = light[1]; *p++ = light[2]; } else { *p++ = ((gdouble) light[0] * frac + (gdouble) opaque[0] * (1.0 - frac)); *p++ = ((gdouble) light[1] * frac + (gdouble) opaque[1] * (1.0 - frac)); *p++ = ((gdouble) light[2] * frac + (gdouble) opaque[2] * (1.0 - frac)); } } else { if ((gint) frac) { *p++ = dark[0]; *p++ = dark[1]; *p++ = dark[2]; } else { *p++ = ((gdouble) dark[0] * frac + (gdouble) opaque[0] * (1.0 - frac)); *p++ = ((gdouble) dark[1] * frac + (gdouble) opaque[1] * (1.0 - frac)); *p++ = ((gdouble) dark[2] * frac + (gdouble) opaque[2] * (1.0 - frac)); } } } } }
static void init_calculation (gint32 drawable_id) { gdouble k; gdouble alpha, beta; gdouble angle; GimpVector2 v1, v2; gint32 *image_layers; gint32 nlayers; GimpRGB color; gimp_layer_add_alpha (drawable_id); /* Image parameters */ /* Determine Position of original Layer in the Layer stack. */ image_layers = gimp_image_get_layers (image_id, &nlayers); drawable_position = 0; while (drawable_position < nlayers && image_layers[drawable_position] != drawable_id) drawable_position++; switch (curl.orientation) { case CURL_ORIENTATION_VERTICAL: sel_width = true_sel_width; sel_height = true_sel_height; break; case CURL_ORIENTATION_HORIZONTAL: sel_width = true_sel_height; sel_height = true_sel_width; break; } /* Circle parameters */ alpha = atan ((double) sel_height / sel_width); beta = alpha / 2.0; k = sel_width / ((G_PI + alpha) * sin (beta) + cos (beta)); gimp_vector2_set (¢er, k * cos (beta), k * sin (beta)); radius = center.y; /* left_tangent */ gimp_vector2_set (&left_tangent, radius * -sin (alpha), radius * cos (alpha)); gimp_vector2_add (&left_tangent, &left_tangent, ¢er); /* right_tangent */ gimp_vector2_sub (&v1, &left_tangent, ¢er); gimp_vector2_set (&v2, sel_width - center.x, sel_height - center.y); angle = -2.0 * acos (gimp_vector2_inner_product (&v1, &v2) / (gimp_vector2_length (&v1) * gimp_vector2_length (&v2))); gimp_vector2_set (&right_tangent, v1.x * cos (angle) + v1.y * -sin (angle), v1.x * sin (angle) + v1.y * cos (angle)); gimp_vector2_add (&right_tangent, &right_tangent, ¢er); /* Slopes */ diagl_slope = (double) sel_width / sel_height; diagr_slope = (sel_width - right_tangent.x) / (sel_height - right_tangent.y); diagb_slope = ((right_tangent.y - left_tangent.y) / (right_tangent.x - left_tangent.x)); diagm_slope = (sel_width - center.x) / sel_height; /* Colors */ gimp_context_get_foreground (&color); gimp_rgb_get_uchar (&color, &fore_color[0], &fore_color[1], &fore_color[2]); gimp_context_get_background (&color); gimp_rgb_get_uchar (&color, &back_color[0], &back_color[1], &back_color[2]); }
void repaint (ppm_t *p, ppm_t *a) { int x, y; int tx = 0, ty = 0; ppm_t tmp = {0, 0, NULL}; ppm_t atmp = {0, 0, NULL}; int r, g, b, h, i, j, on, sn; int num_brushes, maxbrushwidth, maxbrushheight; guchar back[3] = {0, 0, 0}; ppm_t *brushes, *shadows; ppm_t *brush, *shadow = NULL; double *brushes_sum; int cx, cy, maxdist; double scale, relief, startangle, anglespan, density, bgamma; int max_progress; ppm_t paper_ppm = {0, 0, NULL}; ppm_t dirmap = {0, 0, NULL}; ppm_t sizmap = {0, 0, NULL}; int *xpos = NULL, *ypos = NULL; int progstep; static int running = 0; int dropshadow = pcvals.general_drop_shadow; int shadowblur = pcvals.general_shadow_blur; if (running) return; running++; runningvals = pcvals; /* Shouldn't be necessary, but... */ if (img_has_alpha) if ((p->width != a->width) || (p->height != a->height)) { g_printerr ("Huh? Image size != alpha size?\n"); return; } num_brushes = runningvals.orient_num * runningvals.size_num; startangle = runningvals.orient_first; anglespan = runningvals.orient_last; density = runningvals.brush_density; if (runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) density /= 3.0; bgamma = runningvals.brushgamma; brushes = g_malloc (num_brushes * sizeof (ppm_t)); brushes_sum = g_malloc (num_brushes * sizeof (double)); if (dropshadow) shadows = g_malloc (num_brushes * sizeof (ppm_t)); else shadows = NULL; brushes[0].col = NULL; brush_get_selected (&brushes[0]); resize (&brushes[0], brushes[0].width, brushes[0].height * pow (10, runningvals.brush_aspect)); scale = runningvals.size_last / MAX (brushes[0].width, brushes[0].height); if (bgamma != 1.0) ppm_apply_gamma (&brushes[0], 1.0 / bgamma, 1,1,1); resize (&brushes[0], brushes[0].width * scale, brushes[0].height * scale); i = 1 + sqrt (brushes[0].width * brushes[0].width + brushes[0].height * brushes[0].height); ppm_pad (&brushes[0], i-brushes[0].width, i-brushes[0].width, i - brushes[0].height, i - brushes[0].height, back); for (i = 1; i < num_brushes; i++) { brushes[i].col = NULL; ppm_copy (&brushes[0], &brushes[i]); } for (i = 0; i < runningvals.size_num; i++) { double sv; if (runningvals.size_num > 1) sv = i / (runningvals.size_num - 1.0); else sv = 1.0; for (j = 0; j < runningvals.orient_num; j++) { h = j + i * runningvals.orient_num; free_rotate (&brushes[h], startangle + j * anglespan / runningvals.orient_num); rescale (&brushes[h], ( sv * runningvals.size_first + (1.0-sv) * runningvals.size_last ) / runningvals.size_last); autocrop (&brushes[h],1); } } /* Brush-debugging */ #if 0 for (i = 0; i < num_brushes; i++) { char tmp[1000]; g_snprintf (tmp, sizeof (tmp), "/tmp/_brush%03d.ppm", i); ppm_save (&brushes[i], tmp); } #endif for (i = 0; i < num_brushes; i++) { if (!runningvals.color_brushes) prepare_brush (&brushes[i]); brushes_sum[i] = sum_brush (&brushes[i]); } brush = &brushes[0]; maxbrushwidth = maxbrushheight = 0; for (i = 0; i < num_brushes; i++) { if (brushes[i].width > maxbrushwidth) maxbrushwidth = brushes[i].width; if (brushes[i].height > maxbrushheight) maxbrushheight = brushes[i].height; } for (i = 0; i < num_brushes; i++) { int xp, yp; guchar blk[3] = {0, 0, 0}; xp = maxbrushwidth - brushes[i].width; yp = maxbrushheight - brushes[i].height; if (xp || yp) ppm_pad (&brushes[i], xp / 2, xp - xp / 2, yp / 2, yp - yp / 2, blk); } if (dropshadow) { for (i = 0; i < num_brushes; i++) { shadows[i].col = NULL; ppm_copy (&brushes[i], &shadows[i]); ppm_apply_gamma (&shadows[i], 0, 1,1,0); ppm_pad (&shadows[i], shadowblur*2, shadowblur*2, shadowblur*2, shadowblur*2, back); for (j = 0; j < shadowblur; j++) blur (&shadows[i], 2, 2); #if 0 autocrop (&shadows[i],1); #endif } #if 0 maxbrushwidth += shadowdepth*3; maxbrushheight += shadowdepth*3; #endif } /* For extra annoying debugging :-) */ #if 0 ppm_save (brushes, "/tmp/__brush.ppm"); if (shadows) ppm_save (shadows, "/tmp/__shadow.ppm"); system ("xv /tmp/__brush.ppm & xv /tmp/__shadow.ppm & "); #endif if (runningvals.general_paint_edges) { edgepad (p, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight); if (img_has_alpha) edgepad (a, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight); } if (img_has_alpha) { /* Initially fully transparent */ if (runningvals.general_background_type == BG_TYPE_TRANSPARENT) { guchar tmpcol[3] = {255, 255, 255}; ppm_new (&atmp, a->width, a->height); fill (&atmp, tmpcol); } else { ppm_copy (a, &atmp); } } if (runningvals.general_background_type == BG_TYPE_SOLID) { guchar tmpcol[3]; ppm_new (&tmp, p->width, p->height); gimp_rgb_get_uchar (&runningvals.color, &tmpcol[0], &tmpcol[1], &tmpcol[2]); fill (&tmp, tmpcol); } else if (runningvals.general_background_type == BG_TYPE_KEEP_ORIGINAL) { ppm_copy (p, &tmp); } else { int dx, dy; ppm_new (&tmp, p->width, p->height); ppm_load (runningvals.selected_paper, &paper_ppm); if (runningvals.paper_scale != 100.0) { scale = runningvals.paper_scale / 100.0; resize (&paper_ppm, paper_ppm.width * scale, paper_ppm.height * scale); } if (runningvals.paper_invert) ppm_apply_gamma (&paper_ppm, -1.0, 1, 1, 1); dx = runningvals.general_paint_edges ? paper_ppm.width - maxbrushwidth : 0; dy = runningvals.general_paint_edges ? paper_ppm.height - maxbrushheight : 0; for (y = 0; y < tmp.height; y++) { int lx; int ry = (y + dy) % paper_ppm.height; for (x = 0; x < tmp.width; x+=lx) { int rx = (x + dx) % paper_ppm.width; lx = MIN (tmp.width - x, paper_ppm.width - rx); memcpy (&tmp.col[y * tmp.width * 3 + x * 3], &paper_ppm.col[ry * paper_ppm.width * 3 + rx * 3], 3 * lx); } } } cx = p->width / 2; cy = p->height / 2; maxdist = sqrt (cx * cx + cy * cy); switch (runningvals.orient_type) { case ORIENTATION_VALUE: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = (srcrow[x * 3] + srcrow[x * 3 + 1] + srcrow[x * 3 + 2]) / 3; } } break; case ORIENTATION_RADIUS: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; double ysqr = (cy - y) * (cy - y); for (x = 0; x < dirmap.width; x++) { dstrow[x*3] = sqrt ((cx - x) * (cx - x) + ysqr) * 255 / maxdist; } } break; case ORIENTATION_RADIAL: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = (G_PI + atan2 (cy - y, cx - x)) * 255.0 / (G_PI * 2); } } break; case ORIENTATION_FLOWING: ppm_new (&dirmap, p->width / 6 + 5, p->height / 6 + 5); mkgrayplasma (&dirmap, 15); blur (&dirmap, 2, 2); blur (&dirmap, 2, 2); resize (&dirmap, p->width, p->height); blur (&dirmap, 2, 2); if (runningvals.general_paint_edges) edgepad (&dirmap, maxbrushwidth, maxbrushheight, maxbrushwidth, maxbrushheight); break; case ORIENTATION_HUE: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = get_hue (&srcrow[x * 3]); } } break; case ORIENTATION_ADAPTIVE: { guchar tmpcol[3] = {0, 0, 0}; ppm_new (&dirmap, p->width, p->height); fill (&dirmap, tmpcol); } break; case ORIENTATION_MANUAL: ppm_new (&dirmap, p->width-maxbrushwidth*2, p->height-maxbrushheight*2); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; double tmpy = y / (double)dirmap.height; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = get_pixel_value(90 - get_direction(x / (double)dirmap.width, tmpy, 1)); } } edgepad (&dirmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight); break; } if (runningvals.size_type == SIZE_TYPE_VALUE) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = (srcrow[x * 3] + srcrow[x * 3 + 1] + srcrow[x * 3 + 2]) / 3; } } } else if (runningvals.size_type == SIZE_TYPE_RADIUS) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; double ysqr = (cy - y) * (cy - y); for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = sqrt ((cx - x) * (cx - x) + ysqr) * 255 / maxdist; } } } else if (runningvals.size_type == SIZE_TYPE_RADIAL) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = (G_PI + atan2 (cy - y, cx - x)) * 255.0 / (G_PI * 2); } } } else if (runningvals.size_type == SIZE_TYPE_FLOWING) { ppm_new (&sizmap, p->width / 6 + 5, p->height / 6 + 5); mkgrayplasma (&sizmap, 15); blur (&sizmap, 2, 2); blur (&sizmap, 2, 2); resize (&sizmap, p->width, p->height); blur (&sizmap, 2, 2); if (runningvals.general_paint_edges) edgepad (&sizmap, maxbrushwidth, maxbrushheight, maxbrushwidth, maxbrushheight); } else if (runningvals.size_type == SIZE_TYPE_HUE) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < sizmap.width; x++) { dstrow[ x * 3] = get_hue (&srcrow[x * 3]); } } } else if (runningvals.size_type == SIZE_TYPE_ADAPTIVE) { guchar tmpcol[3] = {0, 0, 0}; ppm_new (&sizmap, p->width, p->height); fill (&sizmap, tmpcol); } else if (runningvals.size_type == SIZE_TYPE_MANUAL) { ppm_new (&sizmap, p->width-maxbrushwidth * 2, p->height-maxbrushheight * 2); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; double tmpy = y / (double)sizmap.height; for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = 255 * (1.0 - get_siz_from_pcvals (x / (double)sizmap.width, tmpy)); } } edgepad (&sizmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight); } #if 0 ppm_save(&sizmap, "/tmp/_sizmap.ppm"); #endif if (runningvals.place_type == PLACEMENT_TYPE_RANDOM) { i = tmp.width * tmp.height / (maxbrushwidth * maxbrushheight); i *= density; } else if (runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) { i = (int)(tmp.width * density / maxbrushwidth) * (int)(tmp.height * density / maxbrushheight); #if 0 g_printerr("i=%d\n", i); #endif } if (i < 1) i = 1; max_progress = i; progstep = max_progress / 30; if (progstep < 10) progstep = 10; if (runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) { int j; xpos = g_new (int, i); ypos = g_new (int, i); for (j = 0; j < i; j++) { int factor = (int)(tmp.width * density / maxbrushwidth + 0.5); if (factor < 1) factor = 1; xpos[j] = maxbrushwidth/2 + (j % factor) * maxbrushwidth / density; ypos[j] = maxbrushheight/2 + (j / factor) * maxbrushheight / density; } for (j = 0; j < i; j++) { int a, b; a = g_rand_int_range (random_generator, 0, i); b = xpos[j]; xpos[j] = xpos[a]; xpos[a] = b; b = ypos[j]; ypos[j] = ypos[a]; ypos[a] = b; } }
GimpColorTransform gimp_widget_get_color_transform (GtkWidget *widget, GimpColorConfig *config, GimpColorProfile *src_profile, const Babl **src_format, const Babl **dest_format) { GimpColorTransform transform = NULL; GimpColorProfile *dest_profile = NULL; GimpColorProfile *proof_profile = NULL; cmsHPROFILE src_lcms; cmsHPROFILE dest_lcms; cmsUInt32Number lcms_src_format; cmsUInt32Number lcms_dest_format; cmsUInt16Number alarmCodes[cmsMAXCHANNELS] = { 0, }; g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL); g_return_val_if_fail (GIMP_IS_COLOR_PROFILE (src_profile), NULL); g_return_val_if_fail (GIMP_IS_COLOR_CONFIG (config), NULL); g_return_val_if_fail (src_format != NULL, NULL); g_return_val_if_fail (dest_format != NULL, NULL); switch (config->mode) { case GIMP_COLOR_MANAGEMENT_OFF: return NULL; case GIMP_COLOR_MANAGEMENT_SOFTPROOF: proof_profile = gimp_color_config_get_printer_color_profile (config, NULL); /* fallthru */ case GIMP_COLOR_MANAGEMENT_DISPLAY: dest_profile = get_display_profile (widget, config); break; } src_lcms = gimp_color_profile_get_lcms_profile (src_profile); dest_lcms = gimp_color_profile_get_lcms_profile (dest_profile); *src_format = gimp_color_profile_get_format (*src_format, &lcms_src_format); *dest_format = gimp_color_profile_get_format (*dest_format, &lcms_dest_format); if (proof_profile) { cmsHPROFILE proof_lcms; cmsUInt32Number softproof_flags = cmsFLAGS_SOFTPROOFING; proof_lcms = gimp_color_profile_get_lcms_profile (proof_profile); if (config->simulation_use_black_point_compensation) { softproof_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } if (config->simulation_gamut_check) { guchar r, g, b; softproof_flags |= cmsFLAGS_GAMUTCHECK; gimp_rgb_get_uchar (&config->out_of_gamut_color, &r, &g, &b); alarmCodes[0] = (cmsUInt16Number) r * 256; alarmCodes[1] = (cmsUInt16Number) g * 256; alarmCodes[2] = (cmsUInt16Number) b * 256; cmsSetAlarmCodes (alarmCodes); } transform = cmsCreateProofingTransform (src_lcms, lcms_src_format, dest_lcms, lcms_dest_format, proof_lcms, config->simulation_intent, config->display_intent, softproof_flags); g_object_unref (proof_profile); } else if (! gimp_color_profile_is_equal (src_profile, dest_profile)) { cmsUInt32Number display_flags = 0; if (config->display_use_black_point_compensation) { display_flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; } transform = cmsCreateTransform (src_lcms, lcms_src_format, dest_lcms, lcms_dest_format, config->display_intent, display_flags); } g_object_unref (dest_profile); return transform; }
static inline void filter (void) { static void (* overlap)(guchar *, const guchar *); GimpPixelRgn src; GimpPixelRgn dst; GimpRGB color; guchar pixel[4]; gint division_x; gint division_y; gint offset_x; gint offset_y; Tile *tiles; gint numof_tiles; Tile *t; gint i; gint x; gint y; gint move_max_pixels; gint clear_x0; gint clear_y0; gint clear_x1; gint clear_y1; gint clear_width; gint clear_height; guchar *pixels; guchar *buffer; gint dindex; gint sindex; gint px, py; GRand *gr; gr = g_rand_new (); /* INITIALIZE */ gimp_pixel_rgn_init (&src, p.drawable, 0, 0, p.drawable->width, p.drawable->height, FALSE, FALSE); gimp_pixel_rgn_init (&dst, p.drawable, 0, 0, p.drawable->width, p.drawable->height, TRUE, TRUE); pixels = g_new (guchar, p.drawable->bpp * p.drawable->width * p.drawable->height); buffer = g_new (guchar, p.drawable->bpp * p.params.tile_width * p.params.tile_height); overlap = p.drawable_has_alpha ? overlap_RGBA : overlap_RGB; gimp_progress_init (_("Paper Tile")); gimp_drawable_mask_bounds (p.drawable->drawable_id, &p.selection.x0, &p.selection.y0, &p.selection.x1, &p.selection.y1); p.selection.width = p.selection.x1 - p.selection.x0; p.selection.height = p.selection.y1 - p.selection.y0; gimp_tile_cache_ntiles (2 * (p.selection.width / gimp_tile_width () + 1)); /* TILES */ division_x = p.params.division_x; division_y = p.params.division_y; if (p.params.fractional_type == FRACTIONAL_TYPE_FORCE) { if (0 < p.drawable->width % p.params.tile_width) division_x++; if (0 < p.drawable->height % p.params.tile_height) division_y++; if (p.params.centering) { if (1 < p.drawable->width % p.params.tile_width) { division_x++; offset_x = (p.drawable->width % p.params.tile_width) / 2 - p.params.tile_width; } else { offset_x = 0; } if (1 < p.drawable->height % p.params.tile_height) { division_y++; offset_y = (p.drawable->height % p.params.tile_height) / 2 - p.params.tile_height; } else { offset_y = 0; } } else { offset_x = 0; offset_y = 0; } } else { if (p.params.centering) { offset_x = (p.drawable->width % p.params.tile_width) / 2; offset_y = (p.drawable->height % p.params.tile_height) / 2; } else { offset_x = 0; offset_y = 0; } } move_max_pixels = p.params.move_max_rate * p.params.tile_width / 100.0; numof_tiles = division_x * division_y; t = tiles = g_new(Tile, numof_tiles); for (y = 0; y < division_y; y++) { gint srcy = offset_y + p.params.tile_height * y; for (x = 0; x < division_x; x++, t++) { gint srcx = offset_x + p.params.tile_width * x; if (srcx < 0) { t->x = 0; t->width = srcx + p.params.tile_width; } else if (srcx + p.params.tile_width < p.drawable->width) { t->x = srcx; t->width = p.params.tile_width; } else { t->x = srcx; t->width = p.drawable->width - srcx; } if (srcy < 0) { t->y = 0; t->height = srcy + p.params.tile_height; } else if (srcy + p.params.tile_height < p.drawable->height) { t->y = srcy; t->height = p.params.tile_height; } else { t->y = srcy; t->height = p.drawable->height - srcy; } t->z = g_rand_int (gr); random_move (&t->move_x, &t->move_y, move_max_pixels); } } qsort (tiles, numof_tiles, sizeof *tiles, tile_compare); gimp_pixel_rgn_get_rect (&src, pixels, 0, 0, p.drawable->width, p.drawable->height); if (p.params.fractional_type == FRACTIONAL_TYPE_IGNORE) { clear_x0 = offset_x; clear_y0 = offset_y; clear_width = p.params.tile_width * division_x; clear_height = p.params.tile_height * division_y; } else { clear_x0 = 0; clear_y0 = 0; clear_width = p.drawable->width; clear_height = p.drawable->height; } clear_x1 = clear_x0 + clear_width; clear_y1 = clear_y0 + clear_height; switch (p.params.background_type) { case BACKGROUND_TYPE_TRANSPARENT: for (y = clear_y0; y < clear_y1; y++) { for (x = clear_x0; x < clear_x1; x++) { dindex = p.drawable->bpp * (p.drawable->width * y + x); for (i = 0; i < p.drawable->bpp; i++) { pixels[dindex+i] = 0; } } } break; case BACKGROUND_TYPE_INVERTED: for (y = clear_y0; y < clear_y1; y++) { for (x = clear_x0; x < clear_x1; x++) { dindex = p.drawable->bpp * (p.drawable->width * y + x); pixels[dindex+0] = 255 - pixels[dindex+0]; pixels[dindex+1] = 255 - pixels[dindex+1]; pixels[dindex+2] = 255 - pixels[dindex+2]; } } break; case BACKGROUND_TYPE_IMAGE: break; case BACKGROUND_TYPE_FOREGROUND: gimp_context_get_foreground (&color); gimp_rgb_get_uchar (&color, &pixel[0], &pixel[1], &pixel[2]); pixel[3] = 255; for (y = clear_y0; y < clear_y1; y++) { for (x = clear_x0; x < clear_x1; x++) { dindex = p.drawable->bpp * (p.drawable->width * y + x); for (i = 0; i < p.drawable->bpp; i++) { pixels[dindex+i] = pixel[i]; } } } break; case BACKGROUND_TYPE_BACKGROUND: gimp_context_get_background (&color); gimp_rgb_get_uchar (&color, &pixel[0], &pixel[1], &pixel[2]); pixel[3] = 255; for (y = clear_y0; y < clear_y1; y++) { for (x = clear_x0; x < clear_x1; x++) { dindex = p.drawable->bpp * (p.drawable->width * y + x); for(i = 0; i < p.drawable->bpp; i++) { pixels[dindex+i] = pixel[i]; } } } break; case BACKGROUND_TYPE_COLOR: gimp_rgba_get_uchar (&p.params.background_color, pixel, pixel + 1, pixel + 2, pixel + 3); for (y = clear_y0; y < clear_y1; y++) { for (x = clear_x0; x < clear_x1; x++) { dindex = p.drawable->bpp * (p.drawable->width * y + x); for(i = 0; i < p.drawable->bpp; i++) { pixels[dindex+i] = pixel[i]; } } } break; } /* DRAW */ for (t = tiles, i = 0; i < numof_tiles; i++, t++) { gint x0 = t->x + t->move_x; gint y0 = t->y + t->move_y; gimp_pixel_rgn_get_rect (&src, buffer, t->x, t->y, t->width, t->height); for (y = 0; y < t->height; y++) { py = y0 + y; for (x = 0; x < t->width; x++) { px = x0 + x; sindex = p.drawable->bpp * (t->width * y + x); if (0 <= px && px < p.drawable->width && 0 <= py && py < p.drawable->height) { dindex = p.drawable->bpp * (p.drawable->width * py + px); overlap(&pixels[dindex], &buffer[sindex]); } else if (p.params.wrap_around) { px = (px + p.drawable->width) % p.drawable->width; py = (py + p.drawable->height) % p.drawable->height; dindex = p.drawable->bpp * (p.drawable->width * py + px); overlap(&pixels[dindex], &buffer[sindex]); } } } gimp_progress_update ((gdouble) i / (gdouble) numof_tiles); } gimp_pixel_rgn_set_rect (&dst, pixels, 0, 0, p.drawable->width, p.drawable->height); gimp_progress_update (1.0); gimp_drawable_flush (p.drawable); gimp_drawable_merge_shadow (p.drawable->drawable_id, TRUE); gimp_drawable_update (p.drawable->drawable_id, p.selection.x0, p.selection.y0, p.selection.width, p.selection.height); g_rand_free (gr); g_free (buffer); g_free (pixels); g_free (tiles); }
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); }