comparison OrthancFramework/Sources/DicomFormat/DicomStreamReader.cpp @ 4494:39192eb9b43d

New metadata automatically computed at the instance level: "PixelDataOffset"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 04 Feb 2021 15:31:00 +0100
parents b57ca702a430
children 7053502fbf97
comparison
equal deleted inserted replaced
4493:b57ca702a430 4494:39192eb9b43d
25 25
26 #include "../OrthancException.h" 26 #include "../OrthancException.h"
27 27
28 #include <cassert> 28 #include <cassert>
29 #include <sstream> 29 #include <sstream>
30 30 #include <boost/iostreams/device/array.hpp>
31 #include <boost/iostreams/stream.hpp>
32
33
34 #include <iostream>
31 35
32 namespace Orthanc 36 namespace Orthanc
33 { 37 {
34 static bool IsNormalizationNeeded(const std::string& source, 38 static bool IsNormalizationNeeded(const std::string& source,
35 ValueRepresentation vr) 39 ValueRepresentation vr)
617 621
618 uint64_t GetPixelDataOffset() const 622 uint64_t GetPixelDataOffset() const
619 { 623 {
620 return pixelDataOffset_; 624 return pixelDataOffset_;
621 } 625 }
626
627 static bool LookupPixelDataOffset(uint64_t& offset,
628 std::istream& stream)
629 {
630 PixelDataVisitor visitor;
631 bool isLittleEndian;
632
633 {
634 DicomStreamReader reader(stream);
635
636 try
637 {
638 reader.Consume(visitor);
639 isLittleEndian = reader.IsLittleEndian();
640 }
641 catch (OrthancException& e)
642 {
643 // Invalid DICOM file
644 return false;
645 }
646 }
647
648 if (visitor.HasPixelData())
649 {
650 // Sanity check if we face an unsupported DICOM file: Make
651 // sure that we can read DICOM_TAG_PIXEL_DATA at the reported
652 // position in the stream
653 stream.seekg(visitor.GetPixelDataOffset(), stream.beg);
654
655 std::string s;
656 s.resize(4);
657 stream.read(&s[0], s.size());
658
659 if (!isLittleEndian)
660 {
661 // Byte swapping if reading a file whose transfer syntax is
662 // 1.2.840.10008.1.2.2 (big endian explicit)
663 std::swap(s[0], s[1]);
664 std::swap(s[2], s[3]);
665 }
666
667 if (stream.gcount() == static_cast<std::streamsize>(s.size()) &&
668 s[0] == char(0xe0) &&
669 s[1] == char(0x7f) &&
670 s[2] == char(0x10) &&
671 s[3] == char(0x00))
672 {
673 offset = visitor.GetPixelDataOffset();
674 return true;
675 }
676 else
677 {
678 return false;
679 }
680 }
681 else
682 {
683 return false;
684 }
685 }
622 }; 686 };
623 687
624 688
625 bool DicomStreamReader::LookupPixelDataOffset(uint64_t& offset, 689 bool DicomStreamReader::LookupPixelDataOffset(uint64_t& offset,
626 const std::string& dicom) 690 const std::string& dicom)
627 { 691 {
628 std::stringstream stream(dicom); 692 std::stringstream stream(dicom);
629 693 return PixelDataVisitor::LookupPixelDataOffset(offset, stream);
630 DicomStreamReader reader(stream); 694 }
631 695
632 PixelDataVisitor visitor; 696
633 697 bool DicomStreamReader::LookupPixelDataOffset(uint64_t& offset,
634 try 698 const void* buffer,
635 { 699 size_t size)
636 reader.Consume(visitor); 700 {
637 } 701 boost::iostreams::array_source source(reinterpret_cast<const char*>(buffer), size);
638 catch (OrthancException& e) 702 boost::iostreams::stream<boost::iostreams::array_source> stream(source);
639 { 703 return PixelDataVisitor::LookupPixelDataOffset(offset, stream);
640 // Invalid DICOM file
641 return false;
642 }
643
644 if (visitor.HasPixelData())
645 {
646 offset = visitor.GetPixelDataOffset();
647 return true;
648 }
649 else
650 {
651 return false;
652 }
653 } 704 }
654 } 705 }
706