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 {