Mercurial > hg > orthanc-wsi
annotate Applications/Dicomizer.cpp @ 166:f0dac1e8f736
access to photometric interpretation of source pyramids
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 12 Jul 2019 09:06:54 +0200 |
parents | 6b8ccfc02051 |
children | 605247fc8758 |
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 | |
157 | 5 * Copyright (C) 2017-2019 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "../Framework/Algorithms/ReconstructPyramidCommand.h" | |
23 #include "../Framework/Algorithms/TranscodeTileCommand.h" | |
24 #include "../Framework/DicomToolbox.h" | |
25 #include "../Framework/DicomizerParameters.h" | |
26 #include "../Framework/ImagedVolumeParameters.h" | |
27 #include "../Framework/Inputs/HierarchicalTiff.h" | |
28 #include "../Framework/Inputs/OpenSlidePyramid.h" | |
29 #include "../Framework/Inputs/TiledJpegImage.h" | |
30 #include "../Framework/Inputs/TiledPngImage.h" | |
31 #include "../Framework/Inputs/TiledPyramidStatistics.h" | |
151 | 32 #include "../Framework/MultiThreading/BagOfTasksProcessor.h" |
0 | 33 #include "../Framework/Outputs/DicomPyramidWriter.h" |
34 #include "../Framework/Outputs/TruncatedPyramidWriter.h" | |
35 | |
140
a0f9a3df1110
resort to Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
130
diff
changeset
|
36 #include <Core/DicomParsing/FromDcmtkBridge.h> |
a0f9a3df1110
resort to Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
130
diff
changeset
|
37 #include <Core/Logging.h> |
a0f9a3df1110
resort to Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
130
diff
changeset
|
38 #include <Core/OrthancException.h> |
a0f9a3df1110
resort to Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
130
diff
changeset
|
39 #include <Core/SystemToolbox.h> |
59
7a3853d51c45
Move "Framework/Orthanc/" as "Resources/Orthanc/"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
57
diff
changeset
|
40 |
0 | 41 #include "ApplicationToolbox.h" |
42 | |
43 #include <EmbeddedResources.h> | |
44 | |
45 #include <dcmtk/dcmdata/dcdeftag.h> | |
46 #include <dcmtk/dcmdata/dcuid.h> | |
47 #include <dcmtk/dcmdata/dcvrobow.h> | |
48 #include <dcmtk/dcmdata/dcvrat.h> | |
49 | |
50 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
51 static const char* OPTION_COLOR = "color"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
52 static const char* OPTION_COMPRESSION = "compression"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
53 static const char* OPTION_DATASET = "dataset"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
54 static const char* OPTION_FOLDER = "folder"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
55 static const char* OPTION_FOLDER_PATTERN = "folder-pattern"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
56 static const char* OPTION_HELP = "help"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
57 static const char* OPTION_ICC_PROFILE = "icc-profile"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
58 static const char* OPTION_IMAGED_DEPTH = "imaged-depth"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
59 static const char* OPTION_IMAGED_HEIGHT = "imaged-height"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
60 static const char* OPTION_IMAGED_WIDTH = "imaged-width"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
61 static const char* OPTION_INPUT = "input"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
62 static const char* OPTION_JPEG_QUALITY = "jpeg-quality"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
63 static const char* OPTION_LEVELS = "levels"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
64 static const char* OPTION_LOWER_LEVELS = "lower-levels"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
65 static const char* OPTION_MAX_SIZE = "max-size"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
66 static const char* OPTION_OFFSET_X = "offset-x"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
67 static const char* OPTION_OFFSET_Y = "offset-y"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
68 static const char* OPTION_OPENSLIDE = "openslide"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
69 static const char* OPTION_OPTICAL_PATH = "optical-path"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
70 static const char* OPTION_PYRAMID = "pyramid"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
71 static const char* OPTION_REENCODE = "reencode"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
72 static const char* OPTION_REPAINT = "repaint"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
73 static const char* OPTION_SAFETY = "safety"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
74 static const char* OPTION_SAMPLE_DATASET = "sample-dataset"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
75 static const char* OPTION_SMOOTH = "smooth"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
76 static const char* OPTION_THREADS = "threads"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
77 static const char* OPTION_TILE_HEIGHT = "tile-height"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
78 static const char* OPTION_TILE_WIDTH = "tile-width"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
79 static const char* OPTION_VERBOSE = "verbose"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
80 static const char* OPTION_VERSION = "version"; |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
81 |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
82 |
0 | 83 static void TranscodePyramid(OrthancWSI::PyramidWriterBase& target, |
84 OrthancWSI::ITiledPyramid& source, | |
85 const OrthancWSI::DicomizerParameters& parameters) | |
86 { | |
87 Orthanc::BagOfTasks tasks; | |
88 | |
89 for (unsigned int i = 0; i < source.GetLevelCount(); i++) | |
90 { | |
91 LOG(WARNING) << "Creating level " << i << " of size " | |
92 << source.GetLevelWidth(i) << "x" << source.GetLevelHeight(i); | |
93 target.AddLevel(source.GetLevelWidth(i), source.GetLevelHeight(i)); | |
94 } | |
95 | |
96 LOG(WARNING) << "Transcoding the source pyramid"; | |
97 | |
98 OrthancWSI::TranscodeTileCommand::PrepareBagOfTasks(tasks, target, source, parameters); | |
99 OrthancWSI::ApplicationToolbox::Execute(tasks, parameters.GetThreadsCount()); | |
100 } | |
101 | |
102 | |
103 static void ReconstructPyramid(OrthancWSI::PyramidWriterBase& target, | |
104 OrthancWSI::ITiledPyramid& source, | |
105 const OrthancWSI::DicomizerParameters& parameters) | |
106 { | |
107 Orthanc::BagOfTasks tasks; | |
108 | |
109 unsigned int levelsCount = parameters.GetPyramidLevelsCount(target, source); | |
110 LOG(WARNING) << "The target pyramid will have " << levelsCount << " levels"; | |
111 assert(levelsCount >= 1); | |
112 | |
113 for (unsigned int i = 0; i < levelsCount; i++) | |
114 { | |
115 unsigned int width = OrthancWSI::CeilingDivision(source.GetLevelWidth(0), 1 << i); | |
116 unsigned int height = OrthancWSI::CeilingDivision(source.GetLevelHeight(0), 1 << i); | |
117 | |
118 LOG(WARNING) << "Creating level " << i << " of size " << width << "x" << height; | |
119 target.AddLevel(width, height); | |
120 } | |
121 | |
122 unsigned int lowerLevelsCount = parameters.GetPyramidLowerLevelsCount(target, source); | |
123 if (lowerLevelsCount > levelsCount) | |
124 { | |
125 LOG(WARNING) << "The number of lower levels (" << lowerLevelsCount | |
126 << ") exceeds the number of levels (" << levelsCount | |
127 << "), cropping it"; | |
128 lowerLevelsCount = levelsCount; | |
129 } | |
130 | |
131 assert(lowerLevelsCount <= levelsCount); | |
132 if (lowerLevelsCount != levelsCount) | |
133 { | |
134 LOG(WARNING) << "Constructing the " << lowerLevelsCount << " lower levels of the pyramid"; | |
166
f0dac1e8f736
access to photometric interpretation of source pyramids
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
157
diff
changeset
|
135 OrthancWSI::TruncatedPyramidWriter truncated(target, lowerLevelsCount, source.GetPhotometricInterpretation()); |
0 | 136 OrthancWSI::ReconstructPyramidCommand::PrepareBagOfTasks |
137 (tasks, truncated, source, lowerLevelsCount + 1, 0, parameters); | |
138 OrthancWSI::ApplicationToolbox::Execute(tasks, parameters.GetThreadsCount()); | |
139 | |
140 assert(tasks.GetSize() == 0); | |
141 | |
142 const unsigned int upperLevelsCount = levelsCount - lowerLevelsCount; | |
143 LOG(WARNING) << "Constructing the " << upperLevelsCount << " upper levels of the pyramid"; | |
144 OrthancWSI::ReconstructPyramidCommand::PrepareBagOfTasks | |
145 (tasks, target, truncated.GetUpperLevel(), | |
146 upperLevelsCount, lowerLevelsCount, parameters); | |
147 OrthancWSI::ApplicationToolbox::Execute(tasks, parameters.GetThreadsCount()); | |
148 } | |
149 else | |
150 { | |
151 LOG(WARNING) << "Constructing the pyramid"; | |
152 OrthancWSI::ReconstructPyramidCommand::PrepareBagOfTasks | |
153 (tasks, target, source, levelsCount, 0, parameters); | |
154 OrthancWSI::ApplicationToolbox::Execute(tasks, parameters.GetThreadsCount()); | |
155 } | |
156 } | |
157 | |
158 | |
159 static void Recompress(OrthancWSI::IFileTarget& output, | |
160 OrthancWSI::ITiledPyramid& source, | |
161 const DcmDataset& dataset, | |
162 const OrthancWSI::DicomizerParameters& parameters, | |
163 const OrthancWSI::ImagedVolumeParameters& volume) | |
164 { | |
165 OrthancWSI::TiledPyramidStatistics stats(source); | |
166 | |
167 LOG(WARNING) << "Size of source tiles: " << stats.GetTileWidth() << "x" << stats.GetTileHeight(); | |
168 LOG(WARNING) << "Pixel format: " << Orthanc::EnumerationToString(stats.GetPixelFormat()); | |
169 LOG(WARNING) << "Smoothing is " << (parameters.IsSmoothEnabled() ? "enabled" : "disabled"); | |
170 | |
171 if (parameters.IsRepaintBackground()) | |
172 { | |
173 LOG(WARNING) << "Repainting the background with color: (" | |
174 << static_cast<int>(parameters.GetBackgroundColorRed()) << "," | |
175 << static_cast<int>(parameters.GetBackgroundColorGreen()) << "," | |
176 << static_cast<int>(parameters.GetBackgroundColorBlue()) << ")"; | |
177 } | |
178 else | |
179 { | |
180 LOG(WARNING) << "No repainting of the background"; | |
181 } | |
182 | |
183 OrthancWSI::DicomPyramidWriter target(output, dataset, | |
184 source.GetPixelFormat(), | |
185 parameters.GetTargetCompression(), | |
186 parameters.GetTargetTileWidth(source), | |
187 parameters.GetTargetTileHeight(source), | |
188 parameters.GetDicomMaxFileSize(), | |
189 volume); | |
29 | 190 target.SetJpegQuality(parameters.GetJpegQuality()); |
0 | 191 |
192 LOG(WARNING) << "Size of target tiles: " << target.GetTileWidth() << "x" << target.GetTileHeight(); | |
193 | |
194 if (target.GetImageCompression() == OrthancWSI::ImageCompression_Jpeg) | |
195 { | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
196 LOG(WARNING) << "Target image compression: Jpeg with quality " |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
197 << static_cast<int>(target.GetJpegQuality()); |
0 | 198 target.SetJpegQuality(target.GetJpegQuality()); |
199 } | |
200 else | |
201 { | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
202 LOG(WARNING) << "Target image compression: " |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
203 << OrthancWSI::EnumerationToString(target.GetImageCompression()); |
0 | 204 } |
205 | |
206 if (stats.GetTileWidth() % target.GetTileWidth() != 0 || | |
207 stats.GetTileHeight() % target.GetTileHeight() != 0) | |
208 { | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
209 LOG(ERROR) << "When resampling the tile size, " |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
210 << "it must be a integer divisor of the original tile size"; |
0 | 211 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
212 } | |
213 | |
214 if (target.GetTileWidth() <= 16 || | |
215 target.GetTileHeight() <= 16) | |
216 { | |
217 LOG(ERROR) << "Tiles are too small (16 pixels minimum): " | |
218 << target.GetTileWidth() << "x" << target.GetTileHeight(); | |
219 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); | |
220 } | |
221 | |
222 if (parameters.IsReconstructPyramid()) | |
223 { | |
224 ReconstructPyramid(target, stats, parameters); | |
225 } | |
226 else | |
227 { | |
228 TranscodePyramid(target, stats, parameters); | |
229 } | |
230 | |
231 target.Flush(); | |
232 } | |
233 | |
234 | |
235 | |
236 static DcmDataset* ParseDataset(const std::string& path) | |
237 { | |
238 Json::Value json; | |
239 | |
240 if (path.empty()) | |
241 { | |
242 json = Json::objectValue; // Empty dataset => TODO EMBED | |
243 } | |
244 else | |
245 { | |
246 std::string content; | |
43 | 247 Orthanc::SystemToolbox::ReadFile(content, path); |
0 | 248 |
249 Json::Reader reader; | |
250 if (!reader.parse(content, json, false)) | |
251 { | |
252 LOG(ERROR) << "Cannot parse the JSON file in: " << path; | |
253 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
254 } | |
255 } | |
256 | |
257 std::auto_ptr<DcmDataset> dataset(Orthanc::FromDcmtkBridge::FromJson(json, true, true, Orthanc::Encoding_Latin1)); | |
258 if (dataset.get() == NULL) | |
259 { | |
260 LOG(ERROR) << "Cannot convert to JSON file to a DICOM dataset: " << path; | |
261 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
262 } | |
263 | |
264 // VL Whole Slide Microscopy Image IOD | |
265 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_SOPClassUID, "1.2.840.10008.5.1.4.1.1.77.1.6"); | |
266 | |
267 // Slide Microscopy | |
268 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_Modality, "SM"); | |
269 | |
270 // Patient orientation makes no sense in whole-slide images | |
271 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_PatientOrientation, ""); | |
272 | |
273 // Some basic coordinate information | |
274 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_VolumetricProperties, "VOLUME"); | |
275 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_ImageOrientationSlide, "0\\-1\\0\\-1\\0\\0"); | |
276 | |
277 std::string date, time; | |
130 | 278 Orthanc::SystemToolbox::GetNowDicom(date, time, true /* use UTC time (not local time) */); |
0 | 279 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_StudyDate, date); |
280 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_StudyTime, time); | |
281 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_SeriesDate, date); | |
282 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_SeriesTime, time); | |
283 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_ContentDate, date); | |
284 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_ContentTime, time); | |
285 OrthancWSI::DicomToolbox::SetStringTag(*dataset, DCM_AcquisitionDateTime, date + time); | |
286 | |
287 return dataset.release(); | |
288 } | |
289 | |
290 | |
291 | |
292 static void SetupDimension(DcmDataset& dataset, | |
293 const std::string& opticalPathId, | |
294 const OrthancWSI::ITiledPyramid& source, | |
295 const OrthancWSI::ImagedVolumeParameters& volume) | |
296 { | |
83 | 297 // Extract the identifier of the Dimension Organization, if provided |
298 std::string organization; | |
0 | 299 DcmItem* previous = OrthancWSI::DicomToolbox::ExtractSingleSequenceItem(dataset, DCM_DimensionOrganizationSequence); |
300 | |
83 | 301 if (previous != NULL && |
302 previous->tagExists(DCM_DimensionOrganizationUID)) | |
303 { | |
304 organization = OrthancWSI::DicomToolbox::GetStringTag(*previous, DCM_DimensionOrganizationUID); | |
305 } | |
306 else | |
0 | 307 { |
83 | 308 // No Dimension Organization provided: Generate an unique identifier |
309 organization = Orthanc::FromDcmtkBridge::GenerateUniqueIdentifier(Orthanc::ResourceType_Instance); | |
310 } | |
311 | |
312 | |
313 { | |
314 // Construct tag "Dimension Organization Sequence" (0020,9221) | |
315 std::auto_ptr<DcmItem> item(new DcmItem); | |
316 OrthancWSI::DicomToolbox::SetStringTag(*item, DCM_DimensionOrganizationUID, organization); | |
317 | |
318 std::auto_ptr<DcmSequenceOfItems> sequence(new DcmSequenceOfItems(DCM_DimensionOrganizationSequence)); | |
319 | |
320 if (!sequence->insert(item.release(), false, false).good() || | |
321 !dataset.insert(sequence.release(), true /* replace */, false).good()) | |
0 | 322 { |
83 | 323 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
0 | 324 } |
325 } | |
326 | |
83 | 327 |
0 | 328 { |
83 | 329 // Construct tag "Dimension Index Sequence" (0020,9222) |
330 std::auto_ptr<DcmItem> item(new DcmItem); | |
331 OrthancWSI::DicomToolbox::SetStringTag(*item, DCM_DimensionOrganizationUID, organization); | |
84
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
332 OrthancWSI::DicomToolbox::SetAttributeTag(*item, DCM_FunctionalGroupPointer, DCM_PlanePositionSlideSequence); |
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
333 OrthancWSI::DicomToolbox::SetAttributeTag(*item, DCM_DimensionIndexPointer, DCM_ColumnPositionInTotalImagePixelMatrix); |
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
334 |
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
335 std::auto_ptr<DcmItem> item2(new DcmItem); |
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
336 OrthancWSI::DicomToolbox::SetStringTag(*item2, DCM_DimensionOrganizationUID, organization); |
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
337 OrthancWSI::DicomToolbox::SetAttributeTag(*item2, DCM_FunctionalGroupPointer, DCM_PlanePositionSlideSequence); |
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
338 OrthancWSI::DicomToolbox::SetAttributeTag(*item2, DCM_DimensionIndexPointer, DCM_RowPositionInTotalImagePixelMatrix); |
0 | 339 |
83 | 340 std::auto_ptr<DcmSequenceOfItems> sequence(new DcmSequenceOfItems(DCM_DimensionIndexSequence)); |
0 | 341 |
83 | 342 if (!sequence->insert(item.release(), false, false).good() || |
84
727670c5c125
fix generation of "Dimension Index Sequence" and "Dimension Index Values"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
83
diff
changeset
|
343 !sequence->insert(item2.release(), false, false).good() || |
83 | 344 !dataset.insert(sequence.release(), true /* replace */, false).good()) |
345 { | |
346 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
347 } | |
0 | 348 } |
349 | |
350 | |
83 | 351 { |
352 // Construct tag "Shared Functional Groups Sequence" (5200,9229) | |
0 | 353 |
83 | 354 // In the 2 lines below, remember to switch X/Y when going from physical to pixel coordinates! |
355 float spacingX = volume.GetWidth() / static_cast<float>(source.GetLevelHeight(0)); | |
356 float spacingY = volume.GetHeight() / static_cast<float>(source.GetLevelWidth(0)); | |
357 | |
358 std::string spacing = (boost::lexical_cast<std::string>(spacingX) + '\\' + | |
359 boost::lexical_cast<std::string>(spacingY)); | |
360 | |
361 std::auto_ptr<DcmItem> item(new DcmItem); | |
0 | 362 |
83 | 363 std::auto_ptr<DcmItem> item2(new DcmItem); |
364 OrthancWSI::DicomToolbox::SetStringTag(*item2, DCM_SliceThickness, | |
365 boost::lexical_cast<std::string>(volume.GetDepth())); | |
366 OrthancWSI::DicomToolbox::SetStringTag(*item2, DCM_PixelSpacing, spacing); | |
0 | 367 |
83 | 368 std::auto_ptr<DcmItem> item3(new DcmItem); |
369 OrthancWSI::DicomToolbox::SetStringTag(*item3, DCM_OpticalPathIdentifier, opticalPathId); | |
0 | 370 |
83 | 371 std::auto_ptr<DcmSequenceOfItems> sequence(new DcmSequenceOfItems(DCM_SharedFunctionalGroupsSequence)); |
372 std::auto_ptr<DcmSequenceOfItems> sequence2(new DcmSequenceOfItems(DCM_PixelMeasuresSequence)); | |
373 std::auto_ptr<DcmSequenceOfItems> sequence3(new DcmSequenceOfItems(DCM_OpticalPathIdentificationSequence)); | |
0 | 374 |
83 | 375 if (!sequence2->insert(item2.release(), false, false).good() || |
376 !sequence3->insert(item3.release(), false, false).good() || | |
377 !item->insert(sequence2.release(), false, false).good() || | |
378 !item->insert(sequence3.release(), false, false).good() || | |
379 !sequence->insert(item.release(), false, false).good() || | |
380 !dataset.insert(sequence.release(), true /* replace */, false).good()) | |
381 { | |
382 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
383 } | |
0 | 384 } |
385 } | |
386 | |
387 | |
388 static void EnrichDataset(DcmDataset& dataset, | |
389 const OrthancWSI::ITiledPyramid& source, | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
390 OrthancWSI::ImageCompression sourceCompression, |
0 | 391 const OrthancWSI::DicomizerParameters& parameters, |
392 const OrthancWSI::ImagedVolumeParameters& volume) | |
393 { | |
394 Orthanc::Encoding encoding = Orthanc::FromDcmtkBridge::DetectEncoding(dataset, Orthanc::Encoding_Latin1); | |
395 | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
396 if (sourceCompression == OrthancWSI::ImageCompression_Jpeg || |
0 | 397 parameters.GetTargetCompression() == OrthancWSI::ImageCompression_Jpeg) |
398 { | |
399 // Takes as estimation a 1:10 compression ratio | |
400 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_LossyImageCompression, "01"); | |
401 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_LossyImageCompressionRatio, "10"); | |
402 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_LossyImageCompressionMethod, "ISO_10918_1"); // JPEG Lossy Compression | |
403 } | |
404 else | |
405 { | |
406 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_LossyImageCompression, "00"); | |
407 } | |
408 | |
409 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_ImagedVolumeWidth, boost::lexical_cast<std::string>(volume.GetWidth())); | |
410 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_ImagedVolumeHeight, boost::lexical_cast<std::string>(volume.GetHeight())); | |
411 OrthancWSI::DicomToolbox::SetStringTag(dataset, DCM_ImagedVolumeDepth, boost::lexical_cast<std::string>(volume.GetDepth())); | |
412 | |
413 std::auto_ptr<DcmItem> origin(new DcmItem); | |
414 OrthancWSI::DicomToolbox::SetStringTag(*origin, DCM_XOffsetInSlideCoordinateSystem, | |
415 boost::lexical_cast<std::string>(volume.GetOffsetX())); | |
416 OrthancWSI::DicomToolbox::SetStringTag(*origin, DCM_YOffsetInSlideCoordinateSystem, | |
417 boost::lexical_cast<std::string>(volume.GetOffsetY())); | |
418 | |
419 std::auto_ptr<DcmSequenceOfItems> sequenceOrigin(new DcmSequenceOfItems(DCM_TotalPixelMatrixOriginSequence)); | |
420 if (!sequenceOrigin->insert(origin.release(), false, false).good() || | |
421 !dataset.insert(sequenceOrigin.release(), false, false).good()) | |
422 { | |
423 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
424 } | |
425 | |
426 | |
427 if (parameters.GetOpticalPath() == OrthancWSI::OpticalPath_Brightfield) | |
428 { | |
429 if (dataset.tagExists(DCM_OpticalPathSequence)) | |
430 { | |
431 LOG(ERROR) << "The user DICOM dataset already contains an optical path sequence, giving up"; | |
432 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
433 } | |
434 | |
435 std::string brightfield; | |
436 Orthanc::EmbeddedResources::GetFileResource(brightfield, Orthanc::EmbeddedResources::BRIGHTFIELD_OPTICAL_PATH); | |
437 | |
438 Json::Value json; | |
439 Json::Reader reader; | |
440 if (!reader.parse(brightfield, json, false)) | |
441 { | |
442 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
443 } | |
444 | |
445 std::auto_ptr<DcmElement> element(Orthanc::FromDcmtkBridge::FromJson( | |
446 Orthanc::DicomTag(DCM_OpticalPathSequence.getGroup(), | |
447 DCM_OpticalPathSequence.getElement()), | |
448 json, false, encoding)); | |
449 if (!dataset.insert(element.release()).good()) | |
450 { | |
451 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
452 } | |
453 } | |
454 | |
455 | |
456 std::string profile; | |
457 if (parameters.GetIccProfilePath().empty()) | |
458 { | |
459 Orthanc::EmbeddedResources::GetFileResource(profile, Orthanc::EmbeddedResources::SRGB_ICC_PROFILE); | |
460 } | |
461 else | |
462 { | |
43 | 463 Orthanc::SystemToolbox::ReadFile(profile, parameters.GetIccProfilePath()); |
0 | 464 } |
465 | |
466 | |
467 DcmItem* opticalPath = OrthancWSI::DicomToolbox::ExtractSingleSequenceItem(dataset, DCM_OpticalPathSequence); | |
468 if (opticalPath == NULL) | |
469 { | |
470 LOG(ERROR) << "No optical path specified"; | |
471 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
472 } | |
473 | |
474 if (!opticalPath->tagExists(DCM_ICCProfile)) | |
475 { | |
476 std::auto_ptr<DcmOtherByteOtherWord> icc(new DcmOtherByteOtherWord(DCM_ICCProfile)); | |
477 | |
478 if (!icc->putUint8Array(reinterpret_cast<const Uint8*>(profile.c_str()), profile.size()).good() || | |
479 !opticalPath->insert(icc.release()).good()) | |
480 { | |
481 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
482 } | |
483 } | |
484 | |
485 const char* opticalPathId = NULL; | |
486 if (!opticalPath->findAndGetString(DCM_OpticalPathIdentifier, opticalPathId).good() || | |
487 opticalPathId == NULL) | |
488 { | |
489 LOG(ERROR) << "No identifier in the optical path"; | |
490 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
491 } | |
492 | |
493 SetupDimension(dataset, opticalPathId, source, volume); | |
494 } | |
495 | |
496 | |
497 static bool ParseParameters(int& exitStatus, | |
498 OrthancWSI::DicomizerParameters& parameters, | |
499 OrthancWSI::ImagedVolumeParameters& volume, | |
500 int argc, | |
501 char* argv[]) | |
502 { | |
503 // Declare the supported parameters | |
504 boost::program_options::options_description generic("Generic options"); | |
505 generic.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
506 (OPTION_HELP, "Display this help and exit") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
507 (OPTION_VERSION, "Output version information and exit") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
508 (OPTION_VERBOSE, "Be verbose in logs") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
509 (OPTION_THREADS, |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
510 boost::program_options::value<int>()->default_value(parameters.GetThreadsCount()), |
0 | 511 "Number of processing threads to be used") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
512 (OPTION_OPENSLIDE, boost::program_options::value<std::string>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
513 "Path to the shared library of OpenSlide " |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
514 "(not necessary if converting from standard hierarchical TIFF)") |
0 | 515 ; |
516 | |
517 boost::program_options::options_description source("Options for the source image"); | |
518 source.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
519 (OPTION_DATASET, boost::program_options::value<std::string>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
520 "Path to a JSON file containing the DICOM dataset") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
521 (OPTION_SAMPLE_DATASET, |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
522 "Display a minimalistic sample DICOM dataset in JSON format, then exit") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
523 (OPTION_REENCODE, boost::program_options::value<bool>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
524 "Whether to re-encode each tile (no transcoding, much slower) (Boolean)") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
525 (OPTION_REPAINT, boost::program_options::value<bool>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
526 "Whether to repaint the background of the image (Boolean)") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
527 (OPTION_COLOR, boost::program_options::value<std::string>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
528 "Color of the background (e.g. \"255,0,0\")") |
0 | 529 ; |
530 | |
531 boost::program_options::options_description pyramid("Options to construct the pyramid"); | |
532 pyramid.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
533 (OPTION_PYRAMID, boost::program_options::value<bool>()->default_value(false), |
0 | 534 "Reconstruct the full pyramid (slow) (Boolean)") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
535 (OPTION_SMOOTH, boost::program_options::value<bool>()->default_value(false), |
0 | 536 "Apply smoothing when reconstructing the pyramid " |
537 "(slower, but higher quality) (Boolean)") | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
538 (OPTION_LEVELS, boost::program_options::value<int>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
539 "Number of levels in the target pyramid") |
0 | 540 ; |
541 | |
542 boost::program_options::options_description target("Options for the target image"); | |
543 target.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
544 (OPTION_TILE_WIDTH, boost::program_options::value<int>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
545 "Width of the tiles in the target image") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
546 (OPTION_TILE_HEIGHT, boost::program_options::value<int>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
547 "Height of the tiles in the target image") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
548 (OPTION_COMPRESSION, boost::program_options::value<std::string>(), |
0 | 549 "Compression of the target image (\"none\", \"jpeg\" or \"jpeg2000\")") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
550 (OPTION_JPEG_QUALITY, boost::program_options::value<int>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
551 "Set quality level for JPEG (0..100)") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
552 (OPTION_MAX_SIZE, boost::program_options::value<int>()->default_value(10), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
553 "Maximum size per DICOM instance (in MB), 0 means no limit on the file size") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
554 (OPTION_FOLDER, boost::program_options::value<std::string>(), |
0 | 555 "Folder where to store the output DICOM instances") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
556 (OPTION_FOLDER_PATTERN, |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
557 boost::program_options::value<std::string>()->default_value("wsi-%06d.dcm"), |
0 | 558 "Pattern for the files in the output folder") |
559 ("orthanc", boost::program_options::value<std::string>()->default_value("http://localhost:8042/"), | |
560 "URL to the REST API of the target Orthanc server") | |
561 ; | |
562 | |
563 boost::program_options::options_description volumeOptions("Description of the imaged volume"); | |
564 volumeOptions.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
565 (OPTION_IMAGED_WIDTH, boost::program_options::value<float>()->default_value(15), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
566 "Width of the specimen (in mm)") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
567 (OPTION_IMAGED_HEIGHT, boost::program_options::value<float>()->default_value(15), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
568 "Height of the specimen (in mm)") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
569 (OPTION_IMAGED_DEPTH, boost::program_options::value<float>()->default_value(1), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
570 "Depth of the specimen (in mm)") |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
571 (OPTION_OFFSET_X, boost::program_options::value<float>()->default_value(20), |
0 | 572 "X offset the specimen, wrt. slide coordinates origin (in mm)") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
573 (OPTION_OFFSET_Y, boost::program_options::value<float>()->default_value(40), |
0 | 574 "Y offset the specimen, wrt. slide coordinates origin (in mm)") |
575 ; | |
576 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
577 boost::program_options::options_description restOptions |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
578 ("HTTP/HTTPS client configuration to access the Orthanc REST API"); |
125
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
579 OrthancWSI::ApplicationToolbox::AddRestApiOptions(restOptions); |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
580 |
0 | 581 boost::program_options::options_description advancedOptions("Advanced options"); |
582 advancedOptions.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
583 (OPTION_OPTICAL_PATH, boost::program_options::value<std::string>()->default_value("brightfield"), |
0 | 584 "Optical path to be automatically added to the DICOM dataset (\"none\" or \"brightfield\")") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
585 (OPTION_ICC_PROFILE, boost::program_options::value<std::string>(), |
0 | 586 "Path to the ICC profile to be included. If empty, a default sRGB profile will be added.") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
587 (OPTION_SAFETY, boost::program_options::value<bool>()->default_value(true), |
0 | 588 "Whether to do additional checks to verify the source image is supported (might slow down) (Boolean)") |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
589 (OPTION_LOWER_LEVELS, boost::program_options::value<int>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
590 "Number of pyramid levels up to which multithreading " |
0 | 591 "should be applied (only for performance/memory tuning)") |
592 ; | |
593 | |
594 boost::program_options::options_description hidden; | |
595 hidden.add_options() | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
596 (OPTION_INPUT, boost::program_options::value<std::string>(), |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
597 "Input file"); |
0 | 598 ; |
599 | |
600 boost::program_options::options_description allWithoutHidden; | |
125
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
601 allWithoutHidden |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
602 .add(generic) |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
603 .add(source) |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
604 .add(pyramid) |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
605 .add(target) |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
606 .add(volumeOptions) |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
607 .add(restOptions) |
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
608 .add(advancedOptions); |
0 | 609 |
610 boost::program_options::options_description all = allWithoutHidden; | |
611 all.add(hidden); | |
612 | |
613 boost::program_options::positional_options_description positional; | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
614 positional.add(OPTION_INPUT, 1); |
0 | 615 |
616 boost::program_options::variables_map options; | |
617 bool error = false; | |
618 | |
619 try | |
620 { | |
621 boost::program_options::store(boost::program_options::command_line_parser(argc, argv). | |
622 options(all).positional(positional).run(), options); | |
623 boost::program_options::notify(options); | |
624 } | |
625 catch (boost::program_options::error& e) | |
626 { | |
627 LOG(ERROR) << "Error while parsing the command-line arguments: " << e.what(); | |
628 error = true; | |
629 } | |
630 | |
631 if (!error && | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
632 options.count(OPTION_SAMPLE_DATASET)) |
0 | 633 { |
634 std::string sample; | |
635 Orthanc::EmbeddedResources::GetFileResource(sample, Orthanc::EmbeddedResources::SAMPLE_DATASET); | |
636 | |
637 std::cout << std::endl << sample << std::endl; | |
638 | |
639 return false; | |
640 } | |
641 | |
642 if (!error && | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
643 options.count(OPTION_HELP) == 0 && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
644 options.count(OPTION_VERSION) == 0 && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
645 options.count(OPTION_INPUT) != 1) |
0 | 646 { |
647 LOG(ERROR) << "No input file was specified"; | |
648 error = true; | |
649 } | |
650 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
651 if (error || options.count(OPTION_HELP)) |
0 | 652 { |
653 std::cout << std::endl | |
654 << "Usage: " << argv[0] << " [OPTION]... [INPUT]" | |
655 << std::endl | |
656 << "Orthanc, lightweight, RESTful DICOM server for healthcare and medical research." | |
657 << std::endl << std::endl | |
658 << "Create a DICOM file from a digital pathology image." | |
659 << std::endl; | |
660 | |
661 std::cout << allWithoutHidden << "\n"; | |
662 | |
663 if (error) | |
664 { | |
665 exitStatus = -1; | |
666 } | |
667 | |
668 return false; | |
669 } | |
670 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
671 if (options.count(OPTION_VERSION)) |
8
62adabb8c122
Provide "--version" in command-line tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
672 { |
62adabb8c122
Provide "--version" in command-line tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
673 OrthancWSI::ApplicationToolbox::PrintVersion(argv[0]); |
62adabb8c122
Provide "--version" in command-line tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
674 return false; |
62adabb8c122
Provide "--version" in command-line tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
675 } |
62adabb8c122
Provide "--version" in command-line tools
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
676 |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
677 if (options.count(OPTION_VERBOSE)) |
0 | 678 { |
679 Orthanc::Logging::EnableInfoLevel(true); | |
680 } | |
681 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
682 if (options.count(OPTION_OPENSLIDE)) |
0 | 683 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
684 OrthancWSI::OpenSlideLibrary::Initialize(options[OPTION_OPENSLIDE].as<std::string>()); |
0 | 685 } |
686 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
687 if (options.count(OPTION_PYRAMID) && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
688 options[OPTION_PYRAMID].as<bool>()) |
0 | 689 { |
690 parameters.SetReconstructPyramid(true); | |
691 } | |
692 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
693 if (options.count(OPTION_SMOOTH) && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
694 options[OPTION_SMOOTH].as<bool>()) |
0 | 695 { |
696 parameters.SetSmoothEnabled(true); | |
697 } | |
698 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
699 if (options.count(OPTION_SAFETY) && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
700 options[OPTION_SAFETY].as<bool>()) |
0 | 701 { |
702 parameters.SetSafetyCheck(true); | |
703 } | |
704 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
705 if (options.count(OPTION_REENCODE) && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
706 options[OPTION_REENCODE].as<bool>()) |
0 | 707 { |
708 parameters.SetForceReencode(true); | |
709 } | |
710 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
711 if (options.count(OPTION_REPAINT) && |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
712 options[OPTION_REPAINT].as<bool>()) |
0 | 713 { |
714 parameters.SetRepaintBackground(true); | |
715 } | |
716 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
717 if (options.count(OPTION_TILE_WIDTH) || |
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
718 options.count(OPTION_TILE_HEIGHT)) |
0 | 719 { |
720 int w = 0; | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
721 if (options.count(OPTION_TILE_WIDTH)) |
0 | 722 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
723 w = options[OPTION_TILE_WIDTH].as<int>(); |
0 | 724 } |
725 | |
145 | 726 int h = 0; |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
727 if (options.count(OPTION_TILE_HEIGHT)) |
0 | 728 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
729 h = options[OPTION_TILE_HEIGHT].as<int>(); |
0 | 730 } |
731 | |
732 if (w < 0 || h < 0) | |
733 { | |
734 LOG(ERROR) << "Negative target tile size specified: " << w << "x" << h; | |
735 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
736 } | |
737 | |
738 parameters.SetTargetTileSize(w, h); | |
739 } | |
740 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
741 parameters.SetInputFile(options[OPTION_INPUT].as<std::string>()); |
0 | 742 |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
743 if (options.count(OPTION_COLOR)) |
0 | 744 { |
745 uint8_t r, g, b; | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
746 OrthancWSI::ApplicationToolbox::ParseColor(r, g, b, options[OPTION_COLOR].as<std::string>()); |
0 | 747 parameters.SetBackgroundColor(r, g, b); |
748 } | |
749 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
750 if (options.count(OPTION_COMPRESSION)) |
0 | 751 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
752 std::string s = options[OPTION_COMPRESSION].as<std::string>(); |
0 | 753 if (s == "none") |
754 { | |
755 parameters.SetTargetCompression(OrthancWSI::ImageCompression_None); | |
756 } | |
757 else if (s == "jpeg") | |
758 { | |
759 parameters.SetTargetCompression(OrthancWSI::ImageCompression_Jpeg); | |
760 } | |
761 else if (s == "jpeg2000") | |
762 { | |
763 parameters.SetTargetCompression(OrthancWSI::ImageCompression_Jpeg2000); | |
764 } | |
765 else | |
766 { | |
767 LOG(ERROR) << "Unknown image compression for the target image: " << s; | |
768 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
769 } | |
770 } | |
771 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
772 if (options.count(OPTION_JPEG_QUALITY)) |
0 | 773 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
774 parameters.SetJpegQuality(options[OPTION_JPEG_QUALITY].as<int>()); |
0 | 775 } |
776 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
777 if (options.count(OPTION_LEVELS)) |
0 | 778 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
779 parameters.SetPyramidLevelsCount(options[OPTION_LEVELS].as<int>()); |
0 | 780 } |
781 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
782 if (options.count(OPTION_LOWER_LEVELS)) |
0 | 783 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
784 parameters.SetPyramidLowerLevelsCount(options[OPTION_LOWER_LEVELS].as<int>()); |
0 | 785 } |
786 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
787 if (options.count(OPTION_THREADS)) |
0 | 788 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
789 parameters.SetThreadsCount(options[OPTION_THREADS].as<int>()); |
0 | 790 } |
791 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
792 if (options.count(OPTION_MAX_SIZE)) |
0 | 793 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
794 parameters.SetDicomMaxFileSize(options[OPTION_MAX_SIZE].as<int>() * 1024 * 1024); |
0 | 795 } |
796 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
797 if (options.count(OPTION_FOLDER)) |
0 | 798 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
799 parameters.SetTargetFolder(options[OPTION_FOLDER].as<std::string>()); |
0 | 800 } |
801 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
802 if (options.count(OPTION_FOLDER_PATTERN)) |
0 | 803 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
804 parameters.SetTargetFolderPattern(options[OPTION_FOLDER_PATTERN].as<std::string>()); |
0 | 805 } |
806 | |
125
7a3f4d580625
SSL is enabled by default for HTTPS transfers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
123
diff
changeset
|
807 OrthancWSI::ApplicationToolbox::SetupRestApi(parameters.GetOrthancParameters(), options); |
0 | 808 |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
809 if (options.count(OPTION_DATASET)) |
0 | 810 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
811 parameters.SetDatasetPath(options[OPTION_DATASET].as<std::string>()); |
0 | 812 } |
813 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
814 if (options.count(OPTION_IMAGED_WIDTH)) |
0 | 815 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
816 volume.SetWidth(options[OPTION_IMAGED_WIDTH].as<float>()); |
0 | 817 } |
818 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
819 if (options.count(OPTION_IMAGED_HEIGHT)) |
0 | 820 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
821 volume.SetHeight(options[OPTION_IMAGED_HEIGHT].as<float>()); |
0 | 822 } |
823 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
824 if (options.count(OPTION_IMAGED_DEPTH)) |
0 | 825 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
826 volume.SetDepth(options[OPTION_IMAGED_DEPTH].as<float>()); |
0 | 827 } |
828 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
829 if (options.count(OPTION_OFFSET_X)) |
0 | 830 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
831 volume.SetOffsetX(options[OPTION_OFFSET_X].as<float>()); |
0 | 832 } |
833 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
834 if (options.count(OPTION_OFFSET_Y)) |
0 | 835 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
836 volume.SetOffsetY(options[OPTION_OFFSET_Y].as<float>()); |
0 | 837 } |
838 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
839 if (options.count(OPTION_OPTICAL_PATH)) |
0 | 840 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
841 std::string s = options[OPTION_OPTICAL_PATH].as<std::string>(); |
0 | 842 if (s == "none") |
843 { | |
844 parameters.SetOpticalPath(OrthancWSI::OpticalPath_None); | |
845 } | |
846 else if (s == "brightfield") | |
847 { | |
848 parameters.SetOpticalPath(OrthancWSI::OpticalPath_Brightfield); | |
849 } | |
850 else | |
851 { | |
852 LOG(ERROR) << "Unknown optical path definition: " << s; | |
853 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
854 } | |
855 } | |
856 | |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
857 if (options.count(OPTION_ICC_PROFILE)) |
0 | 858 { |
129
806d1bb56918
cleaning up options in Dicomizer
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
125
diff
changeset
|
859 parameters.SetIccProfilePath(options[OPTION_ICC_PROFILE].as<std::string>()); |
0 | 860 } |
861 | |
862 return true; | |
863 } | |
864 | |
865 | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
866 OrthancWSI::ITiledPyramid* OpenInputPyramid(OrthancWSI::ImageCompression& sourceCompression, |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
867 const std::string& path, |
0 | 868 const OrthancWSI::DicomizerParameters& parameters) |
869 { | |
870 LOG(WARNING) << "The input image is: " << path; | |
871 | |
872 OrthancWSI::ImageCompression format = OrthancWSI::DetectFormatFromFile(path); | |
873 LOG(WARNING) << "File format of the input image: " << EnumerationToString(format); | |
874 | |
875 switch (format) | |
876 { | |
877 case OrthancWSI::ImageCompression_Png: | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
878 { |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
879 sourceCompression = OrthancWSI::ImageCompression_Unknown; |
0 | 880 return new OrthancWSI::TiledPngImage(path, |
881 parameters.GetTargetTileWidth(512), | |
882 parameters.GetTargetTileHeight(512)); | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
883 } |
0 | 884 |
885 case OrthancWSI::ImageCompression_Jpeg: | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
886 { |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
887 sourceCompression = OrthancWSI::ImageCompression_Unknown; |
0 | 888 return new OrthancWSI::TiledJpegImage(path, |
889 parameters.GetTargetTileWidth(512), | |
890 parameters.GetTargetTileHeight(512)); | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
891 } |
0 | 892 |
893 case OrthancWSI::ImageCompression_Tiff: | |
894 { | |
895 try | |
896 { | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
897 std::auto_ptr<OrthancWSI::HierarchicalTiff> tiff(new OrthancWSI::HierarchicalTiff(path)); |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
898 sourceCompression = tiff->GetImageCompression(); |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
899 return tiff.release(); |
0 | 900 } |
901 catch (Orthanc::OrthancException&) | |
902 { | |
903 LOG(WARNING) << "This is not a standard hierarchical TIFF file"; | |
904 } | |
905 } | |
906 | |
907 default: | |
908 break; | |
909 } | |
910 | |
911 try | |
912 { | |
913 LOG(WARNING) << "Trying to open the input pyramid with OpenSlide"; | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
914 sourceCompression = OrthancWSI::ImageCompression_Unknown; |
0 | 915 return new OrthancWSI::OpenSlidePyramid(path, |
916 parameters.GetTargetTileWidth(512), | |
917 parameters.GetTargetTileHeight(512)); | |
918 } | |
919 catch (Orthanc::OrthancException&) | |
920 { | |
921 LOG(ERROR) << "This file is not supported by OpenSlide"; | |
922 return NULL; | |
923 } | |
924 } | |
925 | |
926 | |
927 int main(int argc, char* argv[]) | |
928 { | |
929 OrthancWSI::ApplicationToolbox::GlobalInitialize(); | |
93
14146ecd1688
Display version of the framework in the logs
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
84
diff
changeset
|
930 OrthancWSI::ApplicationToolbox::ShowVersionInLog(argv[0]); |
0 | 931 |
932 int exitStatus = 0; | |
933 | |
934 try | |
935 { | |
936 OrthancWSI::DicomizerParameters parameters; | |
937 OrthancWSI::ImagedVolumeParameters volume; | |
938 | |
939 if (ParseParameters(exitStatus, parameters, volume, argc, argv)) | |
940 { | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
941 OrthancWSI::ImageCompression sourceCompression; |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
942 std::auto_ptr<OrthancWSI::ITiledPyramid> source; |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
943 |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
944 source.reset(OpenInputPyramid(sourceCompression, parameters.GetInputFile(), parameters)); |
0 | 945 if (source.get() == NULL) |
946 { | |
947 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
948 } | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
949 |
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
950 LOG(WARNING) << "Compression of the individual source tiles: " << OrthancWSI::EnumerationToString(sourceCompression); |
0 | 951 |
952 // Create the shared DICOM tags | |
953 std::auto_ptr<DcmDataset> dataset(ParseDataset(parameters.GetDatasetPath())); | |
57
91fc9583b2de
big refactoring to support sparse tiling
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
43
diff
changeset
|
954 EnrichDataset(*dataset, *source, sourceCompression, parameters, volume); |
0 | 955 |
956 std::auto_ptr<OrthancWSI::IFileTarget> output(parameters.CreateTarget()); | |
957 Recompress(*output, *source, *dataset, parameters, volume); | |
958 } | |
959 } | |
960 catch (Orthanc::OrthancException& e) | |
961 { | |
962 LOG(ERROR) << "Terminating on exception: " << e.What(); | |
963 exitStatus = -1; | |
964 } | |
965 | |
966 OrthancWSI::ApplicationToolbox::GlobalFinalize(); | |
967 | |
968 return exitStatus; | |
969 } |