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); }
LOCAL void insert_cuts_and_bdry2d( INTERFACE *intfc, /* an orginal intfc */ double **pc) /* given corners of the subdomain */ { COMPONENT comp; CROSS *cross; CURVE **cc, *c[4]; CURVE **curves1, **curves2; POINT *p; INTERFACE *sav_intfc; NODE *n, **nn, *bn[4]; int i; sav_intfc = current_interface(); set_current_interface(intfc); comp = (intfc->modified) ? long_component(pc[0],intfc) : component(pc[0],intfc); redo_curve_list: for (cc = intfc->curves; cc && *cc; cc++) { if (is_bdry(*cc)) { (void) delete_curve(*cc); goto redo_curve_list; } } for (nn = intfc->nodes; nn && *nn; nn++) { if (is_bdry(*nn)) { int num_in, num_out; if (num_curves_at_node(*nn,&num_in,&num_out) == 0) (void) delete_node(*nn); else set_not_bdry(*nn); } } bn[0] = make_node(Point(pc[0])); bn[1] = make_node(Point(pc[2])); bn[2] = make_node(Point(pc[3])); bn[3] = make_node(Point(pc[1])); for (i = 0; i < 4; i++) { c[i] = make_curve(NO_COMP,NO_COMP,bn[i],bn[(i+1)%4]); set_is_bdry(c[0]); } if (intersections(intfc,&cross,YES) == FUNCTION_FAILED) { screen("ERROR in insert_cuts_and_bdry2d(), " "intersections() failed\n"); clean_up(ERROR); } if (cross == NULL) { for (i = 0; i < 4; i++) { positive_component(c[i]) = comp; negative_component(c[i]) = exterior_component(intfc); } return; } for (; cross != NULL; cross = cross->next) { p = cross->p; if (insert_point_in_bond(p,cross->b1,cross->c1)!=FUNCTION_SUCCEEDED) { screen("ERROR in insert_cuts_and_bdry2d(), " "insert_point_in_bond() failed\n"); clean_up(ERROR); } rcl_after_insert_point(cross,p,cross->b1); curves1 = split_curve(p,cross->b1,cross->c1, positive_component(cross->c1), negative_component(cross->c1), positive_component(cross->c1), negative_component(cross->c1)); rcl_after_split(cross,p,cross->b1,cross->c1,curves1); if (insert_point_in_bond(p,cross->b2,cross->c2)!=FUNCTION_SUCCEEDED) { screen("ERROR in insert_cuts_and_bdry2d(), " "insert_point_in_bond() failed\n"); clean_up(ERROR); } rcl_after_insert_point(cross,p,cross->b2); curves2 = split_curve(p,cross->b2,cross->c2, positive_component(cross->c2), negative_component(cross->c2), positive_component(cross->c2), negative_component(cross->c2)); rcl_after_split(cross,p,cross->b2,cross->c2,curves1); n = curves2[0]->end; change_node_of_curve(curves2[0], NEGATIVE_ORIENTATION,curves1[0]->end); change_node_of_curve(curves2[1], POSITIVE_ORIENTATION,curves1[0]->end); (void) delete_node(n); } set_current_interface(sav_intfc); return; } /*end insert_cuts_and_bdry2d*/