// Called before any real progress is made static void progressStart(gchar * message) { gimp_progress_init(message); gimp_progress_update(0.0); #ifdef DEBUG /* To console. On Windows, it annoyingly opens a console. On Unix it dissappears unless console already open. */ g_printf(message); g_printf("\n"); #endif }
static void notify_progress_cb (WebKitWebView *view, GParamSpec *pspec, gpointer user_data) { static gdouble old_progress = 0.0; gdouble progress = webkit_web_view_get_estimated_load_progress (view); if ((progress - old_progress) > 0.01) { gimp_progress_update (progress); old_progress = progress; } }
static int l_progress(lua_State * lua) { lua_Number percent; if (!lua_gettop(lua)) return 0; percent = lua_tonumber(lua, -1); #if 0 g_warning ("progress,.. %f", percent); gimp_progress_update((double) percent); #endif return 0; }
void gimp_rgn_iterate2 (GimpDrawable *drawable, GimpRunMode unused, GimpRgnFunc2 func, gpointer data) { GimpPixelRgn srcPR, destPR; gint x1, y1, x2, y2; gpointer pr; gint total_area; gint area_so_far; gint progress_skip; g_return_if_fail (drawable != NULL); gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); total_area = (x2 - x1) * (y2 - y1); if (total_area <= 0) return; area_so_far = 0; progress_skip = 0; /* Initialize the pixel regions. */ gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE); gimp_pixel_rgn_init (&destPR, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE); for (pr = gimp_pixel_rgns_register (2, &srcPR, &destPR); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { gimp_rgn_render_region (&srcPR, &destPR, func, data); area_so_far += srcPR.w * srcPR.h; if (((progress_skip++) % 10) == 0) gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area); } /* update the processed region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1)); }
static void mblur (GimpDrawable *drawable, GimpPreview *preview) { gint x, y; gint width, height; if (preview) { gimp_preview_get_position (preview, &x, &y); gimp_preview_get_size (preview, &width, &height); } else if (! gimp_drawable_mask_intersect (drawable->drawable_id, &x, &y, &width, &height)) { return; } if (! preview) gimp_progress_init (_("Motion blurring")); switch (mbvals.mblur_type) { case MBLUR_LINEAR: mblur_linear (drawable, preview, x, y, width, height); break; case MBLUR_RADIAL: mblur_radial (drawable, preview, x, y, width, height); break; case MBLUR_ZOOM: mblur_zoom (drawable, preview, x, y, width, height); break; default: break; } if (! preview) { gimp_progress_update (1.0); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x, y, width, height); } }
static void draw_page (GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, PrintData *data) { GError *error = NULL; if (print_draw_page (context, data, &error)) { gimp_progress_update (1.0); } else { print_show_error (error->message); g_error_free (error); } }
static void notify_progress_cb (WebKitWebView *view, GParamSpec *pspec, gpointer user_data) { static gdouble old_progress = 0.0; gdouble progress; g_object_get (view, "progress", &progress, NULL); if ((progress - old_progress) > 0.01) { gimp_progress_update (progress); old_progress = progress; } }
static void blur (GimpDrawable *drawable) { gint i, j, k, channels; gint x1, y1, x2, y2; GimpPixelRgn rgn_in, rgn_out; guchar *row1, *row2, *row3; guchar *outrow; gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); channels = gimp_drawable_bpp (drawable->drawable_id); gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1, x2 - x1, y2 - y1, FALSE, FALSE); gimp_pixel_rgn_init (&rgn_out, drawable, x1, y1, x2 - x1, y2 - y1, TRUE, TRUE); /* Initialise enough memory for row1, row2, row3, outrow */ row1 = g_new (guchar, channels * (x2 - x1)); outrow = g_new (guchar, channels * (x2 - x1)); for (i = y1; i < y2; i++) { /* Get row i-1, i, i+1 */ gimp_pixel_rgn_get_row (&rgn_in, row1, x1, MAX (y1, i - 1), x2 - x1); for (j = x1; j < x2; j++) { /* For each layer, compute the average of the nine pixels */ for (k = 0; k < channels; k++) { int in = row1[channels * (j - x1) + k]; int a = (1.0 - (in / 255.0)) * 100.0; int r = rand() % 100; outrow[channels * (j - x1) + k] = r < a ? 0 : 255; } } gimp_pixel_rgn_set_row (&rgn_out, outrow, x1, i, x2 - x1); if (i % 10 == 0) gimp_progress_update ((gdouble) (i - y1) / (gdouble) (y2 - y1)); } g_free (row1); g_free (outrow); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1); }
static void gimp_rgn_iterator_iter_single (GimpRgnIterator *iter, GimpPixelRgn *srcPR, GimpRgnFuncSrc func, gpointer data) { gpointer pr; gint total_area; gint area_so_far; total_area = (iter->x2 - iter->x1) * (iter->y2 - iter->y1); area_so_far = 0; for (pr = gimp_pixel_rgns_register (1, srcPR); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { guchar *src = srcPR->data; gint y; for (y = srcPR->y; y < srcPR->y + srcPR->h; y++) { guchar *s = src; gint x; for (x = srcPR->x; x < srcPR->x + srcPR->w; x++) { func (x, y, s, srcPR->bpp, data); s += srcPR->bpp; } src += srcPR->rowstride; } area_so_far += srcPR->w * srcPR->h; gimp_progress_update ((gdouble) area_so_far / (gdouble) total_area); } }
static gboolean copy_file (GFile *src_file, GFile *dest_file, Mode mode, GimpRunMode run_mode, GError **error) { UriProgress progress = { 0, }; gboolean success; gimp_progress_init (_("Connecting to server")); progress.mode = mode; success = g_file_copy (src_file, dest_file, G_FILE_COPY_OVERWRITE, NULL, uri_progress_callback, &progress, error); gimp_progress_update (1.0); if (! success && run_mode == GIMP_RUN_INTERACTIVE && (*error)->domain == G_IO_ERROR && (*error)->code == G_IO_ERROR_NOT_MOUNTED) { g_clear_error (error); if (mount_enclosing_volume (mode == DOWNLOAD ? src_file : dest_file, error)) { success = g_file_copy (src_file, dest_file, 0, NULL, uri_progress_callback, &progress, error); } } return success; }
static gboolean load_finished_idle (gpointer data) { static gint count = 0; gimp_progress_update ((gdouble) count * 0.025); count++; if (count < 10) return G_SOURCE_CONTINUE; webkit_web_view_get_snapshot (WEBKIT_WEB_VIEW (data), WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT, WEBKIT_SNAPSHOT_OPTIONS_NONE, NULL, snapshot_ready, NULL); count = 0; return G_SOURCE_REMOVE; }
gint32 file_vtf_load_image (const gchar *fname, GError **error) { gimp_progress_init_printf ("Opening '%s'", gimp_filename_to_utf8 (fname)); gint32 image = -1; std::auto_ptr<Vtf::File> vtf (new Vtf::File); try { vtf->load(fname); Vtf::HiresImageResource* vres = (Vtf::HiresImageResource*) vtf->findResource (Vtf::Resource::TypeHires); if (!vres) throw Vtf::Exception ("Cound not find high-resolution image"); image = gimp_image_new (vres->width (), vres->height (), GIMP_RGB); gimp_image_set_filename (image, fname); guint16 i, frame_count = vres->frameCount (); for (i = 0; i < frame_count; i++) { if (!file_vtf_load_layer (vres, image, i)) { g_set_error (error, 0, 0, "Unsupported format %s", Vtf::formatToString (vres->format())); gimp_image_delete (image); image = -1; break; } } gimp_progress_update (1.0); } catch (std::exception& e) { g_set_error (error, 0, 0, e.what ()); } return image; }
gint32 file_vtf_load_thumbnail_image (const gchar *fname, gint *width, gint *height, GError **error) { gint32 image = -1; gimp_progress_init_printf ("Opening thumbnail for '%s'", gimp_filename_to_utf8 (fname)); Vtf::File *vtf = new Vtf::File; try { vtf->load(fname); Vtf::HiresImageResource* vres = (Vtf::HiresImageResource*) vtf->findResource(Vtf::Resource::TypeHires); if (!vres) throw Vtf::Exception ("Cound not find high-resolution image"); *width = static_cast<gint> (vres->width ()); *height = static_cast<gint> (vres->height ()); image = gimp_image_new (*width, *height, GIMP_RGB); if (!file_vtf_load_layer (vres, image, 0)) { g_set_error (error, 0, 0, "Unsupported format %s", Vtf::formatToString(vres->format())); gimp_image_delete (image); image = -1; } gimp_progress_update (1.0); } catch (std::exception& e) { g_set_error (error, 0, 0, e.what()); } delete vtf; return image; }
static void snapshot_ready (GObject *source_object, GAsyncResult *result, gpointer user_data) { WebKitWebView *view = WEBKIT_WEB_VIEW (source_object); cairo_surface_t *surface; surface = webkit_web_view_get_snapshot_finish (view, result, &webpagevals.error); if (surface) { gint width; gint height; gint32 layer; width = cairo_image_surface_get_width (surface); height = cairo_image_surface_get_height (surface); webpagevals.image = gimp_image_new (width, height, GIMP_RGB); gimp_image_undo_disable (webpagevals.image); layer = gimp_layer_new_from_surface (webpagevals.image, _("Webpage"), surface, 0.25, 1.0); gimp_image_insert_layer (webpagevals.image, layer, -1, 0); gimp_image_undo_enable (webpagevals.image); cairo_surface_destroy (surface); } gimp_progress_update (1.0); gtk_main_quit (); }
/* * Cartoon algorithm * ----------------- * Mask radius = radius of pixel neighborhood for intensity comparison * Threshold = relative intensity difference which will result in darkening * Ramp = amount of relative intensity difference before total black * Blur radius = mask radius / 3.0 * * Algorithm: * For each pixel, calculate pixel intensity value to be: avg (blur radius) * relative diff = pixel intensity / avg (mask radius) * If relative diff < Threshold * intensity mult = (Ramp - MIN (Ramp, (Threshold - relative diff))) / Ramp * pixel intensity *= intensity mult */ static void cartoon (GimpDrawable *drawable, GimpPreview *preview) { GimpPixelRgn src_rgn, dest_rgn; GimpPixelRgn *pr; gint width, height; gint bytes; gboolean has_alpha; guchar *dest1; guchar *dest2; guchar *src; guchar *src1, *sp_p1, *sp_m1; guchar *src2, *sp_p2, *sp_m2; gdouble n_p1[5], n_m1[5]; gdouble n_p2[5], n_m2[5]; gdouble d_p1[5], d_m1[5]; gdouble d_p2[5], d_m2[5]; gdouble bd_p1[5], bd_m1[5]; gdouble bd_p2[5], bd_m2[5]; gdouble *val_p1, *val_m1, *vp1, *vm1; gdouble *val_p2, *val_m2, *vp2, *vm2; gint x1, y1, x2, y2; gint i, j; gint row, col, b; gint terms; gint progress, max_progress; gint initial_p1[4]; gint initial_p2[4]; gint initial_m1[4]; gint initial_m2[4]; gdouble radius; gdouble std_dev1; gdouble std_dev2; gdouble ramp; guchar *preview_buffer = NULL; if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); } else { gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = (x2 - x1); height = (y2 - y1); } bytes = drawable->bpp; has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); val_p1 = g_new (gdouble, MAX (width, height) * bytes); val_p2 = g_new (gdouble, MAX (width, height) * bytes); val_m1 = g_new (gdouble, MAX (width, height) * bytes); val_m2 = g_new (gdouble, MAX (width, height) * bytes); src = g_new (guchar, MAX (width, height) * bytes); dest1 = g_new0 (guchar, width * height); dest2 = g_new0 (guchar, width * height); gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE); progress = 0; max_progress = width * height * 2; /* Calculate the standard deviations */ radius = 1.0; /* blur radius */ radius = fabs (radius) + 1.0; std_dev1 = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0))); radius = cvals.mask_radius; radius = fabs (radius) + 1.0; std_dev2 = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0))); /* derive the constants for calculating the gaussian from the std dev */ find_constants (n_p1, n_m1, d_p1, d_m1, bd_p1, bd_m1, std_dev1); find_constants (n_p2, n_m2, d_p2, d_m2, bd_p2, bd_m2, std_dev2); /* First the vertical pass */ for (col = 0; col < width; col++) { memset (val_p1, 0, height * bytes * sizeof (gdouble)); memset (val_p2, 0, height * bytes * sizeof (gdouble)); memset (val_m1, 0, height * bytes * sizeof (gdouble)); memset (val_m2, 0, height * bytes * sizeof (gdouble)); gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height); src1 = src; sp_p1 = src1; sp_m1 = src1 + (height - 1) * bytes; vp1 = val_p1; vp2 = val_p2; vm1 = val_m1 + (height - 1) * bytes; vm2 = val_m2 + (height - 1) * bytes; /* Set up the first vals */ for (i = 0; i < bytes; i++) { initial_p1[i] = sp_p1[i]; initial_m1[i] = sp_m1[i]; } for (row = 0; row < height; row++) { gdouble *vpptr1, *vmptr1; gdouble *vpptr2, *vmptr2; terms = (row < 4) ? row : 4; for (b = 0; b < bytes; b++) { vpptr1 = vp1 + b; vmptr1 = vm1 + b; vpptr2 = vp2 + b; vmptr2 = vm2 + b; for (i = 0; i <= terms; i++) { *vpptr1 += n_p1[i] * sp_p1[(-i * bytes) + b] - d_p1[i] * vp1[(-i * bytes) + b]; *vmptr1 += n_m1[i] * sp_m1[(i * bytes) + b] - d_m1[i] * vm1[(i * bytes) + b]; *vpptr2 += n_p2[i] * sp_p1[(-i * bytes) + b] - d_p2[i] * vp2[(-i * bytes) + b]; *vmptr2 += n_m2[i] * sp_m1[(i * bytes) + b] - d_m2[i] * vm2[(i * bytes) + b]; } for (j = i; j <= 4; j++) { *vpptr1 += (n_p1[j] - bd_p1[j]) * initial_p1[b]; *vmptr1 += (n_m1[j] - bd_m1[j]) * initial_m1[b]; *vpptr2 += (n_p2[j] - bd_p2[j]) * initial_p1[b]; *vmptr2 += (n_m2[j] - bd_m2[j]) * initial_m1[b]; } } sp_p1 += bytes; sp_m1 -= bytes; vp1 += bytes; vp2 += bytes; vm1 -= bytes; vm2 -= bytes; } transfer_pixels (val_p1, val_m1, dest1 + col, width, bytes, height); transfer_pixels (val_p2, val_m2, dest2 + col, width, bytes, height); if (!preview) { progress += height; if ((col % 5) == 0) gimp_progress_update ((gdouble) progress / (gdouble) max_progress); } } for (row = 0; row < height; row++) { memset (val_p1, 0, width * sizeof (gdouble)); memset (val_p2, 0, width * sizeof (gdouble)); memset (val_m1, 0, width * sizeof (gdouble)); memset (val_m2, 0, width * sizeof (gdouble)); src1 = dest1 + row * width; src2 = dest2 + row * width; sp_p1 = src1; sp_p2 = src2; sp_m1 = src1 + width - 1; sp_m2 = src2 + width - 1; vp1 = val_p1; vp2 = val_p2; vm1 = val_m1 + width - 1; vm2 = val_m2 + width - 1; /* Set up the first vals */ initial_p1[0] = sp_p1[0]; initial_p2[0] = sp_p2[0]; initial_m1[0] = sp_m1[0]; initial_m2[0] = sp_m2[0]; for (col = 0; col < width; col++) { gdouble *vpptr1, *vmptr1; gdouble *vpptr2, *vmptr2; terms = (col < 4) ? col : 4; vpptr1 = vp1; vmptr1 = vm1; vpptr2 = vp2; vmptr2 = vm2; for (i = 0; i <= terms; i++) { *vpptr1 += n_p1[i] * sp_p1[-i] - d_p1[i] * vp1[-i]; *vmptr1 += n_m1[i] * sp_m1[i] - d_m1[i] * vm1[i]; *vpptr2 += n_p2[i] * sp_p2[-i] - d_p2[i] * vp2[-i]; *vmptr2 += n_m2[i] * sp_m2[i] - d_m2[i] * vm2[i]; } for (j = i; j <= 4; j++) { *vpptr1 += (n_p1[j] - bd_p1[j]) * initial_p1[0]; *vmptr1 += (n_m1[j] - bd_m1[j]) * initial_m1[0]; *vpptr2 += (n_p2[j] - bd_p2[j]) * initial_p2[0]; *vmptr2 += (n_m2[j] - bd_m2[j]) * initial_m2[0]; } sp_p1 ++; sp_p2 ++; sp_m1 --; sp_m2 --; vp1 ++; vp2 ++; vm1 --; vm2 --; } transfer_pixels (val_p1, val_m1, dest1 + row * width, 1, 1, width); transfer_pixels (val_p2, val_m2, dest2 + row * width, 1, 1, width); if (!preview) { progress += width; if ((row % 5) == 0) gimp_progress_update ((gdouble) progress / (gdouble) max_progress); } } /* Compute the ramp value which sets 'pct_black' % of the darkened pixels black */ ramp = compute_ramp (dest1, dest2, width * height, cvals.pct_black); /* Initialize the pixel regions. */ gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, width, height, FALSE, FALSE); if (preview) { pr = gimp_pixel_rgns_register (1, &src_rgn); preview_buffer = g_new (guchar, width * height * bytes); } else { gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, width, height, TRUE, TRUE); pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn); } while (pr) { guchar *src_ptr = src_rgn.data; guchar *dest_ptr; guchar *blur_ptr = dest1 + (src_rgn.y - y1) * width + (src_rgn.x - x1); guchar *avg_ptr = dest2 + (src_rgn.y - y1) * width + (src_rgn.x - x1); gdouble diff; gdouble mult = 0.0; gdouble lightness; if (preview) dest_ptr = preview_buffer + ((src_rgn.y - y1) * width + (src_rgn.x - x1)) * bytes; else dest_ptr = dest_rgn.data; for (row = 0; row < src_rgn.h; row++) { for (col = 0; col < src_rgn.w; col++) { if (avg_ptr[col] != 0) { diff = (gdouble) blur_ptr[col] / (gdouble) avg_ptr[col]; if (diff < cvals.threshold) { if (ramp == 0.0) mult = 0.0; else mult = (ramp - MIN (ramp, (cvals.threshold - diff))) / ramp; } else mult = 1.0; } lightness = CLAMP (blur_ptr[col] * mult, 0, 255); if (bytes < 3) { dest_ptr[col * bytes] = (guchar) lightness; if (has_alpha) dest_ptr[col * bytes + 1] = src_ptr[col * src_rgn.bpp + 1]; } else { /* Convert to HLS, set lightness and convert back */ gint r, g, b; r = src_ptr[col * src_rgn.bpp + 0]; g = src_ptr[col * src_rgn.bpp + 1]; b = src_ptr[col * src_rgn.bpp + 2]; gimp_rgb_to_hsl_int (&r, &g, &b); b = lightness; gimp_hsl_to_rgb_int (&r, &g, &b); dest_ptr[col * bytes + 0] = r; dest_ptr[col * bytes + 1] = g; dest_ptr[col * bytes + 2] = b; if (has_alpha) dest_ptr[col * bytes + 3] = src_ptr[col * src_rgn.bpp + 3]; } } src_ptr += src_rgn.rowstride; if (preview) dest_ptr += width * bytes; else dest_ptr += dest_rgn.rowstride; blur_ptr += width; avg_ptr += width; } if (!preview) { progress += src_rgn.w * src_rgn.h; gimp_progress_update ((gdouble) progress / (gdouble) max_progress); } pr = gimp_pixel_rgns_process (pr); } if (preview) { gimp_preview_draw_buffer (preview, preview_buffer, width * bytes); g_free (preview_buffer); } else { /* merge the shadow, update the drawable */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } /* free up buffers */ g_free (val_p1); g_free (val_p2); g_free (val_m1); g_free (val_m2); g_free (src); g_free (dest1); g_free (dest2); }
static void mblur_zoom (GimpDrawable *drawable, GimpPreview *preview, gint x1, gint y1, gint width, gint height) { GimpPixelRgn dest_rgn; GimpPixelFetcher *pft; gpointer pr; GimpRGB background; gdouble center_x; gdouble center_y; guchar *dest, *d; guchar pixel[4]; guchar p1[4], p2[4], p3[4], p4[4]; gint32 sum[4]; gint progress, max_progress; gint x, y, i, n, p, c; gdouble xx_start, xx_end, yy_start, yy_end; gdouble xx, yy; gdouble dxx, dyy; gdouble dx, dy; gint xy_len; gdouble f, r; gint drawable_x1, drawable_y1; gint drawable_x2, drawable_y2; /* initialize */ xx = 0.0; yy = 0.0; center_x = mbvals.center_x; center_y = mbvals.center_y; gimp_drawable_mask_bounds (drawable->drawable_id, &drawable_x1, &drawable_y1, &drawable_x2, &drawable_y2); gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, width, height, (preview == NULL), TRUE); pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_pixel_fetcher_set_bg_color (pft, &background); progress = 0; max_progress = width * height; n = mbvals.length; if (n == 0) n = 1; r = sqrt (SQR (drawable->width / 2) + SQR (drawable->height / 2)); n = ((gdouble) n * r / MBLUR_LENGTH_MAX); f = (r-n)/r; for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0; pr != NULL; pr = gimp_pixel_rgns_process (pr), p++) { dest = dest_rgn.data; for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) { d = dest; for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) { for (c = 0; c < img_bpp; c++) sum[c] = 0; xx_start = x; yy_start = y; if (mbvals.blur_outward) { xx_end = center_x + ((gdouble) x - center_x) * f; yy_end = center_y + ((gdouble) y - center_y) * f; } else { xx_end = center_x + ((gdouble) x - center_x) * (1.0/f); yy_end = center_y + ((gdouble) y - center_y) * (1.0/f); } xy_len = sqrt (SQR (xx_end-xx_start) + SQR (yy_end-yy_start)) + 1; if (xy_len < 3) xy_len = 3; dxx = (xx_end - xx_start) / (gdouble) xy_len; dyy = (yy_end - yy_start) / (gdouble) xy_len; xx = xx_start; yy = yy_start; for (i = 0; i < xy_len; i++) { if ((yy < drawable_y1) || (yy >= drawable_y2) || (xx < drawable_x1) || (xx >= drawable_x2)) break; if ((xx+1 < drawable_x2) && (yy+1 < drawable_y2)) { dx = xx - floor (xx); dy = yy - floor (yy); gimp_pixel_fetcher_get_pixel (pft, xx, yy, p1); gimp_pixel_fetcher_get_pixel (pft, xx+1, yy, p2); gimp_pixel_fetcher_get_pixel (pft, xx, yy+1, p3); gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4); for (c = 0; c < img_bpp; c++) { pixel[c] = (((gdouble)p1[c] * (1.0-dx) + (gdouble)p2[c] * dx) * (1.0-dy) + ((gdouble)p3[c] * (1.0-dx) + (gdouble)p4[c] * dx) * dy); } } else { gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel); } if (has_alpha) { gint32 alpha = pixel[img_bpp-1]; sum[img_bpp-1] += alpha; for (c = 0; c < img_bpp-1; c++) sum[c] += pixel[c] * alpha; } else { for (c = 0; c < img_bpp; c++) sum[c] += pixel[c]; } xx += dxx; yy += dyy; } if (i == 0) { gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); } else { if (has_alpha) { gint32 alpha = sum[img_bpp-1]; if ((d[img_bpp-1] = alpha/i) != 0) { for (c = 0; c < img_bpp-1; c++) d[c] = sum[c] / alpha; } } else { for (c = 0; c < img_bpp; c++) d[c] = sum[c] / i; } } d += dest_rgn.bpp; } dest += dest_rgn.rowstride; } if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &dest_rgn); } else { progress += dest_rgn.w * dest_rgn.h; if ((p % 8) == 0) gimp_progress_update ((gdouble) progress / max_progress); } } gimp_pixel_fetcher_destroy (pft); }
/** * gimp_layer_new_from_pixbuf: * @image_ID: The RGB image to which to add the layer. * @name: The layer name. * @pixbuf: A GdkPixbuf. * @opacity: The layer opacity. * @mode: The layer combination mode. * @progress_start: start of progress * @progress_end: end of progress * * Create a new layer from a %GdkPixbuf. * * This procedure creates a new layer from the given %GdkPixbuf. The * image has to be an RGB image and just like with gimp_layer_new() * you will still need to add the layer to it. * * If you pass @progress_end > @progress_start to this function, * @gimp_progress_update() will be called for. You have to call * @gimp_progress_init() beforehand. * * Returns: The newly created layer. * * Since: GIMP 2.4 */ gint32 gimp_layer_new_from_pixbuf (gint32 image_ID, const gchar *name, GdkPixbuf *pixbuf, gdouble opacity, GimpLayerModeEffects mode, gdouble progress_start, gdouble progress_end) { GimpDrawable *drawable; GimpPixelRgn rgn; const guchar *pixels; gpointer pr; gint32 layer; gint width; gint height; gint rowstride; gint bpp; gdouble range = progress_end - progress_start; guint count = 0; guint done = 0; g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), -1); if (gimp_image_base_type (image_ID) != GIMP_RGB) { g_warning ("gimp_layer_new_from_pixbuf() needs an RGB image"); return -1; } if (gdk_pixbuf_get_colorspace (pixbuf) != GDK_COLORSPACE_RGB) { g_warning ("gimp_layer_new_from_pixbuf() assumes that GdkPixbuf is RGB"); return -1; } width = gdk_pixbuf_get_width (pixbuf); height = gdk_pixbuf_get_height (pixbuf); bpp = gdk_pixbuf_get_n_channels (pixbuf); layer = gimp_layer_new (image_ID, name, width, height, bpp == 3 ? GIMP_RGB_IMAGE : GIMP_RGBA_IMAGE, opacity, mode); if (layer == -1) return -1; drawable = gimp_drawable_get (layer); gimp_pixel_rgn_init (&rgn, drawable, 0, 0, width, height, TRUE, FALSE); g_assert (bpp == rgn.bpp); rowstride = gdk_pixbuf_get_rowstride (pixbuf); pixels = gdk_pixbuf_get_pixels (pixbuf); for (pr = gimp_pixel_rgns_register (1, &rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { const guchar *src = pixels + rgn.y * rowstride + rgn.x * bpp; guchar *dest = rgn.data; gint y; for (y = 0; y < rgn.h; y++) { memcpy (dest, src, rgn.w * rgn.bpp); src += rowstride; dest += rgn.rowstride; } if (range > 0.0) { done += rgn.h * rgn.w; if (count++ % 32 == 0) gimp_progress_update (progress_start + (gdouble) done / (width * height) * range); } } if (range > 0.0) gimp_progress_update (progress_end); gimp_drawable_detach (drawable); return layer; }
static void mblur_linear (GimpDrawable *drawable, GimpPreview *preview, gint x1, gint y1, gint width, gint height) { GimpPixelRgn dest_rgn; GimpPixelFetcher *pft; gpointer pr; GimpRGB background; guchar *dest; guchar *d; guchar pixel[4]; gint32 sum[4]; gint progress, max_progress; gint c, p; gint x, y, i, xx, yy, n; gint dx, dy, px, py, swapdir, err, e, s1, s2; gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, width, height, (preview == NULL), TRUE); pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_pixel_fetcher_set_bg_color (pft, &background); progress = 0; max_progress = width * height; n = mbvals.length; px = (gdouble) n * cos (mbvals.angle / 180.0 * G_PI); py = (gdouble) n * sin (mbvals.angle / 180.0 * G_PI); /* * Initialization for Bresenham algorithm: * dx = abs(x2-x1), s1 = sign(x2-x1) * dy = abs(y2-y1), s2 = sign(y2-y1) */ if ((dx = px) != 0) { if (dx < 0) { dx = -dx; s1 = -1; } else s1 = 1; } else s1 = 0; if ((dy = py) != 0) { if (dy < 0) { dy = -dy; s2 = -1; } else s2 = 1; } else s2 = 0; if (dy > dx) { swapdir = dx; dx = dy; dy = swapdir; swapdir = 1; } else swapdir = 0; dy *= 2; err = dy - dx; /* Initial error term */ dx *= 2; for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0; pr != NULL; pr = gimp_pixel_rgns_process (pr), p++) { dest = dest_rgn.data; for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) { d = dest; for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) { xx = x; yy = y; e = err; for (c = 0; c < img_bpp; c++) sum[c]= 0; for (i = 0; i < n; ) { gimp_pixel_fetcher_get_pixel (pft, xx, yy, pixel); if (has_alpha) { gint32 alpha = pixel[img_bpp-1]; sum[img_bpp-1] += alpha; for (c = 0; c < img_bpp-1; c++) sum[c] += pixel[c] * alpha; } else { for (c = 0; c < img_bpp; c++) sum[c] += pixel[c]; } i++; while (e >= 0 && dx) { if (swapdir) xx += s1; else yy += s2; e -= dx; } if (swapdir) yy += s2; else xx += s1; e += dy; if ((xx < x1) || (xx >= x1 + width) || (yy < y1) || (yy >= y1 + height)) break; } if (i == 0) { gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); } else { if (has_alpha) { gint32 alpha = sum[img_bpp-1]; if ((d[img_bpp-1] = alpha/i) != 0) { for (c = 0; c < img_bpp-1; c++) d[c] = sum[c] / alpha; } } else { for (c = 0; c < img_bpp; c++) d[c] = sum[c] / i; } } d += dest_rgn.bpp; } dest += dest_rgn.rowstride; } if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &dest_rgn); } else { progress += dest_rgn.w * dest_rgn.h; if ((p % 8) == 0) gimp_progress_update ((gdouble) progress / max_progress); } } gimp_pixel_fetcher_destroy (pft); }
static void mblur_radial (GimpDrawable *drawable, GimpPreview *preview, gint x1, gint y1, gint width, gint height) { GimpPixelRgn dest_rgn; GimpPixelFetcher *pft; gpointer pr; GimpRGB background; gdouble center_x; gdouble center_y; guchar *dest; guchar *d; guchar pixel[4]; guchar p1[4], p2[4], p3[4], p4[4]; gint32 sum[4]; gint progress, max_progress, c; gint x, y, i, p, n, count; gdouble angle, theta, r, xx, yy, xr, yr; gdouble phi, phi_start, s_val, c_val; gdouble dx, dy; /* initialize */ xx = 0.0; yy = 0.0; center_x = mbvals.center_x; center_y = mbvals.center_y; gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, width, height, (preview == NULL), TRUE); pft = gimp_pixel_fetcher_new (drawable, FALSE); gimp_context_get_background (&background); gimp_pixel_fetcher_set_bg_color (pft, &background); progress = 0; max_progress = width * height; angle = gimp_deg_to_rad (mbvals.angle); for (pr = gimp_pixel_rgns_register (1, &dest_rgn), p = 0; pr != NULL; pr = gimp_pixel_rgns_process (pr), p++) { dest = dest_rgn.data; for (y = dest_rgn.y; y < dest_rgn.y + dest_rgn.h; y++) { d = dest; for (x = dest_rgn.x; x < dest_rgn.x + dest_rgn.w; x++) { xr = (gdouble) x - center_x; yr = (gdouble) y - center_y; r = sqrt (SQR (xr) + SQR (yr)); n = r * angle; if (angle == 0.0) { gimp_pixel_fetcher_get_pixel (pft, x, y, d); d += dest_rgn.bpp; continue; } /* ensure quality with small angles */ if (n < 3) n = 3; /* always use at least 3 (interpolation) steps */ /* limit loop count due to performanc reasons */ if (n > 100) n = 100 + sqrt (n-100); if (xr != 0.0) { phi = atan(yr/xr); if (xr < 0.0) phi = G_PI + phi; } else { if (yr >= 0.0) phi = G_PI_2; else phi = -G_PI_2; } for (c = 0; c < img_bpp; c++) sum[c] = 0; if (n == 1) phi_start = phi; else phi_start = phi + angle/2.0; theta = angle / (gdouble)n; count = 0; for (i = 0; i < n; i++) { s_val = sin (phi_start - (gdouble) i * theta); c_val = cos (phi_start - (gdouble) i * theta); xx = center_x + r * c_val; yy = center_y + r * s_val; if ((yy < y1) || (yy >= y1 + height) || (xx < x1) || (xx >= x1 + width)) continue; ++count; if ((xx + 1 < x1 + width) && (yy + 1 < y1 + height)) { dx = xx - floor (xx); dy = yy - floor (yy); gimp_pixel_fetcher_get_pixel (pft, xx, yy, p1); gimp_pixel_fetcher_get_pixel (pft, xx+1, yy, p2); gimp_pixel_fetcher_get_pixel (pft, xx, yy+1, p3); gimp_pixel_fetcher_get_pixel (pft, xx+1, yy+1, p4); for (c = 0; c < img_bpp; c++) { pixel[c] = (((gdouble) p1[c] * (1.0-dx) + (gdouble) p2[c] * dx) * (1.0-dy) + ((gdouble) p3[c] * (1.0-dx) + (gdouble) p4[c] * dx) * dy); } } else { gimp_pixel_fetcher_get_pixel (pft, xx+.5, yy+.5, pixel); } if (has_alpha) { gint32 alpha = pixel[img_bpp-1]; sum[img_bpp-1] += alpha; for (c = 0; c < img_bpp-1; c++) sum[c] += pixel[c] * alpha; } else { for (c = 0; c < img_bpp; c++) sum[c] += pixel[c]; } } if (count == 0) { gimp_pixel_fetcher_get_pixel (pft, xx, yy, d); } else { if (has_alpha) { gint32 alpha = sum[img_bpp-1]; if ((d[img_bpp-1] = alpha/count) != 0) { for (c = 0; c < img_bpp-1; c++) d[c] = sum[c] / alpha; } } else { for (c = 0; c < img_bpp; c++) d[c] = sum[c] / count; } } d += dest_rgn.bpp; } dest += dest_rgn.rowstride; } if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &dest_rgn); } else { progress += dest_rgn.w * dest_rgn.h; if ((p % 8) == 0) gimp_progress_update ((gdouble) progress / max_progress); } } gimp_pixel_fetcher_destroy (pft); }
gboolean draw_page_cairo (GtkPrintContext *context, PrintData *data) { GimpDrawable *drawable = gimp_drawable_get (data->drawable_id); GimpPixelRgn region; cairo_t *cr; cairo_surface_t *surface; guchar *pixels; gdouble cr_width; gdouble cr_height; gdouble cr_dpi_x; gdouble cr_dpi_y; gint width; gint height; gint stride; gint y; gdouble scale_x; gdouble scale_y; width = drawable->width; height = drawable->height; gimp_tile_cache_ntiles (width / gimp_tile_width () + 1); cr = gtk_print_context_get_cairo_context (context); cr_width = gtk_print_context_get_width (context); cr_height = gtk_print_context_get_height (context); cr_dpi_x = gtk_print_context_get_dpi_x (context); cr_dpi_y = gtk_print_context_get_dpi_y (context); scale_x = cr_dpi_x / data->xres; scale_y = cr_dpi_y / data->yres; #if 0 /* print header if it is requested */ if (data->show_info_header) { draw_info_header (context, cr, data); /* In points */ #define HEADER_HEIGHT (20 * 72.0 / 25.4) cairo_translate (cr, 0, HEADER_HEIGHT); cr_height -= HEADER_HEIGHT; } #endif cairo_translate (cr, data->offset_x / cr_dpi_x * 72.0, data->offset_y / cr_dpi_y * 72.0); cairo_scale (cr, scale_x, scale_y); gimp_pixel_rgn_init (®ion, drawable, 0, 0, width, height, FALSE, FALSE); surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); pixels = cairo_image_surface_get_data (surface); stride = cairo_image_surface_get_stride (surface); for (y = 0; y < height; y++, pixels += stride) { gimp_pixel_rgn_get_row (®ion, pixels, 0, y, width); switch (drawable->bpp) { case 3: convert_from_rgb (pixels, width); break; case 4: convert_from_rgba (pixels, width); break; } if (y % 16 == 0) gimp_progress_update ((gdouble) y / (gdouble) height); } cairo_set_source_surface (cr, surface, 0, 0); cairo_rectangle (cr, 0, 0, width, height); cairo_fill (cr); cairo_surface_destroy (surface); gimp_progress_update (1.0); gimp_drawable_detach (drawable); return TRUE; }
/* - Filter function - I wish all filter functions had a pmode :) */ static void glasstile (GimpDrawable *drawable, GimpPreview *preview) { GimpPixelRgn srcPR, destPR; gint width, height; gint bytes; guchar *dest, *d; guchar *cur_row; gint row, col, i; gint x1, y1, x2, y2; /* Translations of variable names from Maswan * rutbredd = grid width * ruthojd = grid height * ymitt = y middle * xmitt = x middle */ gint rutbredd, xpixel1, xpixel2; gint ruthojd , ypixel2; gint xhalv, xoffs, xmitt, xplus; gint yhalv, yoffs, ymitt, yplus; if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); x2 = x1 + width; y2 = y1 + height; } else { gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = x2 - x1; height = y2 - y1; } bytes = drawable->bpp; cur_row = g_new (guchar, width * bytes); dest = g_new (guchar, width * bytes); /* initialize the pixel regions, set grid height/width */ 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); rutbredd = gtvals.xblock; ruthojd = gtvals.yblock; xhalv = rutbredd / 2; yhalv = ruthojd / 2; xplus = rutbredd % 2; yplus = ruthojd % 2; ymitt = y1; yoffs = 0; /* Loop through the rows */ for (row = y1; row < y2; row++) { d = dest; ypixel2 = ymitt + yoffs * 2; ypixel2 = CLAMP (ypixel2, 0, y2 - 1); gimp_pixel_rgn_get_row (&srcPR, cur_row, x1, ypixel2, width); yoffs++; /* if current offset = half, do a displacement next time around */ if (yoffs == yhalv) { ymitt += ruthojd; yoffs = - (yhalv + yplus); } xmitt = 0; xoffs = 0; for (col = 0; col < x2 - x1; col++) /* one pixel */ { xpixel1 = (xmitt + xoffs) * bytes; xpixel2 = (xmitt + xoffs * 2) * bytes; if (xpixel2 < (x2 - x1) * bytes) { if (xpixel2 < 0) xpixel2 = 0; for (i = 0; i < bytes; i++) d[xpixel1 + i] = cur_row[xpixel2 + i]; } else { for (i = 0; i < bytes; i++) d[xpixel1 + i] = cur_row[xpixel1 + i]; } xoffs++; if (xoffs == xhalv) { xmitt += rutbredd; xoffs = - (xhalv + xplus); } } /* Store the dest */ gimp_pixel_rgn_set_row (&destPR, dest, x1, row, width); if (!preview && ((row % 5) == 0)) { gimp_progress_update ((gdouble) row / (gdouble) height); } } /* Update region */ if (preview) { gimp_drawable_preview_draw_region (GIMP_DRAWABLE_PREVIEW (preview), &destPR); } else { gimp_progress_update (1.0); gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } g_free (cur_row); g_free (dest); }
static void gauss_rle (GimpDrawable *drawable, gdouble radius, gint pass, gboolean show_progress) { GimpPixelRgn src_rgn, dest_rgn; gint width, height; gint bytes; gint has_alpha; guchar *dest, *dp; guchar *src, *sp; gint *buf, *bb; gint pixels; gint total = 1; gint x1, y1, x2, y2; gint i, row, col, b; gint start, end; gdouble progress, max_progress; gint *curve; gint *sum = NULL; gint val; gint length; gint initial_p, initial_m; gdouble std_dev; if (radius <= 0.0) return; gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = (x2 - x1); height = (y2 - y1); if (width < 1 || height < 1) return; bytes = drawable->bpp; has_alpha = gimp_drawable_has_alpha(drawable->drawable_id); buf = g_new (gint, MAX (width, height) * 2); /* allocate buffers for source and destination pixels */ src = g_new (guchar, MAX (width, height) * bytes); dest = g_new (guchar, MAX (width, height) * bytes); gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE); gimp_pixel_rgn_init (&dest_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, TRUE); progress = 0.0; max_progress = 2 * width * height; /* First the vertical pass */ radius = fabs (radius) + 1.0; std_dev = sqrt (-(radius * radius) / (2 * log (1.0 / 255.0))); curve = make_curve (std_dev, &length); sum = g_new (gint, 2 * length + 1); sum[0] = 0; for (i = 1; i <= length*2; i++) sum[i] = curve[i-length-1] + sum[i-1]; sum += length; total = sum[length] - sum[-length]; for (col = 0; col < width; col++) { gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, (y2 - y1)); if (has_alpha) multiply_alpha (src, height, bytes); sp = src; dp = dest; for (b = 0; b < bytes; b++) { initial_p = sp[b]; initial_m = sp[(height-1) * bytes + b]; /* Determine a run-length encoded version of the row */ run_length_encode (sp + b, buf, bytes, height); for (row = 0; row < height; row++) { start = (row < length) ? -row : -length; end = (height <= (row + length) ? (height - row - 1) : length); val = 0; i = start; bb = buf + (row + i) * 2; if (start != -length) val += initial_p * (sum[start] - sum[-length]); while (i < end) { pixels = bb[0]; i += pixels; if (i > end) i = end; val += bb[1] * (sum[i] - sum[start]); bb += (pixels * 2); start = i; } if (end != length) val += initial_m * (sum[length] - sum[end]); dp[row * bytes + b] = val / total; } } if (has_alpha) separate_alpha (dest, height, bytes); gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, (y2 - y1)); if (show_progress) { progress += height; if ((col % 32) == 0) gimp_progress_update (0.5 * (pass + (progress / max_progress))); } } /* prepare for the horizontal pass */ gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, TRUE); /* Now the horizontal pass */ for (row = 0; row < height; row++) { gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, (x2 - x1)); if (has_alpha) multiply_alpha (src, width, bytes); sp = src; dp = dest; for (b = 0; b < bytes; b++) { initial_p = sp[b]; initial_m = sp[(width-1) * bytes + b]; /* Determine a run-length encoded version of the row */ run_length_encode (sp + b, buf, bytes, width); for (col = 0; col < width; col++) { start = (col < length) ? -col : -length; end = (width <= (col + length)) ? (width - col - 1) : length; val = 0; i = start; bb = buf + (col + i) * 2; if (start != -length) val += initial_p * (sum[start] - sum[-length]); while (i < end) { pixels = bb[0]; i += pixels; if (i > end) i = end; val += bb[1] * (sum[i] - sum[start]); bb += (pixels * 2); start = i; } if (end != length) val += initial_m * (sum[length] - sum[end]); dp[col * bytes + b] = val / total; } } if (has_alpha) separate_alpha (dest, width, bytes); gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, (x2 - x1)); if (show_progress) { progress += width; if ((row % 32) == 0) gimp_progress_update (0.5 * (pass + (progress / max_progress))); } } /* merge the shadow, update the drawable */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1)); /* free buffers */ g_free (buf); g_free (src); g_free (dest); }
/* * 'load_image()' - Load a WMF image into a new image window. */ static gint32 load_image (const gchar *filename, GError **error) { gint32 image; gint32 layer; GimpDrawable *drawable; guchar *pixels; GimpPixelRgn pixel_rgn; guint width, height; guint rowstride; guint count = 0; guint done = 0; gpointer pr; pixels = wmf_load_file (filename, &width, &height, error); if (! pixels) return -1; rowstride = width * 4; gimp_progress_init_printf (_("Opening '%s'"), gimp_filename_to_utf8 (filename)); image = gimp_image_new (width, height, GIMP_RGB); gimp_image_set_filename (image, filename); gimp_image_set_resolution (image, load_vals.resolution, load_vals.resolution); layer = gimp_layer_new (image, _("Rendered WMF"), width, height, GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE); drawable = gimp_drawable_get (layer); gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, TRUE, FALSE); for (pr = gimp_pixel_rgns_register (1, &pixel_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { const guchar *src = pixels + pixel_rgn.y * rowstride + pixel_rgn.x * 4; guchar *dest = pixel_rgn.data; gint y; for (y = 0; y < pixel_rgn.h; y++) { memcpy (dest, src, pixel_rgn.w * pixel_rgn.bpp); src += rowstride; dest += pixel_rgn.rowstride; } done += pixel_rgn.h * pixel_rgn.w; if (count++ % 16 == 0) gimp_progress_update ((gdouble) done / (width * height)); } g_free (pixels); gimp_drawable_detach (drawable); gimp_progress_update (1.0); /* Tell GIMP to display the image. */ gimp_image_insert_layer (image, layer, -1, 0); gimp_drawable_flush (drawable); return image; }
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); }
static void run (const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) { static GimpParam values[1]; gint32 image_ID; GimpDrawable *drawable; GimpRunMode run_mode; GimpPDBStatusType status = GIMP_PDB_SUCCESS; run_mode = param[0].data.d_int32; INIT_I18N (); *nreturn_vals = 1; *return_vals = values; values[0].type = GIMP_PDB_STATUS; values[0].data.d_status = status; /* Get the specified image and drawable */ image_ID = param[1].data.d_image; drawable = gimp_drawable_get (param[2].data.d_drawable); /* set the tile cache size so that the gaussian blur works well */ gimp_tile_cache_ntiles (2 * (MAX (drawable->width, drawable->height) / gimp_tile_width () + 1)); if (strcmp (name, PLUG_IN_PROC) == 0) { switch (run_mode) { case GIMP_RUN_INTERACTIVE: /* Possibly retrieve data */ gimp_get_data (PLUG_IN_PROC, &dogvals); /* First acquire information with a dialog */ if (! dog_dialog (image_ID, drawable)) return; break; case GIMP_RUN_NONINTERACTIVE: /* Make sure all the arguments are there! */ if (nparams != 7) status = GIMP_PDB_CALLING_ERROR; if (status == GIMP_PDB_SUCCESS) { dogvals.inner = param[3].data.d_float; dogvals.outer = param[4].data.d_float; dogvals.normalize = param[5].data.d_int32; dogvals.invert = param[6].data.d_int32; } if (status == GIMP_PDB_SUCCESS && (dogvals.inner <= 0.0 && dogvals.outer <= 0.0)) status = GIMP_PDB_CALLING_ERROR; break; case GIMP_RUN_WITH_LAST_VALS: /* Possibly retrieve data */ gimp_get_data (PLUG_IN_PROC, &dogvals); break; default: break; } } else { status = GIMP_PDB_CALLING_ERROR; } if (status == GIMP_PDB_SUCCESS) { /* Make sure that the drawable is gray or RGB color */ if (gimp_drawable_is_rgb (drawable->drawable_id) || gimp_drawable_is_gray (drawable->drawable_id)) { gimp_progress_init (_("DoG Edge Detect")); /* run the Difference of Gaussians */ gimp_image_undo_group_start (image_ID); dog (image_ID, drawable, dogvals.inner, dogvals.outer, TRUE); gimp_image_undo_group_end (image_ID); gimp_progress_update (1.0); /* Store data */ if (run_mode == GIMP_RUN_INTERACTIVE) gimp_set_data (PLUG_IN_PROC, &dogvals, sizeof (DoGValues)); if (run_mode != GIMP_RUN_NONINTERACTIVE) gimp_displays_flush (); } else { g_message (_("Cannot operate on indexed color images.")); status = GIMP_PDB_EXECUTION_ERROR; } gimp_drawable_detach (drawable); } values[0].data.d_status = status; }
static gboolean copy_uri (const gchar *src_uri, const gchar *dest_uri, const gchar *copying_format_str, const gchar *copied_format_str, GError **error) { GnomeVFSHandle *read_handle; GnomeVFSHandle *write_handle; GnomeVFSFileInfo *src_info; GnomeVFSFileSize file_size = 0; GnomeVFSFileSize bytes_read = 0; guchar buffer[BUFSIZE]; GnomeVFSResult result; gchar *memsize; GTimeVal last_time = { 0, 0 }; gimp_progress_init (_("Connecting to server")); src_info = gnome_vfs_file_info_new (); result = gnome_vfs_get_file_info (src_uri, src_info, 0); /* ignore errors here, they will be noticed below */ if (result == GNOME_VFS_OK && (src_info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)) { file_size = src_info->size; } gnome_vfs_file_info_unref (src_info); result = gnome_vfs_open (&read_handle, src_uri, GNOME_VFS_OPEN_READ); if (result != GNOME_VFS_OK) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Could not open '%s' for reading: %s"), src_uri, gnome_vfs_result_to_string (result)); return FALSE; } result = gnome_vfs_create (&write_handle, dest_uri, GNOME_VFS_OPEN_WRITE, FALSE, 0644); if (result != GNOME_VFS_OK) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Could not open '%s' for writing: %s"), dest_uri, gnome_vfs_result_to_string (result)); gnome_vfs_close (read_handle); return FALSE; } memsize = g_format_size_for_display (file_size); gimp_progress_init_printf (file_size > 0 ? copying_format_str : copied_format_str, memsize); g_free (memsize); while (TRUE) { GnomeVFSFileSize chunk_read; GnomeVFSFileSize chunk_written; GTimeVal now; result = gnome_vfs_read (read_handle, buffer, sizeof (buffer), &chunk_read); if (chunk_read == 0) { if (result != GNOME_VFS_ERROR_EOF) { memsize = g_format_size_for_display (sizeof (buffer)); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to read %s from '%s': %s"), memsize, src_uri, gnome_vfs_result_to_string (result)); g_free (memsize); gnome_vfs_close (read_handle); gnome_vfs_close (write_handle); return FALSE; } else { gimp_progress_update (1.0); break; } } bytes_read += chunk_read; /* update the progress only up to 10 times a second */ g_get_current_time (&now); if (((now.tv_sec - last_time.tv_sec) * 1000 + (now.tv_usec - last_time.tv_usec) / 1000) > 100) { if (file_size > 0) { gimp_progress_update ((gdouble) bytes_read / (gdouble) file_size); } else { memsize = g_format_size_for_display (bytes_read); gimp_progress_set_text_printf (copied_format_str, memsize); gimp_progress_pulse (); g_free (memsize); } last_time = now; } result = gnome_vfs_write (write_handle, buffer, chunk_read, &chunk_written); if (chunk_written < chunk_read) { memsize = g_format_size_for_display (chunk_read); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Failed to write %s to '%s': %s"), memsize, dest_uri, gnome_vfs_result_to_string (result)); g_free (memsize); gnome_vfs_close (read_handle); gnome_vfs_close (write_handle); return FALSE; } } gnome_vfs_close (read_handle); gnome_vfs_close (write_handle); return TRUE; }
static gint32 tile (gint32 image_id, gint32 drawable_id, gint32 *layer_id) { GimpPixelRgn src_rgn; GimpPixelRgn dest_rgn; GimpDrawable *drawable; GimpDrawable *new_layer; GimpImageBaseType image_type = GIMP_RGB; gint32 new_image_id = 0; gint old_width; gint old_height; gint i, j; gint progress; gint max_progress; gpointer pr; /* sanity check parameters */ if (tvals.new_width < 1 || tvals.new_height < 1) { *layer_id = -1; return -1; } /* initialize */ old_width = gimp_drawable_width (drawable_id); old_height = gimp_drawable_height (drawable_id); if (tvals.new_image) { /* create a new image */ switch (gimp_drawable_type (drawable_id)) { case GIMP_RGB_IMAGE: case GIMP_RGBA_IMAGE: image_type = GIMP_RGB; break; case GIMP_GRAY_IMAGE: case GIMP_GRAYA_IMAGE: image_type = GIMP_GRAY; break; case GIMP_INDEXED_IMAGE: case GIMP_INDEXEDA_IMAGE: image_type = GIMP_INDEXED; break; } new_image_id = gimp_image_new (tvals.new_width, tvals.new_height, image_type); gimp_image_undo_disable (new_image_id); *layer_id = gimp_layer_new (new_image_id, _("Background"), tvals.new_width, tvals.new_height, gimp_drawable_type (drawable_id), 100, GIMP_NORMAL_MODE); if (*layer_id == -1) return -1; gimp_image_insert_layer (new_image_id, *layer_id, -1, 0); new_layer = gimp_drawable_get (*layer_id); /* Get the source drawable */ drawable = gimp_drawable_get (drawable_id); } else { gimp_image_undo_group_start (image_id); gimp_image_resize (image_id, tvals.new_width, tvals.new_height, 0, 0); if (gimp_item_is_layer (drawable_id)) gimp_layer_resize (drawable_id, tvals.new_width, tvals.new_height, 0, 0); /* Get the source drawable */ drawable = gimp_drawable_get (drawable_id); new_layer = drawable; } /* progress */ progress = 0; max_progress = tvals.new_width * tvals.new_height; /* tile... */ for (i = 0; i < tvals.new_height; i += old_height) { gint height = old_height; if (height + i > tvals.new_height) height = tvals.new_height - i; for (j = 0; j < tvals.new_width; j += old_width) { gint width = old_width; gint c; if (width + j > tvals.new_width) width = tvals.new_width - j; gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&dest_rgn, new_layer, j, i, width, height, TRUE, FALSE); for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn), c = 0; pr != NULL; pr = gimp_pixel_rgns_process (pr), c++) { gint k; for (k = 0; k < src_rgn.h; k++) memcpy (dest_rgn.data + k * dest_rgn.rowstride, src_rgn.data + k * src_rgn.rowstride, src_rgn.w * src_rgn.bpp); progress += src_rgn.w * src_rgn.h; if (c % 16 == 0) gimp_progress_update ((gdouble) progress / (gdouble) max_progress); } } } gimp_drawable_update (new_layer->drawable_id, 0, 0, new_layer->width, new_layer->height); gimp_drawable_detach (drawable); if (tvals.new_image) { gimp_drawable_detach (new_layer); /* copy the colormap, if necessary */ if (image_type == GIMP_INDEXED) { guchar *cmap; gint ncols; cmap = gimp_image_get_colormap (image_id, &ncols); gimp_image_set_colormap (new_image_id, cmap, ncols); g_free (cmap); } gimp_image_undo_enable (new_image_id); } else { gimp_image_undo_group_end (image_id); } return new_image_id; }
static void explorer (GimpDrawable * drawable) { GimpPixelRgn srcPR; GimpPixelRgn destPR; gint width; gint height; gint bpp; gint row; gint x1; gint y1; gint x2; gint y2; guchar *src_row; guchar *dest_row; /* Get the input area. This is the bounding box of the selection in * the image (or the entire image if there is no selection). Only * operating on the input area is simply an optimization. It doesn't * need to be done for correct operation. (It simply makes it go * faster, since fewer pixels need to be operated on). */ gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); /* Get the size of the input image. (This will/must be the same * as the size of the output image. */ width = drawable->width; height = drawable->height; bpp = drawable->bpp; /* allocate row buffers */ src_row = g_new (guchar, bpp * (x2 - x1)); dest_row = g_new (guchar, bpp * (x2 - x1)); /* initialize the pixel regions */ gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE); gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE); xbild = width; ybild = height; xdiff = (xmax - xmin) / xbild; ydiff = (ymax - ymin) / ybild; /* for grayscale drawables */ if (bpp < 3) { gint i; for (i = 0; i < MAXNCOLORS; i++) valuemap[i] = GIMP_RGB_LUMINANCE (colormap[i].r, colormap[i].g, colormap[i].b); } for (row = y1; row < y2; row++) { gimp_pixel_rgn_get_row (&srcPR, src_row, x1, row, (x2 - x1)); explorer_render_row (src_row, dest_row, row, (x2 - x1), bpp); /* store the dest */ gimp_pixel_rgn_set_row (&destPR, dest_row, x1, row, (x2 - x1)); if ((row % 10) == 0) gimp_progress_update ((double) row / (double) (y2 - y1)); } /* update the processed region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, (x2 - x1), (y2 - y1)); g_free (src_row); g_free (dest_row); }
/* This function operates on the image when pixelwidth >= tile_width. It simply sets the size of GimpPixelRgn as pixelwidth and proceeds. */ static void pixelize_large (GimpDrawable *drawable, gint pixelwidth, gint pixelheight, GimpPreview *preview) { GimpPixelRgn src_rgn, dest_rgn; guchar *src_row, *dest_row; guchar *src, *dest = NULL, *d; gulong average[4]; gint row, col, b, bpp, has_alpha; gint x, y, x_step, y_step; gint i, j; gulong count; gint x1, y1, x2, y2; gint width, height; gint progress = 0, max_progress = 1; gpointer pr; bpp = gimp_drawable_bpp (drawable->drawable_id); has_alpha = gimp_drawable_has_alpha (drawable->drawable_id); if (preview) { gimp_preview_get_position (preview, &x1, &y1); gimp_preview_get_size (preview, &width, &height); x2 = x1 + width; y2 = y1 + height; dest = g_new (guchar, width * height * bpp); } else { gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2); width = x2 - x1; height = y2 - y1; /* Initialize progress */ progress = 0; max_progress = 2 * width * height; } for (y = y1; y < y2; y += pixelheight - (y % pixelheight)) { for (x = x1; x < x2; x += pixelwidth - (x % pixelwidth)) { x_step = pixelwidth - (x % pixelwidth); y_step = pixelheight - (y % pixelheight); x_step = MIN (x_step, x2 - x); y_step = MIN (y_step, y2 - y); gimp_pixel_rgn_init (&src_rgn, drawable, x, y, x_step, y_step, FALSE, FALSE); for (b = 0; b < bpp; b++) average[b] = 0; count = 0; for (pr = gimp_pixel_rgns_register (1, &src_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { src_row = src_rgn.data; for (row = 0; row < src_rgn.h; row++) { src = src_row; if (has_alpha) { for (col = 0; col < src_rgn.w; col++) { gulong alpha = src[bpp - 1]; average[bpp - 1] += alpha; for (b = 0; b < bpp - 1; b++) average[b] += src[b] * alpha; src += src_rgn.bpp; } } else { for (col = 0; col < src_rgn.w; col++) { for (b = 0; b < bpp; b++) average[b] += src[b]; src += src_rgn.bpp; } } src_row += src_rgn.rowstride; } count += src_rgn.w * src_rgn.h; if (!preview) { /* Update progress */ progress += src_rgn.w * src_rgn.h; gimp_progress_update ((double) progress / (double) max_progress); } } if (count > 0) { if (has_alpha) { gulong alpha = average[bpp - 1]; if ((average[bpp - 1] = alpha / count)) for (b = 0; b < bpp - 1; b++) average[b] /= alpha; } else { for (b = 0; b < bpp; b++) average[b] /= count; } } if (preview) { dest_row = dest + ((y - y1) * width + (x - x1)) * bpp; for (j = 0; j < y_step; j++) { d = dest_row; for (i = 0; i < x_step; i++) for (b = 0; b < bpp; b++) *d++ = average[b]; dest_row += width * bpp; } } else { gimp_pixel_rgn_init (&dest_rgn, drawable, x, y, x_step, y_step, TRUE, TRUE); for (pr = gimp_pixel_rgns_register (1, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr)) { dest_row = dest_rgn.data; for (row = 0; row < dest_rgn.h; row++) { dest = dest_row; for (col = 0; col < dest_rgn.w; col++) { for (b = 0; b < bpp; b++) dest[b] = average[b]; dest += dest_rgn.bpp; } dest_row += dest_rgn.rowstride; } /* Update progress */ progress += dest_rgn.w * dest_rgn.h; gimp_progress_update ((double) progress / (double) max_progress); } } } } if (preview) { gimp_preview_draw_buffer (preview, dest, width * bpp); g_free (dest); } else { /* update the blurred region */ gimp_drawable_flush (drawable); gimp_drawable_merge_shadow (drawable->drawable_id, TRUE); gimp_drawable_update (drawable->drawable_id, x1, y1, width, height); } }
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); } }