~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to app/base/curves.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify
29
29
#include "gimplut.h"
30
30
 
31
31
 
32
 
typedef gdouble CRMatrix[4][4];
33
 
 
34
32
 
35
33
/*  local function prototypes  */
36
34
 
37
 
static void   curves_plot_curve (Curves   *curves,
38
 
                                 gint      channel,
39
 
                                 gint      p1,
40
 
                                 gint      p2,
41
 
                                 gint      p3,
42
 
                                 gint      p4);
43
 
static void   curves_CR_compose (CRMatrix  a,
44
 
                                 CRMatrix  b,
45
 
                                 CRMatrix  ab);
46
 
 
47
 
 
48
 
/*  private variables  */
49
 
 
50
 
static CRMatrix CR_basis =
51
 
{
52
 
  { -0.5,  1.5, -1.5,  0.5 },
53
 
  {  1.0, -2.5,  2.0, -0.5 },
54
 
  { -0.5,  0.0,  0.5,  0.0 },
55
 
  {  0.0,  1.0,  0.0,  0.0 },
56
 
};
 
35
static void  curves_plot_curve (Curves *curves,
 
36
                                gint    channel,
 
37
                                gint    p1,
 
38
                                gint    p2,
 
39
                                gint    p3,
 
40
                                gint    p4);
57
41
 
58
42
 
59
43
/*  public functions  */
118
102
      /*  cycle through the curves  */
119
103
      num_pts = 0;
120
104
      for (i = 0; i < CURVES_NUM_POINTS; i++)
121
 
        if (curves->points[channel][i][0] != -1)
122
 
          points[num_pts++] = i;
 
105
        if (curves->points[channel][i][0] != -1)
 
106
          points[num_pts++] = i;
123
107
 
124
108
      /*  Initialize boundary curve points */
125
109
      if (num_pts != 0)
126
 
        {
127
 
          for (i = 0; i < curves->points[channel][points[0]][0]; i++)
128
 
            curves->curve[channel][i] = curves->points[channel][points[0]][1];
129
 
          for (i = curves->points[channel][points[num_pts - 1]][0]; i < 256; i++)
130
 
            curves->curve[channel][i] = curves->points[channel][points[num_pts - 1]][1];
131
 
        }
 
110
        {
 
111
          for (i = 0; i < curves->points[channel][points[0]][0]; i++)
 
112
            curves->curve[channel][i] = curves->points[channel][points[0]][1];
 
113
 
 
114
          for (i = curves->points[channel][points[num_pts - 1]][0];
 
115
               i < 256;
 
116
               i++)
 
117
            curves->curve[channel][i] =
 
118
              curves->points[channel][points[num_pts - 1]][1];
 
119
        }
132
120
 
133
121
      for (i = 0; i < num_pts - 1; i++)
134
 
        {
135
 
          p1 = (i == 0) ? points[i] : points[(i - 1)];
136
 
          p2 = points[i];
137
 
          p3 = points[(i + 1)];
138
 
          p4 = (i == (num_pts - 2)) ? points[(num_pts - 1)] : points[(i + 2)];
 
122
        {
 
123
          p1 = points[MAX (i - 1, 0)];
 
124
          p2 = points[i];
 
125
          p3 = points[i + 1];
 
126
          p4 = points[MIN (i + 2, num_pts - 1)];
139
127
 
140
 
          curves_plot_curve (curves, channel, p1, p2, p3, p4);
141
 
        }
 
128
          curves_plot_curve (curves, channel, p1, p2, p3, p4);
 
129
        }
142
130
 
143
131
      /* ensure that the control points are used exactly */
144
132
      for (i = 0; i < num_pts; i++)
145
133
        {
146
 
          gint x, y;
 
134
          gint x = curves->points[channel][points[i]][0];
 
135
          gint y = curves->points[channel][points[i]][1];
147
136
 
148
 
          x = curves->points[channel][points[i]][0];
149
 
          y = curves->points[channel][points[i]][1];
150
137
          curves->curve[channel][x] = y;
151
138
        }
152
139
 
156
143
 
157
144
gfloat
158
145
curves_lut_func (Curves *curves,
159
 
                 gint    n_channels,
160
 
                 gint    channel,
161
 
                 gfloat  value)
 
146
                 gint    n_channels,
 
147
                 gint    channel,
 
148
                 gfloat  value)
162
149
{
163
150
  gfloat  f;
164
151
  gint    index;
195
182
        }
196
183
      else /* interpolate the curve */
197
184
        {
198
 
          index = floor(inten * 255.0);
199
 
          f = inten*255.0 - index;
 
185
          index = floor (inten * 255.0);
 
186
          f = inten * 255.0 - index;
200
187
          inten = ((1.0 - f) * curves->curve[j][index    ] +
201
 
                   (      f) * curves->curve[j][index + 1] ) / 255.0;
 
188
                          f  * curves->curve[j][index + 1] ) / 255.0;
202
189
        }
203
190
    }
204
191
 
208
195
 
209
196
/*  private functions  */
210
197
 
 
198
/*
 
199
 * This function calculates the curve values between the control points
 
200
 * p2 and p3, taking the potentially existing neighbors p1 and p4 into
 
201
 * account.
 
202
 *
 
203
 * This function uses a cubic bezier curve for the individual segments and
 
204
 * calculates the necessary intermediate control points depending on the
 
205
 * neighbor curve control points.
 
206
 */
 
207
 
211
208
static void
212
209
curves_plot_curve (Curves *curves,
213
210
                   gint    channel,
214
 
                   gint    p1,
215
 
                   gint    p2,
216
 
                   gint    p3,
217
 
                   gint    p4)
218
 
{
219
 
  CRMatrix geometry;
220
 
  CRMatrix tmp1, tmp2;
221
 
  CRMatrix deltas;
222
 
  gdouble  x, dx, dx2, dx3;
223
 
  gdouble  y, dy, dy2, dy3;
224
 
  gdouble  d, d2, d3;
225
 
  gint     lastx, lasty;
226
 
  gint32   newx, newy;
227
 
  gint     i;
228
 
 
229
 
  /* construct the geometry matrix from the segment */
230
 
  for (i = 0; i < 4; i++)
231
 
    {
232
 
      geometry[i][2] = 0;
233
 
      geometry[i][3] = 0;
234
 
    }
235
 
 
236
 
  for (i = 0; i < 2; i++)
237
 
    {
238
 
      geometry[0][i] = curves->points[channel][p1][i];
239
 
      geometry[1][i] = curves->points[channel][p2][i];
240
 
      geometry[2][i] = curves->points[channel][p3][i];
241
 
      geometry[3][i] = curves->points[channel][p4][i];
242
 
    }
243
 
 
244
 
  /* subdivide the curve 1000 times */
245
 
  /* n can be adjusted to give a finer or coarser curve */
246
 
  d = 1.0 / 1000;
247
 
  d2 = d * d;
248
 
  d3 = d * d * d;
249
 
 
250
 
  /* construct a temporary matrix for determining the forward differencing deltas */
251
 
  tmp2[0][0] = 0;     tmp2[0][1] = 0;     tmp2[0][2] = 0;    tmp2[0][3] = 1;
252
 
  tmp2[1][0] = d3;    tmp2[1][1] = d2;    tmp2[1][2] = d;    tmp2[1][3] = 0;
253
 
  tmp2[2][0] = 6*d3;  tmp2[2][1] = 2*d2;  tmp2[2][2] = 0;    tmp2[2][3] = 0;
254
 
  tmp2[3][0] = 6*d3;  tmp2[3][1] = 0;     tmp2[3][2] = 0;    tmp2[3][3] = 0;
255
 
 
256
 
  /* compose the basis and geometry matrices */
257
 
  curves_CR_compose (CR_basis, geometry, tmp1);
258
 
 
259
 
  /* compose the above results to get the deltas matrix */
260
 
  curves_CR_compose (tmp2, tmp1, deltas);
261
 
 
262
 
  /* extract the x deltas */
263
 
  x = deltas[0][0];
264
 
  dx = deltas[1][0];
265
 
  dx2 = deltas[2][0];
266
 
  dx3 = deltas[3][0];
267
 
 
268
 
  /* extract the y deltas */
269
 
  y = deltas[0][1];
270
 
  dy = deltas[1][1];
271
 
  dy2 = deltas[2][1];
272
 
  dy3 = deltas[3][1];
273
 
 
274
 
  lastx = CLAMP (x, 0, 255);
275
 
  lasty = CLAMP (y, 0, 255);
276
 
 
277
 
  curves->curve[channel][lastx] = lasty;
278
 
 
279
 
  /* loop over the curve */
280
 
  for (i = 0; i < 1000; i++)
281
 
    {
282
 
      /* increment the x values */
283
 
      x += dx;
284
 
      dx += dx2;
285
 
      dx2 += dx3;
286
 
 
287
 
      /* increment the y values */
288
 
      y += dy;
289
 
      dy += dy2;
290
 
      dy2 += dy3;
291
 
 
292
 
      newx = CLAMP0255 (ROUND (x));
293
 
      newy = CLAMP0255 (ROUND (y));
294
 
 
295
 
      /* if this point is different than the last one...then draw it */
296
 
      if ((lastx != newx) || (lasty != newy))
297
 
        curves->curve[channel][newx] = newy;
298
 
 
299
 
      lastx = newx;
300
 
      lasty = newy;
301
 
    }
302
 
}
303
 
 
304
 
static void
305
 
curves_CR_compose (CRMatrix a,
306
 
                   CRMatrix b,
307
 
                   CRMatrix ab)
308
 
{
309
 
  gint i, j;
310
 
 
311
 
  for (i = 0; i < 4; i++)
312
 
    {
313
 
      for (j = 0; j < 4; j++)
314
 
        {
315
 
          ab[i][j] = (a[i][0] * b[0][j] +
316
 
                      a[i][1] * b[1][j] +
317
 
                      a[i][2] * b[2][j] +
318
 
                      a[i][3] * b[3][j]);
319
 
        }
320
 
    }
321
 
}
 
211
                   gint    p1,
 
212
                   gint    p2,
 
213
                   gint    p3,
 
214
                   gint    p4)
 
215
{
 
216
  gint    i;
 
217
  gdouble x0, x3;
 
218
  gdouble y0, y1, y2, y3;
 
219
  gdouble dx, dy;
 
220
  gdouble y, t;
 
221
  gdouble slope;
 
222
 
 
223
  /* the outer control points for the bezier curve. */
 
224
  x0 = curves->points[channel][p2][0];
 
225
  y0 = curves->points[channel][p2][1];
 
226
  x3 = curves->points[channel][p3][0];
 
227
  y3 = curves->points[channel][p3][1];
 
228
 
 
229
  /*
 
230
   * the x values of the inner control points are fixed at
 
231
   * x1 = 1/3*x0 + 2/3*x3   and  x2 = 2/3*x0 + 1/3*x3
 
232
   * this ensures that the x values increase linearily with the
 
233
   * parameter t and enables us to skip the calculation of the x
 
234
   * values altogehter - just calculate y(t) evenly spaced.
 
235
   */
 
236
 
 
237
  dx = x3 - x0;
 
238
  dy = y3 - y0;
 
239
 
 
240
  g_return_if_fail (dx > 0);
 
241
 
 
242
  if (p1 == p2 && p3 == p4)
 
243
    {
 
244
      /* No information about the neighbors,
 
245
       * calculate y1 and y2 to get a straight line
 
246
       */
 
247
      y1 = y0 + dy / 3.0;
 
248
      y2 = y0 + dy * 2.0 / 3.0;
 
249
    }
 
250
  else if (p1 == p2 && p3 != p4)
 
251
    {
 
252
      /* only the right neighbor is available. Make the tangent at the
 
253
       * right endpoint parallel to the line between the left endpoint
 
254
       * and the right neighbor. Then point the tangent at the left towards
 
255
       * the control handle of the right tangent, to ensure that the curve
 
256
       * does not have an inflection point.
 
257
       */
 
258
      slope = (curves->points[channel][p4][1] - y0) /
 
259
              (curves->points[channel][p4][0] - x0);
 
260
 
 
261
      y2 = y3 - slope * dx / 3.0;
 
262
      y1 = y0 + (y2 - y0) / 2.0;
 
263
    }
 
264
  else if (p1 != p2 && p3 == p4)
 
265
    {
 
266
      /* see previous case */
 
267
      slope = (y3 - curves->points[channel][p1][1]) /
 
268
              (x3 - curves->points[channel][p1][0]);
 
269
 
 
270
      y1 = y0 + slope * dx / 3.0;
 
271
      y2 = y3 + (y1 - y3) / 2.0;
 
272
    }
 
273
  else /* (p1 != p2 && p3 != p4) */
 
274
    {
 
275
      /* Both neighbors are available. Make the tangents at the endpoints
 
276
       * parallel to the line between the opposite endpoint and the adjacent
 
277
       * neighbor.
 
278
       */
 
279
      slope = (y3 - curves->points[channel][p1][1]) /
 
280
              (x3 - curves->points[channel][p1][0]);
 
281
 
 
282
      y1 = y0 + slope * dx / 3.0;
 
283
 
 
284
      slope = (curves->points[channel][p4][1] - y0) /
 
285
              (curves->points[channel][p4][0] - x0);
 
286
 
 
287
      y2 = y3 - slope * dx / 3.0;
 
288
    }
 
289
 
 
290
  /*
 
291
   * finally calculate the y(t) values for the given bezier values. We can
 
292
   * use homogenously distributed values for t, since x(t) increases linearily.
 
293
   */
 
294
  for (i = 0; i <= dx; i++)
 
295
    {
 
296
      t = i / dx;
 
297
      y =     y0 * (1-t) * (1-t) * (1-t) +
 
298
          3 * y1 * (1-t) * (1-t) * t     +
 
299
          3 * y2 * (1-t) * t     * t     +
 
300
              y3 * t     * t     * t;
 
301
 
 
302
      curves->curve[channel][ROUND(x0) + i] = CLAMP0255 (ROUND (y));
 
303
    }
 
304
}
 
305