Mercurial > hg > orthanc
comparison Core/DicomFormat/DicomIntegerPixelAccessor.cpp @ 853:839be3022203 jpeg
DicomImageInformation
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 06 Jun 2014 11:45:16 +0200 |
parents | a811bdf8b8eb |
children | ff530685e46a |
comparison
equal
deleted
inserted
replaced
852:5944b8b80842 | 853:839be3022203 |
---|---|
47 namespace Orthanc | 47 namespace Orthanc |
48 { | 48 { |
49 DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values, | 49 DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values, |
50 const void* pixelData, | 50 const void* pixelData, |
51 size_t size) : | 51 size_t size) : |
52 information_(values), | |
52 pixelData_(pixelData), | 53 pixelData_(pixelData), |
53 size_(size) | 54 size_(size) |
54 { | 55 { |
55 unsigned int bitsAllocated; | 56 frame_ = 0; |
56 unsigned int bitsStored; | 57 frameOffset_ = (information_.GetHeight() * information_.GetWidth() * |
57 unsigned int highBit; | 58 information_.GetBytesPerPixel() * information_.GetSamplesPerPixel()); |
58 unsigned int pixelRepresentation; | |
59 planarConfiguration_ = 0; | |
60 | 59 |
61 try | 60 if (information_.GetNumberOfFrames() * frameOffset_ > size) |
62 { | |
63 width_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_COLUMNS).AsString()); | |
64 height_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_ROWS).AsString()); | |
65 samplesPerPixel_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_SAMPLES_PER_PIXEL).AsString()); | |
66 bitsAllocated = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_BITS_ALLOCATED).AsString()); | |
67 bitsStored = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_BITS_STORED).AsString()); | |
68 highBit = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_HIGH_BIT).AsString()); | |
69 pixelRepresentation = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_PIXEL_REPRESENTATION).AsString()); | |
70 | |
71 if (samplesPerPixel_ > 1) | |
72 { | |
73 // The "Planar Configuration" is only set when "Samples per Pixels" is greater than 1 | |
74 // https://www.dabsoft.ch/dicom/3/C.7.6.3.1.3/ | |
75 planarConfiguration_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_PLANAR_CONFIGURATION).AsString()); | |
76 } | |
77 } | |
78 catch (boost::bad_lexical_cast) | |
79 { | |
80 throw OrthancException(ErrorCode_NotImplemented); | |
81 } | |
82 catch (OrthancException) | |
83 { | |
84 throw OrthancException(ErrorCode_NotImplemented); | |
85 } | |
86 | |
87 frame_ = 0; | |
88 try | |
89 { | |
90 numberOfFrames_ = boost::lexical_cast<unsigned int>(values.GetValue(DICOM_TAG_NUMBER_OF_FRAMES).AsString()); | |
91 } | |
92 catch (OrthancException) | |
93 { | |
94 // If the tag "NumberOfFrames" is absent, assume there is a single frame | |
95 numberOfFrames_ = 1; | |
96 } | |
97 catch (boost::bad_lexical_cast) | |
98 { | |
99 throw OrthancException(ErrorCode_NotImplemented); | |
100 } | |
101 | |
102 if ((bitsAllocated != 8 && bitsAllocated != 16 && | |
103 bitsAllocated != 24 && bitsAllocated != 32) || | |
104 numberOfFrames_ == 0 || | |
105 (planarConfiguration_ != 0 && planarConfiguration_ != 1)) | |
106 { | |
107 throw OrthancException(ErrorCode_NotImplemented); | |
108 } | |
109 | |
110 if (bitsAllocated > 32 || | |
111 bitsStored >= 32) | |
112 { | |
113 // Not available, as the accessor internally uses int32_t values | |
114 throw OrthancException(ErrorCode_NotImplemented); | |
115 } | |
116 | |
117 if (samplesPerPixel_ == 0) | |
118 { | |
119 throw OrthancException(ErrorCode_NotImplemented); | |
120 } | |
121 | |
122 bytesPerPixel_ = bitsAllocated / 8; | |
123 shift_ = highBit + 1 - bitsStored; | |
124 frameOffset_ = height_ * width_ * bytesPerPixel_ * samplesPerPixel_; | |
125 | |
126 if (numberOfFrames_ * frameOffset_ > size) | |
127 { | 61 { |
128 throw OrthancException(ErrorCode_BadFileFormat); | 62 throw OrthancException(ErrorCode_BadFileFormat); |
129 } | 63 } |
130 | 64 |
131 /*printf("%d %d %d %d %d %d %d %d\n", width_, height_, samplesPerPixel_, bitsAllocated, | 65 if (information_.IsSigned()) |
132 bitsStored, highBit, pixelRepresentation, numberOfFrames_);*/ | |
133 | |
134 if (pixelRepresentation) | |
135 { | 66 { |
136 // Pixels are signed | 67 // Pixels are signed |
137 mask_ = (1 << (bitsStored - 1)) - 1; | 68 mask_ = (1 << (information_.GetBitsStored() - 1)) - 1; |
138 signMask_ = (1 << (bitsStored - 1)); | 69 signMask_ = (1 << (information_.GetBitsStored() - 1)); |
139 } | 70 } |
140 else | 71 else |
141 { | 72 { |
142 // Pixels are unsigned | 73 // Pixels are unsigned |
143 mask_ = (1 << bitsStored) - 1; | 74 mask_ = (1 << information_.GetBitsStored()) - 1; |
144 signMask_ = 0; | 75 signMask_ = 0; |
145 } | 76 } |
146 | 77 |
147 if (planarConfiguration_ == 0) | 78 if (information_.IsPlanar()) |
148 { | 79 { |
149 /** | 80 /** |
150 * The sample values for the first pixel are followed by the | 81 * The sample values for the first pixel are followed by the |
151 * sample values for the second pixel, etc. For RGB images, this | 82 * sample values for the second pixel, etc. For RGB images, this |
152 * means the order of the pixel values sent shall be R1, G1, B1, | 83 * means the order of the pixel values sent shall be R1, G1, B1, |
153 * R2, G2, B2, ..., etc. | 84 * R2, G2, B2, ..., etc. |
154 **/ | 85 **/ |
155 rowOffset_ = width_ * bytesPerPixel_ * samplesPerPixel_; | 86 rowOffset_ = information_.GetWidth() * information_.GetBytesPerPixel() * information_.GetSamplesPerPixel(); |
156 } | 87 } |
157 else | 88 else |
158 { | 89 { |
159 /** | 90 /** |
160 * Each color plane shall be sent contiguously. For RGB images, | 91 * Each color plane shall be sent contiguously. For RGB images, |
161 * this means the order of the pixel values sent is R1, R2, R3, | 92 * this means the order of the pixel values sent is R1, R2, R3, |
162 * ..., G1, G2, G3, ..., B1, B2, B3, etc. | 93 * ..., G1, G2, G3, ..., B1, B2, B3, etc. |
163 **/ | 94 **/ |
164 rowOffset_ = width_ * bytesPerPixel_; | 95 rowOffset_ = information_.GetWidth() * information_.GetBytesPerPixel(); |
165 } | 96 } |
166 } | 97 } |
167 | 98 |
168 | 99 |
169 void DicomIntegerPixelAccessor::GetExtremeValues(int32_t& min, | 100 void DicomIntegerPixelAccessor::GetExtremeValues(int32_t& min, |
170 int32_t& max) const | 101 int32_t& max) const |
171 { | 102 { |
172 if (height_ == 0 || width_ == 0) | 103 if (information_.GetHeight() == 0 || information_.GetWidth() == 0) |
173 { | 104 { |
174 min = max = 0; | 105 min = max = 0; |
175 return; | 106 return; |
176 } | 107 } |
177 | 108 |
178 min = std::numeric_limits<int32_t>::max(); | 109 min = std::numeric_limits<int32_t>::max(); |
179 max = std::numeric_limits<int32_t>::min(); | 110 max = std::numeric_limits<int32_t>::min(); |
180 | 111 |
181 for (unsigned int y = 0; y < height_; y++) | 112 for (unsigned int y = 0; y < information_.GetHeight(); y++) |
182 { | 113 { |
183 for (unsigned int x = 0; x < width_; x++) | 114 for (unsigned int x = 0; x < information_.GetWidth(); x++) |
184 { | 115 { |
185 for (unsigned int c = 0; c < GetChannelCount(); c++) | 116 for (unsigned int c = 0; c < information_.GetChannelCount(); c++) |
186 { | 117 { |
187 int32_t v = GetValue(x, y); | 118 int32_t v = GetValue(x, y); |
188 if (v < min) | 119 if (v < min) |
189 min = v; | 120 min = v; |
190 if (v > max) | 121 if (v > max) |
197 | 128 |
198 int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, | 129 int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, |
199 unsigned int y, | 130 unsigned int y, |
200 unsigned int channel) const | 131 unsigned int channel) const |
201 { | 132 { |
202 assert(x < width_ && y < height_ && channel < samplesPerPixel_); | 133 assert(x < information_.GetWidth() && y < information_.GetHeight() && channel < information_.GetSamplesPerPixel()); |
203 | 134 |
204 const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) + | 135 const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) + |
205 y * rowOffset_ + frame_ * frameOffset_; | 136 y * rowOffset_ + frame_ * frameOffset_; |
206 | 137 |
207 // https://www.dabsoft.ch/dicom/3/C.7.6.3.1.3/ | 138 // https://www.dabsoft.ch/dicom/3/C.7.6.3.1.3/ |
208 if (planarConfiguration_ == 0) | 139 if (information_.IsPlanar() == 0) |
209 { | 140 { |
210 /** | 141 /** |
211 * The sample values for the first pixel are followed by the | 142 * The sample values for the first pixel are followed by the |
212 * sample values for the second pixel, etc. For RGB images, this | 143 * sample values for the second pixel, etc. For RGB images, this |
213 * means the order of the pixel values sent shall be R1, G1, B1, | 144 * means the order of the pixel values sent shall be R1, G1, B1, |
214 * R2, G2, B2, ..., etc. | 145 * R2, G2, B2, ..., etc. |
215 **/ | 146 **/ |
216 pixel += channel * bytesPerPixel_ + x * samplesPerPixel_ * bytesPerPixel_; | 147 pixel += channel * information_.GetBytesPerPixel() + x * information_.GetSamplesPerPixel() * information_.GetBytesPerPixel(); |
217 } | 148 } |
218 else | 149 else |
219 { | 150 { |
220 /** | 151 /** |
221 * Each color plane shall be sent contiguously. For RGB images, | 152 * Each color plane shall be sent contiguously. For RGB images, |
222 * this means the order of the pixel values sent is R1, R2, R3, | 153 * this means the order of the pixel values sent is R1, R2, R3, |
223 * ..., G1, G2, G3, ..., B1, B2, B3, etc. | 154 * ..., G1, G2, G3, ..., B1, B2, B3, etc. |
224 **/ | 155 **/ |
225 assert(frameOffset_ % samplesPerPixel_ == 0); | 156 assert(frameOffset_ % information_.GetSamplesPerPixel() == 0); |
226 pixel += channel * frameOffset_ / samplesPerPixel_ + x * bytesPerPixel_; | 157 pixel += channel * frameOffset_ / information_.GetSamplesPerPixel() + x * information_.GetBytesPerPixel(); |
227 } | 158 } |
228 | 159 |
229 uint32_t v; | 160 uint32_t v; |
230 v = pixel[0]; | 161 v = pixel[0]; |
231 if (bytesPerPixel_ >= 2) | 162 if (information_.GetBytesPerPixel() >= 2) |
232 v = v + (static_cast<uint32_t>(pixel[1]) << 8); | 163 v = v + (static_cast<uint32_t>(pixel[1]) << 8); |
233 if (bytesPerPixel_ >= 3) | 164 if (information_.GetBytesPerPixel() >= 3) |
234 v = v + (static_cast<uint32_t>(pixel[2]) << 16); | 165 v = v + (static_cast<uint32_t>(pixel[2]) << 16); |
235 if (bytesPerPixel_ >= 4) | 166 if (information_.GetBytesPerPixel() >= 4) |
236 v = v + (static_cast<uint32_t>(pixel[3]) << 24); | 167 v = v + (static_cast<uint32_t>(pixel[3]) << 24); |
237 | 168 |
238 v = v >> shift_; | 169 v = v >> information_.GetShift(); |
239 | 170 |
240 if (v & signMask_) | 171 if (v & signMask_) |
241 { | 172 { |
242 // Signed value | 173 // Signed value |
243 // http://en.wikipedia.org/wiki/Two%27s_complement#Subtraction_from_2N | 174 // http://en.wikipedia.org/wiki/Two%27s_complement#Subtraction_from_2N |
251 } | 182 } |
252 | 183 |
253 | 184 |
254 void DicomIntegerPixelAccessor::SetCurrentFrame(unsigned int frame) | 185 void DicomIntegerPixelAccessor::SetCurrentFrame(unsigned int frame) |
255 { | 186 { |
256 if (frame >= numberOfFrames_) | 187 if (frame >= information_.GetNumberOfFrames()) |
257 { | 188 { |
258 throw OrthancException(ErrorCode_ParameterOutOfRange); | 189 throw OrthancException(ErrorCode_ParameterOutOfRange); |
259 } | 190 } |
260 | 191 |
261 frame_ = frame; | 192 frame_ = frame; |