1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_ImageSequence_HH
21 #define MIRTK_ImageSequence_HH
22 
23 #include "mirtk/ImageSequence.h"
24 #include "mirtk/Stream.h"
25 
26 
27 namespace mirtk {
28 
29 
30 ////////////////////////////////////////////////////////////////////////////////
31 // Inline definitions of ImageChannel
32 ////////////////////////////////////////////////////////////////////////////////
33 
34 // -----------------------------------------------------------------------------
35 template <>
ImageChannel(ImageType * image,bool manage,bool copy)36 ImageChannel<irtkBaseImage>::ImageChannel(ImageType *image, bool manage, bool copy)
37 :
38   _Image (image),
39   _Manage(manage)
40 {
41   if (image) {
42     if (image->GetT() > 0) {
43       cerr << "ImageChannel::ImageChannel: Channel image cannot have fourth dimension" << endl;
44       exit(1);
45     }
46     if (copy && !manage) {
47       _Image  = BaseImage::New(image);
48       _Manage = true;
49     }
50   }
51 }
52 
53 // -----------------------------------------------------------------------------
54 template <class TImage>
ImageChannel(ImageType * image,bool manage,bool copy)55 ImageChannel<TImage>::ImageChannel(ImageType *image, bool manage, bool copy)
56 :
57   _Image (image),
58   _Manage(manage)
59 {
60   if (image) {
61     if (image->GetT() > 0) {
62       cerr << "ImageChannel::ImageChannel: Channel image cannot have fourth dimension" << endl;
63       exit(1);
64     }
65     if (copy && !manage) {
66       _Image  = new ImageType(image);
67       _Manage = true;
68     }
69   }
70 }
71 
72 // -----------------------------------------------------------------------------
73 template <class TImage>
operator =(const ImageChannel<TImage> & other)74 ImageChannel<TImage> &ImageChannel<TImage>::operator =(const ImageChannel<TImage> &other)
75 {
76   if (_Manage) delete _Image;
77   _Image  = other._Image;
78   _Manage = other._Manage;
79   other._Manage = false; // take over ownership
80   return *this;
81 }
82 
83 // -----------------------------------------------------------------------------
84 template <class TImage>
ImageChannel(const ImageChannel<TImage> & other)85 ImageChannel<TImage>::ImageChannel(const ImageChannel<TImage> &other)
86 :
87   Object(other),
88   _Image (NULL),
89   _Manage(false)
90 {
91   *this = other;
92 }
93 
94 // -----------------------------------------------------------------------------
95 template <> template <class TOtherImage>
operator =(const ImageChannel<TOtherImage> & other)96 ImageChannel<irtkBaseImage> &ImageChannel<irtkBaseImage>::operator =(const ImageChannel<TOtherImage> &other)
97 {
98   if (_Manage) delete _Image;
99   _Image  = other._Image;
100   _Manage = other._Manage;
101   other._Manage = false; // take over ownership
102   return *this;
103 }
104 
105 // -----------------------------------------------------------------------------
106 template <> template <class TOtherImage>
ImageChannel(const ImageChannel<TOtherImage> & other)107 ImageChannel<irtkBaseImage>::ImageChannel(const ImageChannel<TOtherImage> &other)
108 :
109   Object(other),
110   _Image (NULL),
111   _Manage(false)
112 {
113   *this = other;
114 }
115 
116 // -----------------------------------------------------------------------------
117 template <class TImage>
~ImageChannel()118 ImageChannel<TImage>::~ImageChannel()
119 {
120   if (_Manage) delete _Image;
121 }
122 
123 // -----------------------------------------------------------------------------
124 template <>
Image(ImageType * image,bool manage,bool copy)125 void ImageChannel<irtkBaseImage>::Image(ImageType *image, bool manage, bool copy)
126 {
127   if (_Manage) delete _Image;
128   if (image && copy && !manage) {
129     _Image  = BaseImage::New(image);
130     _Manage = true;
131   } else {
132     _Image  = image;
133     _Manage = manage;
134   }
135 }
136 
137 // -----------------------------------------------------------------------------
138 template <class TImage>
Image(ImageType * image,bool manage,bool copy)139 void ImageChannel<TImage>::Image(ImageType *image, bool manage, bool copy)
140 {
141   if (_Manage) delete _Image;
142   if (image && copy && !manage) {
143     _Image  = new ImageType(*image);
144     _Manage = true;
145   } else {
146     _Image  = image;
147     _Manage = manage;
148   }
149 }
150 
151 // -----------------------------------------------------------------------------
152 template <class TImage>
Image() const153 TImage *ImageChannel<TImage>::Image() const
154 {
155   return _Image;
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 // Inline definitions of ImageFrame
160 ////////////////////////////////////////////////////////////////////////////////
161 
162 // =============================================================================
163 // Construction/Destruction
164 // =============================================================================
165 
166 // -----------------------------------------------------------------------------
167 template <class TChannel>
ImageFrame()168 inline ImageFrame<TChannel>::ImageFrame()
169 {
170 }
171 
172 // -----------------------------------------------------------------------------
173 template <class TChannel>
~ImageFrame()174 inline ImageFrame<TChannel>::~ImageFrame()
175 {
176 }
177 
178 // =============================================================================
179 // Frame
180 // =============================================================================
181 
182 // -----------------------------------------------------------------------------
183 template <class TChannel>
Add(ImageType * image,bool manage,bool copy)184 inline void ImageFrame<TChannel>::Add(ImageType *image, bool manage, bool copy)
185 {
186   if (_Channel.size() > 0) {
187     ImageAttributes attr = image->Attributes();
188     attr._t  = 1; // may differ
189     attr._dt =  _Channel[0].Image().GetTSize();
190     if (attr != _Channel[0].Image().Attributes()) {
191       cerr << "ImageFrame::Add: Attributes of image do not match those of first channel" << endl;
192       exit(1);
193     }
194   }
195   const int T = image->GetT();
196   if (T > 0) {
197     for (int t = 0; t < T; ++t) {
198       BaseImage *channel;
199       image.GetFrame(t, channel);
200       _Channel.push_back(ChannelType(channel, true, false));
201     }
202   } else {
203     _Channel.push_back(ChannelType(image, manage, copy));
204   }
205 }
206 
207 // -----------------------------------------------------------------------------
208 template <class TChannel>
Clear()209 inline void ImageFrame<TChannel>::Clear()
210 {
211   _Channel.clear();
212 }
213 
214 // =============================================================================
215 // Channels
216 // =============================================================================
217 
218 // -----------------------------------------------------------------------------
219 template <class TChannel>
NumberOfChannels(int n)220 inline void ImageFrame<TChannel>::NumberOfChannels(int n)
221 {
222   _Channel.resize(n);
223 }
224 
225 // -----------------------------------------------------------------------------
226 template <class TChannel>
NumberOfChannels() const227 inline int ImageFrame<TChannel>::NumberOfChannels() const
228 {
229   return static_cast<int>(_Channel.size());
230 }
231 
232 // -----------------------------------------------------------------------------
233 template <class TChannel>
Channel(int idx)234 inline typename ImageFrame<TChannel>::ChannelType &ImageFrame<TChannel>::Channel(int idx)
235 {
236   return _Channel[idx];
237 }
238 
239 // -----------------------------------------------------------------------------
240 template <class TChannel>
Channel(int idx) const241 inline const typename ImageFrame<TChannel>::ChannelType &ImageFrame<TChannel>::Channel(int idx) const
242 {
243   return _Channel[idx];
244 }
245 
246 // -----------------------------------------------------------------------------
247 template <class TChannel>
Image(int idx,ImageType * image,bool manage,bool copy)248 inline void ImageFrame<TChannel>::Image(int idx, ImageType *image, bool manage, bool copy)
249 {
250   _Channel[idx].Image(image, manage, copy);
251 }
252 
253 // -----------------------------------------------------------------------------
254 template <class TChannel>
Image(int idx) const255 inline typename ImageFrame<TChannel>::ImageType *ImageFrame<TChannel>::Image(int idx) const
256 {
257   return _Channel[idx].Image();
258 }
259 
260 // =============================================================================
261 // Attributes
262 // =============================================================================
263 
264 // -----------------------------------------------------------------------------
265 template <class TChannel>
Attributes() const266 inline ImageAttributes ImageFrame<TChannel>::Attributes() const
267 {
268   const ImageType *image = Image(0);
269   return image ? image->GetImageAttributes() : ImageAttributes();
270 }
271 
272 // -----------------------------------------------------------------------------
273 template <class TChannel>
NumberOfVoxels() const274 inline int ImageFrame<TChannel>::NumberOfVoxels() const
275 {
276   const ImageType *image = Image(0);
277   return image ? image->GetNumberOfVoxels() : 0;
278 }
279 
280 // -----------------------------------------------------------------------------
281 template <class TChannel>
X() const282 inline int ImageFrame<TChannel>::X() const
283 {
284   const ImageType *image = Image(0);
285   return image ? image->GetX() : 0;
286 }
287 
288 // -----------------------------------------------------------------------------
289 template <class TChannel>
Y() const290 inline int ImageFrame<TChannel>::Y() const
291 {
292   const ImageType *image = Image(0);
293   return image ? image->GetY() : 0;
294 }
295 
296 // -----------------------------------------------------------------------------
297 template <class TChannel>
Z() const298 inline int ImageFrame<TChannel>::Z() const
299 {
300   const ImageType *image = Image(0);
301   return image ? image->GetZ() : 0;
302 }
303 
304 // -----------------------------------------------------------------------------
305 template <class TChannel>
XSize() const306 inline double ImageFrame<TChannel>::XSize() const
307 {
308   const ImageType *image = Image(0);
309   return image ? image->GetXSize() : .0;
310 }
311 
312 // -----------------------------------------------------------------------------
313 template <class TChannel>
YSize() const314 inline double ImageFrame<TChannel>::YSize() const
315 {
316   const ImageType *image = Image(0);
317   return image ? image->GetYSize() : .0;
318 }
319 
320 // -----------------------------------------------------------------------------
321 template <class TChannel>
ZSize() const322 inline double ImageFrame<TChannel>::ZSize() const
323 {
324   const ImageType *image = Image(0);
325   return image ? image->GetZSize() : .0;
326 }
327 
328 // -----------------------------------------------------------------------------
329 template <class TChannel>
GetPixelSize(double * dx,double * dy,double * dz) const330 inline void ImageFrame<TChannel>::GetPixelSize(double *dx, double *dy, double *dz) const
331 {
332   const ImageType *image = Image(0);
333   if (image) image->GetPixelSize(dx, dy, dz);
334   else {
335     if (dx) *dx = .0;
336     if (dy) *dy = .0;
337     if (dz) *dz = .0;
338   }
339 }
340 
341 // -----------------------------------------------------------------------------
342 template <class TChannel>
ImageToWorld(double & x,double & y,double & z) const343 inline void ImageFrame<TChannel>::ImageToWorld(double &x, double &y, double &z) const
344 {
345   const ImageType *image = Image(0);
346   if (image) image->ImageToWorld(x, y, z);
347 }
348 
349 // -----------------------------------------------------------------------------
350 template <class TChannel>
WorldToImage(double & x,double & y,double & z) const351 inline void ImageFrame<TChannel>::WorldToImage(double &x, double &y, double &z) const
352 {
353   const ImageType *image = Image(0);
354   if (image) image->WorldToImage(x, y, z);
355 }
356 
357 // -----------------------------------------------------------------------------
358 template <class TChannel>
Time() const359 inline double ImageFrame<TChannel>::Time() const
360 {
361   const ImageType *image = Image(0);
362   if (image) image->ImageToTime(.0);
363 }
364 
365 ////////////////////////////////////////////////////////////////////////////////
366 // Inline definitions of ImageSequence
367 ////////////////////////////////////////////////////////////////////////////////
368 
369 // =============================================================================
370 // Construction/Destruction
371 // =============================================================================
372 
373 // -----------------------------------------------------------------------------
374 template <class TFrame>
ImageSequence()375 inline ImageSequence<TFrame>::ImageSequence()
376 {
377 }
378 
379 // -----------------------------------------------------------------------------
380 template <class TFrame>
ImageSequence(const ImageSequence & other)381 inline ImageSequence<TFrame>::ImageSequence(const ImageSequence &other)
382 :
383   Object(other),
384   _Frame(other._Frame)
385 {
386 }
387 
388 // -----------------------------------------------------------------------------
389 template <class TFrame>
operator =(const ImageSequence & other)390 inline ImageSequence<TFrame> &ImageSequence<TFrame>::operator =(const ImageSequence &other)
391 {
392   _Frame = other._Frame;
393   return *this;
394 }
395 
396 // -----------------------------------------------------------------------------
397 template <class TFrame>
~ImageSequence()398 inline ImageSequence<TFrame>::~ImageSequence()
399 {
400 }
401 
402 // =============================================================================
403 // Sequence
404 // =============================================================================
405 
406 // -----------------------------------------------------------------------------
407 template <class TFrame>
Add(ImageType * image,bool manage,bool copy)408 inline void ImageSequence<TFrame>::Add(ImageType *image, bool manage, bool copy)
409 {
410   if (NumberOfFrames() > 0 && NumberOfChannels() > 0) {
411     if (!image->HasSpatialAttributesOf(Image(0, 0))) {
412       cerr << "ImageSequence::Add: Spatial attributes of image differ from those of first frame" << endl;
413       exit(1);
414     }
415   }
416   // Reserve enough entries in vector to ensure that no reallocation
417   // takes place during the insert to keep tmp iterator below valid
418   _Frame.reserve(_Frame.size() + image->GetT());
419   // Insert each input frame (dt != 0) or channel (dt == 0)
420   // Frames are sorted by increasing time and channels appended
421   for (int l = 0; l < image->GetT(); ++l) {
422     // Find corresponding frame or add new one if necessary
423     const double                              time  = image->ImageToTime(l);
424     typename Array<FrameType>::iterator frame = _Frame.begin();
425     while (frame != _Frame.end()) {
426       const double t = frame->Time();
427       if      (t == time) break;
428       else if (t  > time) {
429         typename Array<FrameType>::iterator tmp = frame - 1;
430         _Frame.insert(frame, FrameType());
431         frame = ++tmp;
432         break;
433       }
434       ++frame;
435     }
436     if (frame == _Frame.end()) {
437       _Frame.push_back(FrameType());
438       frame = _Frame.end() - 1;
439     }
440     // Add channel to frame
441     if (image->GetT() > 0) {
442       BaseImage *channel;
443       image->GetFrame(l, channel);
444       frame->Add(channel, true, false);
445     } else {
446       frame->Add(image, manage, copy);
447     }
448   }
449 }
450 
451 // -----------------------------------------------------------------------------
452 template <class TFrame>
Clear()453 inline void ImageSequence<TFrame>::Clear()
454 {
455   _Frame.clear();
456 }
457 
458 // =============================================================================
459 // Frames
460 // =============================================================================
461 
462 // -----------------------------------------------------------------------------
463 template <class TFrame>
NumberOfFrames(int n) const464 inline void ImageSequence<TFrame>::NumberOfFrames(int n) const
465 {
466   _Frame.resize(n);
467 }
468 
469 // -----------------------------------------------------------------------------
470 template <class TFrame>
NumberOfFrames() const471 inline int ImageSequence<TFrame>::NumberOfFrames() const
472 {
473   return static_cast<int>(_Frame.size());
474 }
475 
476 // -----------------------------------------------------------------------------
477 template <class TFrame>
Frame(int f)478 inline typename ImageSequence<TFrame>::FrameType &ImageSequence<TFrame>::Frame(int f)
479 {
480   return _Frame[f];
481 }
482 
483 // -----------------------------------------------------------------------------
484 template <class TFrame>
Frame(int f) const485 inline const typename ImageSequence<TFrame>::FrameType &ImageSequence<TFrame>::Frame(int f) const
486 {
487   return _Frame[f];
488 }
489 
490 // =============================================================================
491 // Channels
492 // =============================================================================
493 
494 // -----------------------------------------------------------------------------
495 template <class TFrame>
NumberOfChannels(int n) const496 inline void ImageSequence<TFrame>::NumberOfChannels(int n) const
497 {
498   for (int f = 0; f < NumberOfChannels(); ++f) Frame(f).NumberOfChannels(n);
499 }
500 
501 // -----------------------------------------------------------------------------
502 template <class TFrame>
NumberOfChannels() const503 inline int ImageSequence<TFrame>::NumberOfChannels() const
504 {
505   return NumberOfFrames() > 0 ? Frame(0).NumberOfChannels() : 0;
506 }
507 
508 // -----------------------------------------------------------------------------
509 template <class TFrame>
Channel(int idx)510 inline typename ImageSequence<TFrame>::ChannelType &ImageSequence<TFrame>::Channel(int idx)
511 {
512   const int num = NumberOfChannels();
513   return _Frame[idx / num][idx % num];
514 }
515 
516 // -----------------------------------------------------------------------------
517 template <class TFrame>
Channel(int idx) const518 inline const typename ImageSequence<TFrame>::ChannelType &ImageSequence<TFrame>::Channel(int idx) const
519 {
520   const int num = NumberOfChannels();
521   return _Frame[idx / num][idx % num];
522 }
523 
524 // -----------------------------------------------------------------------------
525 template <class TFrame>
Channel(int f,int c)526 inline typename ImageSequence<TFrame>::ChannelType &ImageSequence<TFrame>::Channel(int f, int c)
527 {
528   return _Frame[f][c];
529 }
530 
531 // -----------------------------------------------------------------------------
532 template <class TFrame>
Channel(int f,int c) const533 inline const typename ImageSequence<TFrame>::ChannelType &ImageSequence<TFrame>::Channel(int f, int c) const
534 {
535   return _Frame[f][c];
536 }
537 
538 // =============================================================================
539 // Images
540 // =============================================================================
541 
542 // -----------------------------------------------------------------------------
543 template <class TFrame>
NumberOfImages() const544 inline int ImageSequence<TFrame>::NumberOfImages() const
545 {
546   return NumberOfFrames() * NumberOfChannels();
547 }
548 
549 // -----------------------------------------------------------------------------
550 template <class TFrame>
Image(int idx) const551 inline typename ImageSequence<TFrame>::ImageType *ImageSequence<TFrame>::Image(int idx) const
552 {
553   return Channel(idx).Image();
554 }
555 
556 // -----------------------------------------------------------------------------
557 template <class TFrame>
Image(int f,int c) const558 inline typename ImageSequence<TFrame>::ImageType *ImageSequence<TFrame>::Image(int f, int c) const
559 {
560   return Channel(f, c).Image();
561 }
562 
563 // =============================================================================
564 // Attributes
565 // =============================================================================
566 
567 // -----------------------------------------------------------------------------
568 template <class TFrame>
Attributes() const569 inline ImageAttributes ImageSequence<TFrame>::Attributes() const
570 {
571   const ImageType *image = Image(0, 0);
572   ImageAttributes attr;
573   if (image) attr = image->GetImageAttributes();
574   attr._t = NumberOfFrames();
575   return attr;
576 }
577 
578 // -----------------------------------------------------------------------------
579 template <class TFrame>
NumberOfVoxels() const580 inline int ImageSequence<TFrame>::NumberOfVoxels() const
581 {
582   const ImageType *image = Image(0, 0);
583   return image ? image->NumberOfVoxels() : 0;
584 }
585 
586 // -----------------------------------------------------------------------------
587 template <class TFrame>
X() const588 inline int ImageSequence<TFrame>::X() const
589 {
590   const ImageType *image = Image(0, 0);
591   return image ? image->GetX() : 0;
592 }
593 
594 // -----------------------------------------------------------------------------
595 template <class TFrame>
Y() const596 inline int ImageSequence<TFrame>::Y() const
597 {
598   const ImageType *image = Image(0, 0);
599   return image ? image->GetY() : 0;
600 }
601 
602 // -----------------------------------------------------------------------------
603 template <class TFrame>
Z() const604 inline int ImageSequence<TFrame>::Z() const
605 {
606   const ImageType *image = Image(0, 0);
607   return image ? image->GetZ() : 0;
608 }
609 
610 // -----------------------------------------------------------------------------
611 template <class TFrame>
T() const612 inline int ImageSequence<TFrame>::T() const
613 {
614   return NumberOfFrames();
615 }
616 
617 // -----------------------------------------------------------------------------
618 template <class TFrame>
XSize() const619 inline double ImageSequence<TFrame>::XSize() const
620 {
621   const ImageType *image = Image(0, 0);
622   return image ? image->GetXSize() : .0;
623 }
624 
625 // -----------------------------------------------------------------------------
626 template <class TFrame>
YSize() const627 inline double ImageSequence<TFrame>::YSize() const
628 {
629   const ImageType *image = Image(0, 0);
630   return image ? image->GetYSize() : .0;
631 }
632 
633 // -----------------------------------------------------------------------------
634 template <class TFrame>
ZSize() const635 inline double ImageSequence<TFrame>::ZSize() const
636 {
637   const ImageType *image = Image(0, 0);
638   return image ? image->GetZSize() : .0;
639 }
640 
641 // -----------------------------------------------------------------------------
642 template <class TFrame>
GetPixelSize(double * dx,double * dy,double * dz) const643 inline void ImageSequence<TFrame>::GetPixelSize(double *dx, double *dy, double *dz) const
644 {
645   const ImageType *image = Image(0, 0);
646   if (image) image->GetPixelSize(dx, dy, dz);
647   else {
648     if (dx) *dx = .0;
649     if (dy) *dy = .0;
650     if (dz) *dz = .0;
651   }
652 }
653 
654 // -----------------------------------------------------------------------------
655 template <class TFrame>
ImageToWorld(double & x,double & y,double & z) const656 inline void ImageSequence<TFrame>::ImageToWorld(double &x, double &y, double &z) const
657 {
658   const ImageType *image = Image(0, 0);
659   if (image) image->ImageToWorld(x, y, z);
660 }
661 
662 // -----------------------------------------------------------------------------
663 template <class TFrame>
WorldToImage(double & x,double & y,double & z) const664 inline void ImageSequence<TFrame>::WorldToImage(double &x, double &y, double &z) const
665 {
666   const ImageType *image = Image(0, 0);
667   if (image) image->WorldToImage(x, y, z);
668 }
669 
670 
671 } // namespace mirtk
672 
673 #endif // MIRTK_ImageSequence_HH
674