comparison Applications/Dicomizer.cpp @ 167:605247fc8758

Fix issue #144 (OrthancWSIDicomizer PhotometricInterpretation)
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 12 Jul 2019 12:00:31 +0200
parents f0dac1e8f736
children d3aea0af03e1
comparison
equal deleted inserted replaced
166:f0dac1e8f736 167:605247fc8758
82 82
83 static void TranscodePyramid(OrthancWSI::PyramidWriterBase& target, 83 static void TranscodePyramid(OrthancWSI::PyramidWriterBase& target,
84 OrthancWSI::ITiledPyramid& source, 84 OrthancWSI::ITiledPyramid& source,
85 const OrthancWSI::DicomizerParameters& parameters) 85 const OrthancWSI::DicomizerParameters& parameters)
86 { 86 {
87 LOG(WARNING) << "Transcoding the source pyramid (not re-encoding)";
88
87 Orthanc::BagOfTasks tasks; 89 Orthanc::BagOfTasks tasks;
88 90
89 for (unsigned int i = 0; i < source.GetLevelCount(); i++) 91 for (unsigned int i = 0; i < source.GetLevelCount(); i++)
90 { 92 {
91 LOG(WARNING) << "Creating level " << i << " of size " 93 LOG(WARNING) << "Creating level " << i << " of size "
92 << source.GetLevelWidth(i) << "x" << source.GetLevelHeight(i); 94 << source.GetLevelWidth(i) << "x" << source.GetLevelHeight(i);
93 target.AddLevel(source.GetLevelWidth(i), source.GetLevelHeight(i)); 95 target.AddLevel(source.GetLevelWidth(i), source.GetLevelHeight(i));
94 } 96 }
95
96 LOG(WARNING) << "Transcoding the source pyramid";
97 97
98 OrthancWSI::TranscodeTileCommand::PrepareBagOfTasks(tasks, target, source, parameters); 98 OrthancWSI::TranscodeTileCommand::PrepareBagOfTasks(tasks, target, source, parameters);
99 OrthancWSI::ApplicationToolbox::Execute(tasks, parameters.GetThreadsCount()); 99 OrthancWSI::ApplicationToolbox::Execute(tasks, parameters.GetThreadsCount());
100 } 100 }
101 101
102 102
103 static void ReconstructPyramid(OrthancWSI::PyramidWriterBase& target, 103 static void ReconstructPyramid(OrthancWSI::PyramidWriterBase& target,
104 OrthancWSI::ITiledPyramid& source, 104 OrthancWSI::ITiledPyramid& source,
105 const OrthancWSI::DicomizerParameters& parameters) 105 const OrthancWSI::DicomizerParameters& parameters)
106 { 106 {
107 LOG(WARNING) << "Re-encoding the source pyramid (not transcoding, slower process)";
108
107 Orthanc::BagOfTasks tasks; 109 Orthanc::BagOfTasks tasks;
108 110
109 unsigned int levelsCount = parameters.GetPyramidLevelsCount(target, source); 111 unsigned int levelsCount = parameters.GetPyramidLevelsCount(target, source);
110 LOG(WARNING) << "The target pyramid will have " << levelsCount << " levels"; 112 LOG(WARNING) << "The target pyramid will have " << levelsCount << " levels";
111 assert(levelsCount >= 1); 113 assert(levelsCount >= 1);
158 160
159 static void Recompress(OrthancWSI::IFileTarget& output, 161 static void Recompress(OrthancWSI::IFileTarget& output,
160 OrthancWSI::ITiledPyramid& source, 162 OrthancWSI::ITiledPyramid& source,
161 const DcmDataset& dataset, 163 const DcmDataset& dataset,
162 const OrthancWSI::DicomizerParameters& parameters, 164 const OrthancWSI::DicomizerParameters& parameters,
163 const OrthancWSI::ImagedVolumeParameters& volume) 165 const OrthancWSI::ImagedVolumeParameters& volume,
166 OrthancWSI::ImageCompression sourceCompression)
164 { 167 {
165 OrthancWSI::TiledPyramidStatistics stats(source); 168 OrthancWSI::TiledPyramidStatistics stats(source);
166 169
167 LOG(WARNING) << "Size of source tiles: " << stats.GetTileWidth() << "x" << stats.GetTileHeight(); 170 LOG(WARNING) << "Size of source tiles: " << stats.GetTileWidth() << "x" << stats.GetTileHeight();
168 LOG(WARNING) << "Pixel format: " << Orthanc::EnumerationToString(stats.GetPixelFormat()); 171 LOG(WARNING) << "Pixel format: " << Orthanc::EnumerationToString(source.GetPixelFormat());
172 LOG(WARNING) << "Source photometric interpretation: " << Orthanc::EnumerationToString(source.GetPhotometricInterpretation());
173 LOG(WARNING) << "Source compression: " << EnumerationToString(sourceCompression);
169 LOG(WARNING) << "Smoothing is " << (parameters.IsSmoothEnabled() ? "enabled" : "disabled"); 174 LOG(WARNING) << "Smoothing is " << (parameters.IsSmoothEnabled() ? "enabled" : "disabled");
170 175
171 if (parameters.IsRepaintBackground()) 176 if (parameters.IsRepaintBackground())
172 { 177 {
173 LOG(WARNING) << "Repainting the background with color: (" 178 LOG(WARNING) << "Repainting the background with color: ("
178 else 183 else
179 { 184 {
180 LOG(WARNING) << "No repainting of the background"; 185 LOG(WARNING) << "No repainting of the background";
181 } 186 }
182 187
188 Orthanc::PhotometricInterpretation targetPhotometric;
189 bool transcoding;
190
191 if (parameters.IsForceReencode() ||
192 parameters.IsReconstructPyramid() ||
193 sourceCompression != parameters.GetTargetCompression())
194 {
195 // The tiles of the source image will be re-encoded
196 transcoding = false;
197
198 switch (parameters.GetTargetCompression())
199 {
200 case OrthancWSI::ImageCompression_Jpeg:
201 case OrthancWSI::ImageCompression_Jpeg2000:
202 targetPhotometric = Orthanc::PhotometricInterpretation_YBRFull422;
203 break;
204
205 case OrthancWSI::ImageCompression_None:
206 targetPhotometric = Orthanc::PhotometricInterpretation_RGB;
207 break;
208
209 default:
210 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
211 }
212 }
213 else
214 {
215 // Transcoding: The tiles are copied (no re-encoding)
216 transcoding = true;
217 targetPhotometric = source.GetPhotometricInterpretation();
218 }
219
183 OrthancWSI::DicomPyramidWriter target(output, dataset, 220 OrthancWSI::DicomPyramidWriter target(output, dataset,
184 source.GetPixelFormat(), 221 source.GetPixelFormat(),
185 parameters.GetTargetCompression(), 222 parameters.GetTargetCompression(),
186 parameters.GetTargetTileWidth(source), 223 parameters.GetTargetTileWidth(source),
187 parameters.GetTargetTileHeight(source), 224 parameters.GetTargetTileHeight(source),
188 parameters.GetDicomMaxFileSize(), 225 parameters.GetDicomMaxFileSize(),
189 volume); 226 volume, targetPhotometric);
190 target.SetJpegQuality(parameters.GetJpegQuality()); 227 target.SetJpegQuality(parameters.GetJpegQuality());
191 228
192 LOG(WARNING) << "Size of target tiles: " << target.GetTileWidth() << "x" << target.GetTileHeight(); 229 LOG(WARNING) << "Size of target tiles: " << target.GetTileWidth() << "x" << target.GetTileHeight();
193 230 LOG(WARNING) << "Target photometric interpretation: " << Orthanc::EnumerationToString(targetPhotometric);
194 if (target.GetImageCompression() == OrthancWSI::ImageCompression_Jpeg) 231
195 { 232 if (!transcoding &&
196 LOG(WARNING) << "Target image compression: Jpeg with quality " 233 target.GetImageCompression() == OrthancWSI::ImageCompression_Jpeg)
234 {
235 LOG(WARNING) << "Target compression: Jpeg with quality "
197 << static_cast<int>(target.GetJpegQuality()); 236 << static_cast<int>(target.GetJpegQuality());
198 target.SetJpegQuality(target.GetJpegQuality()); 237 target.SetJpegQuality(target.GetJpegQuality());
199 } 238 }
200 else 239 else
201 { 240 {
202 LOG(WARNING) << "Target image compression: " 241 LOG(WARNING) << "Target compression: "
203 << OrthancWSI::EnumerationToString(target.GetImageCompression()); 242 << OrthancWSI::EnumerationToString(target.GetImageCompression());
204 } 243 }
205 244
206 if (stats.GetTileWidth() % target.GetTileWidth() != 0 || 245 if (stats.GetTileWidth() % target.GetTileWidth() != 0 ||
207 stats.GetTileHeight() % target.GetTileHeight() != 0) 246 stats.GetTileHeight() % target.GetTileHeight() != 0)
217 LOG(ERROR) << "Tiles are too small (16 pixels minimum): " 256 LOG(ERROR) << "Tiles are too small (16 pixels minimum): "
218 << target.GetTileWidth() << "x" << target.GetTileHeight(); 257 << target.GetTileWidth() << "x" << target.GetTileHeight();
219 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); 258 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize);
220 } 259 }
221 260
222 if (parameters.IsReconstructPyramid()) 261 if (transcoding)
262 {
263 TranscodePyramid(target, stats, parameters);
264 }
265 else
223 { 266 {
224 ReconstructPyramid(target, stats, parameters); 267 ReconstructPyramid(target, stats, parameters);
225 }
226 else
227 {
228 TranscodePyramid(target, stats, parameters);
229 } 268 }
230 269
231 target.Flush(); 270 target.Flush();
232 } 271 }
233 272
861 900
862 return true; 901 return true;
863 } 902 }
864 903
865 904
905
866 OrthancWSI::ITiledPyramid* OpenInputPyramid(OrthancWSI::ImageCompression& sourceCompression, 906 OrthancWSI::ITiledPyramid* OpenInputPyramid(OrthancWSI::ImageCompression& sourceCompression,
867 const std::string& path, 907 const std::string& path,
868 const OrthancWSI::DicomizerParameters& parameters) 908 const OrthancWSI::DicomizerParameters& parameters)
869 { 909 {
870 LOG(WARNING) << "The input image is: " << path; 910 LOG(WARNING) << "The input image is: " << path;
952 // Create the shared DICOM tags 992 // Create the shared DICOM tags
953 std::auto_ptr<DcmDataset> dataset(ParseDataset(parameters.GetDatasetPath())); 993 std::auto_ptr<DcmDataset> dataset(ParseDataset(parameters.GetDatasetPath()));
954 EnrichDataset(*dataset, *source, sourceCompression, parameters, volume); 994 EnrichDataset(*dataset, *source, sourceCompression, parameters, volume);
955 995
956 std::auto_ptr<OrthancWSI::IFileTarget> output(parameters.CreateTarget()); 996 std::auto_ptr<OrthancWSI::IFileTarget> output(parameters.CreateTarget());
957 Recompress(*output, *source, *dataset, parameters, volume); 997 Recompress(*output, *source, *dataset, parameters, volume, sourceCompression);
958 } 998 }
959 } 999 }
960 catch (Orthanc::OrthancException& e) 1000 catch (Orthanc::OrthancException& e)
961 { 1001 {
962 LOG(ERROR) << "Terminating on exception: " << e.What(); 1002 LOG(ERROR) << "Terminating on exception: " << e.What();