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 ||