1 /*=========================================================================
2 
3   Program: GDCM (Grassroots DICOM). A DICOM library
4 
5   Copyright (c) 2006-2011 Mathieu Malaterre
6   All rights reserved.
7   See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details.
8 
9      This software is distributed WITHOUT ANY WARRANTY; without even
10      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11      PURPOSE.  See the above copyright notice for more information.
12 
13 =========================================================================*/
14 #include "gdcmBoxRegion.h"
15 
16 #include <limits>
17 #include <algorithm> // req C++11
18 
19 namespace gdcm
20 {
21 class BoxRegionInternals
22 {
23 public:
BoxRegionInternals()24   BoxRegionInternals()
25     {
26     XMin = YMin = ZMin = std::numeric_limits<unsigned int>::max();
27     XMax = YMax = ZMax = std::numeric_limits<unsigned int>::min();
28     }
29   unsigned int XMin, XMax;
30   unsigned int YMin, YMax;
31   unsigned int ZMin, ZMax;
Print(std::ostream & os) const32   void Print(std::ostream &os) const
33     {
34     os << "Min:" << XMin << "," << YMin << "," << ZMin << "\n";
35     os << "Max:" << XMax << "," << YMax << "," << ZMax;
36     }
37 
38 };
39 
BoxRegion()40 BoxRegion::BoxRegion()
41 {
42   Internals = new BoxRegionInternals;
43 }
44 
~BoxRegion()45 BoxRegion::~BoxRegion()
46 {
47   delete Internals;
48 }
49 
SetDomain(unsigned int xmin,unsigned int xmax,unsigned int ymin,unsigned int ymax,unsigned int zmin,unsigned int zmax)50 void BoxRegion::SetDomain(unsigned int xmin, unsigned int xmax,
51     unsigned int ymin, unsigned int ymax,
52     unsigned int zmin, unsigned int zmax)
53 {
54   Internals->XMin = xmin;
55   Internals->YMin = ymin;
56   Internals->ZMin = zmin;
57   Internals->XMax = xmax;
58   Internals->YMax = ymax;
59   Internals->ZMax = zmax;
60 }
61 
Clone() const62 Region *BoxRegion::Clone() const
63 {
64   BoxRegion *br = new BoxRegion( *this );
65   return br;
66 }
67 
Empty() const68 bool BoxRegion::Empty() const
69 {
70   assert( 0 );
71   return false;
72 }
73 
IsValid() const74 bool BoxRegion::IsValid() const
75 {
76   if (Internals->XMax < Internals->XMin ||
77     Internals->YMax < Internals->YMin ||
78     Internals->ZMax < Internals->ZMin )
79     {
80     return false;
81     }
82   // Some properly crafted DICOM could have bigger values, reject them:
83   // technically there is no such restrictions for Z direction
84   if (Internals->XMax >= std::numeric_limits<uint16_t>::max() ||
85       Internals->YMax >= std::numeric_limits<uint16_t>::max() ||
86       Internals->ZMax == std::numeric_limits<uint32_t>::max() )
87   {
88     return false;
89   }
90   return true;
91 }
92 
Area() const93 size_t BoxRegion::Area() const
94 {
95   // on some system size_t is too small:
96   const uint64_t A = Internals->XMax - Internals->XMin + 1;
97   const uint64_t B = Internals->YMax - Internals->YMin + 1;
98   const uint64_t C = Internals->ZMax - Internals->ZMin + 1;
99   const uint64_t tmp = A * B;
100   if (tmp != 0 && (std::numeric_limits<size_t>::max() / tmp) < C)
101   {
102     // multiplication exceed range of unsigned
103     return 0;
104   }
105   return (size_t)(tmp * C);
106 }
107 
GetXMin() const108 unsigned int BoxRegion::GetXMin() const
109 {
110   return Internals->XMin;
111 }
GetXMax() const112 unsigned int BoxRegion::GetXMax() const
113 {
114   return Internals->XMax;
115 }
GetYMin() const116 unsigned int BoxRegion::GetYMin() const
117 {
118   return Internals->YMin;
119 }
GetYMax() const120 unsigned int BoxRegion::GetYMax() const
121 {
122   return Internals->YMax;
123 }
GetZMin() const124 unsigned int BoxRegion::GetZMin() const
125 {
126   return Internals->ZMin;
127 }
GetZMax() const128 unsigned int BoxRegion::GetZMax() const
129 {
130   return Internals->ZMax;
131 }
132 
BoundingBox(BoxRegion const & b1,BoxRegion const & b2)133 BoxRegion BoxRegion::BoundingBox(BoxRegion const & b1, BoxRegion const & b2 )
134 {
135   BoxRegion r;
136   unsigned int xmin = std::min( b1.GetXMin(), b2.GetXMin() );
137   unsigned int xmax = std::min( b1.GetXMax(), b2.GetXMax() );
138   unsigned int ymin = std::min( b1.GetYMin(), b2.GetYMin() );
139   unsigned int ymax = std::min( b1.GetYMax(), b2.GetYMax() );
140   unsigned int zmin = std::min( b1.GetZMin(), b2.GetZMin() );
141   unsigned int zmax = std::min( b1.GetZMax(), b2.GetZMax() );
142 
143   r.SetDomain(xmin, xmax, ymin, ymax, zmin, zmax);
144   return r;
145 }
146 
BoxRegion(const BoxRegion & b)147 BoxRegion::BoxRegion(const BoxRegion& b)
148 {
149   assert( b.Internals );
150   Internals = new BoxRegionInternals;
151   *Internals = *b.Internals;
152 }
153 
operator =(const BoxRegion & b)154 void BoxRegion::operator=(const BoxRegion& b)
155 {
156   assert( b.Internals );
157   *Internals = *b.Internals;
158 }
159 
ComputeBoundingBox()160 BoxRegion BoxRegion::ComputeBoundingBox()
161 {
162   return *this;
163 }
164 
Print(std::ostream & os) const165 void BoxRegion::Print(std::ostream &os) const
166 {
167   Region::Print( os );
168   os << "Domain:\n";
169   this->Internals->Print( os );
170 }
171 
172 } // end namespace gdcm
173