590
new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
592
for (b = 0; b < alpha; b++)
593
dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
595
dest[alpha] = (affect[alpha] && new_alpha > 127) ?
596
OPAQUE_OPACITY : src1[alpha];
609
new_alpha = INT_MULT(src2[alpha], opacity, tmp);
611
for (b = 0; b < alpha; b++)
612
dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
614
dest[alpha] = (affect[alpha] && new_alpha > 127) ?
615
OPAQUE_OPACITY : src1[alpha];
563
const gint alpha = 1;
569
const guchar *m = mask;
573
guchar new_alpha = INT_MULT3(src2[alpha], *m, opacity, tmp);
575
for (b = 0; b < alpha; b++)
576
dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
578
dest[alpha] = (affect[alpha] && new_alpha > 127) ?
579
OPAQUE_OPACITY : src1[alpha];
592
guchar new_alpha = INT_MULT(src2[alpha], opacity, tmp);
594
for (b = 0; b < alpha; b++)
595
dest[b] = (affect[b] && new_alpha > 127) ? src2[b] : src1[b];
597
dest[alpha] = (affect[alpha] && new_alpha > 127) ?
598
OPAQUE_OPACITY : src1[alpha];
609
combine_inten_a_and_indexed_pixels (const guchar *src1,
618
const gint src2_bytes = 1;
624
const guchar *m = mask;
628
gint index = src2[0] * 3;
629
guchar new_alpha = INT_MULT3(255, *m, opacity, tmp);
631
for (b = 0; b < bytes-1; b++)
632
dest[b] = (new_alpha > 127) ? cmap[index + b] : src1[b];
634
dest[b] = (new_alpha > 127) ? OPAQUE_OPACITY : src1[b];
635
/* alpha channel is opaque */
648
gint index = src2[0] * 3;
649
guchar new_alpha = INT_MULT(255, opacity, tmp);
651
for (b = 0; b < bytes-1; b++)
652
dest[b] = (new_alpha > 127) ? cmap[index + b] : src1[b];
654
dest[b] = (new_alpha > 127) ? OPAQUE_OPACITY : src1[b];
655
/* alpha channel is opaque */
2833
/* non-interpolating scale_region. [adam]
2836
scale_region_no_resample (PixelRegion *srcPR,
2837
PixelRegion *destPR)
2839
gint *x_src_offsets;
2840
gint *y_src_offsets;
2843
gint width, height, orig_width, orig_height;
2849
orig_width = srcPR->w;
2850
orig_height = srcPR->h;
2855
bytes = srcPR->bytes;
2857
/* the data pointers... */
2858
x_src_offsets = g_new (gint, width * bytes);
2859
y_src_offsets = g_new (gint, height);
2860
src = g_new (guchar, orig_width * bytes);
2861
dest = g_new (guchar, width * bytes);
2863
/* pre-calc the scale tables */
2864
for (b = 0; b < bytes; b++)
2865
for (x = 0; x < width; x++)
2866
x_src_offsets [b + x * bytes] =
2867
b + bytes * ((x * orig_width + orig_width / 2) / width);
2869
for (y = 0; y < height; y++)
2870
y_src_offsets [y] = (y * orig_height + orig_height / 2) / height;
2872
/* do the scaling */
2873
row_bytes = width * bytes;
2875
for (y = 0; y < height; y++)
2877
/* if the source of this line was the same as the source
2878
* of the last line, there's no point in re-rescaling.
2880
if (y_src_offsets[y] != last_src_y)
2882
pixel_region_get_row (srcPR, 0, y_src_offsets[y], orig_width, src, 1);
2883
for (x = 0; x < row_bytes ; x++)
2885
dest[x] = src[x_src_offsets[x]];
2887
last_src_y = y_src_offsets[y];
2890
pixel_region_set_row (destPR, 0, y, width, dest);
2893
g_free (x_src_offsets);
2894
g_free (y_src_offsets);
2901
get_premultiplied_double_row (PixelRegion *srcPR,
2910
gint bytes = srcPR->bytes;
2912
pixel_region_get_row (srcPR, x, y, w, tmp_src, n);
2914
if (pixel_region_has_alpha (srcPR))
2916
/* premultiply the alpha into the double array */
2917
gdouble *irow = row;
2918
gint alpha = bytes - 1;
2921
for (x = 0; x < w; x++)
2923
mod_alpha = tmp_src[alpha] / 255.0;
2924
for (b = 0; b < alpha; b++)
2925
irow[b] = mod_alpha * tmp_src[b];
2926
irow[b] = tmp_src[alpha];
2933
for (x = 0; x < w * bytes; x++)
2934
row[x] = tmp_src[x];
2937
/* set the off edge pixels to their nearest neighbor */
2938
for (b = 0; b < 2 * bytes; b++)
2939
row[b - 2 * bytes] = row[b % bytes];
2940
for (b = 0; b < bytes * 2; b++)
2941
row[b + w * bytes] = row[(w - 1) * bytes + b % bytes];
2946
expand_line (gdouble *dest,
2951
GimpInterpolationType interp)
2959
ratio = old_width / (gdouble) width;
2961
/* we can overflow src's boundaries, so we expect our caller to have
2962
allocated extra space for us to do so safely (see scale_region ()) */
2964
/* this could be optimized much more by precalculating the coefficients for
2968
case GIMP_INTERPOLATION_CUBIC:
2969
for (x = 0; x < width; x++)
2971
src_col = ((int) (x * ratio + 2.0 - 0.5)) - 2;
2972
/* +2, -2 is there because (int) rounds towards 0 and we need
2974
frac = (x * ratio - 0.5) - src_col;
2975
s = &src[src_col * bytes];
2976
for (b = 0; b < bytes; b++)
2977
dest[b] = cubic (frac, s[b - bytes], s[b], s[b + bytes],
2984
case GIMP_INTERPOLATION_LINEAR:
2985
for (x = 0; x < width; x++)
2987
src_col = ((int) (x * ratio + 2.0 - 0.5)) - 2;
2988
/* +2, -2 is there because (int) rounds towards 0 and we need
2990
frac = (x * ratio - 0.5) - src_col;
2991
s = &src[src_col * bytes];
2992
for (b = 0; b < bytes; b++)
2993
dest[b] = ((s[b + bytes] - s[b]) * frac + s[b]);
2998
case GIMP_INTERPOLATION_NONE:
2999
g_assert_not_reached ();
3006
shrink_line (gdouble *dest,
3011
GimpInterpolationType interp)
3019
const gdouble avg_ratio = (gdouble) width / old_width;
3020
const gdouble inv_width = 1.0 / width;
3021
gint slicepos; /* slice position relative to width */
3024
g_printerr ("shrink_line bytes=%d old_width=%d width=%d interp=%d "
3026
bytes, old_width, width, interp, avg_ratio);
3029
g_return_if_fail (bytes <= 4);
3031
/* This algorithm calculates the weighted average of pixel data that
3032
each output pixel must receive, taking into account that it always
3033
scales down, i.e. there's always more than one input pixel per each
3041
/* Initialize accum to the first pixel slice. As there is no partial
3042
pixel at start, that value is 0. The source data is interleaved, so
3043
we maintain BYTES accumulators at the same time to deal with that
3044
many channels simultaneously. */
3045
for (b = 0; b < bytes; b++)
3048
for (x = 0; x < width; x++)
3050
/* Accumulate whole pixels. */
3053
for (b = 0; b < bytes; b++)
3054
accum[b] += *srcp++;
3058
while (slicepos < old_width);
3059
slicepos -= old_width;
3061
if (! (slicepos < width))
3062
g_warning ("Assertion (slicepos < width) failed. Please report.");
3066
/* Simplest case: we have reached a whole pixel boundary. Store
3067
the average value per channel and reset the accumulators for
3070
The main reason to treat this case separately is to avoid an
3071
access to out-of-bounds memory for the first pixel. */
3072
for (b = 0; b < bytes; b++)
3074
*destp++ = accum[b] * avg_ratio;
3080
for (b = 0; b < bytes; b++)
3082
/* We have accumulated a whole pixel per channel where just a
3083
slice of it was needed. Subtract now the previous pixel's
3085
slice = srcp[- bytes + b] * slicepos * inv_width;
3086
*destp++ = (accum[b] - slice) * avg_ratio;
3088
/* That slice is the initial value for the next round. */
3094
/* Sanity check: srcp should point to the next-to-last position, and
3095
slicepos should be zero. */
3096
if (! (srcp - src == old_width * bytes && slicepos == 0))
3097
g_warning ("Assertion (srcp - src == old_width * bytes && slicepos == 0)"
3098
" failed. Please report.");
3101
2828
static inline void
3102
2829
rotate_pointers (guchar **p,
3109
for (i = 0; i < n-1; i++)
2837
for (i = 0; i < n - 1; i++)
3117
get_scaled_row (gdouble **src,
3123
GimpInterpolationType interpolation_type)
3125
/* get the necesary lines from the source image, scale them,
3126
and put them into src[] */
3127
rotate_pointers ((gpointer) src, 4);
3132
get_premultiplied_double_row (srcPR, 0, y, srcPR->w,
3134
if (new_width > srcPR->w)
3135
expand_line(src[3], row, srcPR->bytes,
3136
srcPR->w, new_width, interpolation_type);
3137
else if (srcPR->w > new_width)
3138
shrink_line(src[3], row, srcPR->bytes,
3139
srcPR->w, new_width, interpolation_type);
3140
else /* no scailing needed */
3141
memcpy(src[3], row, sizeof (gdouble) * new_width * srcPR->bytes);
3144
memcpy(src[3], src[2], sizeof (gdouble) * new_width * srcPR->bytes);
3148
scale_region (PixelRegion *srcPR,
3149
PixelRegion *destPR,
3150
GimpInterpolationType interpolation,
3151
GimpProgressFunc progress_callback,
3152
gpointer progress_data)
3157
gdouble *row, *accum;
3160
gint orig_width, orig_height;
3167
if (interpolation == GIMP_INTERPOLATION_NONE)
3169
scale_region_no_resample (srcPR, destPR);
3173
orig_width = srcPR->w;
3174
orig_height = srcPR->h;
3180
g_printerr ("scale_region: (%d x %d) -> (%d x %d)\n",
3181
orig_width, orig_height, width, height);
3184
/* find the ratios of old y to new y */
3185
y_rat = (gdouble) orig_height / (gdouble) height;
3187
bytes = destPR->bytes;
3189
/* the data pointers... */
3190
for (i = 0; i < 4; i++)
3191
src[i] = g_new (gdouble, width * bytes);
3193
dest = g_new (guchar, width * bytes);
3195
src_tmp = g_new (guchar, orig_width * bytes);
3197
/* offset the row pointer by 2*bytes so the range of the array
3198
is [-2*bytes] to [(orig_width + 2)*bytes] */
3199
row = g_new (gdouble, (orig_width + 2 * 2) * bytes);
3202
accum = g_new (gdouble, width * bytes);
3204
/* Scale the selected region */
3206
for (y = 0; y < height; y++)
3208
if (progress_callback && !(y & 0xf))
3209
(* progress_callback) (0, height, y, progress_data);
3211
if (height < orig_height)
3215
const gdouble inv_ratio = 1.0 / y_rat;
3217
if (y == 0) /* load the first row if this is the first time through */
3218
get_scaled_row (&src[0], 0, width, srcPR, row,
3221
new_y = (int) (y * y_rat);
3222
frac = 1.0 - (y * y_rat - new_y);
3223
for (x = 0; x < width * bytes; x++)
3224
accum[x] = src[3][x] * frac;
3226
max = (int) ((y + 1) * y_rat) - new_y - 1;
3228
get_scaled_row (&src[0], ++new_y, width, srcPR, row,
3234
for (x = 0; x < width * bytes; x++)
3235
accum[x] += src[3][x];
3236
get_scaled_row (&src[0], ++new_y, width, srcPR, row,
3241
frac = (y + 1) * y_rat - ((int) ((y + 1) * y_rat));
3242
for (x = 0; x < width * bytes; x++)
3244
accum[x] += frac * src[3][x];
3245
accum[x] *= inv_ratio;
3248
else if (height > orig_height)
3250
new_y = floor (y * y_rat - 0.5);
3252
while (old_y <= new_y)
3254
/* get the necesary lines from the source image, scale them,
3255
and put them into src[] */
3256
get_scaled_row (&src[0], old_y + 2, width, srcPR, row,
3262
switch (interpolation)
3264
case GIMP_INTERPOLATION_CUBIC:
3266
gdouble p0, p1, p2, p3;
3267
gdouble dy = (y * y_rat - 0.5) - new_y;
3269
p0 = cubic (dy, 1, 0, 0, 0);
3270
p1 = cubic (dy, 0, 1, 0, 0);
3271
p2 = cubic (dy, 0, 0, 1, 0);
3272
p3 = cubic (dy, 0, 0, 0, 1);
3273
for (x = 0; x < width * bytes; x++)
3274
accum[x] = (p0 * src[0][x] + p1 * src[1][x] +
3275
p2 * src[2][x] + p3 * src[3][x]);
3280
case GIMP_INTERPOLATION_LINEAR:
3282
gdouble idy = (y * y_rat - 0.5) - new_y;
3283
gdouble dy = 1.0 - idy;
3285
for (x = 0; x < width * bytes; x++)
3286
accum[x] = dy * src[1][x] + idy * src[2][x];
3291
case GIMP_INTERPOLATION_NONE:
3292
g_assert_not_reached ();
3296
else /* height == orig_height */
3298
get_scaled_row (&src[0], y, width, srcPR, row,
3301
memcpy (accum, src[3], sizeof (gdouble) * width * bytes);
3304
if (pixel_region_has_alpha (srcPR))
3306
/* unmultiply the alpha */
3309
gint alpha = bytes - 1;
3313
for (x = 0; x < width; x++)
3315
if (p[alpha] > 0.001)
3317
inv_alpha = 255.0 / p[alpha];
3318
for (b = 0; b < alpha; b++)
3320
result = RINT (inv_alpha * p[b]);
3323
else if (result > 255)
3328
result = RINT (p[alpha]);
3334
else /* alpha <= 0 */
3335
for (b = 0; b <= alpha; b++)
3344
gint w = width * bytes;
3346
for (x = 0; x < w; x++)
3350
else if (accum[x] > 255.0)
3353
dest[x] = RINT (accum[x]);
3356
pixel_region_set_row (destPR, 0, y, width, dest);
3359
/* free up temporary arrays */
3361
for (i = 0; i < 4; i++)
3371
subsample_region (PixelRegion *srcPR,
3372
PixelRegion *destPR,
3379
gint src_row, src_col;
3382
gint orig_width, orig_height;
3383
gdouble x_rat, y_rat;
3384
gdouble x_cum, y_cum;
3385
gdouble x_last, y_last;
3386
gdouble * x_frac, y_frac, tot_frac;
3391
orig_width = srcPR->w / subsample;
3392
orig_height = srcPR->h / subsample;
3397
g_printerr ("subsample_region: (%d x %d) -> (%d x %d)\n",
3398
orig_width, orig_height, width, height);
3401
/* Some calculations... */
3402
bytes = destPR->bytes;
3403
destwidth = destPR->rowstride;
3405
/* the data pointers... */
3406
src = g_new (guchar, orig_width * bytes);
3407
dest = destPR->data;
3409
/* find the ratios of old x to new x and old y to new y */
3410
x_rat = (gdouble) orig_width / (gdouble) width;
3411
y_rat = (gdouble) orig_height / (gdouble) height;
3413
/* allocate an array to help with the calculations */
3414
row = g_new (gdouble, width * bytes);
3415
x_frac = g_new (gdouble, width + orig_width);
3417
/* initialize the pre-calculated pixel fraction array */
3419
x_cum = (gdouble) src_col;
3422
for (i = 0; i < width + orig_width; i++)
3424
if (x_cum + x_rat <= (src_col + 1 + EPSILON))
3427
x_frac[i] = x_cum - x_last;
3432
x_frac[i] = src_col - x_last;
3434
x_last += x_frac[i];
3437
/* clear the "row" array */
3438
memset (row, 0, sizeof (gdouble) * width * bytes);
3442
y_cum = (gdouble) src_row;
3445
pixel_region_get_row (srcPR, 0, src_row * subsample, orig_width * subsample, src, subsample);
3447
/* Scale the selected region */
3448
for (i = 0; i < height; )
3451
x_cum = (gdouble) src_col;
3453
/* determine the fraction of the src pixel we are using for y */
3454
if (y_cum + y_rat <= (src_row + 1 + EPSILON))
3457
y_frac = y_cum - y_last;
3458
advance_dest = TRUE;
3463
y_frac = src_row - y_last;
3464
advance_dest = FALSE;
3477
tot_frac = x_frac[frac++] * y_frac;
3479
for (b = 0; b < bytes; b++)
3480
r[b] += s[b] * tot_frac;
3482
/* increment the destination */
3483
if (x_cum + x_rat <= (src_col + 1 + EPSILON))
3490
/* increment the source */
3500
tot_frac = 1.0 / (x_rat * y_rat);
3502
/* copy "row" to "dest" */
3511
*d++ = (guchar) (*r++ * tot_frac + 0.5);
3516
/* clear the "row" array */
3517
memset (row, 0, sizeof (gdouble) * destwidth);
3522
pixel_region_get_row (srcPR, 0, src_row * subsample, orig_width * subsample, src, subsample);
3525
/* free up temporary arrays */
3533
2845
shapeburst_region (PixelRegion *srcPR,
3746
3067
is [-xradius] to [xradius] */
3747
3068
circ += xradius;
3749
memset (buf[0], 0, src->w);
3750
for (i = 0; i < yradius && i < src->h; i++) /* load top of image */
3751
pixel_region_get_row (src, src->x, src->y + i, src->w, buf[i + 1], 1);
3753
for (x = 0; x < src->w; x++) /* set up max for top of image */
3070
memset (buf[0], 0, region->w);
3072
for (i = 0; i < yradius && i < region->h; i++) /* load top of image */
3073
pixel_region_get_row (region,
3074
region->x, region->y + i, region->w, buf[i + 1], 1);
3076
for (x = 0; x < region->w; x++) /* set up max for top of image */
3755
3078
max[x][0] = 0; /* buf[0][x] is always 0 */
3756
3079
max[x][1] = buf[1][x]; /* MAX (buf[1][x], max[x][0]) always = buf[1][x]*/
3757
3081
for (j = 2; j < yradius + 1; j++)
3758
3082
max[x][j] = MAX(buf[j][x], max[x][j-1]);
3761
for (y = 0; y < src->h; y++)
3085
for (y = 0; y < region->h; y++)
3763
3087
rotate_pointers (buf, yradius + 1);
3764
if (y < src->h - (yradius))
3765
pixel_region_get_row (src, src->x, src->y + y + yradius, src->w,
3089
if (y < region->h - (yradius))
3090
pixel_region_get_row (region,
3091
region->x, region->y + y + yradius, region->w,
3766
3092
buf[yradius], 1);
3768
memset (buf[yradius], 0, src->w);
3769
for (x = 0; x < src->w; x++) /* update max array */
3094
memset (buf[yradius], 0, region->w);
3096
for (x = 0; x < region->w; x++) /* update max array */
3771
3098
for (i = yradius; i > 0; i--)
3773
max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
3099
max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]);
3775
3101
max[x][0] = buf[0][x];
3777
3104
last_max = max[0][circ[-1]];
3778
3105
last_index = 1;
3779
for (x = 0; x < src->w; x++) /* render scan line */
3107
for (x = 0; x < region->w; x++) /* render scan line */
3782
3111
if (last_index >= 0)
3784
3113
if (last_max == 255)
3789
3121
for (i = xradius; i >= 0; i--)
3790
3122
if (last_max < max[x + i][circ[i]])
3792
3124
last_max = max[x + i][circ[i]];
3793
3125
last_index = i;
3795
3128
out[x] = last_max;
3850
3189
if (xradius <= 0 || yradius <= 0)
3853
max = g_new (guchar *, src->w + 2 * xradius);
3192
max = g_new (guchar *, region->w + 2 * xradius);
3855
3193
buf = g_new (guchar *, yradius + 1);
3856
3195
for (i = 0; i < yradius + 1; i++)
3858
buf[i] = g_new (guchar, src->w);
3196
buf[i] = g_new (guchar, region->w);
3861
buffer_size = (src->w + 2 * xradius + 1) * (yradius + 1);
3198
buffer_size = (region->w + 2 * xradius + 1) * (yradius + 1);
3862
3199
buffer = g_new (guchar, buffer_size);
3864
3202
memset(buffer, 255, buffer_size);
3866
3204
memset(buffer, 0, buffer_size);
3868
for (i = 0; i < src->w + 2 * xradius; i++)
3206
for (i = 0; i < region->w + 2 * xradius; i++)
3870
3208
if (i < xradius)
3874
max[i] = &buffer[(yradius + 1) * (src->w + xradius)];
3875
else if (i < src->w + xradius)
3876
max[i] = &buffer[(yradius + 1) * (i - xradius)];
3213
max[i] = &buffer[(yradius + 1) * (region->w + xradius)];
3215
else if (i < region->w + xradius)
3217
max[i] = &buffer[(yradius + 1) * (i - xradius)];
3879
max[i] = &buffer[(yradius + 1) * (src->w + xradius - 1)];
3881
max[i] = &buffer[(yradius + 1) * (src->w + xradius)];
3222
max[i] = &buffer[(yradius + 1) * (region->w + xradius - 1)];
3224
max[i] = &buffer[(yradius + 1) * (region->w + xradius)];
3884
3229
for (j = 0 ; j < xradius + 1; j++)
3887
3232
/* offset the max pointer by xradius so the range of the array
3888
is [-xradius] to [src->w + xradius] */
3233
is [-xradius] to [region->w + xradius] */
3889
3234
max += xradius;
3891
out = g_new (guchar, src->w);
3236
out = g_new (guchar, region->w);
3893
3238
circ = g_new (gint16, 2 * xradius + 1);
3894
compute_border(circ, xradius, yradius);
3239
compute_border (circ, xradius, yradius);
3896
3241
/* offset the circ pointer by xradius so the range of the array
3897
3242
is [-xradius] to [xradius] */
3898
3243
circ += xradius;
3900
for (i = 0; i < yradius && i < src->h; i++) /* load top of image */
3901
pixel_region_get_row (src, src->x, src->y + i, src->w, buf[i + 1], 1);
3245
for (i = 0; i < yradius && i < region->h; i++) /* load top of image */
3246
pixel_region_get_row (region,
3247
region->x, region->y + i, region->w, buf[i + 1], 1);
3903
memcpy (buf[0], buf[1], src->w);
3249
memcpy (buf[0], buf[1], region->w);
3905
memset (buf[0], 0, src->w);
3908
for (x = 0; x < src->w; x++) /* set up max for top of image */
3251
memset (buf[0], 0, region->w);
3254
for (x = 0; x < region->w; x++) /* set up max for top of image */
3910
3256
max[x][0] = buf[0][x];
3911
3257
for (j = 1; j < yradius + 1; j++)
3912
3258
max[x][j] = MIN(buf[j][x], max[x][j-1]);
3915
for (y = 0; y < src->h; y++)
3261
for (y = 0; y < region->h; y++)
3917
3263
rotate_pointers (buf, yradius + 1);
3918
if (y < src->h - yradius)
3919
pixel_region_get_row (src, src->x, src->y + y + yradius, src->w,
3264
if (y < region->h - yradius)
3265
pixel_region_get_row (region,
3266
region->x, region->y + y + yradius, region->w,
3920
3267
buf[yradius], 1);
3921
3268
else if (edge_lock)
3922
memcpy (buf[yradius], buf[yradius - 1], src->w);
3269
memcpy (buf[yradius], buf[yradius - 1], region->w);
3924
memset (buf[yradius], 0, src->w);
3271
memset (buf[yradius], 0, region->w);
3926
for (x = 0 ; x < src->w; x++) /* update max array */
3273
for (x = 0 ; x < region->w; x++) /* update max array */
3928
3275
for (i = yradius; i > 0; i--)
3958
3311
last_index = xradius;
3959
3312
last_max = max[x + xradius][circ[xradius]];
3960
3314
for (i = xradius - 1; i >= -xradius; i--)
3961
3315
if (last_max > max[x + i][circ[i]])
3963
3317
last_max = max[x + i][circ[i]];
3964
3318
last_index = i;
3966
3321
out[x] = last_max;
3969
pixel_region_set_row (src, src->x, src->y + y, src->w, out);
3325
pixel_region_set_row (region, region->x, region->y + y, region->w, out);
3972
3328
/* undo the offsets to the pointers so we can free the malloced memmory */
3973
3329
circ -= xradius;
3974
3330
max -= xradius;
3975
3332
/* free the memmory */
3977
3334
g_free (buffer);
3979
3337
for (i = 0; i < yradius + 1; i++)
3980
3338
g_free (buf[i]);
3344
/* Simple convolution filter to smooth a mask (1bpp). */
3346
smooth_region (PixelRegion *region)
3356
for (i = 0; i < 3; i++)
3357
buf[i] = g_new (guchar, width + 2);
3359
out = g_new (guchar, width);
3361
/* load top of image */
3362
pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1);
3364
buf[0][0] = buf[0][1];
3365
buf[0][width + 1] = buf[0][width];
3367
memcpy (buf[1], buf[0], width + 2);
3369
for (y = 0; y < region->h; y++)
3371
if (y + 1 < region->h)
3373
pixel_region_get_row (region, region->x, region->y + y + 1, width,
3376
buf[2][0] = buf[2][1];
3377
buf[2][width + 1] = buf[2][width];
3381
memcpy (buf[2], buf[1], width + 2);
3384
for (x = 0 ; x < width; x++)
3386
gint value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] +
3387
buf[1][x] + buf[2][x+1] + buf[1][x+2] +
3388
buf[2][x] + buf[1][x+1] + buf[2][x+2]);
3393
pixel_region_set_row (region, region->x, region->y + y, width, out);
3395
rotate_pointers (buf, 3);
3398
for (i = 0; i < 3; i++)
3404
/* Erode (radius 1 pixel) a mask (1bpp). */
3406
erode_region (PixelRegion *region)
3416
for (i = 0; i < 3; i++)
3417
buf[i] = g_new (guchar, width + 2);
3419
out = g_new (guchar, width);
3421
/* load top of image */
3422
pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1);
3424
buf[0][0] = buf[0][1];
3425
buf[0][width + 1] = buf[0][width];
3427
memcpy (buf[1], buf[0], width + 2);
3429
for (y = 0; y < region->h; y++)
3431
if (y + 1 < region->h)
3433
pixel_region_get_row (region, region->x, region->y + y + 1, width,
3436
buf[2][0] = buf[2][1];
3437
buf[2][width + 1] = buf[2][width];
3441
memcpy (buf[2], buf[1], width + 2);
3444
for (x = 0 ; x < width; x++)
3448
if (buf[0][x+1] < min) min = buf[0][x+1];
3449
if (buf[1][x] < min) min = buf[1][x];
3450
if (buf[1][x+1] < min) min = buf[1][x+1];
3451
if (buf[1][x+2] < min) min = buf[1][x+2];
3452
if (buf[2][x+1] < min) min = buf[2][x+1];
3457
pixel_region_set_row (region, region->x, region->y + y, width, out);
3459
rotate_pointers (buf, 3);
3462
for (i = 0; i < 3; i++)
3468
/* Dilate (radius 1 pixel) a mask (1bpp). */
3470
dilate_region (PixelRegion *region)
3480
for (i = 0; i < 3; i++)
3481
buf[i] = g_new (guchar, width + 2);
3483
out = g_new (guchar, width);
3485
/* load top of image */
3486
pixel_region_get_row (region, region->x, region->y, width, buf[0] + 1, 1);
3488
buf[0][0] = buf[0][1];
3489
buf[0][width + 1] = buf[0][width];
3491
memcpy (buf[1], buf[0], width + 2);
3493
for (y = 0; y < region->h; y++)
3495
if (y + 1 < region->h)
3497
pixel_region_get_row (region, region->x, region->y + y + 1, width,
3500
buf[2][0] = buf[2][1];
3501
buf[2][width + 1] = buf[2][width];
3505
memcpy (buf[2], buf[1], width + 2);
3508
for (x = 0 ; x < width; x++)
3512
if (buf[0][x+1] > max) max = buf[0][x+1];
3513
if (buf[1][x] > max) max = buf[1][x];
3514
if (buf[1][x+1] > max) max = buf[1][x+1];
3515
if (buf[1][x+2] > max) max = buf[1][x+2];
3516
if (buf[2][x+1] > max) max = buf[2][x+1];
3521
pixel_region_set_row (region, region->x, region->y + y, width, out);
3523
rotate_pointers (buf, 3);
3526
for (i = 0; i < 3; i++)
3532
/* Computes whether pixels in `buf[1]', if they are selected, have neighbouring
3533
pixels that are unselected. Put result in `transition'. */
3986
compute_transition (guchar *transition,
3535
compute_transition (guchar *transition,
3990
3540
register gint32 x = 0;
3992
3542
if (width == 1)
3994
if (buf[1][x] > 127 && (buf[0][x] < 128 || buf[2][x] < 128))
3995
transition[x] = 255;
3544
if (buf[1][0] > 127 && (buf[0][0] < 128 || buf[2][0] < 128))
3545
transition[0] = 255;
4000
if (buf[1][x] > 127)
3551
if (buf[1][0] > 127 && edge_lock)
4002
if ( buf[0][x] < 128 || buf[0][x + 1] < 128 ||
4003
buf[1][x + 1] < 128 ||
4004
buf[2][x] < 128 || buf[2][x + 1] < 128 )
4005
transition[x] = 255;
3553
/* The pixel to the left (outside of the canvas) is considered selected,
3554
so we check if there are any unselected pixels in neighbouring pixels
3556
if (buf[0][x] < 128 || buf[0][x + 1] < 128 ||
3557
buf[1][x + 1] < 128 ||
3558
buf[2][x] < 128 || buf[2][x + 1] < 128 )
3560
transition[x] = 255;
3567
else if (buf[1][0] > 127 && !edge_lock)
3569
/* We must not care about neighbouring pixels on the image canvas since
3570
there always are unselected pixels to the left (which is outside of
3571
the image canvas). */
3572
transition[x] = 255;
4011
3579
for (x = 1; x < width - 1; x++)
4013
3581
if (buf[1][x] >= 128)
4015
3583
if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 ||
4016
buf[1][x - 1] < 128 || buf[1][x + 1] < 128 ||
3584
buf[1][x - 1] < 128 || buf[1][x + 1] < 128 ||
4017
3585
buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128)
4018
3586
transition[x] = 255;
4020
3588
transition[x] = 0;
4025
if (buf[1][x] >= 128)
3596
if (buf[1][width - 1] >= 128 && edge_lock)
3598
/* The pixel to the right (outside of the canvas) is considered selected,
3599
so we check if there are any unselected pixels in neighbouring pixels
4027
3601
if ( buf[0][x - 1] < 128 || buf[0][x] < 128 ||
4028
3602
buf[1][x - 1] < 128 ||
4029
3603
buf[2][x - 1] < 128 || buf[2][x] < 128)
4030
transition[x] = 255;
3605
transition[width - 1] = 255;
3609
transition[width - 1] = 0;
3612
else if (buf[1][width - 1] >= 128 && !edge_lock)
3614
/* We must not care about neighbouring pixels on the image canvas since
3615
there always are unselected pixels to the right (which is outside of
3616
the image canvas). */
3617
transition[width - 1] = 255;
3621
transition[width - 1] = 0;
4039
3626
border_region (PixelRegion *src,
4040
3627
gint16 xradius,
4044
3633
This function has no bugs, but if you imagine some you can
4045
3634
blame them on jaycox@gimp.org
4047
3637
register gint32 i, j, x, y;
3639
/* A cache used in the algorithm as it works its way down. `buf[1]' is the
3640
current row. Thus, at algorithm initialization, `buf[0]' represents the
3641
row 'above' the first row of the region. */
4048
3642
guchar *buf[3];
3644
/* The resulting selection is calculated row by row, and this buffer holds the
3645
output for each individual row, on each iteration. */
3648
/* Keeps track of transitional pixels (pixels that are selected and have
3649
unselected neighbouring pixels). */
3650
guchar **transition;
3652
/* TODO: Figure out role clearly in algorithm. */
3655
/* TODO: Figure out role clearly in algorithm. */
4051
3656
guchar **density;
4052
guchar **transition;
4053
3658
guchar last_max;
4054
3659
gint16 last_index;
4078
3685
transition = g_new (guchar, src->w);
4080
pixel_region_get_row (src, src->x, src->y + 0, src->w, source[0], 1);
4081
memcpy (source[1], source[0], src->w);
3687
/* With `edge_lock', initialize row above image as selected, otherwise,
3688
initialize as unselected. */
3689
memset (source[0], edge_lock ? 255 : 0, src->w);
3691
pixel_region_get_row (src, src->x, src->y + 0, src->w, source[1], 1);
4082
3693
if (src->h > 1)
4083
3694
pixel_region_get_row (src, src->x, src->y + 1, src->w, source[2], 1);
4085
3696
memcpy (source[2], source[1], src->w);
4087
compute_transition (transition, source, src->w);
3698
compute_transition (transition, source, src->w, edge_lock);
4088
3699
pixel_region_set_row (src, src->x, src->y , src->w, transition);
4090
3701
for (y = 1; y < src->h; y++)
4092
3703
rotate_pointers (source, 3);
4093
3705
if (y + 1 < src->h)
4094
pixel_region_get_row (src, src->x, src->y + y + 1, src->w,
3707
pixel_region_get_row (src, src->x, src->y + y + 1, src->w,
4097
memcpy(source[2], source[1], src->w);
4098
compute_transition (transition, source, src->w);
3712
/* Depending on `edge_lock', set the row below the image as either
3713
selected or non-selected. */
3714
memset(source[2], edge_lock ? 255 : 0, src->w);
3717
compute_transition (transition, source, src->w, edge_lock);
4099
3718
pixel_region_set_row (src, src->x, src->y + y, src->w, transition);
4102
3721
for (i = 0; i < 3; i++)
4103
3722
g_free (source[i]);
4104
3724
g_free (transition);
3726
/* Finnished handling the radius = 1 special case, return here. */
4108
3730
max = g_new (gint16, src->w + 2 * xradius);
4109
3732
for (i = 0; i < (src->w + 2 * xradius); i++)
4110
3733
max[i] = yradius + 2;
4111
3735
max += xradius;
4113
3737
for (i = 0; i < 3; i++)
4114
3738
buf[i] = g_new (guchar, src->w);
4116
3740
transition = g_new (guchar *, yradius + 1);
4117
3742
for (i = 0; i < yradius + 1; i++)
4119
3744
transition[i] = g_new (guchar, src->w + 2 * xradius);
4120
3745
memset(transition[i], 0, src->w + 2 * xradius);
4121
3746
transition[i] += xradius;
4123
3749
out = g_new (guchar, src->w);
4124
3751
density = g_new (guchar *, 2 * xradius + 1);
4125
3752
density += xradius;
4127
for (x = 0; x < (xradius + 1); x++) /* allocate density[][] */
3754
/* allocate density[][] */
3755
for (x = 0; x < (xradius + 1); x++)
4129
3757
density[ x] = g_new (guchar, 2 * yradius + 1);
4130
3758
density[ x] += yradius;
4131
3759
density[-x] = density[x];
4133
for (x = 0; x < (xradius + 1); x++) /* compute density[][] */
3762
/* compute density[][] */
3763
for (x = 0; x < (xradius + 1); x++)
4135
3765
register gdouble tmpx, tmpy, dist;
4150
3780
tmpy = y + 0.5;
4153
3784
dist = ((tmpy * tmpy) / (yradius * yradius) +
4154
3785
(tmpx * tmpx) / (xradius * xradius));
4155
3787
if (dist < 1.0)
4156
a = 255 * (1.0 - sqrt (dist));
3790
a = 255 * (1.0 - sqrt (dist));
4159
3799
density[ x][ y] = a;
4160
3800
density[ x][-y] = a;
4161
3801
density[-x][ y] = a;
4162
3802
density[-x][-y] = a;
4165
pixel_region_get_row (src, src->x, src->y + 0, src->w, buf[0], 1);
4166
memcpy (buf[1], buf[0], src->w);
3806
/* Since the algorithm considerers `buf[0]' to be 'over' the row currently
3807
calculated, we must start with `buf[0]' as non-selected if there is no
3808
`edge_lock. If there is an 'edge_lock', initialize the first row to
3809
'selected'. Refer to bug #350009. */
3810
memset (buf[0], edge_lock ? 255 : 0, src->w);
3811
pixel_region_get_row (src, src->x, src->y + 0, src->w, buf[1], 1);
4167
3813
if (src->h > 1)
4168
3814
pixel_region_get_row (src, src->x, src->y + 1, src->w, buf[2], 1);
4170
3816
memcpy (buf[2], buf[1], src->w);
4171
compute_transition (transition[1], buf, src->w);
4173
for (y = 1; y < yradius && y + 1 < src->h; y++) /* set up top of image */
3818
compute_transition (transition[1], buf, src->w, edge_lock);
3820
/* set up top of image */
3821
for (y = 1; y < yradius && y + 1 < src->h; y++)
4175
3823
rotate_pointers (buf, 3);
4176
3824
pixel_region_get_row (src, src->x, src->y + y + 1, src->w, buf[2], 1);
4177
compute_transition (transition[y + 1], buf, src->w);
3825
compute_transition (transition[y + 1], buf, src->w, edge_lock);
4179
for (x = 0; x < src->w; x++) /* set up max[] for top of image */
3828
/* set up max[] for top of image */
3829
for (x = 0; x < src->w; x++)
4181
3831
max[x] = -(yradius + 7);
4182
3833
for (j = 1; j < yradius + 1; j++)
4183
3834
if (transition[j][x])