Mercurial > hg > orthanc-stone
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 } |