1 |
|
|
/* |
2 |
|
|
Teem: Tools to process and visualize scientific data and images . |
3 |
|
|
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
4 |
|
|
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
5 |
|
|
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
6 |
|
|
|
7 |
|
|
This library is free software; you can redistribute it and/or |
8 |
|
|
modify it under the terms of the GNU Lesser General Public License |
9 |
|
|
(LGPL) as published by the Free Software Foundation; either |
10 |
|
|
version 2.1 of the License, or (at your option) any later version. |
11 |
|
|
The terms of redistributing and/or modifying this software also |
12 |
|
|
include exceptions to the LGPL that facilitate static linking. |
13 |
|
|
|
14 |
|
|
This library is distributed in the hope that it will be useful, |
15 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 |
|
|
Lesser General Public License for more details. |
18 |
|
|
|
19 |
|
|
You should have received a copy of the GNU Lesser General Public License |
20 |
|
|
along with this library; if not, write to Free Software Foundation, Inc., |
21 |
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "moss.h" |
25 |
|
|
#include "privateMoss.h" |
26 |
|
|
|
27 |
|
|
/* |
28 |
|
|
|
29 |
|
|
0 1 2 |
30 |
|
|
3 4 5 |
31 |
|
|
6 7 8 |
32 |
|
|
|
33 |
|
|
a c tx |
34 |
|
|
b d ty |
35 |
|
|
0 0 1 |
36 |
|
|
|
37 |
|
|
0 1 2 |
38 |
|
|
3 4 5 |
39 |
|
|
|
40 |
|
|
*/ |
41 |
|
|
|
42 |
|
|
void |
43 |
|
|
mossMatPrint (FILE *f, double *mat) { |
44 |
|
|
|
45 |
|
|
fprintf(f, "% 15.7f % 15.7f % 15.7f\n", |
46 |
|
|
(float)mat[0], (float)mat[1], (float)mat[2]); |
47 |
|
|
fprintf(f, "% 15.7f % 15.7f % 15.7f\n", |
48 |
|
|
(float)mat[3], (float)mat[4], (float)mat[5]); |
49 |
|
|
} |
50 |
|
|
|
51 |
|
|
double * |
52 |
|
|
mossMatRightMultiply (double *_mat, double *_x) { |
53 |
|
|
double mat[9], x[9]; |
54 |
|
|
|
55 |
|
|
MOSS_MAT_6TO9(x, _x); |
56 |
|
|
MOSS_MAT_6TO9(mat, _mat); |
57 |
|
|
ell_3m_pre_mul_d(mat, x); |
58 |
|
|
MOSS_MAT_9TO6(_mat, mat); |
59 |
|
|
return _mat; |
60 |
|
|
} |
61 |
|
|
|
62 |
|
|
double * |
63 |
|
|
mossMatLeftMultiply (double *_mat, double *_x) { |
64 |
|
|
double mat[9], x[9]; |
65 |
|
|
|
66 |
|
|
MOSS_MAT_6TO9(x, _x); |
67 |
|
|
MOSS_MAT_6TO9(mat, _mat); |
68 |
|
|
ell_3m_post_mul_d(mat, x); |
69 |
|
|
MOSS_MAT_9TO6(_mat, mat); |
70 |
|
|
return _mat; |
71 |
|
|
} |
72 |
|
|
|
73 |
|
|
double * |
74 |
|
|
mossMatInvert (double *inv, double *mat) { |
75 |
|
|
double inv9[9], mat9[9]; |
76 |
|
|
|
77 |
|
|
MOSS_MAT_6TO9(mat9, mat); |
78 |
|
|
ell_3m_inv_d(inv9, mat9); |
79 |
|
|
MOSS_MAT_9TO6(inv, inv9); |
80 |
|
|
return inv; |
81 |
|
|
} |
82 |
|
|
|
83 |
|
|
double * |
84 |
|
|
mossMatIdentitySet (double *mat) { |
85 |
|
|
|
86 |
|
|
MOSS_MAT_SET(mat, 1, 0, 0, 0, 1, 0); |
87 |
|
|
return mat; |
88 |
|
|
} |
89 |
|
|
|
90 |
|
|
double * |
91 |
|
|
mossMatTranslateSet (double *mat, double tx, double ty) { |
92 |
|
|
|
93 |
|
|
MOSS_MAT_SET(mat, 1, 0, tx, 0, 1, ty); |
94 |
|
|
return mat; |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
double * |
98 |
|
|
mossMatRotateSet (double *mat, double angle) { |
99 |
|
|
|
100 |
|
|
angle *= AIR_PI/180.0; |
101 |
|
|
MOSS_MAT_SET(mat, cos(angle), -sin(angle), 0, sin(angle), cos(angle), 0); |
102 |
|
|
return mat; |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
double * |
106 |
|
|
mossMatFlipSet (double *mat, double angle) { |
107 |
|
|
double rot[6], flip[6]; |
108 |
|
|
|
109 |
|
|
MOSS_MAT_SET(flip, -1, 0, 0, 0, 1, 0); |
110 |
|
|
mossMatIdentitySet(mat); |
111 |
|
|
mossMatLeftMultiply(mat, mossMatRotateSet(rot, -angle)); |
112 |
|
|
mossMatLeftMultiply(mat, flip); |
113 |
|
|
mossMatLeftMultiply(mat, mossMatRotateSet(rot, angle)); |
114 |
|
|
return mat; |
115 |
|
|
} |
116 |
|
|
|
117 |
|
|
double * |
118 |
|
|
mossMatShearSet (double *mat, double angleFixed, double amount) { |
119 |
|
|
double rot[6], shear[6]; |
120 |
|
|
|
121 |
|
|
MOSS_MAT_SET(shear, 1, amount, 0, 0, 1, 0); |
122 |
|
|
mossMatIdentitySet(mat); |
123 |
|
|
mossMatLeftMultiply(mat, mossMatRotateSet(rot, -angleFixed)); |
124 |
|
|
mossMatLeftMultiply(mat, shear); |
125 |
|
|
mossMatLeftMultiply(mat, mossMatRotateSet(rot, angleFixed)); |
126 |
|
|
return mat; |
127 |
|
|
} |
128 |
|
|
|
129 |
|
|
double * |
130 |
|
|
mossMatScaleSet (double *mat, double sx, double sy) { |
131 |
|
|
|
132 |
|
|
MOSS_MAT_SET(mat, sx, 0, 0, 0, sy, 0); |
133 |
|
|
return mat; |
134 |
|
|
} |
135 |
|
|
|
136 |
|
|
void |
137 |
|
|
mossMatApply (double *ox, double *oy, double *mat, double ix, double iy) { |
138 |
|
|
|
139 |
|
|
*ox = mat[0]*ix + mat[1]*iy + mat[2]; |
140 |
|
|
*oy = mat[3]*ix + mat[4]*iy + mat[5]; |
141 |
|
|
} |
142 |
|
|
|
143 |
|
|
int |
144 |
|
|
mossLinearTransform (Nrrd *nout, Nrrd *nin, float *bg, |
145 |
|
|
double *mat, mossSampler *msp, |
146 |
|
|
double xMin, double xMax, |
147 |
|
|
double yMin, double yMax, |
148 |
|
|
int xSize, int ySize) { |
149 |
|
|
static const char me[]="mossLinearTransform"; |
150 |
|
|
int ncol, xi, yi, ci, ax0, xCent, yCent; |
151 |
|
|
float *val, (*ins)(void *v, size_t I, float f), (*clamp)(float val); |
152 |
|
|
double inv[6], xInPos, xOutPos, yInPos, yOutPos; |
153 |
|
|
|
154 |
|
|
if (!(nout && nin && mat && msp && !mossImageCheck(nin))) { |
155 |
|
|
biffAddf(MOSS, "%s: got NULL pointer or bad image", me); |
156 |
|
|
return 1; |
157 |
|
|
} |
158 |
|
|
if (mossSamplerImageSet(msp, nin, bg) || mossSamplerUpdate(msp)) { |
159 |
|
|
biffAddf(MOSS, "%s: trouble with sampler", me); |
160 |
|
|
return 1; |
161 |
|
|
} |
162 |
|
|
if (!( xMin != xMax && yMin != yMax && xSize > 1 && ySize > 1 )) { |
163 |
|
|
biffAddf(MOSS, "%s: bad args: {x,y}Min == {x,y}Max or {x,y}Size <= 1", me); |
164 |
|
|
return 1; |
165 |
|
|
} |
166 |
|
|
ax0 = MOSS_AXIS0(nin); |
167 |
|
|
if (!( AIR_EXISTS(nin->axis[ax0+0].min) |
168 |
|
|
&& AIR_EXISTS(nin->axis[ax0+0].max) |
169 |
|
|
&& AIR_EXISTS(nin->axis[ax0+1].min) |
170 |
|
|
&& AIR_EXISTS(nin->axis[ax0+1].max) )) { |
171 |
|
|
biffAddf(MOSS, "%s: input axis min,max not set on axes %d and %d", me, |
172 |
|
|
ax0+0, ax0+1); |
173 |
|
|
return 1; |
174 |
|
|
} |
175 |
|
|
|
176 |
|
|
ncol = MOSS_NCOL(nin); |
177 |
|
|
if (mossImageAlloc(nout, nin->type, xSize, ySize, ncol)) { |
178 |
|
|
biffAddf(MOSS, "%s: ", me); return 1; |
179 |
|
|
} |
180 |
|
|
val = (float*)calloc(ncol, sizeof(float)); |
181 |
|
|
if (nrrdCenterUnknown == nout->axis[ax0+0].center) |
182 |
|
|
nout->axis[ax0+0].center = _mossCenter(nin->axis[ax0+0].center); |
183 |
|
|
xCent = nout->axis[ax0+0].center; |
184 |
|
|
if (nrrdCenterUnknown == nout->axis[ax0+1].center) |
185 |
|
|
nout->axis[ax0+1].center = _mossCenter(nin->axis[ax0+1].center); |
186 |
|
|
yCent = nout->axis[ax0+1].center; |
187 |
|
|
nout->axis[ax0+0].min = xMin; |
188 |
|
|
nout->axis[ax0+0].max = xMax; |
189 |
|
|
nout->axis[ax0+1].min = yMin; |
190 |
|
|
nout->axis[ax0+1].max = yMax; |
191 |
|
|
ins = nrrdFInsert[nin->type]; |
192 |
|
|
clamp = nrrdFClamp[nin->type]; |
193 |
|
|
|
194 |
|
|
if (mossSamplerSample(val, msp, 0, 0)) { |
195 |
|
|
biffAddf(MOSS, "%s: trouble in sampler", me); |
196 |
|
|
free(val); return 1; |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
mossMatInvert(inv, mat); |
200 |
|
|
for (yi=0; yi<ySize; yi++) { |
201 |
|
|
yOutPos = NRRD_POS(yCent, yMin, yMax, ySize, yi); |
202 |
|
|
for (xi=0; xi<xSize; xi++) { |
203 |
|
|
/* |
204 |
|
|
mossVerbose = ( (36 == xi && 72 == yi) || |
205 |
|
|
(37 == xi && 73 == yi) || |
206 |
|
|
(105 == xi && 175 == yi) ); |
207 |
|
|
*/ |
208 |
|
|
xOutPos = NRRD_POS(xCent, xMin, xMax, xSize, xi); |
209 |
|
|
mossMatApply(&xInPos, &yInPos, inv, xOutPos, yOutPos); |
210 |
|
|
xInPos = NRRD_IDX(xCent, nin->axis[ax0+0].min, nin->axis[ax0+0].max, |
211 |
|
|
nin->axis[ax0+0].size, xInPos); |
212 |
|
|
yInPos = NRRD_IDX(yCent, nin->axis[ax0+1].min, nin->axis[ax0+1].max, |
213 |
|
|
nin->axis[ax0+1].size, yInPos); |
214 |
|
|
mossSamplerSample(val, msp, xInPos, yInPos); |
215 |
|
|
for (ci=0; ci<ncol; ci++) { |
216 |
|
|
ins(nout->data, ci + ncol*(xi + xSize*yi), clamp(val[ci])); |
217 |
|
|
} |
218 |
|
|
} |
219 |
|
|
} |
220 |
|
|
|
221 |
|
|
free(val); |
222 |
|
|
return 0; |
223 |
|
|
} |