Mercurial > hg > orthanc-wsi
annotate 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 |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU Affero General Public License | |
8 * as published by the Free Software Foundation, either version 3 of | |
9 * the License, or (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Affero General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Affero General Public License | |
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 **/ | |
19 | |
20 | |
16
7a88c614be04
preparing for precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
21 #include "../PrecompiledHeadersWSI.h" |
0 | 22 #include "DicomPyramidInstance.h" |
23 | |
59
7a3853d51c45
Move "Framework/Orthanc/" as "Resources/Orthanc/"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
24 #include "../../Resources/Orthanc/Core/Logging.h" |
7a3853d51c45
Move "Framework/Orthanc/" as "Resources/Orthanc/"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
25 #include "../../Resources/Orthanc/Core/OrthancException.h" |
7a3853d51c45
Move "Framework/Orthanc/" as "Resources/Orthanc/"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
56
diff
changeset
|
26 #include "../../Resources/Orthanc/Core/Toolbox.h" |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
27 #include "../../Resources/Orthanc/Plugins/Samples/Common/DicomDatasetReader.h" |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
28 #include "../../Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h" |
0 | 29 #include "../DicomToolbox.h" |
30 | |
31 #include <cassert> | |
32 | |
33 namespace OrthancWSI | |
34 { | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
35 static ImageCompression DetectImageCompression(OrthancPlugins::IOrthancConnection& orthanc, |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
36 const std::string& instanceId) |
0 | 37 { |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
38 using namespace OrthancPlugins; |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
39 |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
40 DicomDatasetReader header(new FullOrthancDataset |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
41 (orthanc, "/instances/" + instanceId + "/header")); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
42 |
0 | 43 std::string s = Orthanc::Toolbox::StripSpaces |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
44 (header.GetMandatoryStringValue(DICOM_TAG_TRANSFER_SYNTAX_UID)); |
0 | 45 |
46 if (s == "1.2.840.10008.1.2" || | |
47 s == "1.2.840.10008.1.2.1") | |
48 { | |
49 return ImageCompression_None; | |
50 } | |
51 else if (s == "1.2.840.10008.1.2.4.50") | |
52 { | |
53 return ImageCompression_Jpeg; | |
54 } | |
55 else if (s == "1.2.840.10008.1.2.4.90" || | |
56 s == "1.2.840.10008.1.2.4.91") | |
57 { | |
58 return ImageCompression_Jpeg2000; | |
59 } | |
60 else | |
61 { | |
62 LOG(ERROR) << "Unsupported transfer syntax: " << s; | |
63 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
64 } | |
65 } | |
66 | |
67 | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
68 static Orthanc::PixelFormat DetectPixelFormat(OrthancPlugins::DicomDatasetReader& reader) |
0 | 69 { |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
70 using namespace OrthancPlugins; |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
71 |
0 | 72 std::string photometric = Orthanc::Toolbox::StripSpaces |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
73 (reader.GetMandatoryStringValue(DICOM_TAG_PHOTOMETRIC_INTERPRETATION)); |
0 | 74 |
75 if (photometric == "PALETTE") | |
76 { | |
77 LOG(ERROR) << "Unsupported photometric interpretation: " << photometric; | |
78 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
79 } | |
80 | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
81 unsigned int bitsStored = reader.GetUnsignedIntegerValue(DICOM_TAG_BITS_STORED); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
82 unsigned int samplesPerPixel = reader.GetUnsignedIntegerValue(DICOM_TAG_SAMPLES_PER_PIXEL); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
83 bool isSigned = (reader.GetUnsignedIntegerValue(DICOM_TAG_PIXEL_REPRESENTATION) != 0); |
0 | 84 |
85 if (bitsStored == 8 && | |
86 samplesPerPixel == 1 && | |
87 !isSigned) | |
88 { | |
89 return Orthanc::PixelFormat_Grayscale8; | |
90 } | |
91 else if (bitsStored == 8 && | |
92 samplesPerPixel == 3 && | |
93 !isSigned) | |
94 { | |
95 return Orthanc::PixelFormat_RGB24; | |
96 } | |
97 else | |
98 { | |
99 LOG(ERROR) << "Unsupported pixel format"; | |
100 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
101 } | |
102 } | |
103 | |
56
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
104 |
61
147bd6dc28db
refactoring using new items in the plugin toolbox of Orthanc
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
105 ImageCompression DicomPyramidInstance::GetImageCompression(OrthancPlugins::IOrthancConnection& orthanc) |
56
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
106 { |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
107 /** |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
108 * Lazy detection of the image compression using the transfer |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
109 * syntax stored inside the DICOM header. Given the fact that |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
110 * reading the header is a time-consuming operation (it implies |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
111 * the decoding of the DICOM image by Orthanc, whereas the "/tags" |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
112 * endpoint only reads the "DICOM-as-JSON" attachment), the |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
113 * "/header" REST call is delayed until it is really required. |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
114 **/ |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
115 |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
116 if (!hasCompression_) |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
117 { |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
118 compression_ = DetectImageCompression(orthanc, instanceId_); |
56
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
119 hasCompression_ = true; |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
120 } |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
121 |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
122 return compression_; |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
123 } |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
124 |
0 | 125 |
61
147bd6dc28db
refactoring using new items in the plugin toolbox of Orthanc
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
59
diff
changeset
|
126 DicomPyramidInstance::DicomPyramidInstance(OrthancPlugins::IOrthancConnection& orthanc, |
0 | 127 const std::string& instanceId) : |
56
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
128 instanceId_(instanceId), |
83cd735c885d
speedup the loading of DICOM sources
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
129 hasCompression_(false) |
0 | 130 { |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
131 using namespace OrthancPlugins; |
0 | 132 |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
133 DicomDatasetReader reader(new FullOrthancDataset(orthanc, "/instances/" + instanceId + "/tags")); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
134 |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
135 if (reader.GetMandatoryStringValue(DICOM_TAG_SOP_CLASS_UID) != "1.2.840.10008.5.1.4.1.1.77.1.6" || |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
136 reader.GetMandatoryStringValue(DICOM_TAG_MODALITY) != "SM") |
0 | 137 { |
138 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
139 } | |
140 | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
141 format_ = DetectPixelFormat(reader); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
142 tileWidth_ = reader.GetUnsignedIntegerValue(DICOM_TAG_COLUMNS); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
143 tileHeight_ = reader.GetUnsignedIntegerValue(DICOM_TAG_ROWS); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
144 totalWidth_ = reader.GetUnsignedIntegerValue(DICOM_TAG_TOTAL_PIXEL_MATRIX_COLUMNS); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
145 totalHeight_ = reader.GetUnsignedIntegerValue(DICOM_TAG_TOTAL_PIXEL_MATRIX_ROWS); |
0 | 146 |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
147 size_t countFrames; |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
148 if (!reader.GetDataset().GetSequenceSize(countFrames, DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE)) |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
149 { |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
150 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
151 } |
0 | 152 |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
153 if (countFrames != reader.GetUnsignedIntegerValue(DICOM_TAG_NUMBER_OF_FRAMES)) |
0 | 154 { |
155 LOG(ERROR) << "Mismatch between the number of frames in instance: " << instanceId; | |
156 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
157 } | |
158 | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
159 frames_.resize(countFrames); |
0 | 160 |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
161 for (size_t i = 0; i < countFrames; i++) |
0 | 162 { |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
163 int xx = reader.GetIntegerValue(DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
164 DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE, 0, |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
165 DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)); |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
166 |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
167 int yy = reader.GetIntegerValue(DicomPath(DICOM_TAG_PER_FRAME_FUNCTIONAL_GROUPS_SEQUENCE, i, |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
168 DICOM_TAG_PLANE_POSITION_SLIDE_SEQUENCE, 0, |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
169 DICOM_TAG_ROW_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX)); |
0 | 170 |
171 // "-1", because coordinates are shifted by 1 in DICOM | |
62
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
172 xx -= 1; |
f45cec2c32e2
Speed-up in the Web viewer plugin
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
61
diff
changeset
|
173 yy -= 1; |
0 | 174 |
175 unsigned int x = static_cast<unsigned int>(xx); | |
176 unsigned int y = static_cast<unsigned int>(yy); | |
177 | |
178 if (xx < 0 || | |
179 yy < 0 || | |
180 x % tileWidth_ != 0 || | |
181 y % tileHeight_ != 0 || | |
182 x >= totalWidth_ || | |
183 y >= totalHeight_) | |
184 { | |
185 LOG(ERROR) << "Frame " << i << " with unexpected tile location (" | |
186 << x << "," << y << ") in instance: " << instanceId; | |
187 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
188 } | |
189 | |
190 frames_[i].first = x / tileWidth_; | |
191 frames_[i].second = y / tileHeight_; | |
192 } | |
193 } | |
194 | |
195 | |
196 unsigned int DicomPyramidInstance::GetFrameLocationX(size_t frame) const | |
197 { | |
198 assert(frame < frames_.size()); | |
199 return frames_[frame].first; | |
200 } | |
201 | |
202 | |
203 unsigned int DicomPyramidInstance::GetFrameLocationY(size_t frame) const | |
204 { | |
205 assert(frame < frames_.size()); | |
206 return frames_[frame].second; | |
207 } | |
208 } |