Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Annotation of /trunk/src/lib/common/image.c
ViewVC logotype

Annotation of /trunk/src/lib/common/image.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1640 - (view) (download) (as text)

1 : jhr 1115 /*! \file image.c
2 :     *
3 :     * \author John Reppy
4 : jhr 1232 *
5 :     * \brief code to support the loading of image data from Nrrd files.
6 : jhr 1115 */
7 :    
8 :     /*
9 : jhr 1232 * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu)
10 : jhr 1115 * All rights reserved.
11 :     */
12 :    
13 :     #include "Diderot/diderot.h"
14 :     #include <teem/nrrd.h>
15 :    
16 : jhr 1232 // we use double precision representations of the transforms here to
17 :     // improve robustness, even when the results are stored as single-precision
18 :     typedef double Matrix2x2_t[4];
19 :     typedef double Matrix3x3_t[9];
20 :     typedef double Matrix4x4_t[16];
21 :    
22 :     typedef double Vec2_t[2];
23 :     typedef double Vec3_t[3];
24 :    
25 :     static void PrintMat2x2 (const char *title, Matrix2x2_t m)
26 : jhr 1115 {
27 : jhr 1301 #define M(i) m[i]
28 : jhr 1115 printf ("%s @ %p:\n", title, (void *)m);
29 :     for (int i = 0; i < 2; i++) {
30 : jhr 1301 int j = 2*i;
31 :     printf (" [ %6lf %6lf ]\n", M(j+0), M(j+1));
32 : jhr 1115 }
33 :     #undef M
34 :    
35 :     }
36 :    
37 : jhr 1232 static void PrintMat3x3 (const char *title, Matrix3x3_t m)
38 : jhr 1115 {
39 : jhr 1301 #define M(i) m[i]
40 : jhr 1115 printf ("%s @ %p:\n", title, (void *)m);
41 :     for (int i = 0; i < 3; i++) {
42 : jhr 1301 int j = 3*i;
43 :     printf (" [ %6lf %6lf %6lf ]\n", M(j+0), M(j+1), M(j+2));
44 : jhr 1115 }
45 :     #undef M
46 :    
47 :     }
48 :    
49 : jhr 1232 static void PrintMat4x4 (const char *title, Matrix4x4_t m)
50 : jhr 1115 {
51 : jhr 1301 #define M(i) m[i]
52 : jhr 1115 printf ("%s @ %p:\n", title, (void *)m);
53 :     for (int i = 0; i < 4; i++) {
54 : jhr 1301 int j = 4*i;
55 :     printf (" [ %6lf %6lf %6lf %6lf ]\n", M(j+0), M(j+1), M(j+2), M(j+3));
56 : jhr 1115 }
57 :     #undef M
58 :    
59 :     }
60 :    
61 :     /* Loading transfomation information from Nrrd files */
62 :    
63 : jhr 1232 static void LoadTransform1D (Nrrd *nin, double *s, double *t)
64 : jhr 1115 {
65 :     // compute the offset to the first space axis
66 :     int base = nin->dim - nin->spaceDim;
67 :    
68 :     // Image axis Scaling and Rotation
69 :     *s = nin->axis[base+0].spaceDirection[0];
70 :    
71 :     // Image location
72 :     *t = nin->spaceOrigin[0];
73 :     }
74 :    
75 : jhr 1232 static void LoadTransform2D (Nrrd *nin, Matrix2x2_t m, Vec2_t t)
76 : jhr 1115 {
77 : jhr 1301 #define M(i,j) m[(i)*2+(j)]
78 : jhr 1115
79 :     // compute the offset to the first space axis
80 :     int base = nin->dim - nin->spaceDim;
81 :    
82 :     // Image axis Scaling and Rotation
83 :     M(0,0) = nin->axis[base+0].spaceDirection[0];
84 :     M(1,0) = nin->axis[base+0].spaceDirection[1];
85 :     M(0,1) = nin->axis[base+1].spaceDirection[0];
86 :     M(1,1) = nin->axis[base+1].spaceDirection[1];
87 :    
88 :     // Image location
89 : jhr 1232 t[0] = nin->spaceOrigin[0];
90 :     t[1] = nin->spaceOrigin[1];
91 : jhr 1115
92 :     #undef M
93 :     }
94 :    
95 : jhr 1232 static void LoadTransform3D (Nrrd *nin, Matrix3x3_t m, Vec3_t t)
96 : jhr 1115 {
97 : jhr 1301 #define M(i,j) m[3*(i)+(j)]
98 : jhr 1115
99 :     // compute the offset to the first space axis
100 :     int base = nin->dim - nin->spaceDim;
101 :    
102 :     // Image axis Scaling and Rotation
103 :     M(0,0) = nin->axis[base+0].spaceDirection[0];
104 :     M(1,0) = nin->axis[base+0].spaceDirection[1];
105 :     M(2,0) = nin->axis[base+0].spaceDirection[2];
106 :     M(0,1) = nin->axis[base+1].spaceDirection[0];
107 :     M(1,1) = nin->axis[base+1].spaceDirection[1];
108 :     M(2,1) = nin->axis[base+1].spaceDirection[2];
109 :     M(0,2) = nin->axis[base+2].spaceDirection[0];
110 :     M(1,2) = nin->axis[base+2].spaceDirection[1];
111 :     M(2,2) = nin->axis[base+2].spaceDirection[2];
112 :    
113 :     // Image location
114 : jhr 1232 t[0] = nin->spaceOrigin[0];
115 :     t[1] = nin->spaceOrigin[1];
116 :     t[2] = nin->spaceOrigin[2];
117 : jhr 1115
118 :     #undef M
119 :     }
120 :    
121 :    
122 :     /* Transformation matrix operations */
123 :    
124 : jhr 1232 STATIC_INLINE double Det2 (
125 :     double a, double b,
126 :     double c, double d)
127 : jhr 1115 {
128 :     return (a*d - b*c);
129 :     }
130 :    
131 : jhr 1232 STATIC_INLINE double Det3 (
132 :     double a, double b, double c,
133 :     double d, double e, double f,
134 :     double g, double h, double i)
135 : jhr 1115 {
136 :     return (a*e*i
137 : jhr 1301 + d*h*c
138 :     + g*b*f
139 :     - g*e*c
140 :     - d*b*i
141 :     - a*h*f);
142 : jhr 1115 }
143 :    
144 : jhr 1232 static double DetM3x3 (Matrix3x3_t m)
145 : jhr 1115 {
146 : jhr 1301 #define M(i) m[i]
147 : jhr 1115 return Det3(M(0), M(1), M(2),
148 : jhr 1301 M(3), M(4), M(5),
149 :     M(6), M(7), M(8));
150 : jhr 1115 #undef M
151 :     }
152 :    
153 : jhr 1232 static double DetM4x4 (Matrix4x4_t m)
154 : jhr 1115 {
155 : jhr 1301 #define M(i) m[i]
156 :     return (M( 0) * Det3(M( 5), M( 6), M( 7),
157 :     M( 9), M(10), M(11),
158 :     M(13), M(14), M(15))
159 :     - M( 1) * Det3(M( 4), M( 6), M( 7),
160 :     M( 8), M(10), M(11),
161 :     M(12), M(14), M(15))
162 :     + M( 2) * Det3(M( 4), M( 5), M( 7),
163 :     M( 8), M( 9), M(11),
164 :     M(12), M(13), M(15))
165 :     - M( 3) * Det3(M( 4), M( 5), M( 6),
166 :     M( 8), M( 9), M(10),
167 :     M(12), M(13), M(14)));
168 : jhr 1115 #undef M
169 :    
170 :     }
171 :    
172 :     /*! \brief compute the inverse of \arg m, storing the result in \arg i.
173 :     * \param m the matrix to invert
174 :     * \param i the inverted matrix
175 :     */
176 : jhr 1232 static void InvertM2x2 (Matrix2x2_t i, Matrix2x2_t m)
177 : jhr 1115 {
178 : jhr 1301 #define M(i) m[i]
179 :     #define I(j) i[j]
180 :     double scale = 1.0 / Det2(M(0), M(1), M(2), M(3));
181 : jhr 1115
182 : jhr 1301 I(0) = scale * M(3);
183 :     I(1) = -scale * M(1);
184 :     I(2) = -scale * M(2);
185 :     I(3) = scale * M(0);
186 : jhr 1115 #undef M
187 :     #undef I
188 :     }
189 :    
190 :     /*! \brief compute the inverse of \arg m, storing the result in \arg i.
191 :     * \param m the matrix to invert
192 :     * \param i the inverted matrix
193 :     */
194 : jhr 1232 static void InvertM3x3 (Matrix3x3_t i, Matrix3x3_t m)
195 : jhr 1115 {
196 : jhr 1301 double scale = 1.0 / DetM3x3(m);
197 : jhr 1115
198 : jhr 1301 #define M(i) m[i]
199 :     #define I(j) i[j]
200 :     I(0) = scale * Det2 (M(4), M(5), M(7), M(8));
201 :     I(1) = scale * Det2 (M(2), M(1), M(8), M(7));
202 :     I(2) = scale * Det2 (M(1), M(2), M(4), M(5));
203 :     I(3) = scale * Det2 (M(5), M(3), M(8), M(6));
204 :     I(4) = scale * Det2 (M(0), M(2), M(6), M(8));
205 :     I(5) = scale * Det2 (M(2), M(0), M(5), M(3));
206 :     I(6) = scale * Det2 (M(3), M(4), M(6), M(7));
207 :     I(7) = scale * Det2 (M(1), M(0), M(7), M(6));
208 :     I(8) = scale * Det2 (M(0), M(1), M(3), M(4));
209 : jhr 1115 #undef M
210 :     #undef I
211 :     }
212 :    
213 :     /*! \brief compute the inverse of \arg m, storing the result in \arg i.
214 :     * \param m the matrix to invert
215 :     * \param i the inverted matrix
216 :     */
217 : jhr 1232 static void InvertM4x4 (Matrix4x4_t i, Matrix4x4_t m)
218 : jhr 1115 {
219 : jhr 1301 double scale = 1.0 / DetM4x4(m);
220 : jhr 1115
221 : jhr 1301 #define M(i) m[i]
222 :     #define I(j) i[j]
223 :     I( 0) = Det3(M( 5),M( 6),M( 7),
224 :     M( 9),M(10),M(11),
225 :     M(13),M(14),M(15)) * scale;
226 :    
227 :     I( 1) = -Det3(M( 1),M( 2),M( 3),
228 :     M( 9),M(10),M(11),
229 :     M(13),M(14),M(15)) * scale;
230 :    
231 :     I( 2) = Det3(M( 1),M( 2),M( 3),
232 :     M( 5),M( 6),M( 7),
233 :     M(13),M(14),M(15)) * scale;
234 :    
235 :     I( 3) = -Det3(M( 1),M( 2),M( 3),
236 :     M( 5),M( 6),M( 7),
237 :     M( 9),M(10),M(11)) * scale;
238 :    
239 :     I( 4) = -Det3(M( 4),M( 6),M( 7),
240 :     M( 8),M(10),M(11),
241 :     M(12),M(14),M(15)) * scale;
242 :    
243 :     I( 5) = Det3(M( 0),M( 2),M( 3),
244 :     M( 8),M(10),M(11),
245 :     M(12),M(14),M(15)) * scale;
246 :    
247 :     I( 6) = -Det3(M( 0),M( 2),M( 3),
248 :     M( 4),M( 6),M( 7),
249 :     M(12),M(14),M(15)) * scale;
250 :    
251 :     I( 7) = Det3(M( 0),M( 2),M( 3),
252 :     M( 4),M( 6),M( 7),
253 :     M( 8),M(10),M(11)) * scale;
254 :    
255 :     I( 8) = Det3(M( 4),M( 5),M( 7),
256 :     M( 8),M( 9),M(11),
257 :     M(12),M(13),M(15)) * scale;
258 :    
259 :     I( 9) = -Det3(M( 0),M( 1),M( 3),
260 :     M( 8),M( 9),M(11),
261 :     M(12),M(13),M(15)) * scale;
262 :    
263 :     I(10) = Det3(M( 0),M( 1),M( 3),
264 :     M( 4),M( 5),M( 7),
265 :     M(12),M(13),M(15)) * scale;
266 :    
267 :     I(11) = -Det3(M( 0),M( 1),M( 3),
268 :     M( 4),M( 5),M( 7),
269 :     M( 8),M( 9),M(11)) * scale;
270 :    
271 :     I(12) = -Det3(M( 4),M( 5),M( 6),
272 :     M( 8),M( 9),M(10),
273 :     M(12),M(13),M(14)) * scale;
274 :    
275 :     I(13) = Det3(M( 0),M( 1),M( 2),
276 :     M( 8),M( 9),M(10),
277 :     M(12),M(13),M(14)) * scale;
278 :    
279 :     I(14) = -Det3(M( 0),M( 1),M( 2),
280 :     M( 4),M( 5),M( 6),
281 :     M(12),M(13),M(14)) * scale;
282 :    
283 :     I(15) = Det3(M( 0),M( 1),M( 2),
284 :     M( 4),M( 5),M( 6),
285 :     M( 8),M( 9),M(10)) * scale;
286 : jhr 1115 #undef M
287 :     #undef I
288 :     }
289 :    
290 :     static Nrrd *LoadNrrdFile (const char *filename)
291 :     {
292 :     /* create a nrrd; at this point this is just an empty container */
293 :     Nrrd *nin = nrrdNew();
294 :    
295 :     /* read in the nrrd from file */
296 :     if (nrrdLoad(nin, filename, NULL)) {
297 : jhr 1301 char *err = biffGetDone(NRRD);
298 :     fprintf (stderr, "Diderot: trouble reading \"%s\":\n%s", filename, err);
299 :     free (err);
300 :     return NULL;
301 : jhr 1115 }
302 :    
303 :     return nin;
304 :    
305 :     }
306 :    
307 :     STATIC_INLINE bool CheckAxis (Nrrd *nin, int i)
308 :     {
309 :     return (nin->axis[i].kind != nrrdKindSpace);
310 :     }
311 :    
312 :     /* load image data from Nrrd files */
313 :     Status_t Diderot_LoadImage1D (Diderot_string_t name, Diderot_image1D_t **imgOut)
314 :     {
315 :     Nrrd *nin = LoadNrrdFile (name);
316 :     Diderot_image1D_t *img = (Diderot_image1D_t *)malloc(sizeof(Diderot_image1D_t));
317 :    
318 :     // compute the offset to the first space axis
319 :     int base = nin->dim - nin->spaceDim;
320 :    
321 : jhr 1444 // FIXME: we should also be checking the shape of the voxels and the type of the samples.
322 : jhr 1115 // check that the image format is what we expect
323 :     if (nin->spaceDim != 1) {
324 : jhr 1301 fprintf(stderr, "nrrd file \"%s\" has unexpected dimension %d, expected 1\n",
325 :     name, nin->spaceDim);
326 :     return DIDEROT_FAIL;
327 : jhr 1115 }
328 :     else if (CheckAxis(nin, base)) {
329 : jhr 1301 fprintf(stderr,
330 :     "nrrd file \"%s\" has unexpected axis structure: %s\n",
331 :     name,
332 :     airEnumStr(nrrdKind, nin->axis[base].kind));
333 :     return DIDEROT_FAIL;
334 : jhr 1115 }
335 :    
336 :     img->dim = 1;
337 :     img->size[0] = nin->axis[base+0].size;
338 :     img->data = nin->data;
339 : jhr 1640 img->dataSzb = nrrdElementSize(nin) * nrrdElementNumber(nin);
340 : jhr 1115
341 : jhr 1301 //printf("LoadImage \"%s\": space dim = 1, axes = <%d>\n",
342 :     //name, img->size[base+0]);
343 : jhr 1115
344 :     // from the Nrrd file, we load the scaling and translation
345 : jhr 1232 double s, t;
346 : jhr 1115 LoadTransform1D (nin, &s, &t);
347 :    
348 : jhr 1232 img->s = (Diderot_real_t)(1.0 / s);
349 :     img->t = (Diderot_real_t)(-t / s);
350 : jhr 1115
351 :     *imgOut = img;
352 :     return DIDEROT_OK;
353 :     }
354 :    
355 :     Status_t Diderot_LoadImage2D (Diderot_string_t name, Diderot_image2D_t **imgOut)
356 :     {
357 :     Nrrd *nin = LoadNrrdFile (name);
358 :     Diderot_image2D_t *img = (Diderot_image2D_t *)malloc(sizeof(Diderot_image2D_t));
359 :    
360 :     // compute the offset to the first space axis
361 :     int base = nin->dim - nin->spaceDim;
362 :    
363 :     // check that the image format is what we expect
364 :     if (nin->spaceDim != 2) {
365 : jhr 1301 fprintf(stderr, "nrrd file \"%s\" has unexpected dimension %d, expected 2\n",
366 :     name, nin->spaceDim);
367 :     return DIDEROT_FAIL;
368 : jhr 1115 }
369 :     else if (CheckAxis(nin, base) || CheckAxis(nin, base+1)) {
370 : jhr 1301 fprintf(stderr,
371 :     "nrrd file \"%s\" has unexpected axis structure: %s %s\n",
372 :     name,
373 :     airEnumStr(nrrdKind, nin->axis[base].kind),
374 :     airEnumStr(nrrdKind, nin->axis[base+1].kind));
375 :     return DIDEROT_FAIL;
376 : jhr 1115 }
377 :    
378 :     img->dim = 2;
379 :     img->size[0] = nin->axis[base+0].size;
380 :     img->size[1] = nin->axis[base+1].size;
381 :     img->data = nin->data;
382 : jhr 1640 img->dataSzb = nrrdElementSize(nin) * nrrdElementNumber(nin);
383 : jhr 1115
384 : jhr 1301 //printf("LoadImage \"%s\": space dim = 2, axes = <%d, %d>\n",
385 :     //name, img->size[0], img->size[1]);
386 : jhr 1115
387 :     // from the Nrrd file, we load the affine image-to-world transform matrix
388 : jhr 1301 Matrix2x2_t m; // rotation and scaling
389 :     Vec2_t t; // translation part of the transform
390 : jhr 1232 LoadTransform2D (nin, m, t);
391 : jhr 1115
392 : jhr 1301 //PrintMat2x2("m", m);
393 :     //printf("t = <%f, %f>\n", t[0], t[1]);
394 : jhr 1115
395 :     // compute inverse of m, which is the transform from the world basis to the image basis
396 : jhr 1232 Matrix2x2_t mInv;
397 :     InvertM2x2 (mInv, m);
398 : jhr 1301 //PrintMat2x2("w2i", mInv);
399 : jhr 1115
400 : jhr 1232 // copy results into the image data structure
401 :     for (int i = 0; i < 2; i++) {
402 : jhr 1301 for (int j = 0; j < 2; j++) {
403 :     img->w2i[i].r[j] = mInv[2*i+j];
404 :     }
405 : jhr 1232 }
406 : jhr 1640 transpose2x2 (img->w2iT, img->w2i);
407 : jhr 1232 Diderot_vec2_t tVec = vec2(t[0], t[1]);
408 :     img->tVec = -mulMat2x2Vec2(img->w2i, tVec); // inv([M t]) = [inv(M) -inv(M)t]
409 : jhr 1301 //printf("tVec = <%f, %f>\n", ((union2f_t)img->tVec).r[0], ((union2f_t)img->tVec).r[1]);
410 : jhr 1115
411 :     *imgOut = img;
412 :     return DIDEROT_OK;
413 :     }
414 :    
415 :     Status_t Diderot_LoadImage3D (Diderot_string_t name, Diderot_image3D_t **imgOut)
416 :     {
417 :     Nrrd *nin = LoadNrrdFile (name);
418 :    
419 :     // compute the offset to the first space axis
420 :     int base = nin->dim - nin->spaceDim;
421 :    
422 :     // check that the image format is what we expect
423 :     if (nin->spaceDim != 3) {
424 : jhr 1301 fprintf(stderr, "nrrd file \"%s\" has unexpected dimension %d, expected 3\n",
425 :     name, nin->spaceDim);
426 :     return DIDEROT_FAIL;
427 : jhr 1115 }
428 :     else if (CheckAxis(nin, base) || CheckAxis(nin, base+1) || CheckAxis(nin, base+2)) {
429 : jhr 1301 fprintf(stderr,
430 :     "nrrd file \"%s\" has unexpected axis structure: %s %s %s\n",
431 :     name,
432 :     airEnumStr(nrrdKind, nin->axis[base].kind),
433 :     airEnumStr(nrrdKind, nin->axis[base+1].kind),
434 :     airEnumStr(nrrdKind, nin->axis[base+2].kind));
435 :     return DIDEROT_FAIL;
436 : jhr 1115 }
437 :    
438 :     Diderot_image3D_t *img = (Diderot_image3D_t *)malloc(sizeof(Diderot_image3D_t));
439 :    
440 :     img->dim = 3;
441 :     img->size[0] = nin->axis[base+0].size;
442 :     img->size[1] = nin->axis[base+1].size;
443 :     img->size[2] = nin->axis[base+2].size;
444 :     img->data = nin->data;
445 : jhr 1640 img->dataSzb = nrrdElementSize(nin) * nrrdElementNumber(nin);
446 : jhr 1115
447 : jhr 1301 //printf("LoadImage \"%s\": space dim = 3, axes = <%d, %d, %d>\n",
448 :     //name, img->size[0], img->size[1], img->size[2]);
449 : jhr 1115
450 :     // from the Nrrd file, we load the affine image-to-world transform matrix
451 : jhr 1301 Matrix3x3_t m; // rotation and scaling
452 :     Vec3_t t; // translation part of the transform
453 : jhr 1232 LoadTransform3D (nin, m, t);
454 : jhr 1115
455 : jhr 1301 //PrintMat3x3("m", m);
456 :     //printf("t = <%f, %f, %f>\n", t[0], t[1], t[2]);
457 : jhr 1115
458 :     // compute inverse of m, which is the transform from the world basis to the image basis
459 : jhr 1232 Matrix3x3_t mInv;
460 :     InvertM3x3 (mInv, m);
461 : jhr 1301 //PrintMat3x3("w2i", mInv);
462 : jhr 1115
463 : jhr 1232 // copy results into the image data structure
464 :     for (int i = 0; i < 3; i++) {
465 : jhr 1301 for (int j = 0; j < 3; j++) {
466 :     img->w2i[i].r[j] = mInv[3*i+j];
467 :     }
468 : jhr 1232 }
469 : jhr 1640 transpose3x3 (img->w2iT, img->w2i);
470 : jhr 1232 Diderot_vec3_t tVec = vec3(t[0], t[1], t[2]);
471 :     img->tVec = -mulMat3x3Vec3(img->w2i, tVec); // inv([M t]) = [inv(M) -inv(M)t]
472 : jhr 1301 //printf("tVec = <%f, %f, %f>\n", ((Diderot_union3_t)img->tVec).r[0], ((Diderot_union3_t)img->tVec).r[1], ((Diderot_union3_t)img->tVec).r[2]);
473 : jhr 1115
474 :     *imgOut = img;
475 :     return DIDEROT_OK;
476 :     }

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0