# HG changeset patch # User Sebastien Jodogne # Date 1557492843 -7200 # Node ID 7ca8dc7ec17b23c32c7a68e6c679c21c25cc4e16 # Parent 392783c906071e8976ddb1a7307428757e234ba9 GetOrthancWebViewerJpegCommand::ProcessHttpHandler() diff -r 392783c90607 -r 7ca8dc7ec17b Framework/StoneEnumerations.h --- a/Framework/StoneEnumerations.h Fri May 10 10:59:37 2019 +0200 +++ b/Framework/StoneEnumerations.h Fri May 10 14:54:03 2019 +0200 @@ -173,10 +173,12 @@ MessageType_Test2, - MessageType_ImageReady, - MessageType_OrthancException, - + MessageType_OrthancRestApiCommand, + MessageType_GetOrthancImageCommand, + MessageType_GetOrthancWebViewerJpegCommand, + MessageType_OracleCommandExceptionMessage, + MessageType_CustomMessage // Custom messages ids ust be greater than this (this one must remain in last position) }; diff -r 392783c90607 -r 7ca8dc7ec17b Samples/Sdl/Loader.cpp --- a/Samples/Sdl/Loader.cpp Fri May 10 10:59:37 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Fri May 10 14:54:03 2019 +0200 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -139,7 +140,7 @@ class OracleCommandExceptionMessage : - public OrthancStone::BaseMessage + public OrthancStone::BaseMessage { private: const IOracleCommand& command_; @@ -177,7 +178,7 @@ class OrthancRestApiCommand : public OracleCommandWithPayload { public: - class SuccessMessage : public OrthancStone::OriginMessage { private: @@ -315,7 +316,7 @@ class GetOrthancImageCommand : public OracleCommandWithPayload { public: - class SuccessMessage : public OrthancStone::OriginMessage { private: @@ -450,7 +451,7 @@ std::string(Orthanc::EnumerationToString(contentType))); } - GetOrthancImageCommand::SuccessMessage message(*this, image.release(), contentType); + SuccessMessage message(*this, image.release(), contentType); emitter.EmitMessage(receiver, message); } }; @@ -460,7 +461,7 @@ class GetOrthancWebViewerJpegCommand : public OracleCommandWithPayload { public: - class SuccessMessage : public OrthancStone::OriginMessage { private: @@ -485,11 +486,12 @@ }; private: - std::string instanceId_; - unsigned int frame_; - unsigned int quality_; - HttpHeaders headers_; - unsigned int timeout_; + std::string instanceId_; + unsigned int frame_; + unsigned int quality_; + HttpHeaders headers_; + unsigned int timeout_; + Orthanc::PixelFormat expectedFormat_; std::auto_ptr< OrthancStone::MessageHandler > successCallback_; std::auto_ptr< OrthancStone::MessageHandler > failureCallback_; @@ -498,7 +500,8 @@ GetOrthancWebViewerJpegCommand() : frame_(0), quality_(95), - timeout_(10) + timeout_(10), + expectedFormat_(Orthanc::PixelFormat_Grayscale8) { } @@ -507,6 +510,11 @@ return Type_GetOrthancWebViewerJpeg; } + void SetExpectedFormat(Orthanc::PixelFormat format) + { + expectedFormat_ = format; + } + void SetInstance(const std::string& instanceId) { instanceId_ = instanceId; @@ -536,6 +544,11 @@ headers_[key] = value; } + Orthanc::PixelFormat GetExpectedFormat() const + { + return expectedFormat_; + } + const std::string& GetInstanceId() const { return instanceId_; @@ -576,15 +589,139 @@ const OrthancStone::IObserver& receiver, const std::string& answer) const { - Json::Value value; - Json::Reader reader; - if (!reader.parse(answer, value)) + // This code comes from older "OrthancSlicesLoader::ParseSliceImageJpeg()" + + Json::Value encoded; + + { + Json::Reader reader; + if (!reader.parse(answer, encoded)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + } + + if (encoded.type() != Json::objectValue || + !encoded.isMember("Orthanc") || + encoded["Orthanc"].type() != Json::objectValue) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + const Json::Value& info = encoded["Orthanc"]; + if (!info.isMember("PixelData") || + !info.isMember("Stretched") || + !info.isMember("Compression") || + info["Compression"].type() != Json::stringValue || + info["PixelData"].type() != Json::stringValue || + info["Stretched"].type() != Json::booleanValue || + info["Compression"].asString() != "Jpeg") { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); } + + bool isSigned = false; + bool isStretched = info["Stretched"].asBool(); + + if (info.isMember("IsSigned")) + { + if (info["IsSigned"].type() != Json::booleanValue) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + else + { + isSigned = info["IsSigned"].asBool(); + } + } + + std::auto_ptr reader; + + { + std::string jpeg; + Orthanc::Toolbox::DecodeBase64(jpeg, info["PixelData"].asString()); + + reader.reset(new Orthanc::JpegReader); + dynamic_cast(*reader).ReadFromMemory(jpeg); + } + + if (reader->GetFormat() == Orthanc::PixelFormat_RGB24) // This is a color image + { + if (expectedFormat_ != Orthanc::PixelFormat_RGB24) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + if (isSigned || isStretched) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + else + { + SuccessMessage message(*this, reader.release()); + emitter.EmitMessage(receiver, message); + return; + } + } + + if (reader->GetFormat() != Orthanc::PixelFormat_Grayscale8) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + if (!isStretched) + { + if (expectedFormat_ != reader->GetFormat()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + else + { + SuccessMessage message(*this, reader.release()); + emitter.EmitMessage(receiver, message); + return; + } + } + + int32_t stretchLow = 0; + int32_t stretchHigh = 0; + + if (!info.isMember("StretchLow") || + !info.isMember("StretchHigh") || + info["StretchLow"].type() != Json::intValue || + info["StretchHigh"].type() != Json::intValue) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + stretchLow = info["StretchLow"].asInt(); + stretchHigh = info["StretchHigh"].asInt(); + + if (stretchLow < -32768 || + stretchHigh > 65535 || + (stretchLow < 0 && stretchHigh > 32767)) + { + // This range cannot be represented with a uint16_t or an int16_t + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + // Decode a grayscale JPEG 8bpp image coming from the Web viewer + std::auto_ptr image + (new Orthanc::Image(expectedFormat_, reader->GetWidth(), reader->GetHeight(), false)); - //GetOrthancWebViewerJpegCommand::SuccessMessage message(command, image.release(), contentType); - //emitter.EmitMessage(receiver, message); + Orthanc::ImageProcessing::Convert(*image, *reader); + reader.reset(); + + float scaling = static_cast(stretchHigh - stretchLow) / 255.0f; + + if (!OrthancStone::LinearAlgebra::IsCloseToZero(scaling)) + { + float offset = static_cast(stretchLow) / scaling; + Orthanc::ImageProcessing::ShiftScale(*image, offset, scaling, true); + } + + SuccessMessage message(*this, image.release()); + emitter.EmitMessage(receiver, message); } }; @@ -671,7 +808,6 @@ } else { - // TODO - Emit error message? throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, "Unsupported HTTP Content-Encoding: " + it->second); } @@ -759,6 +895,8 @@ if (object.get() != NULL) { + printf("===========================> REQUEST\n"); + const Item& item = dynamic_cast(*object); try @@ -1463,6 +1601,11 @@ printf("IMAGE %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); } + void Handle(const Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage& message) + { + printf("WebViewer %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); + } + void Handle(const Refactoring::OracleCommandExceptionMessage& message) { printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), message.GetCommand().GetType()); @@ -1493,6 +1636,10 @@ oracle.RegisterObserverCallback (new OrthancStone::Callable + (*this, &Toto::Handle)); + + oracle.RegisterObserverCallback + (new OrthancStone::Callable (*this, &Toto::Handle)); } }; @@ -1521,7 +1668,7 @@ oracle.Start(); - if (0) + if (1) { Json::Value v = Json::objectValue; v["Level"] = "Series"; @@ -1535,7 +1682,7 @@ oracle.Schedule(*toto, command.release()); } - if (0) + if (1) { std::auto_ptr command(new Refactoring::GetOrthancImageCommand); command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Jpeg))); @@ -1543,7 +1690,7 @@ oracle.Schedule(*toto, command.release()); } - if (0) + if (1) { std::auto_ptr command(new Refactoring::GetOrthancImageCommand); command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Png))); @@ -1590,7 +1737,9 @@ loader1->LoadSeries(oracle, "cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT loader2->LoadInstance(oracle, "41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE - boost::this_thread::sleep(boost::posix_time::seconds(1)); + LOG(WARNING) << "...Waiting for Ctrl-C..."; + Orthanc::SystemToolbox::ServerBarrier(); + //boost::this_thread::sleep(boost::posix_time::seconds(1)); oracle.Stop(); }