comparison OrthancFramework/Sources/DicomParsing/ParsedDicomFile.cpp @ 4203:4d42408da117

improving const-correctness in ParsedDicomFile
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 17 Sep 2020 15:01:31 +0200
parents 7112a8af0b63
children afad57ac30ef
comparison
equal deleted inserted replaced
4202:2007ab69ac16 4203:4d42408da117
70 70
71 #include "ParsedDicomFile.h" 71 #include "ParsedDicomFile.h"
72 72
73 #include "FromDcmtkBridge.h" 73 #include "FromDcmtkBridge.h"
74 #include "Internals/DicomFrameIndex.h" 74 #include "Internals/DicomFrameIndex.h"
75 #include "Internals/DicomImageDecoder.h"
75 #include "ToDcmtkBridge.h" 76 #include "ToDcmtkBridge.h"
76 77
77 #include "../Images/PamReader.h" 78 #include "../Images/PamReader.h"
78 #include "../Logging.h" 79 #include "../Logging.h"
79 #include "../OrthancException.h" 80 #include "../OrthancException.h"
440 } 441 }
441 442
442 443
443 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1 444 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
444 void ParsedDicomFile::SendPathValue(RestApiOutput& output, 445 void ParsedDicomFile::SendPathValue(RestApiOutput& output,
445 const UriComponents& uri) 446 const UriComponents& uri) const
446 { 447 {
447 DcmItem* dicom = GetDcmtkObject().getDataset(); 448 DcmItem* dicom = GetDcmtkObjectConst().getDataset();
448 E_TransferSyntax transferSyntax = GetDcmtkObject().getDataset()->getCurrentXfer(); 449 E_TransferSyntax transferSyntax = GetDcmtkObjectConst().getDataset()->getCurrentXfer();
449 450
450 // Special case: Accessing the pixel data 451 // Special case: Accessing the pixel data
451 if (uri.size() == 1 || 452 if (uri.size() == 1 ||
452 uri.size() == 2) 453 uri.size() == 2)
453 { 454 {
851 } 852 }
852 } 853 }
853 854
854 855
855 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1 856 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
856 void ParsedDicomFile::Answer(RestApiOutput& output) 857 void ParsedDicomFile::Answer(RestApiOutput& output) const
857 { 858 {
858 std::string serialized; 859 std::string serialized;
859 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, *GetDcmtkObject().getDataset())) 860 if (FromDcmtkBridge::SaveToMemoryBuffer(serialized, *GetDcmtkObjectConst().getDataset()))
860 { 861 {
861 output.AnswerBuffer(serialized, MimeType_Dicom); 862 output.AnswerBuffer(serialized, MimeType_Dicom);
862 } 863 }
863 } 864 }
864 #endif 865 #endif
865 866
866 867
867 bool ParsedDicomFile::GetTagValue(std::string& value, 868 bool ParsedDicomFile::GetTagValue(std::string& value,
868 const DicomTag& tag) 869 const DicomTag& tag) const
869 { 870 {
870 DcmTagKey k(tag.GetGroup(), tag.GetElement()); 871 DcmTagKey k(tag.GetGroup(), tag.GetElement());
871 DcmDataset& dataset = *GetDcmtkObject().getDataset(); 872 DcmDataset& dataset = *GetDcmtkObjectConst().getDataset();
872 873
873 if (tag.IsPrivate() || 874 if (tag.IsPrivate() ||
874 FromDcmtkBridge::IsUnknownTag(tag) || 875 FromDcmtkBridge::IsUnknownTag(tag) ||
875 tag == DICOM_TAG_PIXEL_DATA || 876 tag == DICOM_TAG_PIXEL_DATA ||
876 tag == DICOM_TAG_ENCAPSULATED_DOCUMENT) 877 tag == DICOM_TAG_ENCAPSULATED_DOCUMENT)
928 return true; 929 return true;
929 } 930 }
930 } 931 }
931 932
932 933
933 DicomInstanceHasher ParsedDicomFile::GetHasher() 934 DicomInstanceHasher ParsedDicomFile::GetHasher() const
934 { 935 {
935 std::string patientId, studyUid, seriesUid, instanceUid; 936 std::string patientId, studyUid, seriesUid, instanceUid;
936 937
937 if (!GetTagValue(patientId, DICOM_TAG_PATIENT_ID)) 938 if (!GetTagValue(patientId, DICOM_TAG_PATIENT_ID))
938 { 939 {
1105 1106
1106 ParsedDicomFile::ParsedDicomFile(const ParsedDicomFile& other, 1107 ParsedDicomFile::ParsedDicomFile(const ParsedDicomFile& other,
1107 bool keepSopInstanceUid) : 1108 bool keepSopInstanceUid) :
1108 pimpl_(new PImpl) 1109 pimpl_(new PImpl)
1109 { 1110 {
1110 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.GetDcmtkObject().clone())); 1111 pimpl_->file_.reset(dynamic_cast<DcmFileFormat*>(other.GetDcmtkObjectConst().clone()));
1111 1112
1112 if (!keepSopInstanceUid) 1113 if (!keepSopInstanceUid)
1113 { 1114 {
1114 // Create a new instance-level identifier 1115 // Create a new instance-level identifier
1115 ReplacePlainString(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance)); 1116 ReplacePlainString(DICOM_TAG_SOP_INSTANCE_UID, FromDcmtkBridge::GenerateUniqueIdentifier(ResourceType_Instance));
1133 { 1134 {
1134 pimpl_->file_.reset(dicom); // No cloning 1135 pimpl_->file_.reset(dicom); // No cloning
1135 } 1136 }
1136 1137
1137 1138
1138 DcmFileFormat& ParsedDicomFile::GetDcmtkObject() const 1139 DcmFileFormat& ParsedDicomFile::GetDcmtkObjectConst() const
1139 { 1140 {
1140 if (pimpl_->file_.get() == NULL) 1141 if (pimpl_->file_.get() == NULL)
1141 { 1142 {
1142 throw OrthancException(ErrorCode_BadSequenceOfCalls, 1143 throw OrthancException(ErrorCode_BadSequenceOfCalls,
1143 "ReleaseDcmtkObject() was called"); 1144 "ReleaseDcmtkObject() was called");
1162 return pimpl_->file_.release(); 1163 return pimpl_->file_.release();
1163 } 1164 }
1164 } 1165 }
1165 1166
1166 1167
1167 ParsedDicomFile* ParsedDicomFile::Clone(bool keepSopInstanceUid) 1168 ParsedDicomFile* ParsedDicomFile::Clone(bool keepSopInstanceUid) const
1168 { 1169 {
1169 return new ParsedDicomFile(*this, keepSopInstanceUid); 1170 return new ParsedDicomFile(*this, keepSopInstanceUid);
1170 } 1171 }
1171 1172
1172 1173
1401 1402
1402 1403
1403 Encoding ParsedDicomFile::DetectEncoding(bool& hasCodeExtensions) const 1404 Encoding ParsedDicomFile::DetectEncoding(bool& hasCodeExtensions) const
1404 { 1405 {
1405 return FromDcmtkBridge::DetectEncoding(hasCodeExtensions, 1406 return FromDcmtkBridge::DetectEncoding(hasCodeExtensions,
1406 *GetDcmtkObject().getDataset(), 1407 *GetDcmtkObjectConst().getDataset(),
1407 GetDefaultDicomEncoding()); 1408 GetDefaultDicomEncoding());
1408 } 1409 }
1409 1410
1410 1411
1411 void ParsedDicomFile::SetEncoding(Encoding encoding) 1412 void ParsedDicomFile::SetEncoding(Encoding encoding)
1422 } 1423 }
1423 1424
1424 void ParsedDicomFile::DatasetToJson(Json::Value& target, 1425 void ParsedDicomFile::DatasetToJson(Json::Value& target,
1425 DicomToJsonFormat format, 1426 DicomToJsonFormat format,
1426 DicomToJsonFlags flags, 1427 DicomToJsonFlags flags,
1427 unsigned int maxStringLength) 1428 unsigned int maxStringLength) const
1428 { 1429 {
1429 std::set<DicomTag> ignoreTagLength; 1430 std::set<DicomTag> ignoreTagLength;
1430 FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(), 1431 FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObjectConst().getDataset(),
1431 format, flags, maxStringLength, ignoreTagLength); 1432 format, flags, maxStringLength, ignoreTagLength);
1432 } 1433 }
1433 1434
1434 1435
1435 void ParsedDicomFile::DatasetToJson(Json::Value& target, 1436 void ParsedDicomFile::DatasetToJson(Json::Value& target,
1436 DicomToJsonFormat format, 1437 DicomToJsonFormat format,
1437 DicomToJsonFlags flags, 1438 DicomToJsonFlags flags,
1438 unsigned int maxStringLength, 1439 unsigned int maxStringLength,
1439 const std::set<DicomTag>& ignoreTagLength) 1440 const std::set<DicomTag>& ignoreTagLength) const
1440 { 1441 {
1441 FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObject().getDataset(), 1442 FromDcmtkBridge::ExtractDicomAsJson(target, *GetDcmtkObjectConst().getDataset(),
1442 format, flags, maxStringLength, ignoreTagLength); 1443 format, flags, maxStringLength, ignoreTagLength);
1443 } 1444 }
1444 1445
1445 1446
1446 void ParsedDicomFile::HeaderToJson(Json::Value& target, 1447 void ParsedDicomFile::HeaderToJson(Json::Value& target,
1447 DicomToJsonFormat format) 1448 DicomToJsonFormat format) const
1448 { 1449 {
1449 FromDcmtkBridge::ExtractHeaderAsJson(target, *GetDcmtkObject().getMetaInfo(), format, DicomToJsonFlags_None, 0); 1450 FromDcmtkBridge::ExtractHeaderAsJson(target, *GetDcmtkObjectConst().getMetaInfo(), format, DicomToJsonFlags_None, 0);
1450 } 1451 }
1451 1452
1452 1453
1453 bool ParsedDicomFile::HasTag(const DicomTag& tag) const 1454 bool ParsedDicomFile::HasTag(const DicomTag& tag) const
1454 { 1455 {
1455 DcmTag key(tag.GetGroup(), tag.GetElement()); 1456 DcmTag key(tag.GetGroup(), tag.GetElement());
1456 return GetDcmtkObject().getDataset()->tagExists(key); 1457 return GetDcmtkObjectConst().getDataset()->tagExists(key);
1457 } 1458 }
1458 1459
1459 1460
1460 void ParsedDicomFile::EmbedPdf(const std::string& pdf) 1461 void ParsedDicomFile::EmbedPdf(const std::string& pdf)
1461 { 1462 {
1503 throw OrthancException(ErrorCode_NotEnoughMemory); 1504 throw OrthancException(ErrorCode_NotEnoughMemory);
1504 } 1505 }
1505 } 1506 }
1506 1507
1507 1508
1508 bool ParsedDicomFile::ExtractPdf(std::string& pdf) 1509 bool ParsedDicomFile::ExtractPdf(std::string& pdf) const
1509 { 1510 {
1510 std::string sop, mime; 1511 std::string sop, mime;
1511 1512
1512 if (!GetTagValue(sop, DICOM_TAG_SOP_CLASS_UID) || 1513 if (!GetTagValue(sop, DICOM_TAG_SOP_CLASS_UID) ||
1513 !GetTagValue(mime, FromDcmtkBridge::Convert(DCM_MIMETypeOfEncapsulatedDocument)) || 1514 !GetTagValue(mime, FromDcmtkBridge::Convert(DCM_MIMETypeOfEncapsulatedDocument)) ||
1580 } 1581 }
1581 1582
1582 1583
1583 void ParsedDicomFile::GetRawFrame(std::string& target, 1584 void ParsedDicomFile::GetRawFrame(std::string& target,
1584 MimeType& mime, 1585 MimeType& mime,
1585 unsigned int frameId) 1586 unsigned int frameId) const
1586 { 1587 {
1587 if (pimpl_->frameIndex_.get() == NULL) 1588 if (pimpl_->frameIndex_.get() == NULL)
1588 { 1589 {
1589 assert(pimpl_->file_ != NULL && 1590 assert(pimpl_->file_ != NULL &&
1590 GetDcmtkObject().getDataset() != NULL); 1591 GetDcmtkObjectConst().getDataset() != NULL);
1591 pimpl_->frameIndex_.reset(new DicomFrameIndex(*GetDcmtkObject().getDataset())); 1592 pimpl_->frameIndex_.reset(new DicomFrameIndex(*GetDcmtkObjectConst().getDataset()));
1592 } 1593 }
1593 1594
1594 pimpl_->frameIndex_->GetRawFrame(target, frameId); 1595 pimpl_->frameIndex_->GetRawFrame(target, frameId);
1595 1596
1596 E_TransferSyntax transferSyntax = GetDcmtkObject().getDataset()->getCurrentXfer(); 1597 E_TransferSyntax transferSyntax = GetDcmtkObjectConst().getDataset()->getCurrentXfer();
1597 switch (transferSyntax) 1598 switch (transferSyntax)
1598 { 1599 {
1599 case EXS_JPEGProcess1: 1600 case EXS_JPEGProcess1:
1600 mime = MimeType_Jpeg; 1601 mime = MimeType_Jpeg;
1601 break; 1602 break;
1619 1620
1620 1621
1621 unsigned int ParsedDicomFile::GetFramesCount() const 1622 unsigned int ParsedDicomFile::GetFramesCount() const
1622 { 1623 {
1623 assert(pimpl_->file_ != NULL && 1624 assert(pimpl_->file_ != NULL &&
1624 GetDcmtkObject().getDataset() != NULL); 1625 GetDcmtkObjectConst().getDataset() != NULL);
1625 return DicomFrameIndex::GetFramesCount(*GetDcmtkObject().getDataset()); 1626 return DicomFrameIndex::GetFramesCount(*GetDcmtkObjectConst().getDataset());
1626 } 1627 }
1627 1628
1628 1629
1629 void ParsedDicomFile::ChangeEncoding(Encoding target) 1630 void ParsedDicomFile::ChangeEncoding(Encoding target)
1630 { 1631 {
1641 1642
1642 void ParsedDicomFile::ExtractDicomSummary(DicomMap& target, 1643 void ParsedDicomFile::ExtractDicomSummary(DicomMap& target,
1643 unsigned int maxTagLength) const 1644 unsigned int maxTagLength) const
1644 { 1645 {
1645 std::set<DicomTag> ignoreTagLength; 1646 std::set<DicomTag> ignoreTagLength;
1646 FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObject().getDataset(), 1647 FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObjectConst().getDataset(),
1647 maxTagLength, ignoreTagLength); 1648 maxTagLength, ignoreTagLength);
1648 } 1649 }
1649 1650
1650 1651
1651 void ParsedDicomFile::ExtractDicomSummary(DicomMap& target, 1652 void ParsedDicomFile::ExtractDicomSummary(DicomMap& target,
1652 unsigned int maxTagLength, 1653 unsigned int maxTagLength,
1653 const std::set<DicomTag>& ignoreTagLength) const 1654 const std::set<DicomTag>& ignoreTagLength) const
1654 { 1655 {
1655 FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObject().getDataset(), 1656 FromDcmtkBridge::ExtractDicomSummary(target, *GetDcmtkObjectConst().getDataset(),
1656 maxTagLength, ignoreTagLength); 1657 maxTagLength, ignoreTagLength);
1657 } 1658 }
1658 1659
1659 1660
1660 bool ParsedDicomFile::LookupTransferSyntax(std::string& result) 1661 bool ParsedDicomFile::LookupTransferSyntax(std::string& result) const
1661 { 1662 {
1662 #if 0 1663 #if 0
1663 // This was the implementation in Orthanc <= 1.6.1 1664 // This was the implementation in Orthanc <= 1.6.1
1664 1665
1665 // TODO - Shouldn't "dataset.getCurrentXfer()" be used instead of 1666 // TODO - Shouldn't "dataset.getCurrentXfer()" be used instead of
1666 // using the meta header? 1667 // using the meta header?
1667 const char* value = NULL; 1668 const char* value = NULL;
1668 1669
1669 if (GetDcmtkObject().getMetaInfo() != NULL && 1670 if (GetDcmtkObjectConst().getMetaInfo() != NULL &&
1670 GetDcmtkObject().getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() && 1671 GetDcmtkObjectConst().getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, value).good() &&
1671 value != NULL) 1672 value != NULL)
1672 { 1673 {
1673 result.assign(value); 1674 result.assign(value);
1674 return true; 1675 return true;
1675 } 1676 }
1677 { 1678 {
1678 return false; 1679 return false;
1679 } 1680 }
1680 #else 1681 #else
1681 DicomTransferSyntax s; 1682 DicomTransferSyntax s;
1682 if (FromDcmtkBridge::LookupOrthancTransferSyntax(s, GetDcmtkObject())) 1683 if (FromDcmtkBridge::LookupOrthancTransferSyntax(s, GetDcmtkObjectConst()))
1683 { 1684 {
1684 result.assign(GetTransferSyntaxUid(s)); 1685 result.assign(GetTransferSyntaxUid(s));
1685 return true; 1686 return true;
1686 } 1687 }
1687 else 1688 else
1695 bool ParsedDicomFile::LookupPhotometricInterpretation(PhotometricInterpretation& result) const 1696 bool ParsedDicomFile::LookupPhotometricInterpretation(PhotometricInterpretation& result) const
1696 { 1697 {
1697 DcmTagKey k(DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetGroup(), 1698 DcmTagKey k(DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetGroup(),
1698 DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetElement()); 1699 DICOM_TAG_PHOTOMETRIC_INTERPRETATION.GetElement());
1699 1700
1700 DcmDataset& dataset = *GetDcmtkObject().getDataset(); 1701 DcmDataset& dataset = *GetDcmtkObjectConst().getDataset();
1701 1702
1702 const char *c = NULL; 1703 const char *c = NULL;
1703 if (dataset.findAndGetString(k, c).good() && 1704 if (dataset.findAndGetString(k, c).good() &&
1704 c != NULL) 1705 c != NULL)
1705 { 1706 {
1711 return false; 1712 return false;
1712 } 1713 }
1713 } 1714 }
1714 1715
1715 1716
1716 void ParsedDicomFile::Apply(ITagVisitor& visitor) 1717 void ParsedDicomFile::Apply(ITagVisitor& visitor) const
1717 { 1718 {
1718 FromDcmtkBridge::Apply(*GetDcmtkObject().getDataset(), visitor, GetDefaultDicomEncoding()); 1719 FromDcmtkBridge::Apply(*GetDcmtkObjectConst().getDataset(), visitor, GetDefaultDicomEncoding());
1720 }
1721
1722
1723 ImageAccessor* ParsedDicomFile::DecodeFrame(unsigned int frame) const
1724 {
1725 if (GetDcmtkObjectConst().getDataset() == NULL)
1726 {
1727 throw OrthancException(ErrorCode_InternalError);
1728 }
1729 else
1730 {
1731 return DicomImageDecoder::Decode(*GetDcmtkObjectConst().getDataset(), frame);
1732 }
1719 } 1733 }
1720 } 1734 }