Mercurial > hg > orthanc-wsi
comparison Framework/Inputs/DicomPyramidInstance.cpp @ 217:20bc074ec19a
Viewer can display DICOM pyramids whose tile sizes vary across levels
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 12 Jan 2021 14:24:18 +0100 |
parents | c35a3a0627b9 |
children | ef3f8c5126a4 |
comparison
equal
deleted
inserted
replaced
216:c35a3a0627b9 | 217:20bc074ec19a |
---|---|
26 #include "../../Resources/Orthanc/Stone/DicomDatasetReader.h" | 26 #include "../../Resources/Orthanc/Stone/DicomDatasetReader.h" |
27 #include "../../Resources/Orthanc/Stone/FullOrthancDataset.h" | 27 #include "../../Resources/Orthanc/Stone/FullOrthancDataset.h" |
28 | 28 |
29 #include <Logging.h> | 29 #include <Logging.h> |
30 #include <OrthancException.h> | 30 #include <OrthancException.h> |
31 #include <SerializationToolbox.h> | |
31 #include <Toolbox.h> | 32 #include <Toolbox.h> |
32 | 33 |
33 #include <cassert> | 34 #include <cassert> |
34 | 35 |
35 #define SERIALIZED_METADATA "4200" | 36 #define SERIALIZED_METADATA "4201" // Was "4200" if versions <= 0.7 of this plugin |
36 | 37 |
37 | 38 |
38 namespace OrthancWSI | 39 namespace OrthancWSI |
39 { | 40 { |
40 static const Orthanc::DicomTag DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021e); | 41 static const Orthanc::DicomTag DICOM_TAG_COLUMN_POSITION_IN_TOTAL_IMAGE_PIXEL_MATRIX(0x0048, 0x021e); |
83 { | 84 { |
84 using namespace OrthancStone; | 85 using namespace OrthancStone; |
85 | 86 |
86 std::string p = Orthanc::Toolbox::StripSpaces | 87 std::string p = Orthanc::Toolbox::StripSpaces |
87 (reader.GetMandatoryStringValue(OrthancStone::DicomPath(Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION))); | 88 (reader.GetMandatoryStringValue(OrthancStone::DicomPath(Orthanc::DICOM_TAG_PHOTOMETRIC_INTERPRETATION))); |
88 | 89 |
89 photometric = Orthanc::StringToPhotometricInterpretation(p.c_str()); | 90 photometric = Orthanc::StringToPhotometricInterpretation(p.c_str()); |
90 | 91 |
91 if (photometric == Orthanc::PhotometricInterpretation_Palette) | 92 if (photometric == Orthanc::PhotometricInterpretation_Palette) |
92 { | 93 { |
93 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, | 94 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented, |
258 | 259 |
259 DicomPyramidInstance::DicomPyramidInstance(OrthancStone::IOrthancConnection& orthanc, | 260 DicomPyramidInstance::DicomPyramidInstance(OrthancStone::IOrthancConnection& orthanc, |
260 const std::string& instanceId, | 261 const std::string& instanceId, |
261 bool useCache) : | 262 bool useCache) : |
262 instanceId_(instanceId), | 263 instanceId_(instanceId), |
263 hasCompression_(false) | 264 hasCompression_(false), |
265 compression_(ImageCompression_None) // Dummy initialization for serialization | |
264 { | 266 { |
265 if (useCache) | 267 if (useCache) |
266 { | 268 { |
267 try | 269 try |
268 { | 270 { |
269 // Try and deserialized the cached information about this instance | 271 // Try and deserialized the cached information about this instance |
270 std::string serialized; | 272 std::string serialized; |
271 orthanc.RestApiGet(serialized, "/instances/" + instanceId + "/metadata/" + SERIALIZED_METADATA); | 273 orthanc.RestApiGet(serialized, "/instances/" + instanceId + "/metadata/" + SERIALIZED_METADATA); |
274 std::cout << serialized; | |
272 Deserialize(serialized); | 275 Deserialize(serialized); |
273 return; // Success | 276 return; // Success |
274 } | 277 } |
275 catch (Orthanc::OrthancException&) | 278 catch (Orthanc::OrthancException&) |
276 { | 279 { |
302 { | 305 { |
303 assert(frame < frames_.size()); | 306 assert(frame < frames_.size()); |
304 return frames_[frame].second; | 307 return frames_[frame].second; |
305 } | 308 } |
306 | 309 |
310 | |
311 | |
312 static const char* const HAS_COMPRESSION = "HasCompression"; | |
313 static const char* const IMAGE_COMPRESSION = "ImageCompression"; | |
314 static const char* const PIXEL_FORMAT = "PixelFormat"; | |
315 static const char* const FRAMES = "Frames"; | |
316 static const char* const TILE_WIDTH = "TileWidth"; | |
317 static const char* const TILE_HEIGHT = "TileHeight"; | |
318 static const char* const TOTAL_WIDTH = "TotalWidth"; | |
319 static const char* const TOTAL_HEIGHT = "TotalHeight"; | |
320 static const char* const PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation"; | |
321 | |
307 | 322 |
308 void DicomPyramidInstance::Serialize(std::string& result) const | 323 void DicomPyramidInstance::Serialize(std::string& result) const |
309 { | 324 { |
310 Json::Value frames = Json::arrayValue; | 325 Json::Value frames = Json::arrayValue; |
311 for (size_t i = 0; i < frames_.size(); i++) | 326 for (size_t i = 0; i < frames_.size(); i++) |
312 { | 327 { |
313 Json::Value frame = Json::arrayValue; | 328 Json::Value frame = Json::arrayValue; |
314 frame.append(frames_[i].first); | 329 frame.append(frames_[i].first); |
315 frame.append(frames_[i].second); | 330 frame.append(frames_[i].second); |
316 | |
317 frames.append(frame); | 331 frames.append(frame); |
318 } | 332 } |
319 | 333 |
334 Json::Value content = Json::objectValue; | |
335 content[FRAMES] = frames; | |
336 | |
337 // "instanceId_" is set by the constructor | |
338 | |
339 content[HAS_COMPRESSION] = hasCompression_; | |
340 content[IMAGE_COMPRESSION] = static_cast<int>(compression_); | |
341 content[PIXEL_FORMAT] = static_cast<int>(format_); | |
342 content[TILE_WIDTH] = tileWidth_; | |
343 content[TILE_HEIGHT] = tileHeight_; | |
344 content[TOTAL_WIDTH] = totalWidth_; | |
345 content[TOTAL_HEIGHT] = totalHeight_; | |
346 content[PHOTOMETRIC_INTERPRETATION] = Orthanc::EnumerationToString(photometric_); | |
347 | |
348 Orthanc::Toolbox::WriteFastJson(result, content); | |
349 } | |
350 | |
351 | |
352 void DicomPyramidInstance::Deserialize(const std::string& s) | |
353 { | |
320 Json::Value content; | 354 Json::Value content; |
321 content["Frames"] = frames; | 355 Orthanc::Toolbox::ReadJson(content, s); |
322 content["TileHeight"] = tileHeight_; | |
323 content["TileWidth"] = tileWidth_; | |
324 content["TotalHeight"] = totalHeight_; | |
325 content["TotalWidth"] = totalWidth_; | |
326 | |
327 switch (format_) | |
328 { | |
329 case Orthanc::PixelFormat_RGB24: | |
330 content["PixelFormat"] = 0; | |
331 break; | |
332 | |
333 case Orthanc::PixelFormat_Grayscale8: | |
334 content["PixelFormat"] = 1; | |
335 break; | |
336 | |
337 default: | |
338 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
339 } | |
340 | |
341 Orthanc::Toolbox::WriteFastJson(result, content); | |
342 } | |
343 | |
344 | |
345 void DicomPyramidInstance::Deserialize(const std::string& s) | |
346 { | |
347 hasCompression_ = false; | |
348 | |
349 Json::Value content; | |
350 OrthancStone::IOrthancConnection::ParseJson(content, s); | |
351 | 356 |
352 if (content.type() != Json::objectValue || | 357 if (content.type() != Json::objectValue || |
353 !content.isMember("Frames") || | 358 !content.isMember(FRAMES) || |
354 !content.isMember("PixelFormat") || | 359 content[FRAMES].type() != Json::arrayValue) |
355 !content.isMember("TileHeight") || | |
356 !content.isMember("TileWidth") || | |
357 !content.isMember("TotalHeight") || | |
358 !content.isMember("TotalWidth") || | |
359 content["Frames"].type() != Json::arrayValue || | |
360 content["PixelFormat"].type() != Json::intValue || | |
361 content["TileHeight"].type() != Json::intValue || | |
362 content["TileWidth"].type() != Json::intValue || | |
363 content["TotalHeight"].type() != Json::intValue || | |
364 content["TotalWidth"].type() != Json::intValue || | |
365 content["TileHeight"].asInt() < 0 || | |
366 content["TileWidth"].asInt() < 0 || | |
367 content["TotalHeight"].asInt() < 0 || | |
368 content["TotalWidth"].asInt() < 0) | |
369 { | 360 { |
370 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 361 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
371 } | 362 } |
372 | 363 |
373 switch (content["PixelFormat"].asInt()) | 364 hasCompression_ = Orthanc::SerializationToolbox::ReadBoolean(content, HAS_COMPRESSION); |
374 { | 365 compression_ = static_cast<ImageCompression>(Orthanc::SerializationToolbox::ReadInteger(content, IMAGE_COMPRESSION)); |
375 case 0: | 366 format_ = static_cast<Orthanc::PixelFormat>(Orthanc::SerializationToolbox::ReadInteger(content, PIXEL_FORMAT)); |
376 format_ = Orthanc::PixelFormat_RGB24; | 367 tileWidth_ = Orthanc::SerializationToolbox::ReadUnsignedInteger(content, TILE_WIDTH); |
377 break; | 368 tileHeight_ = Orthanc::SerializationToolbox::ReadUnsignedInteger(content, TILE_HEIGHT); |
378 | 369 totalWidth_ = Orthanc::SerializationToolbox::ReadUnsignedInteger(content, TOTAL_WIDTH); |
379 case 1: | 370 totalHeight_ = Orthanc::SerializationToolbox::ReadUnsignedInteger(content, TOTAL_HEIGHT); |
380 format_ = Orthanc::PixelFormat_Grayscale8; | 371 |
381 break; | 372 std::string p = Orthanc::SerializationToolbox::ReadString(content, PHOTOMETRIC_INTERPRETATION); |
382 | 373 photometric_ = Orthanc::StringToPhotometricInterpretation(p.c_str()); |
383 default: | 374 |
384 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 375 const Json::Value f = content[FRAMES]; |
385 } | |
386 | |
387 hasCompression_ = false; | |
388 tileHeight_ = static_cast<unsigned int>(content["TileHeight"].asInt()); | |
389 tileWidth_ = static_cast<unsigned int>(content["TileWidth"].asInt()); | |
390 totalHeight_ = static_cast<unsigned int>(content["TotalHeight"].asInt()); | |
391 totalWidth_ = static_cast<unsigned int>(content["TotalWidth"].asInt()); | |
392 | |
393 const Json::Value f = content["Frames"]; | |
394 frames_.resize(f.size()); | 376 frames_.resize(f.size()); |
395 | 377 |
396 for (Json::Value::ArrayIndex i = 0; i < f.size(); i++) | 378 for (Json::Value::ArrayIndex i = 0; i < f.size(); i++) |
397 { | 379 { |
398 if (f[i].type() != Json::arrayValue || | 380 if (f[i].type() != Json::arrayValue || |