Mercurial > hg > orthanc
comparison Core/DicomParsing/Internals/DicomFrameIndex.cpp @ 3745:113a7b994a12
extracting the raw frame in the transcoder
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 12 Mar 2020 21:48:35 +0100 |
parents | 94f4a18a79cc |
children |
comparison
equal
deleted
inserted
replaced
3744:accf1b60b108 | 3745:113a7b994a12 |
---|---|
66 } | 66 } |
67 | 67 |
68 uint32_t length = item->getLength(); | 68 uint32_t length = item->getLength(); |
69 if (length == 0) | 69 if (length == 0) |
70 { | 70 { |
71 table.clear(); | 71 // Degenerate case: Empty offset table means only one frame |
72 // that overlaps all the fragments | |
73 table.resize(1); | |
74 table[0] = 0; | |
72 return; | 75 return; |
73 } | 76 } |
74 | 77 |
75 if (length % 4 != 0) | 78 if (length % 4 != 0) |
76 { | 79 { |
143 if (offsetOfFrame.size() != countFrames || | 146 if (offsetOfFrame.size() != countFrames || |
144 offsetOfFrame[0] != 0) | 147 offsetOfFrame[0] != 0) |
145 { | 148 { |
146 throw OrthancException(ErrorCode_BadFileFormat); | 149 throw OrthancException(ErrorCode_BadFileFormat); |
147 } | 150 } |
148 | |
149 | 151 |
150 // Loop over the fragments (ignoring the offset table). This is | 152 // Loop over the fragments (ignoring the offset table). This is |
151 // an alternative, faster implementation to DCMTK's | 153 // an alternative, faster implementation to DCMTK's |
152 // "DcmCodec::determineStartFragment()". | 154 // "DcmCodec::determineStartFragment()". |
153 DcmObject* fragment = pixelSequence_->nextInContainer(NULL); | 155 DcmObject* fragment = pixelSequence_->nextInContainer(NULL); |
316 } | 318 } |
317 } | 319 } |
318 }; | 320 }; |
319 | 321 |
320 | 322 |
321 | 323 unsigned int DicomFrameIndex::GetFramesCount(DcmDataset& dicom) |
322 bool DicomFrameIndex::IsVideo(DcmFileFormat& dicom) | 324 { |
323 { | |
324 // Retrieve the transfer syntax from the DICOM header | |
325 const char* value = NULL; | |
326 if (!dicom.getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() || | |
327 value == NULL) | |
328 { | |
329 return false; | |
330 } | |
331 | |
332 const std::string transferSyntax(value); | |
333 | |
334 // Video standards supported in DICOM 2016a | |
335 // http://dicom.nema.org/medical/dicom/2016a/output/html/part05.html | |
336 if (transferSyntax == "1.2.840.10008.1.2.4.100" || // MPEG2 MP@ML option of ISO/IEC MPEG2 | |
337 transferSyntax == "1.2.840.10008.1.2.4.101" || // MPEG2 MP@HL option of ISO/IEC MPEG2 | |
338 transferSyntax == "1.2.840.10008.1.2.4.102" || // MPEG-4 AVC/H.264 High Profile / Level 4.1 of ITU-T H.264 | |
339 transferSyntax == "1.2.840.10008.1.2.4.103" || // MPEG-4 AVC/H.264 BD-compat High Profile / Level 4.1 of ITU-T H.264 | |
340 transferSyntax == "1.2.840.10008.1.2.4.104" || // MPEG-4 AVC/H.264 High Profile / Level 4.2 of ITU-T H.264 | |
341 transferSyntax == "1.2.840.10008.1.2.4.105" || // MPEG-4 AVC/H.264 High Profile / Level 4.2 of ITU-T H.264 | |
342 transferSyntax == "1.2.840.10008.1.2.4.106") // MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2 of the ITU-T H.264 | |
343 { | |
344 return true; | |
345 } | |
346 | |
347 return false; | |
348 } | |
349 | |
350 | |
351 unsigned int DicomFrameIndex::GetFramesCount(DcmFileFormat& dicom) | |
352 { | |
353 // Assume 1 frame for video transfer syntaxes | |
354 if (IsVideo(dicom)) | |
355 { | |
356 return 1; | |
357 } | |
358 | |
359 const char* tmp = NULL; | 325 const char* tmp = NULL; |
360 if (!dicom.getDataset()->findAndGetString(DCM_NumberOfFrames, tmp).good() || | 326 if (!dicom.findAndGetString(DCM_NumberOfFrames, tmp).good() || |
361 tmp == NULL) | 327 tmp == NULL) |
362 { | 328 { |
363 return 1; | 329 return 1; |
364 } | 330 } |
365 | 331 |
376 { | 342 { |
377 throw OrthancException(ErrorCode_BadFileFormat); | 343 throw OrthancException(ErrorCode_BadFileFormat); |
378 } | 344 } |
379 else | 345 else |
380 { | 346 { |
381 return count; | 347 return static_cast<unsigned int>(count); |
382 } | 348 } |
383 } | 349 } |
384 | 350 |
385 | 351 |
386 DicomFrameIndex::DicomFrameIndex(DcmFileFormat& dicom) | 352 DicomFrameIndex::DicomFrameIndex(DcmDataset& dicom) |
387 { | 353 { |
388 countFrames_ = GetFramesCount(dicom); | 354 countFrames_ = GetFramesCount(dicom); |
389 if (countFrames_ == 0) | 355 if (countFrames_ == 0) |
390 { | 356 { |
391 // The image has no frame. No index is to be built. | 357 // The image has no frame. No index is to be built. |
392 return; | 358 return; |
393 } | 359 } |
394 | 360 |
395 DcmDataset& dataset = *dicom.getDataset(); | |
396 | |
397 // Test whether this image is composed of a sequence of fragments | 361 // Test whether this image is composed of a sequence of fragments |
398 DcmPixelSequence* pixelSequence = FromDcmtkBridge::GetPixelSequence(dataset); | 362 DcmPixelSequence* pixelSequence = FromDcmtkBridge::GetPixelSequence(dicom); |
399 if (pixelSequence != NULL) | 363 if (pixelSequence != NULL) |
400 { | 364 { |
401 index_.reset(new FragmentIndex(pixelSequence, countFrames_)); | 365 index_.reset(new FragmentIndex(pixelSequence, countFrames_)); |
402 return; | 366 return; |
403 } | 367 } |
404 | 368 |
405 // Extract information about the image structure | 369 // Extract information about the image structure |
406 DicomMap tags; | 370 DicomMap tags; |
407 FromDcmtkBridge::ExtractDicomSummary(tags, dataset); | 371 FromDcmtkBridge::ExtractDicomSummary(tags, dicom); |
408 | 372 |
409 DicomImageInformation information(tags); | 373 DicomImageInformation information(tags); |
410 | 374 |
411 // Access to the raw pixel data | 375 // Access to the raw pixel data |
412 if (DicomImageDecoder::IsPsmctRle1(dataset)) | 376 if (DicomImageDecoder::IsPsmctRle1(dicom)) |
413 { | 377 { |
414 index_.reset(new PsmctRle1Index(dataset, countFrames_, information.GetFrameSize())); | 378 index_.reset(new PsmctRle1Index(dicom, countFrames_, information.GetFrameSize())); |
415 } | 379 } |
416 else | 380 else |
417 { | 381 { |
418 index_.reset(new UncompressedIndex(dataset, countFrames_, information.GetFrameSize())); | 382 index_.reset(new UncompressedIndex(dicom, countFrames_, information.GetFrameSize())); |
419 } | 383 } |
420 } | 384 } |
421 | 385 |
422 | 386 |
423 void DicomFrameIndex::GetRawFrame(std::string& frame, | 387 void DicomFrameIndex::GetRawFrame(std::string& frame, |