1
/* GIMP - The GNU Image Manipulation Program
2
* Copyright (C) 1995-2003 Spencer Kimball, Peter Mattis, and others
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
#include <glib-object.h>
25
#include "libgimpbase/gimpbase.h"
26
#include "libgimpmath/gimpmath.h"
28
#include "core-types.h"
30
#include "base/pixel-region.h"
31
#include "base/pixel-surround.h"
32
#include "base/tile-manager.h"
33
#include "base/tile.h"
35
#include "paint-funcs/scale-funcs.h"
37
#include "gimp-transform-region.h"
38
#include "gimpchannel.h"
39
#include "gimpcontext.h"
40
#include "gimpimage.h"
41
#include "gimppickable.h"
42
#include "gimpprogress.h"
45
/* forward function prototypes */
47
static void gimp_transform_region_nearest (TileManager *orig_tiles,
59
const guchar *bg_color,
60
GimpProgress *progress);
61
static void gimp_transform_region_linear (TileManager *orig_tiles,
75
const guchar *bg_color,
76
GimpProgress *progress);
77
static void gimp_transform_region_cubic (TileManager *orig_tiles,
91
const guchar *bg_color,
92
GimpProgress *progress);
93
static void gimp_transform_region_lanczos (TileManager *orig_tiles,
103
const GimpMatrix3 *m,
105
gboolean supersample,
106
gint recursion_level,
107
const guchar *bg_color,
108
GimpProgress *progress);
110
static inline void untransform_coords (const GimpMatrix3 *m,
116
static inline void normalize_coords (const gint coords,
123
static inline gboolean supersample_dtest (gdouble u0,
132
static void sample_adapt (TileManager *tm,
145
const guchar *bg_color,
149
static void sample_linear (PixelSurround *surround,
155
static void sample_cubic (PixelSurround *surround,
161
static void sample_lanczos (PixelSurround *surround,
162
const gfloat *lanczos,
170
/* public functions */
173
gimp_transform_region (GimpPickable *pickable,
174
GimpContext *context,
175
TileManager *orig_tiles,
181
const GimpMatrix3 *matrix,
182
GimpInterpolationType interpolation_type,
183
gboolean supersample,
184
gint recursion_level,
185
GimpProgress *progress)
187
GimpImageType pickable_type;
189
gint u1, v1, u2, v2; /* source bounding box */
191
guchar bg_color[MAX_CHANNELS];
193
g_return_if_fail (GIMP_IS_PICKABLE (pickable));
195
tile_manager_get_offsets (orig_tiles, &u1, &v1);
197
u2 = u1 + tile_manager_width (orig_tiles);
198
v2 = v1 + tile_manager_height (orig_tiles);
201
gimp_matrix3_invert (&m);
205
/* turn interpolation off for simple transformations (e.g. rot90) */
206
if (gimp_matrix3_is_simple (matrix))
207
interpolation_type = GIMP_INTERPOLATION_NONE;
209
pickable_type = gimp_pickable_get_image_type (pickable);
211
/* Get the background color */
212
gimp_image_get_background (gimp_pickable_get_image (pickable), context,
213
pickable_type, bg_color);
215
switch (GIMP_IMAGE_TYPE_BASE_TYPE (pickable_type))
218
bg_color[ALPHA_PIX] = TRANSPARENT_OPACITY;
223
bg_color[ALPHA_G_PIX] = TRANSPARENT_OPACITY;
228
bg_color[ALPHA_I_PIX] = TRANSPARENT_OPACITY;
230
/* If the image is indexed color, ignore interpolation value */
231
interpolation_type = GIMP_INTERPOLATION_NONE;
235
g_assert_not_reached ();
239
/* "Outside" a channel is transparency, not the bg color */
240
if (GIMP_IS_CHANNEL (pickable))
241
bg_color[0] = TRANSPARENT_OPACITY;
243
/* setting alpha = 0 will cause the channel's value to be treated
244
* as alpha and the color channel loops never to be entered
246
if (tile_manager_bpp (orig_tiles) == 1)
249
switch (interpolation_type)
251
case GIMP_INTERPOLATION_NONE:
252
gimp_transform_region_nearest (orig_tiles, destPR,
253
dest_x1, dest_y1, dest_x2, dest_y2,
255
&m, alpha, bg_color, progress);
258
case GIMP_INTERPOLATION_LINEAR:
259
gimp_transform_region_linear (orig_tiles, destPR,
260
dest_x1, dest_y1, dest_x2, dest_y2,
262
&m, alpha, supersample, recursion_level,
266
case GIMP_INTERPOLATION_CUBIC:
267
gimp_transform_region_cubic (orig_tiles, destPR,
268
dest_x1, dest_y1, dest_x2, dest_y2,
270
&m, alpha, supersample, recursion_level,
274
case GIMP_INTERPOLATION_LANCZOS:
275
gimp_transform_region_lanczos (orig_tiles, destPR,
276
dest_x1, dest_y1, dest_x2, dest_y2,
278
&m, alpha, supersample, recursion_level,
285
gimp_transform_region_nearest (TileManager *orig_tiles,
295
const GimpMatrix3 *m,
297
const guchar *bg_color,
298
GimpProgress *progress)
300
gdouble uinc, vinc, winc; /* increments in source coordinates */
306
uinc = m->coeff[0][0];
307
vinc = m->coeff[1][0];
308
winc = m->coeff[2][0];
310
total = destPR->w * destPR->h;
312
for (pr = pixel_regions_register (1, destPR), pixels = 0, n = 0;
314
pr = pixel_regions_process (pr), n++)
316
guchar *dest = destPR->data;
319
for (y = destPR->y; y < destPR->y + destPR->h; y++)
321
gint x = dest_x1 + destPR->x;
322
gint width = destPR->w;
324
gdouble tu, tv, tw; /* undivided source coordinates and divisor */
326
/* set up inverse transform steps */
327
tu = uinc * x + m->coeff[0][1] * (dest_y1 + y) + m->coeff[0][2];
328
tv = vinc * x + m->coeff[1][1] * (dest_y1 + y) + m->coeff[1][2];
329
tw = winc * x + m->coeff[2][1] * (dest_y1 + y) + m->coeff[2][2];
333
gdouble u, v; /* source coordinates */
336
/* normalize homogeneous coords */
337
normalize_coords (1, &tu, &tv, &tw, &u, &v);
342
/* Set the destination pixels */
343
if (iu >= u1 && iu < u2 &&
346
read_pixel_data_1 (orig_tiles, iu - u1, iv - v1, d);
350
else /* not in source range */
354
for (b = 0; b < destPR->bytes; b++)
363
dest += destPR->rowstride;
368
pixels += destPR->w * destPR->h;
371
gimp_progress_set_value (progress,
372
(gdouble) pixels / (gdouble) total);
378
gimp_transform_region_linear (TileManager *orig_tiles,
388
const GimpMatrix3 *m,
390
gboolean supersample,
391
gint recursion_level,
392
const guchar *bg_color,
393
GimpProgress *progress)
395
PixelSurround *surround;
396
gdouble uinc, vinc, winc; /* increments in source coordinates */
402
surround = pixel_surround_new (orig_tiles, 2, 2, bg_color);
404
uinc = m->coeff[0][0];
405
vinc = m->coeff[1][0];
406
winc = m->coeff[2][0];
408
total = destPR->w * destPR->h;
410
for (pr = pixel_regions_register (1, destPR), pixels = 0, n = 0;
412
pr = pixel_regions_process (pr), n++)
414
guchar *dest = destPR->data;
417
for (y = destPR->y; y < destPR->y + destPR->h; y++)
420
gint width = destPR->w;
421
gdouble tu[5], tv[5]; /* undivided source coordinates */
422
gdouble tw[5]; /* divisor */
424
/* set up inverse transform steps */
425
untransform_coords (m, dest_x1 + destPR->x, dest_y1 + y, tu, tv, tw);
429
gdouble u[5], v[5]; /* source coordinates */
432
/* normalize homogeneous coords */
433
normalize_coords (5, tu, tv, tw, u, v);
435
/* Set the destination pixels */
437
supersample_dtest (u[1], v[1], u[2], v[2],
438
u[3], v[3], u[4], v[4]))
440
sample_adapt (orig_tiles,
441
u[0] - u1, v[0] - v1,
442
u[1] - u1, v[1] - v1,
443
u[2] - u1, v[2] - v1,
444
u[3] - u1, v[3] - v1,
445
u[4] - u1, v[4] - v1,
447
d, bg_color, destPR->bytes, alpha);
451
sample_linear (surround, u[0] - u1, v[0] - v1,
452
d, destPR->bytes, alpha);
457
for (i = 0; i < 5; i++)
465
dest += destPR->rowstride;
470
pixels += destPR->w * destPR->h;
473
gimp_progress_set_value (progress,
474
(gdouble) pixels / (gdouble) total);
478
pixel_surround_destroy (surround);
482
gimp_transform_region_cubic (TileManager *orig_tiles,
492
const GimpMatrix3 *m,
494
gboolean supersample,
495
gint recursion_level,
496
const guchar *bg_color,
497
GimpProgress *progress)
499
PixelSurround *surround;
500
gdouble uinc, vinc, winc; /* increments in source coordinates */
506
surround = pixel_surround_new (orig_tiles, 4, 4, bg_color);
508
uinc = m->coeff[0][0];
509
vinc = m->coeff[1][0];
510
winc = m->coeff[2][0];
512
total = destPR->w * destPR->h;
514
for (pr = pixel_regions_register (1, destPR), pixels = 0, n = 0;
516
pr = pixel_regions_process (pr), n++)
518
guchar *dest = destPR->data;
521
for (y = destPR->y; y < destPR->y + destPR->h; y++)
524
gint width = destPR->w;
525
gdouble tu[5], tv[5]; /* undivided source coordinates */
526
gdouble tw[5]; /* divisor */
528
/* set up inverse transform steps */
529
untransform_coords (m, dest_x1 + destPR->x, dest_y1 + y, tu, tv, tw);
533
gdouble u[5], v[5]; /* source coordinates */
536
/* normalize homogeneous coords */
537
normalize_coords (5, tu, tv, tw, u, v);
540
supersample_dtest (u[1], v[1], u[2], v[2],
541
u[3], v[3], u[4], v[4]))
543
sample_adapt (orig_tiles,
544
u[0] - u1, v[0] - v1,
545
u[1] - u1, v[1] - v1,
546
u[2] - u1, v[2] - v1,
547
u[3] - u1, v[3] - v1,
548
u[4] - u1, v[4] - v1,
550
d, bg_color, destPR->bytes, alpha);
554
sample_cubic (surround, u[0] - u1, v[0] - v1,
555
d, destPR->bytes, alpha);
560
for (i = 0; i < 5; i++)
568
dest += destPR->rowstride;
573
pixels += destPR->w * destPR->h;
576
gimp_progress_set_value (progress,
577
(gdouble) pixels / (gdouble) total);
581
pixel_surround_destroy (surround);
585
gimp_transform_region_lanczos (TileManager *orig_tiles,
595
const GimpMatrix3 *m,
597
gboolean supersample,
598
gint recursion_level,
599
const guchar *bg_color,
600
GimpProgress *progress)
602
PixelSurround *surround;
603
gfloat *lanczos; /* Lanczos lookup table */
604
gdouble uinc, vinc, winc; /* increments in source coordinates */
610
surround = pixel_surround_new (orig_tiles,
611
LANCZOS_WIDTH2, LANCZOS_WIDTH2, bg_color);
613
/* allocate and fill lanczos lookup table */
614
lanczos = create_lanczos_lookup ();
616
uinc = m->coeff[0][0];
617
vinc = m->coeff[1][0];
618
winc = m->coeff[2][0];
620
total = destPR->w * destPR->h;
622
for (pr = pixel_regions_register (1, destPR), pixels = 0, n = 0;
624
pr = pixel_regions_process (pr), n++)
626
guchar *dest = destPR->data;
629
for (y = destPR->y; y < destPR->y + destPR->h; y++)
632
gint width = destPR->w;
633
gdouble tu[5], tv[5]; /* undivided source coordinates */
634
gdouble tw[5]; /* divisor */
636
/* set up inverse transform steps */
637
untransform_coords (m, dest_x1 + destPR->x, dest_y1 + y, tu, tv, tw);
641
gdouble u[5], v[5]; /* source coordinates */
644
/* normalize homogeneous coords */
645
normalize_coords (5, tu, tv, tw, u, v);
648
supersample_dtest (u[1], v[1], u[2], v[2],
649
u[3], v[3], u[4], v[4]))
651
sample_adapt (orig_tiles,
652
u[0] - u1, v[0] - v1,
653
u[1] - u1, v[1] - v1,
654
u[2] - u1, v[2] - v1,
655
u[3] - u1, v[3] - v1,
656
u[4] - u1, v[4] - v1,
658
d, bg_color, destPR->bytes, alpha);
662
sample_lanczos (surround, lanczos, u[0] - u1, v[0] - v1,
663
d, destPR->bytes, alpha);
668
for (i = 0; i < 5; i++)
676
dest += destPR->rowstride;
681
pixels += destPR->w * destPR->h;
684
gimp_progress_set_value (progress,
685
(gdouble) pixels / (gdouble) total);
690
pixel_surround_destroy (surround);
694
/* private functions */
697
untransform_coords (const GimpMatrix3 *m,
704
tu[0] = m->coeff[0][0] * (x ) + m->coeff[0][1] * (y ) + m->coeff[0][2];
705
tv[0] = m->coeff[1][0] * (x ) + m->coeff[1][1] * (y ) + m->coeff[1][2];
706
tw[0] = m->coeff[2][0] * (x ) + m->coeff[2][1] * (y ) + m->coeff[2][2];
708
tu[1] = m->coeff[0][0] * (x - 1) + m->coeff[0][1] * (y ) + m->coeff[0][2];
709
tv[1] = m->coeff[1][0] * (x - 1) + m->coeff[1][1] * (y ) + m->coeff[1][2];
710
tw[1] = m->coeff[2][0] * (x - 1) + m->coeff[2][1] * (y ) + m->coeff[2][2];
712
tu[2] = m->coeff[0][0] * (x ) + m->coeff[0][1] * (y - 1) + m->coeff[0][2];
713
tv[2] = m->coeff[1][0] * (x ) + m->coeff[1][1] * (y - 1) + m->coeff[1][2];
714
tw[2] = m->coeff[2][0] * (x ) + m->coeff[2][1] * (y - 1) + m->coeff[2][2];
716
tu[3] = m->coeff[0][0] * (x + 1) + m->coeff[0][1] * (y ) + m->coeff[0][2];
717
tv[3] = m->coeff[1][0] * (x + 1) + m->coeff[1][1] * (y ) + m->coeff[1][2];
718
tw[3] = m->coeff[2][0] * (x + 1) + m->coeff[2][1] * (y ) + m->coeff[2][2];
720
tu[4] = m->coeff[0][0] * (x ) + m->coeff[0][1] * (y + 1) + m->coeff[0][2];
721
tv[4] = m->coeff[1][0] * (x ) + m->coeff[1][1] * (y + 1) + m->coeff[1][2];
722
tw[4] = m->coeff[2][0] * (x ) + m->coeff[2][1] * (y + 1) + m->coeff[2][2];
726
normalize_coords (const gint coords,
735
for (i = 0; i < coords; i++)
737
if (G_LIKELY (tw[i] != 0.0))
739
u[i] = tu[i] / tw[i];
740
v[i] = tv[i] / tw[i];
744
g_warning ("homogeneous coordinate = 0...\n");
753
#define BILINEAR(jk, j1k, jk1, j1k1, dx, dy) \
754
((1 - dy) * (jk + dx * (j1k - jk)) + \
755
dy * (jk1 + dx * (j1k1 - jk1)))
757
/* u & v are the subpixel coordinates of the point in
758
* the original selection's floating buffer.
759
* We need the two pixel coords around them:
760
* iu to iu + 1, iv to iv + 1
763
sample_linear (PixelSurround *surround,
770
gdouble a_val, a_recip;
776
const guchar *alphachan;
779
/* lock the pixel surround */
780
data = pixel_surround_lock (surround, iu, iv, &rowstride);
782
/* the fractional error */
786
/* calculate alpha value of result pixel */
787
alphachan = &data[alpha];
788
a_val = BILINEAR (alphachan[0], alphachan[bytes],
789
alphachan[rowstride], alphachan[rowstride + bytes], du, dv);
796
else if (a_val >= 255.0)
798
a_recip = 1.0 / a_val;
803
a_recip = 1.0 / a_val;
804
color[alpha] = RINT (a_val);
807
/* for colour channels c,
808
* result = bilinear (c * alpha) / bilinear (alpha)
810
* never entered for alpha == 0
812
for (i = 0; i < alpha; i++)
817
BILINEAR (alphachan[0] * data[i],
818
alphachan[bytes] * data[bytes + i],
819
alphachan[rowstride] * data[rowstride + i],
820
alphachan[rowstride + bytes] * data[rowstride + bytes + i],
823
color[i] = CLAMP (newval, 0, 255);
827
/* macros to handle conversion to/from fixed point, this fixed point code
828
* uses signed integers, by using 8 bits for the fractional part we have
831
* 21 bits integer part
832
* 8 bit fractional part
834
* 1023 discrete subpixel sample positions should be enough for the needs
835
* of the supersampling algorithm, drawables where the dimensions have a need
836
* exceeding 2^21 ( 2097152px, will typically use terabytes of memory, when
837
* that is the common need, we can probably assume 64 bit integers and adjust
838
* FIXED_SHIFT accordingly.
840
#define FIXED_SHIFT 10
841
#define FIXED_UNIT (1 << FIXED_SHIFT)
842
#define DOUBLE2FIXED(val) ((val) * FIXED_UNIT)
843
#define FIXED2DOUBLE(val) ((val) / FIXED_UNIT)
846
bilinear interpolation of a fixed point pixel
849
sample_bi (TileManager *tm,
853
const guchar *bg_color,
859
gint xscale = (x & (FIXED_UNIT-1));
860
gint yscale = (y & (FIXED_UNIT-1));
862
gint x0 = x >> FIXED_SHIFT;
863
gint y0 = y >> FIXED_SHIFT;
868
/* fill the color with default values, since read_pixel_data_1
869
* does nothing, when accesses are out of bounds.
871
for (i = 0; i < 4; i++)
872
*(guint*) (&C[i]) = *(guint*) (bg_color);
874
read_pixel_data_1 (tm, x0, y0, C[0]);
875
read_pixel_data_1 (tm, x1, y0, C[2]);
876
read_pixel_data_1 (tm, x0, y1, C[1]);
877
read_pixel_data_1 (tm, x1, y1, C[3]);
879
#define lerp(v1, v2, r) \
880
(((guint)(v1) * (FIXED_UNIT - (guint)(r)) + \
881
(guint)(v2) * (guint)(r)) >> FIXED_SHIFT)
883
color[alpha]= lerp (lerp (C[0][alpha], C[1][alpha], yscale),
884
lerp (C[2][alpha], C[3][alpha], yscale), xscale);
887
{ /* to avoid problems, calculate with premultiplied alpha */
888
for (i = 0; i < alpha; i++)
890
C[0][i] = (C[0][i] * C[0][alpha] / 255);
891
C[1][i] = (C[1][i] * C[1][alpha] / 255);
892
C[2][i] = (C[2][i] * C[2][alpha] / 255);
893
C[3][i] = (C[3][i] * C[3][alpha] / 255);
896
for (i = 0; i < alpha; i++)
897
color[i] = lerp (lerp (C[0][i], C[1][i], yscale),
898
lerp (C[2][i], C[3][i], yscale), xscale);
902
for (i = 0; i < alpha; i++)
911
* Returns TRUE if one of the deltas of the
912
* quad edge is > 1.0 (16.16 fixed values).
914
static inline gboolean
915
supersample_test (gint x0, gint y0,
920
return (abs (x0 - x1) > FIXED_UNIT ||
921
abs (x1 - x2) > FIXED_UNIT ||
922
abs (x2 - x3) > FIXED_UNIT ||
923
abs (x3 - x0) > FIXED_UNIT ||
925
abs (y0 - y1) > FIXED_UNIT ||
926
abs (y1 - y2) > FIXED_UNIT ||
927
abs (y2 - y3) > FIXED_UNIT ||
928
abs (y3 - y0) > FIXED_UNIT);
932
* Returns TRUE if one of the deltas of the
933
* quad edge is > 1.0 (double values).
935
static inline gboolean
936
supersample_dtest (gdouble x0, gdouble y0,
937
gdouble x1, gdouble y1,
938
gdouble x2, gdouble y2,
939
gdouble x3, gdouble y3)
941
return (fabs (x0 - x1) > 1.0 ||
942
fabs (x1 - x2) > 1.0 ||
943
fabs (x2 - x3) > 1.0 ||
944
fabs (x3 - x0) > 1.0 ||
946
fabs (y0 - y1) > 1.0 ||
947
fabs (y1 - y2) > 1.0 ||
948
fabs (y2 - y3) > 1.0 ||
949
fabs (y3 - y0) > 1.0);
953
sample a grid that is spaced according to the quadraliteral's edges,
954
it subdivides a maximum of level times before sampling.
955
0..3 is a cycle around the quad
958
get_sample (TileManager *tm,
972
const guchar *bg_color,
976
if (!level || !supersample_test (x0, y0, x1, y1, x2, y2, x3, y3))
981
sample_bi (tm, xc, yc, C, bg_color, bpp, alpha);
983
for (i = 0; i < bpp; i++)
986
(*cc)++; /* increase number of samples taken */
990
gint tx, lx, rx, bx, tlx, trx, blx, brx;
991
gint ty, ly, ry, by, tly, try, bly, bry;
993
/* calculate subdivided corner coordinates (including centercoords
994
thus using a bilinear interpolation,. almost as good as
995
doing the perspective transform for each subpixel coordinate*/
1002
blx = (x3 + xc) / 2;
1003
brx = (x2 + xc) / 2;
1007
tly = (y0 + yc) / 2;
1008
try = (y1 + yc) / 2;
1011
bly = (y3 + yc) / 2;
1012
bry = (y2 + yc) / 2;
1017
x0,y0, tx,ty, xc,yc, lx,ly,
1018
cc, level-1, color, bg_color, bpp, alpha);
1022
tx,ty, x1,y1, rx,ry, xc,yc,
1023
cc, level-1, color, bg_color, bpp, alpha);
1027
xc,yc, rx,ry, x2,y2, bx,by,
1028
cc, level-1, color, bg_color, bpp, alpha);
1032
lx,ly, xc,yc, bx,by, x3,y3,
1033
cc, level-1, color, bg_color, bpp, alpha);
1038
sample_adapt (TileManager *tm,
1051
const guchar *bg_color,
1057
guint C[MAX_CHANNELS];
1059
C[0] = C[1] = C[2] = C[3] = 0;
1062
DOUBLE2FIXED (xc), DOUBLE2FIXED (yc),
1063
DOUBLE2FIXED (x0), DOUBLE2FIXED (y0),
1064
DOUBLE2FIXED (x1), DOUBLE2FIXED (y1),
1065
DOUBLE2FIXED (x2), DOUBLE2FIXED (y2),
1066
DOUBLE2FIXED (x3), DOUBLE2FIXED (y3),
1067
&cc, level, C, bg_color, bpp, alpha);
1072
color[alpha] = C[alpha] / cc;
1076
/* go from premultiplied to postmultiplied alpha */
1077
for (i = 0; i < alpha; i++)
1078
color[i] = ((C[i] / cc) * 255) / color[alpha];
1082
for (i = 0; i < alpha; i++)
1087
/* access interleaved pixels */
1088
#define CUBIC_ROW(dx, row, step) \
1089
gimp_drawable_transform_cubic(dx,\
1090
(row)[0], (row)[step], (row)[step+step], (row)[step+step+step])
1092
#define CUBIC_SCALED_ROW(dx, row, arow, step) \
1093
gimp_drawable_transform_cubic(dx, \
1094
(arow)[0] * (row)[0], \
1095
(arow)[step] * (row)[step], \
1096
(arow)[step+step] * (row)[step+step], \
1097
(arow)[step+step+step] * (row)[step+step+step])
1100
/* Note: cubic function no longer clips result. */
1101
/* Inlining this function makes sample_cubic() run about 10% faster. (Sven) */
1102
static inline gdouble
1103
gimp_drawable_transform_cubic (gdouble dx,
1112
/* Equivalent to Gimp 1.1.1 and earlier - some ringing */
1113
result = ((( ( - jm1 + j - jp1 + jp2 ) * dx +
1114
( jm1 + jm1 - j - j + jp1 - jp2 ) ) * dx +
1115
( - jm1 + jp1 ) ) * dx + j );
1116
/* Recommended by Mitchell and Netravali - too blurred? */
1117
result = ((( ( - 7 * jm1 + 21 * j - 21 * jp1 + 7 * jp2 ) * dx +
1118
( 15 * jm1 - 36 * j + 27 * jp1 - 6 * jp2 ) ) * dx +
1119
( - 9 * jm1 + 9 * jp1 ) ) * dx + (jm1 + 16 * j + jp1) ) / 18.0;
1122
/* Catmull-Rom - not bad */
1123
result = ((( ( - jm1 + 3 * j - 3 * jp1 + jp2 ) * dx +
1124
( 2 * jm1 - 5 * j + 4 * jp1 - jp2 ) ) * dx +
1125
( - jm1 + jp1 ) ) * dx + (j + j) ) / 2.0;
1131
/* u & v are the subpixel coordinates of the point in
1132
* the original selection's floating buffer.
1133
* We need the four integer pixel coords around them:
1134
* iu to iu + 3, iv to iv + 3
1137
sample_cubic (PixelSurround *surround,
1144
gdouble a_val, a_recip;
1152
/* lock the pixel surround */
1153
data = pixel_surround_lock (surround, iu - 1 , iv - 1, &rowstride);
1155
/* the fractional error */
1159
/* calculate alpha of result */
1160
a_val = gimp_drawable_transform_cubic
1162
CUBIC_ROW (du, data + alpha + rowstride * 0, bytes),
1163
CUBIC_ROW (du, data + alpha + rowstride * 1, bytes),
1164
CUBIC_ROW (du, data + alpha + rowstride * 2, bytes),
1165
CUBIC_ROW (du, data + alpha + rowstride * 3, bytes));
1172
else if (a_val > 255.0)
1174
a_recip = 1.0 / a_val;
1179
a_recip = 1.0 / a_val;
1180
color[alpha] = RINT (a_val);
1183
/* for colour channels c,
1184
* result = bicubic (c * alpha) / bicubic (alpha)
1186
* never entered for alpha == 0
1188
for (i = 0; i < alpha; i++)
1190
gint newval = (a_recip *
1191
gimp_drawable_transform_cubic
1193
CUBIC_SCALED_ROW (du,
1194
i + data + rowstride * 0,
1195
data + alpha + rowstride * 0,
1197
CUBIC_SCALED_ROW (du,
1198
i + data + rowstride * 1,
1199
data + alpha + rowstride * 1,
1201
CUBIC_SCALED_ROW (du,
1202
i + data + rowstride * 2,
1203
data + alpha + rowstride * 2,
1205
CUBIC_SCALED_ROW (du,
1206
i + data + rowstride * 3,
1207
data + alpha + rowstride * 3,
1210
color[i] = CLAMP (newval, 0, 255);
1215
sample_lanczos (PixelSurround *surround,
1216
const gfloat *lanczos,
1223
gdouble x_kernel[LANCZOS_WIDTH2]; /* 1-D kernels of window coeffs */
1224
gdouble y_kernel[LANCZOS_WIDTH2];
1225
gdouble x_sum, y_sum; /* sum of Lanczos weights */
1239
/* get weight for fractional error */
1240
su = (gint) ((u - iu) * LANCZOS_SPP);
1241
sv = (gint) ((v - iv) * LANCZOS_SPP);
1243
/* fill 1D kernels */
1244
for (x_sum = y_sum = 0.0, i = LANCZOS_WIDTH; i >= -LANCZOS_WIDTH; i--)
1246
gint pos = i * LANCZOS_SPP;
1248
x_sum += x_kernel[LANCZOS_WIDTH + i] = lanczos[ABS (su - pos)];
1249
y_sum += y_kernel[LANCZOS_WIDTH + i] = lanczos[ABS (sv - pos)];
1252
/* normalise the weighted arrays */
1253
for (i = 0; i < LANCZOS_WIDTH2 ; i++)
1255
x_kernel[i] /= x_sum;
1256
y_kernel[i] /= y_sum;
1259
/* lock the pixel surround */
1260
data = pixel_surround_lock (surround,
1261
iu - LANCZOS_WIDTH, iv - LANCZOS_WIDTH,
1267
for (j = 0; j < LANCZOS_WIDTH2 ; j++)
1269
for (i = 0; i < LANCZOS_WIDTH2 ; i++)
1270
aval += y_kernel[j] * x_kernel[i] * (gdouble) src[i * bytes];
1280
else if (aval > 255.0)
1282
arecip = 1.0 / aval;
1287
arecip = 1.0 / aval;
1290
for (b = 0; b < alpha; b++)
1293
gdouble newval = 0.0;
1296
asrc = data + alpha;
1298
for (j = 0; j < LANCZOS_WIDTH2; j++)
1300
for (i = 0; i < LANCZOS_WIDTH2; i++)
1301
newval += (y_kernel[j] * x_kernel[i] *
1302
(gdouble) src[i * bytes] * (gdouble) asrc[i * bytes]);
1309
color[b] = CLAMP (newval, 0, 255);
1312
color[alpha] = RINT (aval);