Mercurial > hg > orthanc-wsi
comparison Framework/Inputs/DicomPyramidInstance.cpp @ 62:f45cec2c32e2
Speed-up in the Web viewer plugin
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 25 Nov 2016 18:21:15 +0100 |
parents | 147bd6dc28db |
children | 63d0a5c74460 |
comparison
equal
deleted
inserted
replaced
61:147bd6dc28db | 62:f45cec2c32e2 |
---|---|
22 #include "DicomPyramidInstance.h" | 22 #include "DicomPyramidInstance.h" |
23 | 23 |
24 #include "../../Resources/Orthanc/Core/Logging.h" | 24 #include "../../Resources/Orthanc/Core/Logging.h" |
25 #include "../../Resources/Orthanc/Core/OrthancException.h" | 25 #include "../../Resources/Orthanc/Core/OrthancException.h" |
26 #include "../../Resources/Orthanc/Core/Toolbox.h" | 26 #include "../../Resources/Orthanc/Core/Toolbox.h" |
27 #include "../../Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h" | |
28 #include "../../Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h" | |
27 #include "../DicomToolbox.h" | 29 #include "../DicomToolbox.h" |
28 | 30 |
29 #include <cassert> | 31 #include <cassert> |
30 | 32 |
31 namespace OrthancWSI | 33 namespace OrthancWSI |
32 { | 34 { |
33 static ImageCompression DetectImageCompression(const Json::Value& header) | 35 static ImageCompression DetectImageCompression(OrthancPlugins::IOrthancConnection& orthanc, |
34 { | 36 const std::string& instanceId) |
37 { | |
38 using namespace OrthancPlugins; | |
39 | |
40 DicomDatasetReader header(new FullOrthancDataset | |
41 (orthanc, "/instances/" + instanceId + "/header")); | |
42 | |
35 std::string s = Orthanc::Toolbox::StripSpaces | 43 std::string s = Orthanc::Toolbox::StripSpaces |
36 (DicomToolbox::GetMandatoryStringTag(header, "TransferSyntaxUID")); | 44 (header.GetMandatoryStringValue(DICOM_TAG_TRANSFER_SYNTAX_UID)); |
37 | 45 |
38 if (s == "1.2.840.10008.1.2" || | 46 if (s == "1.2.840.10008.1.2" || |
39 s == "1.2.840.10008.1.2.1") | 47 s == "1.2.840.10008.1.2.1") |
40 { | 48 { |
41 return ImageCompression_None; | 49 return ImageCompression_None; |
55 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 63 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
56 } | 64 } |
57 } | 65 } |
58 | 66 |
59 | 67 |
60 static Orthanc::PixelFormat DetectPixelFormat(const Json::Value& dicom) | 68 static Orthanc::PixelFormat DetectPixelFormat(OrthancPlugins::DicomDatasetReader& reader) |
61 { | 69 { |
70 using namespace OrthancPlugins; | |
71 | |
62 std::string photometric = Orthanc::Toolbox::StripSpaces | 72 std::string photometric = Orthanc::Toolbox::StripSpaces |
63 (DicomToolbox::GetMandatoryStringTag(dicom, "PhotometricInterpretation")); | 73 (reader.GetMandatoryStringValue(DICOM_TAG_PHOTOMETRIC_INTERPRETATION)); |
64 | 74 |
65 if (photometric == "PALETTE") | 75 if (photometric == "PALETTE") |
66 { | 76 { |
67 LOG(ERROR) << "Unsupported photometric interpretation: " << photometric; | 77 LOG(ERROR) << "Unsupported photometric interpretation: " << photometric; |
68 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 78 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
69 } | 79 } |
70 | 80 |
71 unsigned int bitsStored = DicomToolbox::GetUnsignedIntegerTag(dicom, "BitsStored"); | 81 unsigned int bitsStored = reader.GetUnsignedIntegerValue(DICOM_TAG_BITS_STORED); |
72 unsigned int samplesPerPixel = DicomToolbox::GetUnsignedIntegerTag(dicom, "SamplesPerPixel"); | 82 unsigned int samplesPerPixel = reader.GetUnsignedIntegerValue(DICOM_TAG_SAMPLES_PER_PIXEL); |
73 bool isSigned = (DicomToolbox::GetUnsignedIntegerTag(dicom, "PixelRepresentation") != 0); | 83 bool isSigned = (reader.GetUnsignedIntegerValue(DICOM_TAG_PIXEL_REPRESENTATION) != 0); |
74 | 84 |
75 if (bitsStored == 8 && | 85 if (bitsStored == 8 && |
76 samplesPerPixel == 1 && | 86 samplesPerPixel == 1 && |
77 !isSigned) | 87 !isSigned) |
78 { | 88 { |
103 * "/header" REST call is delayed until it is really required. | 113 * "/header" REST call is delayed until it is really required. |
104 **/ | 114 **/ |
105 | 115 |
106 if (!hasCompression_) | 116 if (!hasCompression_) |
107 { | 117 { |
108 Json::Value header; | 118 compression_ = DetectImageCompression(orthanc, instanceId_); |
109 OrthancPlugins::IOrthancConnection::RestApiGet | |
110 (header, orthanc, "/instances/" + instanceId_ + "/header?simplify"); | |
111 | |
112 hasCompression_ = true; | 119 hasCompression_ = true; |
113 compression_ = DetectImageCompression(header); | |
114 } | 120 } |
115 | 121 |
116 return compression_; | 122 return compression_; |
117 } | 123 } |
118 | 124 |
120 DicomPyramidInstance::DicomPyramidInstance(OrthancPlugins::IOrthancConnection& orthanc, | 126 DicomPyramidInstance::DicomPyramidInstance(OrthancPlugins::IOrthancConnection& orthanc, |
121 const std::string& instanceId) : | 127 const std::string& instanceId) : |
122 instanceId_(instanceId), | 128 instanceId_(instanceId), |
123 hasCompression_(false) | 129 hasCompression_(false) |
124 { | 130 { |
125 Json::Value dicom; | 131 using namespace OrthancPlugins; |
126 OrthancPlugins::IOrthancConnection::RestApiGet | 132 |
127 (dicom, orthanc, "/instances/" + instanceId + "/tags?simplify"); | 133 DicomDatasetReader reader(new FullOrthancDataset(orthanc, "/instances/" + instanceId + "/tags")); |
128 | 134 |
129 if (DicomToolbox::GetMandatoryStringTag(dicom, "SOPClassUID") != "1.2.840.10008.5.1.4.1.1.77.1.6" || | 135 if (reader.GetMandatoryStringValue(DICOM_TAG_SOP_CLASS_UID) != "1.2.840.10008.5.1.4.1.1.77.1.6" || |
130 DicomToolbox::GetMandatoryStringTag(dicom, "Modality") != "SM") | 136 reader.GetMandatoryStringValue(DICOM_TAG_MODALITY) != "SM") |
131 { | 137 { |
132 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 138 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
133 } | 139 } |
134 | 140 |
135 format_ = DetectPixelFormat(dicom); | 141 format_ = DetectPixelFormat(reader); |
136 tileWidth_ = DicomToolbox::GetUnsignedIntegerTag(dicom, "Columns"); | 142 tileWidth_ = reader.GetUnsignedIntegerValue(DICOM_TAG_COLUMNS); |
137 tileHeight_ = DicomToolbox::GetUnsignedIntegerTag(dicom, "Rows"); | 143 tileHeight_ = reader.GetUnsignedIntegerValue(DICOM_TAG_ROWS); |
138 totalWidth_ = DicomToolbox::GetUnsignedIntegerTag(dicom, "TotalPixelMatrixColumns"); | 144 totalWidth_ = reader.GetUnsignedIntegerValue(DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS); |
139 totalHeight_ = DicomToolbox::GetUnsignedIntegerTag(dicom, "TotalPixelMatrixRows"); | 145 totalHeight_ = reader.GetUnsignedIntegerValue(DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS); |
140 | 146 |
141 const Json::Value& frames = DicomToolbox::GetSequenceTag(dicom, "PerFrameFunctionalGroupsSequence"); | 147 size_t countFrames; |
142 | 148 if (!reader.GetDataset().GetSequenceSize(countFrames, DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE)) |
143 if (frames.size() != DicomToolbox::GetUnsignedIntegerTag(dicom, "NumberOfFrames")) | 149 { |
150 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
151 } | |
152 | |
153 if (countFrames != reader.GetUnsignedIntegerValue(DICOM_TAG_NUMBER_OF_FRAMES)) | |
144 { | 154 { |
145 LOG(ERROR) << "Mismatch between the number of frames in instance: " << instanceId; | 155 LOG(ERROR) << "Mismatch between the number of frames in instance: " << instanceId; |
146 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 156 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
147 } | 157 } |
148 | 158 |
149 frames_.resize(frames.size()); | 159 frames_.resize(countFrames); |
150 | 160 |
151 for (Json::Value::ArrayIndex i = 0; i < frames.size(); i++) | 161 for (size_t i = 0; i < countFrames; i++) |
152 { | 162 { |
153 const Json::Value& frame = DicomToolbox::GetSequenceTag(frames[i], "PlanePositionSlideSequence"); | 163 int xx = reader.GetIntegerValue(DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, |
154 if (frame.size() != 1) | 164 DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE, 0, |
155 { | 165 DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)); |
156 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 166 |
157 } | 167 int yy = reader.GetIntegerValue(DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, |
168 DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE, 0, | |
169 DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)); | |
158 | 170 |
159 // "-1", because coordinates are shifted by 1 in DICOM | 171 // "-1", because coordinates are shifted by 1 in DICOM |
160 int xx = DicomToolbox::GetIntegerTag(frame[0], "ColumnPositionInTotalImagePixelMatrix") - 1; | 172 xx -= 1; |
161 int yy = DicomToolbox::GetIntegerTag(frame[0], "RowPositionInTotalImagePixelMatrix") - 1; | 173 yy -= 1; |
162 | 174 |
163 unsigned int x = static_cast<unsigned int>(xx); | 175 unsigned int x = static_cast<unsigned int>(xx); |
164 unsigned int y = static_cast<unsigned int>(yy); | 176 unsigned int y = static_cast<unsigned int>(yy); |
165 | 177 |
166 if (xx < 0 || | 178 if (xx < 0 || |