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;