Speed up cubism by 2x (I think) and mosaic something along the same vein.

Speed up cubism by 2x (I think) and mosaic something along the same vein.
This commit is contained in:
Elliot Lee 1998-10-12 04:33:20 +00:00
parent 0c635a62c1
commit 6707a8969f
4 changed files with 364 additions and 186 deletions

View file

@ -17,6 +17,7 @@
* *
* You can contact me at quartic@polloux.fciencias.unam.mx * You can contact me at quartic@polloux.fciencias.unam.mx
* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu * You can contact the original The Gimp authors at gimp@xcf.berkeley.edu
* Speedups by Elliot Lee
*/ */
@ -96,7 +97,7 @@ static void randomize_indices (gint count,
static gdouble fp_rand (gdouble val); static gdouble fp_rand (gdouble val);
static gint int_rand (gint val); static gint int_rand (gint val);
static gdouble calc_alpha_blend (gdouble * vec, static gdouble calc_alpha_blend (gdouble * vec,
gdouble dist, gdouble one_over_dist,
gdouble x, gdouble x,
gdouble y); gdouble y);
static void polygon_add_point (Polygon * poly, static void polygon_add_point (Polygon * poly,
@ -501,6 +502,27 @@ render_cubism (GDrawable *drawable)
free (random_indices); free (random_indices);
} }
G_INLINE_FUNC gdouble
calc_alpha_blend (gdouble *vec,
gdouble one_over_dist,
gdouble x,
gdouble y)
{
gdouble r;
if (!one_over_dist)
return 1.0;
else
{
r = (vec[0] * x + vec[1] * y) * one_over_dist;
if (r < 0.2)
r = 0.2;
else if (r > 1.0)
r = 1.0;
}
return r;
}
static void static void
fill_poly_color (Polygon *poly, fill_poly_color (Polygon *poly,
GDrawable *drawable, GDrawable *drawable,
@ -514,22 +536,23 @@ fill_poly_color (Polygon *poly,
gint min_x, min_y; gint min_x, min_y;
gint max_x, max_y; gint max_x, max_y;
gint size_x, size_y; gint size_x, size_y;
gint * max_scanlines; gint * max_scanlines, *max_scanlines_iter, *max_scanlines_end;
gint * min_scanlines; gint * min_scanlines, *min_scanlines_iter, *min_scanlines_end;
gint * vals;
gint val; gint val;
gint alpha; gint alpha;
gint bytes; gint bytes;
guchar buf[4]; guchar buf[4];
gint b, i, j, k, x, y; gint i, j, x, y;
gdouble sx, sy; gdouble sx, sy;
gdouble ex, ey; gdouble ex, ey;
gdouble xx, yy; gdouble xx, yy;
gdouble vec[2]; gdouble vec[2];
gdouble dist; gdouble dist, one_over_dist;
gint supersample; gint supersample;
gint supersample2; gint supersample2;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
gint *vals, *vals_iter, *vals_end;
gint pixel_gen_on_next_pass = -1;
sx = poly->pts[0].x; sx = poly->pts[0].x;
sy = poly->pts[0].y; sy = poly->pts[0].y;
@ -539,9 +562,11 @@ fill_poly_color (Polygon *poly,
dist = sqrt (SQR (ex - sx) + SQR (ey - sy)); dist = sqrt (SQR (ex - sx) + SQR (ey - sy));
if (dist > 0.0) if (dist > 0.0)
{ {
vec[0] = (ex - sx) / dist; one_over_dist = 1/dist;
vec[1] = (ey - sy) / dist; vec[0] = (ex - sx) * one_over_dist;
} vec[1] = (ey - sy) * one_over_dist;
} else
one_over_dist = 0.0;
supersample = SUPERSAMPLE; supersample = SUPERSAMPLE;
supersample2 = SQR (supersample); supersample2 = SQR (supersample);
@ -558,20 +583,37 @@ fill_poly_color (Polygon *poly,
size_y = (max_y - min_y) * supersample; size_y = (max_y - min_y) * supersample;
size_x = (max_x - min_x) * supersample; size_x = (max_x - min_x) * supersample;
min_scanlines = (gint *) malloc (sizeof (gint) * size_y); min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
max_scanlines = (gint *) malloc (sizeof (gint) * size_y); max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++)
{ {
min_scanlines[i] = max_x * supersample; min_scanlines[i] = max_x * supersample;
max_scanlines[i] = min_x * supersample; max_scanlines[i] = min_x * supersample;
} }
for (i = 0; i < poly->npts; i++) if(poly->npts) {
{ gint poly_npts = poly->npts;
xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); Vertex *curptr;
ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y);
xe = (gint) poly->pts[i].x; xs = (gint) (poly->pts[poly_npts-1].x);
ye = (gint) poly->pts[i].y; ys = (gint) (poly->pts[poly_npts-1].y);
xe = (gint) poly->pts[0].x;
ye = (gint) poly->pts[0].y;
xs *= supersample;
ys *= supersample;
xe *= supersample;
ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines);
for(i = 1, curptr = &poly->pts[0]; i < poly_npts; i++) {
xs = (gint) curptr->x;
ys = (gint) curptr->y;
curptr++;
xe = (gint) curptr->x;
ye = (gint) curptr->y;
xs *= supersample; xs *= supersample;
ys *= supersample; ys *= supersample;
@ -581,20 +623,22 @@ fill_poly_color (Polygon *poly,
convert_segment (xs, ys, xe, ye, min_y * supersample, convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines); min_scanlines, max_scanlines);
} }
}
gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0,
drawable->width, drawable->height, drawable->width, drawable->height,
TRUE, TRUE); TRUE, TRUE);
vals = (gint *) malloc (sizeof (gint) * size_x); vals = (gint *) malloc (sizeof (gint) * size_x);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++)
{ {
if (! (i % supersample)) if (! (i % supersample)) {
memset (vals, 0, sizeof (gint) * size_x); memset (vals, 0, sizeof (gint) * size_x);
}
yy = (gdouble) i / (gdouble) supersample + min_y; yy = (gdouble)i / (gdouble)supersample + min_y;
for (j = min_scanlines[i]; j < max_scanlines[i]; j++) for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++)
{ {
x = j - min_x * supersample; x = j - min_x * supersample;
vals[x] += 255; vals[x] += 255;
@ -612,21 +656,37 @@ fill_poly_color (Polygon *poly,
if (x >= x1 && x < x2) if (x >= x1 && x < x2)
{ {
val = 0; for (val = 0, vals_iter = &vals[j],
for (k = 0; k < supersample; k++) vals_end = &vals_iter[supersample];
val += vals[j + k]; vals_iter < vals_end;
vals_iter++)
val += *vals_iter;
val /= supersample2; val /= supersample2;
if (val > 0) if (val > 0)
{ {
xx = (gdouble) j / (gdouble) supersample + min_x; xx = (gdouble) j / (gdouble) supersample + min_x;
alpha = (gint) (val * calc_alpha_blend (vec, dist, xx - sx, yy - sy)); alpha = (gint) (val * calc_alpha_blend (vec, one_over_dist, xx - sx, yy - sy));
gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y); gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y);
#ifndef USE_READABLE_BUT_SLOW_CODE
{
guchar *buf_iter = buf,
*col_iter = col,
*buf_end = buf+bytes;
for(; buf_iter < buf_end; buf_iter++, col_iter++)
*buf_iter = ((guint)(*col_iter * alpha)
+ (((guint)*buf_iter)
* (256 - alpha))) >> 8;
}
#else /* original, pre-ECL code */
for (b = 0; b < bytes; b++) for (b = 0; b < bytes; b++)
buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255; buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255;
#endif
gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y); gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y);
} }
} }
@ -673,27 +733,6 @@ convert_segment (gint x1,
} }
} }
static gdouble
calc_alpha_blend (gdouble *vec,
gdouble dist,
gdouble x,
gdouble y)
{
gdouble r;
if (!dist)
return 1.0;
else
{
r = (vec[1] * y + vec[0] * x) / dist;
if (r < 0.2)
r = 0.2;
else if (r > 1.0)
r = 1.0;
}
return r;
}
static void static void
randomize_indices (gint count, randomize_indices (gint count,
gint *indices) gint *indices)

View file

@ -20,6 +20,7 @@
* what appears to be a mosaic, composed of small primitives, * what appears to be a mosaic, composed of small primitives,
* each of constant color and of an approximate size. * each of constant color and of an approximate size.
* Copyright (C) 1996 Spencer Kimball * Copyright (C) 1996 Spencer Kimball
* Speedups by Elliot Lee
*/ */
#include <math.h> #include <math.h>
@ -887,23 +888,19 @@ find_gradients (GDrawable *drawable,
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
{ {
for (j = 0; j < width; j++) for (j = 0; j < width; j++, dh++, dv++, gr++)
{ {
hmax = dh[j] - 128;
vmax = dv[j] - 128;
/* Find the gradient */ /* Find the gradient */
gradient = sqrt (SQR (hmax) + SQR (vmax));
if (!j || !i || (j == width - 1) || (i == height - 1)) if (!j || !i || (j == width - 1) || (i == height - 1))
gr[j] = MAG_THRESHOLD; *gr = MAG_THRESHOLD;
else else {
gr[j] = (guchar) gradient; hmax = *dh - 128;
} vmax = *dv - 128;
*gr = (guchar)sqrt (SQR (hmax) + SQR (hmax));
}
dh += width; }
dv += width;
gr += width;
} }
} }
@ -912,7 +909,7 @@ static void
find_max_gradient (GPixelRgn *src_rgn, find_max_gradient (GPixelRgn *src_rgn,
GPixelRgn *dest_rgn) GPixelRgn *dest_rgn)
{ {
guchar *s, *d; guchar *s, *d, *s_iter, *s_end;
gpointer pr; gpointer pr;
gint i, j; gint i, j;
gint b; gint b;
@ -931,14 +928,25 @@ find_max_gradient (GPixelRgn *src_rgn,
for (j = 0; j < src_rgn->w; j++) for (j = 0; j < src_rgn->w; j++)
{ {
max = 0; max = 0;
#ifndef SLOW_CODE
#define ABSVAL(x) ((x) >= 0 ? (x) : -(x))
for(s_iter = s, s_end = s + src_rgn->bpp;
s_iter < s_end; s_iter++) {
val = *s;
if(ABSVAL(val) > ABSVAL(max))
max = val;
}
*d++ = max;
#else
for (b = 0; b < src_rgn->bpp; b++) for (b = 0; b < src_rgn->bpp; b++)
{ {
val = (gint) s[b] - 128; val = (gint) s[b] - 128;
if (abs (val) > abs (max)) if (abs (val) > abs (max))
max = val; max = val;
} }
*d++ = (max + 128); *d++ = (max + 128);
#endif
s += src_rgn->bpp; s += src_rgn->bpp;
} }
@ -993,7 +1001,12 @@ gaussian_deriv (GPixelRgn *src_rgn,
src = data; src = data;
dest = data + length; dest = data + length;
#ifdef UNOPTIMIZED_CODE
length = 3; /* static for speed */ length = 3; /* static for speed */
#else
/* badhack :) */
# define length 3
#endif
/* initialize */ /* initialize */
curve = curve_array + length; curve = curve_array + length;
@ -1188,6 +1201,10 @@ gaussian_deriv (GPixelRgn *src_rgn,
free (buf); free (buf);
free (data); free (data);
#ifndef UNOPTIMIZED_CODE
/* end bad hack */
#undef length
#endif
} }
/* /*
@ -2105,8 +2122,8 @@ fill_poly_color (Polygon *poly,
gint min_x, min_y; gint min_x, min_y;
gint max_x, max_y; gint max_x, max_y;
gint size_x, size_y; gint size_x, size_y;
gint * max_scanlines; gint * max_scanlines, *max_scanlines_iter;
gint * min_scanlines; gint * min_scanlines, *min_scanlines_iter;
gint * vals; gint * vals;
gint val; gint val;
gint pixel; gint pixel;
@ -2118,6 +2135,8 @@ fill_poly_color (Polygon *poly,
gint supersample; gint supersample;
gint supersample2; gint supersample2;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
Vertex *pts_tmp;
const int poly_npts = poly->npts;
/* Determine antialiasing */ /* Determine antialiasing */
if (mvals.antialiasing) if (mvals.antialiasing)
@ -2132,15 +2151,29 @@ fill_poly_color (Polygon *poly,
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
bytes = drawable->bpp; bytes = drawable->bpp;
for (i = 0; i < poly->npts; i++)
{
xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x);
ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y);
xe = (gint) poly->pts[i].x;
ye = (gint) poly->pts[i].y;
calc_spec_vec (vecs+i, xs, ys, xe, ye); /* begin loop */
} if(poly_npts) {
pts_tmp = poly->pts;
xs = (gint) pts_tmp[poly_npts-1].x;
ys = (gint) pts_tmp[poly_npts-1].y;
xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
calc_spec_vec (vecs, xs, ys, xe, ye);
for (i = 1; i < poly_npts; i++)
{
xs = (gint) (pts_tmp->x);
ys = (gint) (pts_tmp->y);
pts_tmp++;
xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
calc_spec_vec (vecs+i, xs, ys, xe, ye);
}
}
/* end loop */
polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y); polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y);
min_x = (gint) dmin_x; min_x = (gint) dmin_x;
@ -2151,43 +2184,62 @@ fill_poly_color (Polygon *poly,
size_y = (max_y - min_y) * supersample; size_y = (max_y - min_y) * supersample;
size_x = (max_x - min_x) * supersample; size_x = (max_x - min_x) * supersample;
min_scanlines = (gint *) malloc (sizeof (gint) * size_y); min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
max_scanlines = (gint *) malloc (sizeof (gint) * size_y); max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++)
{ {
min_scanlines[i] = max_x * supersample; min_scanlines[i] = max_x * supersample;
max_scanlines[i] = min_x * supersample; max_scanlines[i] = min_x * supersample;
} }
for (i = 0; i < poly->npts; i++) /* begin loop */
{ if(poly_npts) {
xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); pts_tmp = poly->pts;
ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); xs = (gint) pts_tmp[poly_npts-1].x;
xe = (gint) poly->pts[i].x; ys = (gint) pts_tmp[poly_npts-1].y;
ye = (gint) poly->pts[i].y; xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
xs *= supersample; xs *= supersample;
ys *= supersample; ys *= supersample;
xe *= supersample; xe *= supersample;
ye *= supersample; ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample, convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines); min_scanlines, max_scanlines);
}
for (i = 1; i < poly_npts; i++)
{
xs = (gint) pts_tmp->x;
ys = (gint) pts_tmp->y;
pts_tmp++;
xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
xs *= supersample;
ys *= supersample;
xe *= supersample;
ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines);
}
}
/* end loop */
gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0,
drawable->width, drawable->height, drawable->width, drawable->height,
TRUE, TRUE); TRUE, TRUE);
vals = (gint *) malloc (sizeof (gint) * size_x); vals = (gint *) malloc (sizeof (gint) * size_x);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++)
{ {
if (! (i % supersample)) if (! (i % supersample))
memset (vals, 0, sizeof (gint) * size_x); memset (vals, 0, sizeof (gint) * size_x);
yy = (gdouble) i / (gdouble) supersample + min_y; yy = (gdouble) i / (gdouble) supersample + min_y;
for (j = min_scanlines[i]; j < max_scanlines[i]; j++) for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++)
{ {
x = j - min_x * supersample; x = j - min_x * supersample;
vals[x] += 255; vals[x] += 255;
@ -2212,15 +2264,13 @@ fill_poly_color (Polygon *poly,
if (val > 0) if (val > 0)
{ {
xx = (gdouble) j / (gdouble) supersample + min_x; xx = (gdouble) j / (gdouble) supersample + min_x;
contrib = calc_spec_contrib (vecs, poly->npts, xx, yy); contrib = calc_spec_contrib (vecs, poly_npts, xx, yy);
for (b = 0; b < bytes; b++) for (b = 0; b < bytes; b++)
{ {
if (contrib < 0.0) pixel = col[b] + (gint) (((contrib < 0.0)?(col[b] - back[b]):(fore[b] - col[b])) * contrib);
pixel = col[b] + (gint) ((col[b] - back[b]) * contrib);
else
pixel = col[b] + (gint) ((fore[b] - col[b]) * contrib);
buf[b] = ((pixel * val) + (back[b] * (255 - val))) / 255; buf[b] = ((pixel * val) + (back[b] * (255 - val))) / 255;
} }

View file

@ -17,6 +17,7 @@
* *
* You can contact me at quartic@polloux.fciencias.unam.mx * You can contact me at quartic@polloux.fciencias.unam.mx
* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu * You can contact the original The Gimp authors at gimp@xcf.berkeley.edu
* Speedups by Elliot Lee
*/ */
@ -96,7 +97,7 @@ static void randomize_indices (gint count,
static gdouble fp_rand (gdouble val); static gdouble fp_rand (gdouble val);
static gint int_rand (gint val); static gint int_rand (gint val);
static gdouble calc_alpha_blend (gdouble * vec, static gdouble calc_alpha_blend (gdouble * vec,
gdouble dist, gdouble one_over_dist,
gdouble x, gdouble x,
gdouble y); gdouble y);
static void polygon_add_point (Polygon * poly, static void polygon_add_point (Polygon * poly,
@ -501,6 +502,27 @@ render_cubism (GDrawable *drawable)
free (random_indices); free (random_indices);
} }
G_INLINE_FUNC gdouble
calc_alpha_blend (gdouble *vec,
gdouble one_over_dist,
gdouble x,
gdouble y)
{
gdouble r;
if (!one_over_dist)
return 1.0;
else
{
r = (vec[0] * x + vec[1] * y) * one_over_dist;
if (r < 0.2)
r = 0.2;
else if (r > 1.0)
r = 1.0;
}
return r;
}
static void static void
fill_poly_color (Polygon *poly, fill_poly_color (Polygon *poly,
GDrawable *drawable, GDrawable *drawable,
@ -514,22 +536,23 @@ fill_poly_color (Polygon *poly,
gint min_x, min_y; gint min_x, min_y;
gint max_x, max_y; gint max_x, max_y;
gint size_x, size_y; gint size_x, size_y;
gint * max_scanlines; gint * max_scanlines, *max_scanlines_iter, *max_scanlines_end;
gint * min_scanlines; gint * min_scanlines, *min_scanlines_iter, *min_scanlines_end;
gint * vals;
gint val; gint val;
gint alpha; gint alpha;
gint bytes; gint bytes;
guchar buf[4]; guchar buf[4];
gint b, i, j, k, x, y; gint i, j, x, y;
gdouble sx, sy; gdouble sx, sy;
gdouble ex, ey; gdouble ex, ey;
gdouble xx, yy; gdouble xx, yy;
gdouble vec[2]; gdouble vec[2];
gdouble dist; gdouble dist, one_over_dist;
gint supersample; gint supersample;
gint supersample2; gint supersample2;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
gint *vals, *vals_iter, *vals_end;
gint pixel_gen_on_next_pass = -1;
sx = poly->pts[0].x; sx = poly->pts[0].x;
sy = poly->pts[0].y; sy = poly->pts[0].y;
@ -539,9 +562,11 @@ fill_poly_color (Polygon *poly,
dist = sqrt (SQR (ex - sx) + SQR (ey - sy)); dist = sqrt (SQR (ex - sx) + SQR (ey - sy));
if (dist > 0.0) if (dist > 0.0)
{ {
vec[0] = (ex - sx) / dist; one_over_dist = 1/dist;
vec[1] = (ey - sy) / dist; vec[0] = (ex - sx) * one_over_dist;
} vec[1] = (ey - sy) * one_over_dist;
} else
one_over_dist = 0.0;
supersample = SUPERSAMPLE; supersample = SUPERSAMPLE;
supersample2 = SQR (supersample); supersample2 = SQR (supersample);
@ -558,20 +583,37 @@ fill_poly_color (Polygon *poly,
size_y = (max_y - min_y) * supersample; size_y = (max_y - min_y) * supersample;
size_x = (max_x - min_x) * supersample; size_x = (max_x - min_x) * supersample;
min_scanlines = (gint *) malloc (sizeof (gint) * size_y); min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
max_scanlines = (gint *) malloc (sizeof (gint) * size_y); max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++)
{ {
min_scanlines[i] = max_x * supersample; min_scanlines[i] = max_x * supersample;
max_scanlines[i] = min_x * supersample; max_scanlines[i] = min_x * supersample;
} }
for (i = 0; i < poly->npts; i++) if(poly->npts) {
{ gint poly_npts = poly->npts;
xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); Vertex *curptr;
ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y);
xe = (gint) poly->pts[i].x; xs = (gint) (poly->pts[poly_npts-1].x);
ye = (gint) poly->pts[i].y; ys = (gint) (poly->pts[poly_npts-1].y);
xe = (gint) poly->pts[0].x;
ye = (gint) poly->pts[0].y;
xs *= supersample;
ys *= supersample;
xe *= supersample;
ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines);
for(i = 1, curptr = &poly->pts[0]; i < poly_npts; i++) {
xs = (gint) curptr->x;
ys = (gint) curptr->y;
curptr++;
xe = (gint) curptr->x;
ye = (gint) curptr->y;
xs *= supersample; xs *= supersample;
ys *= supersample; ys *= supersample;
@ -581,20 +623,22 @@ fill_poly_color (Polygon *poly,
convert_segment (xs, ys, xe, ye, min_y * supersample, convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines); min_scanlines, max_scanlines);
} }
}
gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0,
drawable->width, drawable->height, drawable->width, drawable->height,
TRUE, TRUE); TRUE, TRUE);
vals = (gint *) malloc (sizeof (gint) * size_x); vals = (gint *) malloc (sizeof (gint) * size_x);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++)
{ {
if (! (i % supersample)) if (! (i % supersample)) {
memset (vals, 0, sizeof (gint) * size_x); memset (vals, 0, sizeof (gint) * size_x);
}
yy = (gdouble) i / (gdouble) supersample + min_y; yy = (gdouble)i / (gdouble)supersample + min_y;
for (j = min_scanlines[i]; j < max_scanlines[i]; j++) for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++)
{ {
x = j - min_x * supersample; x = j - min_x * supersample;
vals[x] += 255; vals[x] += 255;
@ -612,21 +656,37 @@ fill_poly_color (Polygon *poly,
if (x >= x1 && x < x2) if (x >= x1 && x < x2)
{ {
val = 0; for (val = 0, vals_iter = &vals[j],
for (k = 0; k < supersample; k++) vals_end = &vals_iter[supersample];
val += vals[j + k]; vals_iter < vals_end;
vals_iter++)
val += *vals_iter;
val /= supersample2; val /= supersample2;
if (val > 0) if (val > 0)
{ {
xx = (gdouble) j / (gdouble) supersample + min_x; xx = (gdouble) j / (gdouble) supersample + min_x;
alpha = (gint) (val * calc_alpha_blend (vec, dist, xx - sx, yy - sy)); alpha = (gint) (val * calc_alpha_blend (vec, one_over_dist, xx - sx, yy - sy));
gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y); gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y);
#ifndef USE_READABLE_BUT_SLOW_CODE
{
guchar *buf_iter = buf,
*col_iter = col,
*buf_end = buf+bytes;
for(; buf_iter < buf_end; buf_iter++, col_iter++)
*buf_iter = ((guint)(*col_iter * alpha)
+ (((guint)*buf_iter)
* (256 - alpha))) >> 8;
}
#else /* original, pre-ECL code */
for (b = 0; b < bytes; b++) for (b = 0; b < bytes; b++)
buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255; buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255;
#endif
gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y); gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y);
} }
} }
@ -673,27 +733,6 @@ convert_segment (gint x1,
} }
} }
static gdouble
calc_alpha_blend (gdouble *vec,
gdouble dist,
gdouble x,
gdouble y)
{
gdouble r;
if (!dist)
return 1.0;
else
{
r = (vec[1] * y + vec[0] * x) / dist;
if (r < 0.2)
r = 0.2;
else if (r > 1.0)
r = 1.0;
}
return r;
}
static void static void
randomize_indices (gint count, randomize_indices (gint count,
gint *indices) gint *indices)

View file

@ -20,6 +20,7 @@
* what appears to be a mosaic, composed of small primitives, * what appears to be a mosaic, composed of small primitives,
* each of constant color and of an approximate size. * each of constant color and of an approximate size.
* Copyright (C) 1996 Spencer Kimball * Copyright (C) 1996 Spencer Kimball
* Speedups by Elliot Lee
*/ */
#include <math.h> #include <math.h>
@ -887,23 +888,19 @@ find_gradients (GDrawable *drawable,
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
{ {
for (j = 0; j < width; j++) for (j = 0; j < width; j++, dh++, dv++, gr++)
{ {
hmax = dh[j] - 128;
vmax = dv[j] - 128;
/* Find the gradient */ /* Find the gradient */
gradient = sqrt (SQR (hmax) + SQR (vmax));
if (!j || !i || (j == width - 1) || (i == height - 1)) if (!j || !i || (j == width - 1) || (i == height - 1))
gr[j] = MAG_THRESHOLD; *gr = MAG_THRESHOLD;
else else {
gr[j] = (guchar) gradient; hmax = *dh - 128;
} vmax = *dv - 128;
*gr = (guchar)sqrt (SQR (hmax) + SQR (hmax));
}
dh += width; }
dv += width;
gr += width;
} }
} }
@ -912,7 +909,7 @@ static void
find_max_gradient (GPixelRgn *src_rgn, find_max_gradient (GPixelRgn *src_rgn,
GPixelRgn *dest_rgn) GPixelRgn *dest_rgn)
{ {
guchar *s, *d; guchar *s, *d, *s_iter, *s_end;
gpointer pr; gpointer pr;
gint i, j; gint i, j;
gint b; gint b;
@ -931,14 +928,25 @@ find_max_gradient (GPixelRgn *src_rgn,
for (j = 0; j < src_rgn->w; j++) for (j = 0; j < src_rgn->w; j++)
{ {
max = 0; max = 0;
#ifndef SLOW_CODE
#define ABSVAL(x) ((x) >= 0 ? (x) : -(x))
for(s_iter = s, s_end = s + src_rgn->bpp;
s_iter < s_end; s_iter++) {
val = *s;
if(ABSVAL(val) > ABSVAL(max))
max = val;
}
*d++ = max;
#else
for (b = 0; b < src_rgn->bpp; b++) for (b = 0; b < src_rgn->bpp; b++)
{ {
val = (gint) s[b] - 128; val = (gint) s[b] - 128;
if (abs (val) > abs (max)) if (abs (val) > abs (max))
max = val; max = val;
} }
*d++ = (max + 128); *d++ = (max + 128);
#endif
s += src_rgn->bpp; s += src_rgn->bpp;
} }
@ -993,7 +1001,12 @@ gaussian_deriv (GPixelRgn *src_rgn,
src = data; src = data;
dest = data + length; dest = data + length;
#ifdef UNOPTIMIZED_CODE
length = 3; /* static for speed */ length = 3; /* static for speed */
#else
/* badhack :) */
# define length 3
#endif
/* initialize */ /* initialize */
curve = curve_array + length; curve = curve_array + length;
@ -1188,6 +1201,10 @@ gaussian_deriv (GPixelRgn *src_rgn,
free (buf); free (buf);
free (data); free (data);
#ifndef UNOPTIMIZED_CODE
/* end bad hack */
#undef length
#endif
} }
/* /*
@ -2105,8 +2122,8 @@ fill_poly_color (Polygon *poly,
gint min_x, min_y; gint min_x, min_y;
gint max_x, max_y; gint max_x, max_y;
gint size_x, size_y; gint size_x, size_y;
gint * max_scanlines; gint * max_scanlines, *max_scanlines_iter;
gint * min_scanlines; gint * min_scanlines, *min_scanlines_iter;
gint * vals; gint * vals;
gint val; gint val;
gint pixel; gint pixel;
@ -2118,6 +2135,8 @@ fill_poly_color (Polygon *poly,
gint supersample; gint supersample;
gint supersample2; gint supersample2;
gint x1, y1, x2, y2; gint x1, y1, x2, y2;
Vertex *pts_tmp;
const int poly_npts = poly->npts;
/* Determine antialiasing */ /* Determine antialiasing */
if (mvals.antialiasing) if (mvals.antialiasing)
@ -2132,15 +2151,29 @@ fill_poly_color (Polygon *poly,
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2); gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
bytes = drawable->bpp; bytes = drawable->bpp;
for (i = 0; i < poly->npts; i++)
{
xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x);
ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y);
xe = (gint) poly->pts[i].x;
ye = (gint) poly->pts[i].y;
calc_spec_vec (vecs+i, xs, ys, xe, ye); /* begin loop */
} if(poly_npts) {
pts_tmp = poly->pts;
xs = (gint) pts_tmp[poly_npts-1].x;
ys = (gint) pts_tmp[poly_npts-1].y;
xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
calc_spec_vec (vecs, xs, ys, xe, ye);
for (i = 1; i < poly_npts; i++)
{
xs = (gint) (pts_tmp->x);
ys = (gint) (pts_tmp->y);
pts_tmp++;
xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
calc_spec_vec (vecs+i, xs, ys, xe, ye);
}
}
/* end loop */
polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y); polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y);
min_x = (gint) dmin_x; min_x = (gint) dmin_x;
@ -2151,43 +2184,62 @@ fill_poly_color (Polygon *poly,
size_y = (max_y - min_y) * supersample; size_y = (max_y - min_y) * supersample;
size_x = (max_x - min_x) * supersample; size_x = (max_x - min_x) * supersample;
min_scanlines = (gint *) malloc (sizeof (gint) * size_y); min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
max_scanlines = (gint *) malloc (sizeof (gint) * size_y); max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++)
{ {
min_scanlines[i] = max_x * supersample; min_scanlines[i] = max_x * supersample;
max_scanlines[i] = min_x * supersample; max_scanlines[i] = min_x * supersample;
} }
for (i = 0; i < poly->npts; i++) /* begin loop */
{ if(poly_npts) {
xs = (gint) ((i) ? poly->pts[i-1].x : poly->pts[poly->npts-1].x); pts_tmp = poly->pts;
ys = (gint) ((i) ? poly->pts[i-1].y : poly->pts[poly->npts-1].y); xs = (gint) pts_tmp[poly_npts-1].x;
xe = (gint) poly->pts[i].x; ys = (gint) pts_tmp[poly_npts-1].y;
ye = (gint) poly->pts[i].y; xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
xs *= supersample; xs *= supersample;
ys *= supersample; ys *= supersample;
xe *= supersample; xe *= supersample;
ye *= supersample; ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample, convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines); min_scanlines, max_scanlines);
}
for (i = 1; i < poly_npts; i++)
{
xs = (gint) pts_tmp->x;
ys = (gint) pts_tmp->y;
pts_tmp++;
xe = (gint) pts_tmp->x;
ye = (gint) pts_tmp->y;
xs *= supersample;
ys *= supersample;
xe *= supersample;
ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines);
}
}
/* end loop */
gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0, gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0,
drawable->width, drawable->height, drawable->width, drawable->height,
TRUE, TRUE); TRUE, TRUE);
vals = (gint *) malloc (sizeof (gint) * size_x); vals = (gint *) malloc (sizeof (gint) * size_x);
for (i = 0; i < size_y; i++) for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++)
{ {
if (! (i % supersample)) if (! (i % supersample))
memset (vals, 0, sizeof (gint) * size_x); memset (vals, 0, sizeof (gint) * size_x);
yy = (gdouble) i / (gdouble) supersample + min_y; yy = (gdouble) i / (gdouble) supersample + min_y;
for (j = min_scanlines[i]; j < max_scanlines[i]; j++) for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++)
{ {
x = j - min_x * supersample; x = j - min_x * supersample;
vals[x] += 255; vals[x] += 255;
@ -2212,15 +2264,13 @@ fill_poly_color (Polygon *poly,
if (val > 0) if (val > 0)
{ {
xx = (gdouble) j / (gdouble) supersample + min_x; xx = (gdouble) j / (gdouble) supersample + min_x;
contrib = calc_spec_contrib (vecs, poly->npts, xx, yy); contrib = calc_spec_contrib (vecs, poly_npts, xx, yy);
for (b = 0; b < bytes; b++) for (b = 0; b < bytes; b++)
{ {
if (contrib < 0.0) pixel = col[b] + (gint) (((contrib < 0.0)?(col[b] - back[b]):(fore[b] - col[b])) * contrib);
pixel = col[b] + (gint) ((col[b] - back[b]) * contrib);
else
pixel = col[b] + (gint) ((fore[b] - col[b]) * contrib);
buf[b] = ((pixel * val) + (back[b] * (255 - val))) / 255; buf[b] = ((pixel * val) + (back[b] * (255 - val))) / 255;
} }