comparison Samples/Sdl/Loader.cpp @ 765:f6438fdc447e

cont
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 23 May 2019 14:57:52 +0200
parents f36a6f7e7bdf
children d6cd7c5ca6ea
comparison
equal deleted inserted replaced
764:f36a6f7e7bdf 765:f6438fdc447e
869 GetTarget().SetTransferSyntax(message.GetAnswer()); 869 GetTarget().SetTransferSyntax(message.GetAnswer());
870 } 870 }
871 }; 871 };
872 872
873 873
874 class LoadUncompressedPixelData : public State
875 {
876 public:
877 LoadUncompressedPixelData(OrthancMultiframeVolumeLoader& that) :
878 State(that)
879 {
880 }
881
882 virtual void Handle(const OrthancRestApiCommand::SuccessMessage& message) const
883 {
884 GetTarget().SetUncompressedPixelData(message.GetAnswer());
885 }
886 };
887
888
874 889
875 IOracle& oracle_; 890 IOracle& oracle_;
876 bool active_; 891 bool active_;
877 std::string instanceId_; 892 std::string instanceId_;
878 std::string transferSyntaxUid_; 893 std::string transferSyntaxUid_;
894 uint64_t revision_;
879 895
880 std::auto_ptr<DicomInstanceParameters> dicom_; 896 std::auto_ptr<DicomInstanceParameters> dicom_;
881 std::auto_ptr<VolumeImageGeometry> geometry_; 897 std::auto_ptr<VolumeImageGeometry> geometry_;
882 std::auto_ptr<ImageBuffer3D> image_; 898 std::auto_ptr<ImageBuffer3D> image_;
883 899
901 !HasGeometry()) 917 !HasGeometry())
902 { 918 {
903 return; 919 return;
904 } 920 }
905 921
906 if (transferSyntaxUid_ != "1.2.840.10008.1.2" && 922 if (transferSyntaxUid_ == "1.2.840.10008.1.2" ||
907 transferSyntaxUid_ != "1.2.840.10008.1.2.1" && 923 transferSyntaxUid_ == "1.2.840.10008.1.2.1" ||
908 transferSyntaxUid_ != "1.2.840.10008.1.2.2") 924 transferSyntaxUid_ == "1.2.840.10008.1.2.2")
925 {
926 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
927 command->SetHttpHeader("Accept-Encoding", "gzip");
928 command->SetUri("/instances/" + instanceId_ + "/content/" +
929 Orthanc::DICOM_TAG_PIXEL_DATA.Format() + "/0");
930 command->SetPayload(new LoadUncompressedPixelData(*this));
931 oracle_.Schedule(*this, command.release());
932 }
933 else
909 { 934 {
910 throw Orthanc::OrthancException( 935 throw Orthanc::OrthancException(
911 Orthanc::ErrorCode_NotImplemented, 936 Orthanc::ErrorCode_NotImplemented,
912 "No support for multiframe instances with transfer syntax: " + transferSyntaxUid_); 937 "No support for multiframe instances with transfer syntax: " + transferSyntaxUid_);
913 } 938 }
957 982
958 image_.reset(new ImageBuffer3D(format, width, height, depth, 983 image_.reset(new ImageBuffer3D(format, width, height, depth,
959 false /* don't compute range */)); 984 false /* don't compute range */));
960 985
961 ScheduleFrameDownloads(); 986 ScheduleFrameDownloads();
987 }
988
989
990 ORTHANC_FORCE_INLINE
991 static void CopyPixel(uint32_t& target,
992 const void* source)
993 {
994 // TODO - check alignement?
995 target = le32toh(*reinterpret_cast<const uint32_t*>(source));
996 }
997
998
999 template <typename T>
1000 void CopyPixelData(const std::string& pixelData)
1001 {
1002 const Orthanc::PixelFormat format = image_->GetFormat();
1003 const unsigned int bpp = image_->GetBytesPerPixel();
1004 const unsigned int width = image_->GetWidth();
1005 const unsigned int height = image_->GetHeight();
1006 const unsigned int depth = image_->GetDepth();
1007
1008 if (pixelData.size() != bpp * width * height * depth)
1009 {
1010 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
1011 "The pixel data has not the proper size");
1012 }
1013
1014 if (pixelData.empty())
1015 {
1016 return;
1017 }
1018
1019 const uint8_t* source = reinterpret_cast<const uint8_t*>(pixelData.c_str());
1020
1021 for (unsigned int z = 0; z < depth; z++)
1022 {
1023 ImageBuffer3D::SliceWriter writer(*image_, VolumeProjection_Axial, z);
1024
1025 assert (writer.GetAccessor().GetWidth() == width &&
1026 writer.GetAccessor().GetHeight() == height);
1027
1028 for (unsigned int y = 0; y < height; y++)
1029 {
1030 assert(sizeof(T) == Orthanc::GetBytesPerPixel(format));
1031
1032 T* target = reinterpret_cast<T*>(writer.GetAccessor().GetRow(y));
1033
1034 for (unsigned int x = 0; x < width; x++)
1035 {
1036 CopyPixel(*target, source);
1037
1038 target ++;
1039 source += bpp;
1040 }
1041 }
1042 }
1043 }
1044
1045
1046 void SetUncompressedPixelData(const std::string& pixelData)
1047 {
1048 switch (image_->GetFormat())
1049 {
1050 case Orthanc::PixelFormat_Grayscale32:
1051 CopyPixelData<uint32_t>(pixelData);
1052 break;
1053
1054 default:
1055 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
1056 }
1057
1058 revision_ ++;
962 } 1059 }
963 1060
964 1061
965 public: 1062 public:
966 OrthancMultiframeVolumeLoader(IOracle& oracle, 1063 OrthancMultiframeVolumeLoader(IOracle& oracle,
994 active_ = true; 1091 active_ = true;
995 instanceId_ = instanceId; 1092 instanceId_ = instanceId;
996 1093
997 { 1094 {
998 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand); 1095 std::auto_ptr<OrthancRestApiCommand> command(new OrthancRestApiCommand);
1096 command->SetHttpHeader("Accept-Encoding", "gzip");
999 command->SetUri("/instances/" + instanceId + "/tags"); 1097 command->SetUri("/instances/" + instanceId + "/tags");
1000 command->SetPayload(new LoadGeometry(*this)); 1098 command->SetPayload(new LoadGeometry(*this));
1001 oracle_.Schedule(*this, command.release()); 1099 oracle_.Schedule(*this, command.release());
1002 } 1100 }
1003 1101
1230 Orthanc::PngWriter writer; 1328 Orthanc::PngWriter writer;
1231 writer.WriteToFile(buf, tmp); 1329 writer.WriteToFile(buf, tmp);
1232 } 1330 }
1233 } 1331 }
1234 1332
1333 /**
1334 * The sleep() leads to a crash if the oracle is still running,
1335 * while this object is destroyed. Always stop the oracle before
1336 * destroying active objects. (*)
1337 **/
1338 // boost::this_thread::sleep(boost::posix_time::seconds(2));
1339
1235 oracle_.Schedule(*this, new OrthancStone::SleepOracleCommand(message.GetOrigin().GetDelay())); 1340 oracle_.Schedule(*this, new OrthancStone::SleepOracleCommand(message.GetOrigin().GetDelay()));
1236 } 1341 }
1237 } 1342 }
1238 1343
1239 void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message) 1344 void Handle(const OrthancStone::OrthancRestApiCommand::SuccessMessage& message)
1304 } 1409 }
1305 }; 1410 };
1306 1411
1307 1412
1308 void Run(OrthancStone::NativeApplicationContext& context, 1413 void Run(OrthancStone::NativeApplicationContext& context,
1309 OrthancStone::IOracle& oracle) 1414 OrthancStone::ThreadedOracle& oracle)
1310 { 1415 {
1311 boost::shared_ptr<Toto> toto; 1416 boost::shared_ptr<Toto> toto;
1312 boost::shared_ptr<OrthancStone::OrthancSeriesVolumeProgressiveLoader> loader1, loader2; 1417 boost::shared_ptr<OrthancStone::OrthancSeriesVolumeProgressiveLoader> loader1, loader2;
1313 boost::shared_ptr<OrthancStone::OrthancMultiframeVolumeLoader> loader3; 1418 boost::shared_ptr<OrthancStone::OrthancMultiframeVolumeLoader> loader3;
1314 1419
1409 //loader1->LoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); // Lung 1/10mm 1514 //loader1->LoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); // Lung 1/10mm
1410 1515
1411 1516
1412 toto->SetVolume(0, new OrthancStone::OrthancSeriesVolumeProgressiveLoader::MPRSlicer(loader1)); 1517 toto->SetVolume(0, new OrthancStone::OrthancSeriesVolumeProgressiveLoader::MPRSlicer(loader1));
1413 1518
1414 LOG(WARNING) << "...Waiting for Ctrl-C..."; 1519 {
1415 Orthanc::SystemToolbox::ServerBarrier(); 1520 oracle.Start();
1416 //boost::this_thread::sleep(boost::posix_time::seconds(1)); 1521
1522 LOG(WARNING) << "...Waiting for Ctrl-C...";
1523 Orthanc::SystemToolbox::ServerBarrier();
1524
1525 /**
1526 * WARNING => The oracle must be stopped BEFORE the objects using
1527 * it are destroyed!!! This forces to wait for the completion of
1528 * the running callback methods. Otherwise, the callbacks methods
1529 * might still be running while their parent object is destroyed,
1530 * resulting in crashes. This is very visible if adding a sleep(),
1531 * as in (*).
1532 **/
1533
1534 oracle.Stop();
1535 }
1417 } 1536 }
1418 1537
1419 1538
1420 1539
1421 /** 1540 /**
1440 //p.SetUrl("http://localhost:8043/"); 1559 //p.SetUrl("http://localhost:8043/");
1441 p.SetCredentials("orthanc", "orthanc"); 1560 p.SetCredentials("orthanc", "orthanc");
1442 oracle.SetOrthancParameters(p); 1561 oracle.SetOrthancParameters(p);
1443 } 1562 }
1444 1563
1445 oracle.Start(); 1564 //oracle.Start();
1446 1565
1447 Run(context, oracle); 1566 Run(context, oracle);
1448 1567
1449 oracle.Stop(); 1568 //oracle.Stop();
1450 } 1569 }
1451 catch (Orthanc::OrthancException& e) 1570 catch (Orthanc::OrthancException& e)
1452 { 1571 {
1453 LOG(ERROR) << "EXCEPTION: " << e.What(); 1572 LOG(ERROR) << "EXCEPTION: " << e.What();
1454 } 1573 }