2
* Copyright (C) 2006-2009 Anders Brander <anders@brander.dk> and
3
* Anders Kvist <akv@lnxbx.dk>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
static void matrix4_zshear (RS_MATRIX4 *matrix, double dx, double dy);
26
static void matrix4_xrotate(RS_MATRIX4 *matrix, double rs, double rc);
27
static void matrix4_yrotate(RS_MATRIX4 *matrix, double rs, double rc);
28
static void matrix4_zrotate(RS_MATRIX4 *matrix, double rs, double rc);
29
static void matrix4_affine_transform_3dpoint(RS_MATRIX4 *matrix, double x, double y, double z, double *tx, double *ty, double *tz);
32
printmat(RS_MATRIX4 *mat)
39
printf("%f ",mat->coeff[x][y]);
46
matrix4_identity (RS_MATRIX4 *matrix)
48
static const RS_MATRIX4 identity = { { { 1.0, 0.0, 0.0, 0.0 },
49
{ 0.0, 1.0, 0.0, 0.0 },
50
{ 0.0, 0.0, 1.0, 0.0 },
51
{ 0.0, 0.0, 0.0, 1.0 } } };
57
matrix4_multiply(const RS_MATRIX4 *left, RS_MATRIX4 *right, RS_MATRIX4 *result)
61
double t1, t2, t3, t4;
63
for (i = 0; i < 4; i++)
65
t1 = left->coeff[i][0];
66
t2 = left->coeff[i][1];
67
t3 = left->coeff[i][2];
68
t4 = left->coeff[i][3];
70
for (j = 0; j < 4; j++)
72
tmp.coeff[i][j] = t1 * right->coeff[0][j];
73
tmp.coeff[i][j] += t2 * right->coeff[1][j];
74
tmp.coeff[i][j] += t3 * right->coeff[2][j];
75
tmp.coeff[i][j] += t4 * right->coeff[3][j];
81
/* copied almost verbatim from dcraw.c:pseudoinverse()
82
- but this one doesn't transpose */
84
matrix4_color_invert(const RS_MATRIX4 *in, RS_MATRIX4 *out)
87
double work[3][6], num;
90
matrix4_identity(&tmp);
95
work[i][j] = j == i+3;
98
work[i][j] += in->coeff[k][i] * in->coeff[k][j];
100
for (i=0; i < 3; i++)
103
for (j=0; j < 6; j++)
105
for (k=0; k < 3; k++)
110
for (j=0; j < 6; j++)
111
work[k][j] -= work[i][j] * num;
114
for (i=0; i < 3; i++)
115
for (j=0; j < 3; j++)
116
for (tmp.coeff[i][j]=k=0; k < 3; k++)
117
tmp.coeff[i][j] += work[j][k+3] * in->coeff[i][k];
118
for (i=0; i < 4; i++)
119
for (j=0; j < 4; j++)
120
out->coeff[i][j] = tmp.coeff[j][i];
124
matrix4_zshear (RS_MATRIX4 *matrix, double dx, double dy)
128
zshear.coeff[0][0] = 1.0;
129
zshear.coeff[1][0] = 0.0;
130
zshear.coeff[2][0] = dx;
131
zshear.coeff[3][0] = 0.0;
133
zshear.coeff[0][1] = 0.0;
134
zshear.coeff[1][1] = 1.0;
135
zshear.coeff[2][1] = dy;
136
zshear.coeff[3][1] = 0.0;
138
zshear.coeff[0][2] = 0.0;
139
zshear.coeff[1][2] = 0.0;
140
zshear.coeff[2][2] = 1.0;
141
zshear.coeff[3][2] = 0.0;
143
zshear.coeff[0][3] = 0.0;
144
zshear.coeff[1][3] = 0.0;
145
zshear.coeff[2][3] = 0.0;
146
zshear.coeff[3][3] = 1.0;
148
matrix4_multiply(&zshear, matrix, matrix);
152
matrix4_to_matrix4int(RS_MATRIX4 *matrix, RS_MATRIX4Int *matrixi)
157
matrixi->coeff[a][b] = (int) (matrix->coeff[a][b] * (double) (1<<MATRIX_RESOLUTION));
162
matrix4_xrotate(RS_MATRIX4 *matrix, double rs, double rc)
166
tmp.coeff[0][0] = 1.0;
167
tmp.coeff[1][0] = 0.0;
168
tmp.coeff[2][0] = 0.0;
169
tmp.coeff[3][0] = 0.0;
171
tmp.coeff[0][1] = 0.0;
172
tmp.coeff[1][1] = rc;
173
tmp.coeff[2][1] = rs;
174
tmp.coeff[3][1] = 0.0;
176
tmp.coeff[0][2] = 0.0;
177
tmp.coeff[1][2] = -rs;
178
tmp.coeff[2][2] = rc;
179
tmp.coeff[3][2] = 0.0;
181
tmp.coeff[0][3] = 0.0;
182
tmp.coeff[1][3] = 0.0;
183
tmp.coeff[2][3] = 0.0;
184
tmp.coeff[3][3] = 1.0;
186
matrix4_multiply(&tmp, matrix, matrix);
190
matrix4_yrotate(RS_MATRIX4 *matrix, double rs, double rc)
194
tmp.coeff[0][0] = rc;
195
tmp.coeff[1][0] = 0.0;
196
tmp.coeff[2][0] = -rs;
197
tmp.coeff[3][0] = 0.0;
199
tmp.coeff[0][1] = 0.0;
200
tmp.coeff[1][1] = 1.0;
201
tmp.coeff[2][1] = 0.0;
202
tmp.coeff[3][1] = 0.0;
204
tmp.coeff[0][2] = rs;
205
tmp.coeff[1][2] = 0.0;
206
tmp.coeff[2][2] = rc;
207
tmp.coeff[3][2] = 0.0;
209
tmp.coeff[0][3] = 0.0;
210
tmp.coeff[1][3] = 0.0;
211
tmp.coeff[2][3] = 0.0;
212
tmp.coeff[3][3] = 1.0;
214
matrix4_multiply(&tmp, matrix, matrix);
218
matrix4_zrotate(RS_MATRIX4 *matrix, double rs, double rc)
222
tmp.coeff[0][0] = rc;
223
tmp.coeff[1][0] = rs;
224
tmp.coeff[2][0] = 0.0;
225
tmp.coeff[3][0] = 0.0;
227
tmp.coeff[0][1] = -rs;
228
tmp.coeff[1][1] = rc;
229
tmp.coeff[2][1] = 0.0;
230
tmp.coeff[3][1] = 0.0;
232
tmp.coeff[0][2] = 0.0;
233
tmp.coeff[1][2] = 0.0;
234
tmp.coeff[2][2] = 1.0;
235
tmp.coeff[3][2] = 0.0;
237
tmp.coeff[0][3] = 0.0;
238
tmp.coeff[1][3] = 0.0;
239
tmp.coeff[2][3] = 0.0;
240
tmp.coeff[3][3] = 1.0;
242
matrix4_multiply(&tmp, matrix, matrix);
246
matrix4_color_normalize(RS_MATRIX4 *mat)
251
for(row=0;row<3;row++)
254
for(col=0;col<3;col++)
255
lum += mat->coeff[row][col];
256
for(col=0;col<3;col++)
257
mat->coeff[row][col] /= lum;
263
matrix4_color_saturate(RS_MATRIX4 *mat, double sat)
267
if (sat == 1.0) return;
269
tmp.coeff[0][0] = (1.0-sat)*RLUM + sat;
270
tmp.coeff[1][0] = (1.0-sat)*RLUM;
271
tmp.coeff[2][0] = (1.0-sat)*RLUM;
272
tmp.coeff[3][0] = 0.0;
274
tmp.coeff[0][1] = (1.0-sat)*GLUM;
275
tmp.coeff[1][1] = (1.0-sat)*GLUM + sat;
276
tmp.coeff[2][1] = (1.0-sat)*GLUM;
277
tmp.coeff[3][1] = 0.0;
279
tmp.coeff[0][2] = (1.0-sat)*BLUM;
280
tmp.coeff[1][2] = (1.0-sat)*BLUM;
281
tmp.coeff[2][2] = (1.0-sat)*BLUM + sat;
282
tmp.coeff[3][2] = 0.0;
284
tmp.coeff[0][3] = 0.0;
285
tmp.coeff[1][3] = 0.0;
286
tmp.coeff[2][3] = 0.0;
287
tmp.coeff[3][3] = 1.0;
288
matrix4_multiply(mat, &tmp, mat);
292
matrix4_affine_transform_3dpoint(RS_MATRIX4 *matrix, double x, double y, double z, double *tx, double *ty, double *tz)
294
*tx = x*matrix->coeff[0][0] + y*matrix->coeff[0][1]
295
+ z*matrix->coeff[0][2] + matrix->coeff[0][3];
296
*ty = x*matrix->coeff[1][0] + y*matrix->coeff[1][1]
297
+ z*matrix->coeff[1][2] + matrix->coeff[1][3];
298
*tz = x*matrix->coeff[2][0] + y*matrix->coeff[2][1]
299
+ z*matrix->coeff[2][2] + matrix->coeff[2][3];
303
matrix4_color_hue(RS_MATRIX4 *mat, double rot)
313
if (rot==0.0) return;
315
matrix4_identity(&tmp);
317
/* rotate the grey vector into positive Z */
321
matrix4_xrotate(&tmp, xrs, xrc);
326
matrix4_yrotate(&tmp, yrs ,yrc);
328
/* shear the space to make the luminance plane horizontal */
329
matrix4_affine_transform_3dpoint(&tmp,RLUM,GLUM,BLUM,&lx,&ly,&lz);
332
matrix4_zshear(&tmp, zsx, zsy);
335
zrs = sin(rot*M_PI/180.0);
336
zrc = cos(rot*M_PI/180.0);
337
matrix4_zrotate(&tmp, zrs, zrc);
339
/* unshear the space to put the luminance plane back */
340
matrix4_zshear(&tmp, -zsx, -zsy);
342
/* rotate the grey vector back into place */
343
matrix4_yrotate(&tmp,-yrs,yrc);
344
matrix4_xrotate(&tmp,-xrs,xrc);
345
matrix4_multiply(mat,&tmp,mat);
349
matrix4_color_exposure(RS_MATRIX4 *mat, double exp)
351
double expcom = pow(2.0, exp);
352
mat->coeff[0][0] *= expcom;
353
mat->coeff[0][1] *= expcom;
354
mat->coeff[0][2] *= expcom;
355
mat->coeff[1][0] *= expcom;
356
mat->coeff[1][1] *= expcom;
357
mat->coeff[1][2] *= expcom;
358
mat->coeff[2][0] *= expcom;
359
mat->coeff[2][1] *= expcom;
360
mat->coeff[2][2] *= expcom;
365
matrix3_identity (RS_MATRIX3 *matrix)
367
static const RS_MATRIX3 identity = { { { 1.0, 0.0, 0.0 },
369
{ 0.0, 0.0, 1.0 } } };
375
matrix3_multiply(const RS_MATRIX3 *left, RS_MATRIX3 *right, RS_MATRIX3 *result)
381
for (i = 0; i < 3; i++)
383
t1 = left->coeff[i][0];
384
t2 = left->coeff[i][1];
385
t3 = left->coeff[i][2];
387
for (j = 0; j < 3; j++)
389
tmp.coeff[i][j] = t1 * right->coeff[0][j];
390
tmp.coeff[i][j] += t2 * right->coeff[1][j];
391
tmp.coeff[i][j] += t3 * right->coeff[2][j];
399
matrix3_weight(const RS_MATRIX3 *mat)
415
matrix3_to_matrix3int(RS_MATRIX3 *matrix, RS_MATRIX3Int *matrixi)
420
matrixi->coeff[a][b] = (int) (matrix->coeff[a][b] * (double) (1<<MATRIX_RESOLUTION));
426
Affine transformations
428
The following transformation matrix is used:
438
tx: x translation (offset)
439
ty: y translation (offset)
449
matrix3_affine_invert(RS_MATRIX3 *mat)
452
const double reverse_det = 1.0/(mat->coeff[0][0]*mat->coeff[1][1] - mat->coeff[0][1]*mat->coeff[1][0]);
453
matrix3_identity(&tmp);
454
tmp.coeff[0][0] = mat->coeff[1][1] * reverse_det;
455
tmp.coeff[0][1] = -mat->coeff[0][1] * reverse_det;
456
tmp.coeff[1][0] = -mat->coeff[1][0] * reverse_det;
457
tmp.coeff[1][1] = mat->coeff[0][0] * reverse_det;
458
tmp.coeff[2][0] = (mat->coeff[1][0]*mat->coeff[2][1] - mat->coeff[1][1]*mat->coeff[2][0])/
459
(mat->coeff[0][0]*mat->coeff[1][1] - mat->coeff[0][1]*mat->coeff[1][0]);
460
tmp.coeff[2][1] = -(mat->coeff[0][0]*mat->coeff[2][1] - mat->coeff[0][1]*mat->coeff[2][0])/
461
(mat->coeff[0][0]*mat->coeff[1][1] - mat->coeff[0][1]*mat->coeff[1][0]);
466
matrix3_affine_scale(RS_MATRIX3 *matrix, double xscale, double yscale)
469
matrix3_identity(&tmp);
470
tmp.coeff[0][0] *= xscale;
471
tmp.coeff[1][1] *= yscale;
472
matrix3_multiply(matrix, &tmp, matrix);
477
matrix3_affine_translate(RS_MATRIX3 *matrix, double xtrans, double ytrans)
479
matrix->coeff[2][0] += xtrans;
480
matrix->coeff[2][1] += ytrans;
485
matrix3_affine_rotate(RS_MATRIX3 *matrix, double degrees)
488
const double s = sin (degrees * M_PI / 180.0);
489
const double c = cos (degrees * M_PI / 180.0);
491
matrix3_identity(&tmp);
494
tmp.coeff[1][0] = -s;
496
matrix3_multiply(matrix, &tmp, matrix);
501
matrix3_affine_transform_point(RS_MATRIX3 *matrix, double x, double y, double *x2, double *y2)
503
const double x_tmp = x*matrix->coeff[0][0] + y*matrix->coeff[1][0] + matrix->coeff[2][0];
504
const double y_tmp = x*matrix->coeff[0][1] + y*matrix->coeff[1][1] + matrix->coeff[2][1];
511
matrix3_affine_transform_point_int(RS_MATRIX3 *matrix, int x, int y, int *x2, int *y2)
513
const int x_tmp = (int) (x*matrix->coeff[0][0] + y*matrix->coeff[1][0] + matrix->coeff[2][0]);
514
const int y_tmp = (int) (x*matrix->coeff[0][1] + y*matrix->coeff[1][1] + matrix->coeff[2][1]);
521
matrix3_affine_get_minmax(RS_MATRIX3 *matrix,
522
double *minx, double *miny,
523
double *maxx, double *maxy,
524
double x1, double y1,
525
double x2, double y2)
528
*minx = *miny = 100000.0;
531
matrix3_affine_transform_point(matrix, x1, y1, &x, &y);
532
if (x<*minx) *minx=x;
533
if (x>*maxx) *maxx=x;
534
if (y<*miny) *miny=y;
535
if (y>*maxy) *maxy=y;
536
matrix3_affine_transform_point(matrix, x2, y1, &x, &y);
537
if (x<*minx) *minx=x;
538
if (x>*maxx) *maxx=x;
539
if (y<*miny) *miny=y;
540
if (y>*maxy) *maxy=y;
541
matrix3_affine_transform_point(matrix, x1, y2, &x, &y);
542
if (x<*minx) *minx=x;
543
if (x>*maxx) *maxx=x;
544
if (y<*miny) *miny=y;
545
if (y>*maxy) *maxy=y;
546
matrix3_affine_transform_point(matrix, x2, y2, &x, &y);
547
if (x<*minx) *minx=x;
548
if (x>*maxx) *maxx=x;
549
if (y<*miny) *miny=y;
550
if (y>*maxy) *maxy=y;
556
* Interpolate an array of unsigned integers
557
* @param input_dataset An array of unsigned integers to be inperpolated
558
* @param input_length The length of the input array
559
* @param output_dataset An array of unsigned integers for output or NULL
560
* @param output_length The length of the output array
561
* @param max A pointer to an unsigned int or NULL
562
* @return the interpolated dataset
565
interpolate_dataset_int(unsigned int *input_dataset, unsigned int input_length, unsigned int *output_dataset, unsigned int output_length, unsigned int *max)
567
const double scale = ((double)input_length) / ((double)output_length);
568
int i, source1, source2;
570
float weight1, weight2;
572
if (output_dataset == NULL)
573
output_dataset = malloc(sizeof(unsigned int)*output_length);
575
for(i=0;i<output_length;i++)
577
source = ((float)i) * scale;
578
source1 = (int) floor(source);
580
weight1 = 1.0f - (source - floor(source));
581
weight2 = 1.0f - weight1;
582
output_dataset[i] = (unsigned int) (((float)input_dataset[source1]) * weight1
583
+ ((float)input_dataset[source2]) * weight2);
585
if (output_dataset[i] > (*max))
586
*max = output_dataset[i];
589
return output_dataset;