Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomFormat/DicomImageInformation.cpp @ 4827:4cfd96732076
Support decoding of black-and-white images (with 1 bit per pixel), notably DICOM SEG
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 25 Nov 2021 15:52:54 +0100 |
parents | d9473bd5ed43 |
children | 7053502fbf97 |
comparison
equal
deleted
inserted
replaced
4825:381c2ca04860 | 4827:4cfd96732076 |
---|---|
122 if (!values.ParseUnsignedInteger32(bitsStored_, DICOM_TAG_BITS_STORED)) | 122 if (!values.ParseUnsignedInteger32(bitsStored_, DICOM_TAG_BITS_STORED)) |
123 { | 123 { |
124 bitsStored_ = bitsAllocated_; | 124 bitsStored_ = bitsAllocated_; |
125 } | 125 } |
126 | 126 |
127 if (bitsStored_ > bitsAllocated_) | |
128 { | |
129 throw OrthancException(ErrorCode_BadFileFormat); | |
130 } | |
131 | |
127 if (!values.ParseUnsignedInteger32(highBit_, DICOM_TAG_HIGH_BIT)) | 132 if (!values.ParseUnsignedInteger32(highBit_, DICOM_TAG_HIGH_BIT)) |
128 { | 133 { |
129 highBit_ = bitsStored_ - 1; | 134 highBit_ = bitsStored_ - 1; |
130 } | 135 } |
131 | 136 |
166 { | 171 { |
167 numberOfFrames_ = 1; | 172 numberOfFrames_ = 1; |
168 } | 173 } |
169 | 174 |
170 if (bitsAllocated_ != 8 && bitsAllocated_ != 16 && | 175 if (bitsAllocated_ != 8 && bitsAllocated_ != 16 && |
171 bitsAllocated_ != 24 && bitsAllocated_ != 32) | 176 bitsAllocated_ != 24 && bitsAllocated_ != 32 && |
177 bitsAllocated_ != 1 /* new in Orthanc 1.9.8 */) | |
172 { | 178 { |
173 throw OrthancException(ErrorCode_IncompatibleImageFormat, "Image not supported: " + boost::lexical_cast<std::string>(bitsAllocated_) + " bits allocated"); | 179 throw OrthancException(ErrorCode_IncompatibleImageFormat, "Image not supported: " + boost::lexical_cast<std::string>(bitsAllocated_) + " bits allocated"); |
174 } | 180 } |
175 else if (numberOfFrames_ == 0) | 181 else if (numberOfFrames_ == 0) |
176 { | 182 { |
184 if (samplesPerPixel_ == 0) | 190 if (samplesPerPixel_ == 0) |
185 { | 191 { |
186 throw OrthancException(ErrorCode_IncompatibleImageFormat, "Image not supported: samples per pixel is 0"); | 192 throw OrthancException(ErrorCode_IncompatibleImageFormat, "Image not supported: samples per pixel is 0"); |
187 } | 193 } |
188 | 194 |
189 bytesPerValue_ = bitsAllocated_ / 8; | 195 if (bitsStored_ == 1) |
196 { | |
197 // This is the case of DICOM SEG, new in Orthanc 1.9.8 | |
198 if (bitsAllocated_ != 1) | |
199 { | |
200 throw OrthancException(ErrorCode_BadFileFormat); | |
201 } | |
202 else if (width_ % 8 != 0) | |
203 { | |
204 throw OrthancException(ErrorCode_BadFileFormat, "Bad number of columns for a black-and-white image"); | |
205 } | |
206 else | |
207 { | |
208 bytesPerValue_ = 0; // Arbitrary initialization | |
209 } | |
210 } | |
211 else | |
212 { | |
213 bytesPerValue_ = bitsAllocated_ / 8; | |
214 } | |
190 | 215 |
191 isPlanar_ = (planarConfiguration != 0 ? true : false); | 216 isPlanar_ = (planarConfiguration != 0 ? true : false); |
192 isSigned_ = (pixelRepresentation != 0 ? true : false); | 217 isSigned_ = (pixelRepresentation != 0 ? true : false); |
193 } | 218 } |
194 | 219 |
235 return bitsStored_; | 260 return bitsStored_; |
236 } | 261 } |
237 | 262 |
238 size_t DicomImageInformation::GetBytesPerValue() const | 263 size_t DicomImageInformation::GetBytesPerValue() const |
239 { | 264 { |
240 return bytesPerValue_; | 265 if (bitsStored_ == 1) |
266 { | |
267 throw OrthancException(ErrorCode_BadSequenceOfCalls, | |
268 "This call is incompatible with black-and-white images"); | |
269 } | |
270 else | |
271 { | |
272 assert(bitsAllocated_ >= 8); | |
273 return bytesPerValue_; | |
274 } | |
241 } | 275 } |
242 | 276 |
243 bool DicomImageInformation::IsSigned() const | 277 bool DicomImageInformation::IsSigned() const |
244 { | 278 { |
245 return isSigned_; | 279 return isSigned_; |
313 if (GetBitsAllocated() == 32 && GetChannelCount() == 1 && !IsSigned()) | 347 if (GetBitsAllocated() == 32 && GetChannelCount() == 1 && !IsSigned()) |
314 { | 348 { |
315 format = PixelFormat_Grayscale32; | 349 format = PixelFormat_Grayscale32; |
316 return true; | 350 return true; |
317 } | 351 } |
352 | |
353 if (GetBitsStored() == 1 && GetChannelCount() == 1 && !IsSigned()) | |
354 { | |
355 // This is the case of DICOM SEG, new in Orthanc 1.9.8 | |
356 format = PixelFormat_Grayscale8; | |
357 return true; | |
358 } | |
318 } | 359 } |
319 | 360 |
320 if (GetBitsStored() == 8 && | 361 if (GetBitsStored() == 8 && |
321 GetChannelCount() == 3 && | 362 GetChannelCount() == 3 && |
322 !IsSigned() && | 363 !IsSigned() && |
330 } | 371 } |
331 | 372 |
332 | 373 |
333 size_t DicomImageInformation::GetFrameSize() const | 374 size_t DicomImageInformation::GetFrameSize() const |
334 { | 375 { |
335 return (GetHeight() * | 376 if (bitsStored_ == 1) |
336 GetWidth() * | 377 { |
337 GetBytesPerValue() * | 378 assert(GetWidth() % 8 == 0); |
338 GetChannelCount()); | 379 |
380 if (GetChannelCount() == 1) | |
381 { | |
382 return GetHeight() * GetWidth() / 8; | |
383 } | |
384 else | |
385 { | |
386 throw OrthancException(ErrorCode_IncompatibleImageFormat, | |
387 "Image not supported (multi-channel black-and-image image)"); | |
388 } | |
389 } | |
390 else | |
391 { | |
392 return (GetHeight() * | |
393 GetWidth() * | |
394 GetBytesPerValue() * | |
395 GetChannelCount()); | |
396 } | |
339 } | 397 } |
340 | 398 |
341 | 399 |
342 unsigned int DicomImageInformation::GetUsefulTagLength() | 400 unsigned int DicomImageInformation::GetUsefulTagLength() |
343 { | 401 { |