1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkVideoStream_hxx
19 #define itkVideoStream_hxx
20 
21 #include "itkVideoStream.h"
22 
23 namespace itk
24 {
25 
26 template<typename TFrameType>
27 void
28 VideoStream<TFrameType>
SetFrameLargestPossibleSpatialRegion(SizeValueType frameNumber,typename TFrameType::RegionType region)29 ::SetFrameLargestPossibleSpatialRegion(SizeValueType frameNumber, typename TFrameType::RegionType region)
30 {
31   m_LargestPossibleSpatialRegionCache[frameNumber] = region;
32 
33   // If the frame is currently buffered, set the actual frame's region
34   SizeValueType bufStart = m_BufferedTemporalRegion.GetFrameStart();
35   SizeValueType bufDur = m_BufferedTemporalRegion.GetFrameDuration();
36   if (frameNumber >= bufStart && frameNumber < bufStart + bufDur)
37     {
38     FrameType* frame = this->GetFrame(frameNumber);
39     frame->SetLargestPossibleRegion(region);
40     }
41 }
42 
43 
44 template<typename TFrameType>
45 const typename TFrameType::RegionType &
46 VideoStream<TFrameType>
GetFrameLargestPossibleSpatialRegion(SizeValueType frameNumber) const47 ::GetFrameLargestPossibleSpatialRegion(SizeValueType frameNumber) const
48 {
49   // It seems that std::map's [] operator isn't const correct, so we need to
50   // access this member from an non-const version of ourselves
51   return const_cast<Self*>(this)->m_LargestPossibleSpatialRegionCache[frameNumber];
52 }
53 
54 
55 template<typename TFrameType>
56 void
57 VideoStream<TFrameType>
SetFrameRequestedSpatialRegion(SizeValueType frameNumber,typename TFrameType::RegionType region)58 ::SetFrameRequestedSpatialRegion(SizeValueType frameNumber, typename TFrameType::RegionType region)
59 {
60   m_RequestedSpatialRegionCache[frameNumber] = region;
61 
62   // If the frame is currently buffered, set the actual frame's region
63   SizeValueType bufStart = m_BufferedTemporalRegion.GetFrameStart();
64   SizeValueType bufDur = m_BufferedTemporalRegion.GetFrameDuration();
65   if (frameNumber >= bufStart && frameNumber < bufStart + bufDur)
66     {
67     FrameType* frame = this->GetFrame(frameNumber);
68     frame->SetRequestedRegion(region);
69     }
70 }
71 
72 
73 template<typename TFrameType>
74 const typename TFrameType::RegionType &
75 VideoStream<TFrameType>
GetFrameRequestedSpatialRegion(SizeValueType frameNumber) const76 ::GetFrameRequestedSpatialRegion(SizeValueType frameNumber) const
77 {
78   // It seems that std::map's [] operator isn't const correct, so we need to
79   // access this member from an non-const version of ourselves
80   return const_cast<Self*>(this)->m_RequestedSpatialRegionCache[frameNumber];
81 }
82 
83 
84 template<typename TFrameType>
85 void
86 VideoStream<TFrameType>
SetFrameBufferedSpatialRegion(SizeValueType frameNumber,typename TFrameType::RegionType region)87 ::SetFrameBufferedSpatialRegion(SizeValueType frameNumber, typename TFrameType::RegionType region)
88 {
89   m_BufferedSpatialRegionCache[frameNumber] = region;
90 
91   // If the frame is currently buffered, set the actual frame's region
92   SizeValueType bufStart = m_BufferedTemporalRegion.GetFrameStart();
93   SizeValueType bufDur = m_BufferedTemporalRegion.GetFrameDuration();
94   if (frameNumber >= bufStart && frameNumber < bufStart + bufDur)
95     {
96     FrameType* frame = this->GetFrame(frameNumber);
97     frame->SetBufferedRegion(region);
98     }
99 }
100 
101 
102 template<typename TFrameType>
103 const typename TFrameType::RegionType &
104 VideoStream<TFrameType>
GetFrameBufferedSpatialRegion(SizeValueType frameNumber) const105 ::GetFrameBufferedSpatialRegion(SizeValueType frameNumber) const
106 {
107   // It seems that std::map's [] operator isn't const correct, so we need to
108   // access this member from an non-const version of ourselves
109   return const_cast<Self*>(this)->m_BufferedSpatialRegionCache[frameNumber];
110 }
111 
112 
113 template<typename TFrameType>
114 void
115 VideoStream<TFrameType>
SetFrameSpacing(SizeValueType frameNumber,typename TFrameType::SpacingType spacing)116 ::SetFrameSpacing(SizeValueType frameNumber, typename TFrameType::SpacingType spacing)
117 {
118   // Make sure spacing is non-zero
119   for (unsigned int i = 0; i < FrameType::ImageDimension; ++i)
120     {
121     if (spacing[i] == 0.0)
122       {
123       itkExceptionMacro("Zero spacing is not allowed for any dimension: Spacing is " << spacing);
124       }
125     }
126 
127   m_SpacingCache[frameNumber] = spacing;
128 
129   // If the frame is currently buffered, set the actual frame's spacing
130   SizeValueType bufStart = m_BufferedTemporalRegion.GetFrameStart();
131   SizeValueType bufDur = m_BufferedTemporalRegion.GetFrameDuration();
132   if (frameNumber >= bufStart && frameNumber < bufStart + bufDur)
133     {
134     FrameType* frame = this->GetFrame(frameNumber);
135     frame->SetSpacing(spacing);
136     }
137 }
138 
139 
140 template<typename TFrameType>
141 const typename TFrameType::SpacingType &
142 VideoStream<TFrameType>
GetFrameSpacing(SizeValueType frameNumber) const143 ::GetFrameSpacing(SizeValueType frameNumber) const
144 {
145   // It seems that std::map's [] operator isn't const correct, so we need to
146   // access this member from an non-const version of ourselves
147   return const_cast<Self*>(this)->m_SpacingCache[frameNumber];
148 }
149 
150 
151 template<typename TFrameType>
152 void
153 VideoStream<TFrameType>
SetFrameOrigin(SizeValueType frameNumber,typename TFrameType::PointType origin)154 ::SetFrameOrigin(SizeValueType frameNumber, typename TFrameType::PointType origin)
155 {
156   m_OriginCache[frameNumber] = origin;
157 
158   // If the frame is currently buffered, set the actual frame's spacing
159   SizeValueType bufStart = m_BufferedTemporalRegion.GetFrameStart();
160   SizeValueType bufDur = m_BufferedTemporalRegion.GetFrameDuration();
161   if (frameNumber >= bufStart && frameNumber < bufStart + bufDur)
162     {
163     FrameType* frame = this->GetFrame(frameNumber);
164     frame->SetOrigin(origin);
165     }
166 }
167 
168 
169 template<typename TFrameType>
170 const typename TFrameType::PointType &
171 VideoStream<TFrameType>
GetFrameOrigin(SizeValueType frameNumber) const172 ::GetFrameOrigin(SizeValueType frameNumber) const
173 {
174   // It seems that std::map's [] operator isn't const correct, so we need to
175   // access this member from an non-const version of ourselves
176   return const_cast<Self*>(this)->m_OriginCache[frameNumber];
177 }
178 
179 
180 template<typename TFrameType>
181 void
182 VideoStream<TFrameType>
SetFrameDirection(SizeValueType frameNumber,typename TFrameType::DirectionType direction)183 ::SetFrameDirection(SizeValueType frameNumber, typename TFrameType::DirectionType direction)
184 {
185   // Determinant is non-zero
186   if (itk::Math::abs(vnl_determinant(direction.GetVnlMatrix())) <= itk::Math::eps)
187     {
188     itkExceptionMacro("Bad direction, determinant is 0. Direction is " << direction);
189     }
190 
191   m_DirectionCache[frameNumber] = direction;
192 
193   // If the frame is currently buffered, set the actual frame's spacing
194   SizeValueType bufStart = m_BufferedTemporalRegion.GetFrameStart();
195   SizeValueType bufDur = m_BufferedTemporalRegion.GetFrameDuration();
196   if (frameNumber >= bufStart && frameNumber < bufStart + bufDur)
197     {
198     FrameType* frame = this->GetFrame(frameNumber);
199     frame->SetDirection(direction);
200     }
201 }
202 
203 
204 template<typename TFrameType>
205 const typename TFrameType::DirectionType &
206 VideoStream<TFrameType>
GetFrameDirection(SizeValueType frameNumber) const207 ::GetFrameDirection(SizeValueType frameNumber) const
208 {
209   // It seems that std::map's [] operator isn't const correct, so we need to
210   // access this member from an non-const version of ourselves
211   return const_cast<Self*>(this)->m_DirectionCache[frameNumber];
212 }
213 
214 
215 template<typename TFrameType>
216 void
217 VideoStream<TFrameType>
SetFrameBuffer(typename VideoStream<TFrameType>::BufferType * buffer)218 ::SetFrameBuffer(typename VideoStream<TFrameType>::BufferType* buffer)
219 {
220   // We reinterpret the buffer to match TemporalDataObject's buffer type. We
221   // assume that any tampering with the internal buffer will use our BufferType
222   // so this will be safe.
223   auto * castBuffer = reinterpret_cast<TemporalDataObject::BufferType*>(buffer);
224 
225   if (m_DataObjectBuffer != castBuffer)
226     {
227     m_DataObjectBuffer = castBuffer;
228     this->Modified();
229     }
230 }
231 
232 
233 template<typename TFrameType>
234 void
235 VideoStream<TFrameType>
SetMinimumBufferSize(SizeValueType minimumNumberOfFrames)236 ::SetMinimumBufferSize(SizeValueType minimumNumberOfFrames)
237 {
238   // If we don't have enough buffer space to handle the number of requested
239   // frames, we need to resize the ring buffer. Just resizing can cause data to
240   // be in the wrong place. For example if the head of the buffer is at index 0
241   // and the buffer has 3 slots, setting frame number 3 will actually place the
242   // data into slot 0.  If we then resize the buffer to have 4 slots, the data
243   // for frame 3 will live in slot 0 even though a request for frame 3 will
244   // return the data from the newly created slot 3. To circumvent this problem,
245   // we move the buffered data to the proper indices in the ring buffer after
246   // resizing.
247   if (m_DataObjectBuffer->GetNumberOfBuffers() < minimumNumberOfFrames)
248     {
249     // Save the indices of all frames in the currently buffered region
250     const SizeValueType bufferedStart = m_BufferedTemporalRegion.GetFrameStart();
251     const SizeValueType bufferedDuration = m_BufferedTemporalRegion.GetFrameDuration();
252     std::vector< DataObject * > frames( bufferedDuration - bufferedStart, nullptr );
253     for (SizeValueType i = bufferedStart; i < bufferedStart + bufferedDuration; ++i)
254       {
255       frames[i - bufferedStart] = m_DataObjectBuffer->GetBufferContents(i);
256       }
257 
258     // Resize the ring buffer
259     m_DataObjectBuffer->SetNumberOfBuffers(minimumNumberOfFrames);
260 
261     // Move previously buffered data to the locations where their frame numbers now map
262     for (SizeValueType i = bufferedStart; i < bufferedStart + bufferedDuration; ++i)
263       {
264       m_DataObjectBuffer->SetBufferContents(i, frames[i - bufferedStart]);
265       }
266     }
267 }
268 
269 
270 template<typename TFrameType>
271 void
272 VideoStream<TFrameType>
InitializeEmptyFrames()273 ::InitializeEmptyFrames()
274 {
275   // If we don't have any frames requested, just return
276   SizeValueType numFrames = m_RequestedTemporalRegion.GetFrameDuration();
277   if (numFrames == 0)
278     {
279     return;
280     }
281 
282 
283   // Safely expand the ring buffer if necessary
284   this->SetMinimumBufferSize(numFrames);
285 
286   // Go through the number of required frames and make sure none are empty
287   SizeValueType startFrame = m_RequestedTemporalRegion.GetFrameStart();
288   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
289     {
290     if (!m_DataObjectBuffer->BufferIsFull(i))
291       {
292       FramePointer newFrame = FrameType::New();
293       FrameType* newFrameRawPointer = newFrame.GetPointer();
294       typename BufferType::ElementPointer element =
295         dynamic_cast<typename BufferType::ElementType*>(newFrameRawPointer);
296       m_DataObjectBuffer->SetBufferContents(i, element);
297       }
298 
299     // Check to see if any cached meta data exists and if it does, assign it
300     if (m_LargestPossibleSpatialRegionCache.find(i) !=
301         m_LargestPossibleSpatialRegionCache.end())
302       {
303       this->GetFrame(i)->SetLargestPossibleRegion(m_LargestPossibleSpatialRegionCache[i]);
304       }
305     if (m_RequestedSpatialRegionCache.find(i) !=
306         m_RequestedSpatialRegionCache.end())
307       {
308       this->GetFrame(i)->SetRequestedRegion(m_RequestedSpatialRegionCache[i]);
309       }
310     if (m_BufferedSpatialRegionCache.find(i) !=
311         m_BufferedSpatialRegionCache.end())
312       {
313       this->GetFrame(i)->SetBufferedRegion(m_BufferedSpatialRegionCache[i]);
314       }
315     if (m_SpacingCache.find(i) != m_SpacingCache.end())
316       {
317       this->GetFrame(i)->SetSpacing(m_SpacingCache[i]);
318       }
319     if (m_OriginCache.find(i) != m_OriginCache.end())
320       {
321       this->GetFrame(i)->SetOrigin(m_OriginCache[i]);
322       }
323     if (m_DirectionCache.find(i) != m_DirectionCache.end())
324       {
325       this->GetFrame(i)->SetDirection(m_DirectionCache[i]);
326       }
327     }
328 }
329 
330 
331 template<typename TFrameType>
332 void
333 VideoStream<TFrameType>
SetFrame(SizeValueType frameNumber,FramePointer frame)334 ::SetFrame(SizeValueType frameNumber, FramePointer frame)
335 {
336   auto * dataObjectRawPointer = dynamic_cast<typename BufferType::ElementType*>(frame.GetPointer());
337   typename BufferType::ElementPointer dataObject = dataObjectRawPointer;
338   m_DataObjectBuffer->SetBufferContents(frameNumber,dataObject);
339 
340   // Cache the meta data
341   m_LargestPossibleSpatialRegionCache[frameNumber] = frame->GetLargestPossibleRegion();
342   m_RequestedSpatialRegionCache[frameNumber] = frame->GetRequestedRegion();
343   m_BufferedSpatialRegionCache[frameNumber] = frame->GetBufferedRegion();
344   m_SpacingCache[frameNumber] = frame->GetSpacing();
345   m_OriginCache[frameNumber] = frame->GetOrigin();
346   m_DirectionCache[frameNumber] = frame->GetDirection();
347 }
348 
349 
350 template<typename TFrameType>
351 typename VideoStream<TFrameType>::FramePointer
352 VideoStream<TFrameType>
GetFrame(SizeValueType frameNumber)353 ::GetFrame(SizeValueType frameNumber)
354 {
355 
356   // Fetch the frame
357   typename BufferType::ElementPointer element =
358     m_DataObjectBuffer->GetBufferContents(frameNumber);
359   FramePointer frame = dynamic_cast<FrameType*>(element.GetPointer());
360   return frame;
361 }
362 
363 
364 template<typename TFrameType>
365 typename VideoStream<TFrameType>::FrameConstPointer
366 VideoStream<TFrameType>
GetFrame(SizeValueType frameNumber) const367 ::GetFrame(SizeValueType frameNumber) const
368 {
369   typename BufferType::ElementPointer element =
370     m_DataObjectBuffer->GetBufferContents(frameNumber);
371   FrameConstPointer frame = dynamic_cast<FrameType*>(element.GetPointer());
372   return frame;
373 }
374 
375 
376 template<typename TFrameType>
377 void
378 VideoStream<TFrameType>
Graft(const DataObject * data)379 ::Graft(const DataObject* data)
380 {
381   // Call TemporalDataObject's Graft implementation
382   Superclass::Graft(data);
383 
384   if (data)
385     {
386     // Attempt to cast to a VideoStream
387     const auto * videoData = dynamic_cast< const Self* >(data);
388     if (!videoData)
389       {
390       itkExceptionMacro( << "itk::VideoStream::Graft() cannot cast "
391                          << typeid( data ).name() << " to "
392                          << typeid( const Self* ).name() );
393       }
394 
395     // Copy the meta data caches
396     this->SetLargestPossibleSpatialRegionCache(
397       videoData->GetLargestPossibleSpatialRegionCache());
398     this->SetRequestedSpatialRegionCache(
399       videoData->GetRequestedSpatialRegionCache());
400     this->SetBufferedSpatialRegionCache(
401       videoData->GetBufferedSpatialRegionCache());
402     this->SetSpacingCache(videoData->GetSpacingCache());
403     this->SetOriginCache(videoData->GetOriginCache());
404     this->SetDirectionCache(videoData->GetDirectionCache());
405 
406     // Copy the frame buffer
407     this->SetFrameBuffer(const_cast< BufferType* >(videoData->GetFrameBuffer()));
408     }
409 }
410 
411 
412 template<typename TFrameType>
413 void
414 VideoStream<TFrameType>
SetAllLargestPossibleSpatialRegions(typename TFrameType::RegionType region)415 ::SetAllLargestPossibleSpatialRegions(typename TFrameType::RegionType region)
416 {
417   SizeValueType numFrames = m_LargestPossibleTemporalRegion.GetFrameDuration();
418   SizeValueType startFrame = m_LargestPossibleTemporalRegion.GetFrameStart();
419 
420   // If the largest region is infinite, use the largest of the requested or
421   // buffered region
422   if (numFrames == ITK_INFINITE_FRAME_DURATION)
423       {
424       SizeValueType bufEnd = m_BufferedTemporalRegion.GetFrameStart() +
425                               m_BufferedTemporalRegion.GetFrameDuration();
426       SizeValueType reqEnd = m_RequestedTemporalRegion.GetFrameStart() +
427                               m_RequestedTemporalRegion.GetFrameDuration();
428       (bufEnd > reqEnd) ? (numFrames = bufEnd) : (numFrames = reqEnd);
429       }
430 
431   // Go through the number of required frames, making sure none are empty and
432   // setting the region
433   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
434     {
435     this->SetFrameLargestPossibleSpatialRegion(i, region);
436     }
437 }
438 
439 
440 template<typename TFrameType>
441 void
442 VideoStream<TFrameType>
SetAllRequestedSpatialRegions(typename TFrameType::RegionType region)443 ::SetAllRequestedSpatialRegions(typename TFrameType::RegionType region)
444 {
445   SizeValueType numFrames = m_LargestPossibleTemporalRegion.GetFrameDuration();
446   SizeValueType startFrame = m_LargestPossibleTemporalRegion.GetFrameStart();
447 
448   // If the largest region is infinite, use the largest of the requested or
449   // buffered region
450   if (numFrames == ITK_INFINITE_FRAME_DURATION)
451       {
452       SizeValueType bufEnd = m_BufferedTemporalRegion.GetFrameStart() +
453                               m_BufferedTemporalRegion.GetFrameDuration();
454       SizeValueType reqEnd = m_RequestedTemporalRegion.GetFrameStart() +
455                               m_RequestedTemporalRegion.GetFrameDuration();
456       (bufEnd > reqEnd) ? (numFrames = bufEnd) : (numFrames = reqEnd);
457       }
458 
459   // Go through the number of required frames, making sure none are empty and
460   // setting the region
461   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
462     {
463     this->SetFrameRequestedSpatialRegion(i, region);
464     }
465 }
466 
467 
468 template<typename TFrameType>
469 void
470 VideoStream<TFrameType>
SetAllBufferedSpatialRegions(typename TFrameType::RegionType region)471 ::SetAllBufferedSpatialRegions(typename TFrameType::RegionType region)
472 {
473   SizeValueType numFrames = m_LargestPossibleTemporalRegion.GetFrameDuration();
474   SizeValueType startFrame = m_LargestPossibleTemporalRegion.GetFrameStart();
475 
476   // If the largest region is infinite, use the largest of the requested or
477   // buffered region
478   if (numFrames == ITK_INFINITE_FRAME_DURATION)
479       {
480       SizeValueType bufEnd = m_BufferedTemporalRegion.GetFrameStart() +
481                               m_BufferedTemporalRegion.GetFrameDuration();
482       SizeValueType reqEnd = m_RequestedTemporalRegion.GetFrameStart() +
483                               m_RequestedTemporalRegion.GetFrameDuration();
484       (bufEnd > reqEnd) ? (numFrames = bufEnd) : (numFrames = reqEnd);
485       }
486 
487   // Go through the number of required frames, making sure none are empty and
488   // setting the region
489   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
490     {
491     this->SetFrameBufferedSpatialRegion(i, region);
492     }
493 }
494 
495 
496 template<typename TFrameType>
497 void
498 VideoStream<TFrameType>
SetAllFramesSpacing(typename TFrameType::SpacingType spacing)499 ::SetAllFramesSpacing(typename TFrameType::SpacingType spacing)
500 {
501   SizeValueType numFrames = m_LargestPossibleTemporalRegion.GetFrameDuration();
502   SizeValueType startFrame = m_LargestPossibleTemporalRegion.GetFrameStart();
503 
504   // If the largest region is infinite, use the largest of the requested or
505   // buffered region
506   if (numFrames == ITK_INFINITE_FRAME_DURATION)
507       {
508       SizeValueType bufEnd = m_BufferedTemporalRegion.GetFrameStart() +
509                               m_BufferedTemporalRegion.GetFrameDuration();
510       SizeValueType reqEnd = m_RequestedTemporalRegion.GetFrameStart() +
511                               m_RequestedTemporalRegion.GetFrameDuration();
512       (bufEnd > reqEnd) ? (numFrames = bufEnd) : (numFrames = reqEnd);
513       }
514 
515   // Go through the number of required frames, making sure none are empty and
516   // setting the region
517   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
518     {
519     this->SetFrameSpacing(i, spacing);
520     }
521 }
522 
523 
524 template<typename TFrameType>
525 void
526 VideoStream<TFrameType>
SetAllFramesOrigin(typename TFrameType::PointType origin)527 ::SetAllFramesOrigin(typename TFrameType::PointType origin)
528 {
529   SizeValueType numFrames = m_LargestPossibleTemporalRegion.GetFrameDuration();
530   SizeValueType startFrame = m_LargestPossibleTemporalRegion.GetFrameStart();
531 
532   // If the largest region is infinite, use the largest of the requested or
533   // buffered region
534   if (numFrames == ITK_INFINITE_FRAME_DURATION)
535       {
536       SizeValueType bufEnd = m_BufferedTemporalRegion.GetFrameStart() +
537                               m_BufferedTemporalRegion.GetFrameDuration();
538       SizeValueType reqEnd = m_RequestedTemporalRegion.GetFrameStart() +
539                               m_RequestedTemporalRegion.GetFrameDuration();
540       (bufEnd > reqEnd) ? (numFrames = bufEnd) : (numFrames = reqEnd);
541       }
542 
543   // Go through the number of required frames, making sure none are empty and
544   // setting the region
545   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
546     {
547     this->SetFrameOrigin(i, origin);
548     }
549 }
550 
551 
552 template<typename TFrameType>
553 void
554 VideoStream<TFrameType>
SetAllFramesDirection(typename TFrameType::DirectionType direction)555 ::SetAllFramesDirection(typename TFrameType::DirectionType direction)
556 {
557   SizeValueType numFrames = m_LargestPossibleTemporalRegion.GetFrameDuration();
558   SizeValueType startFrame = m_LargestPossibleTemporalRegion.GetFrameStart();
559 
560   // If the largest region is infinite, use the largest of the requested or
561   // buffered region
562   if (numFrames == ITK_INFINITE_FRAME_DURATION)
563       {
564       SizeValueType bufEnd = m_BufferedTemporalRegion.GetFrameStart() +
565                               m_BufferedTemporalRegion.GetFrameDuration();
566       SizeValueType reqEnd = m_RequestedTemporalRegion.GetFrameStart() +
567                               m_RequestedTemporalRegion.GetFrameDuration();
568       (bufEnd > reqEnd) ? (numFrames = bufEnd) : (numFrames = reqEnd);
569       }
570 
571   // Go through the number of required frames, making sure none are empty and
572   // setting the region
573   for (SizeValueType i = startFrame; i < startFrame + numFrames; ++i)
574     {
575     this->SetFrameDirection(i, direction);
576     }
577 }
578 
579 
580 template<typename TFrameType>
581 void
582 VideoStream<TFrameType>
Allocate()583 ::Allocate()
584 {
585   SizeValueType numFrames = m_BufferedTemporalRegion.GetFrameDuration();
586   if (m_DataObjectBuffer->GetNumberOfBuffers() < numFrames)
587     {
588     itkExceptionMacro("itk::VideoStream::SetAllLargestPossibleSpatialRegions "
589                       "not enough frame buffers available. Call InitializeEmptyFrames "
590                       "to prepare the frame buffer correctly.");
591     }
592 
593   // Go through the number of required frames, making sure none are empty and
594   // allocating them. We start at 1 and move forwards because frames will be
595   // added using AppendFrame which first moves the Head forward, then adds the
596   // frame
597   for (SizeValueType i = 1; i <= numFrames; ++i)
598     {
599     if (!m_DataObjectBuffer->BufferIsFull(i))
600       {
601       itkExceptionMacro("itk::VideoStream::SetAllLargestPossibleSpatialRegions "
602                         "empty frame buffer found at offset " << i << ". Call "
603                         "InitializeEmptyFrames to prepare the frame buffer correctly.");
604       }
605     FrameType* frame = dynamic_cast<FrameType*>(
606                         m_DataObjectBuffer->GetBufferContents(i).GetPointer());
607     if (!frame)
608       {
609       itkExceptionMacro("itk::VideoStream::SetAllLargestPossibleSpatialRegions "
610                         "could not cast frame " << i << " to the correct type.");
611       }
612     frame->Allocate();
613     }
614 }
615 
616 } // end namespace itk
617 
618 #endif
619