Mercurial > hg > orthanc-stone
comparison Samples/Sdl/Loader.cpp @ 642:7ca8dc7ec17b
GetOrthancWebViewerJpegCommand::ProcessHttpHandler()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 10 May 2019 14:54:03 +0200 |
parents | 392783c90607 |
children | f0008c55e5f7 1e9ed656318e |
comparison
equal
deleted
inserted
replaced
641:392783c90607 | 642:7ca8dc7ec17b |
---|---|
42 #include <Core/Images/PngWriter.h> | 42 #include <Core/Images/PngWriter.h> |
43 #include <Core/Logging.h> | 43 #include <Core/Logging.h> |
44 #include <Core/MultiThreading/SharedMessageQueue.h> | 44 #include <Core/MultiThreading/SharedMessageQueue.h> |
45 #include <Core/OrthancException.h> | 45 #include <Core/OrthancException.h> |
46 #include <Core/Toolbox.h> | 46 #include <Core/Toolbox.h> |
47 #include <Core/SystemToolbox.h> | |
47 | 48 |
48 #include <json/reader.h> | 49 #include <json/reader.h> |
49 #include <json/value.h> | 50 #include <json/value.h> |
50 #include <json/writer.h> | 51 #include <json/writer.h> |
51 | 52 |
137 }; | 138 }; |
138 | 139 |
139 | 140 |
140 | 141 |
141 class OracleCommandExceptionMessage : | 142 class OracleCommandExceptionMessage : |
142 public OrthancStone::BaseMessage<OrthancStone::MessageType_OrthancException> | 143 public OrthancStone::BaseMessage<OrthancStone::MessageType_OracleCommandExceptionMessage> |
143 { | 144 { |
144 private: | 145 private: |
145 const IOracleCommand& command_; | 146 const IOracleCommand& command_; |
146 Orthanc::OrthancException exception_; | 147 Orthanc::OrthancException exception_; |
147 | 148 |
175 typedef std::map<std::string, std::string> HttpHeaders; | 176 typedef std::map<std::string, std::string> HttpHeaders; |
176 | 177 |
177 class OrthancRestApiCommand : public OracleCommandWithPayload | 178 class OrthancRestApiCommand : public OracleCommandWithPayload |
178 { | 179 { |
179 public: | 180 public: |
180 class SuccessMessage : public OrthancStone::OriginMessage<OrthancStone::MessageType_HttpRequestSuccess, // TODO | 181 class SuccessMessage : public OrthancStone::OriginMessage<OrthancStone::MessageType_OrthancRestApiCommand, |
181 OrthancRestApiCommand> | 182 OrthancRestApiCommand> |
182 { | 183 { |
183 private: | 184 private: |
184 HttpHeaders headers_; | 185 HttpHeaders headers_; |
185 std::string answer_; | 186 std::string answer_; |
313 | 314 |
314 | 315 |
315 class GetOrthancImageCommand : public OracleCommandWithPayload | 316 class GetOrthancImageCommand : public OracleCommandWithPayload |
316 { | 317 { |
317 public: | 318 public: |
318 class SuccessMessage : public OrthancStone::OriginMessage<OrthancStone::MessageType_ImageReady, // TODO | 319 class SuccessMessage : public OrthancStone::OriginMessage<OrthancStone::MessageType_GetOrthancImageCommand, |
319 GetOrthancImageCommand> | 320 GetOrthancImageCommand> |
320 { | 321 { |
321 private: | 322 private: |
322 std::auto_ptr<Orthanc::ImageAccessor> image_; | 323 std::auto_ptr<Orthanc::ImageAccessor> image_; |
323 Orthanc::MimeType mime_; | 324 Orthanc::MimeType mime_; |
448 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, | 449 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, |
449 "Unsupported HTTP Content-Type for an image: " + | 450 "Unsupported HTTP Content-Type for an image: " + |
450 std::string(Orthanc::EnumerationToString(contentType))); | 451 std::string(Orthanc::EnumerationToString(contentType))); |
451 } | 452 } |
452 | 453 |
453 GetOrthancImageCommand::SuccessMessage message(*this, image.release(), contentType); | 454 SuccessMessage message(*this, image.release(), contentType); |
454 emitter.EmitMessage(receiver, message); | 455 emitter.EmitMessage(receiver, message); |
455 } | 456 } |
456 }; | 457 }; |
457 | 458 |
458 | 459 |
459 | 460 |
460 class GetOrthancWebViewerJpegCommand : public OracleCommandWithPayload | 461 class GetOrthancWebViewerJpegCommand : public OracleCommandWithPayload |
461 { | 462 { |
462 public: | 463 public: |
463 class SuccessMessage : public OrthancStone::OriginMessage<OrthancStone::MessageType_ImageReady, // TODO | 464 class SuccessMessage : public OrthancStone::OriginMessage<OrthancStone::MessageType_GetOrthancWebViewerJpegCommand, |
464 GetOrthancWebViewerJpegCommand> | 465 GetOrthancWebViewerJpegCommand> |
465 { | 466 { |
466 private: | 467 private: |
467 std::auto_ptr<Orthanc::ImageAccessor> image_; | 468 std::auto_ptr<Orthanc::ImageAccessor> image_; |
468 | 469 |
483 return *image_; | 484 return *image_; |
484 } | 485 } |
485 }; | 486 }; |
486 | 487 |
487 private: | 488 private: |
488 std::string instanceId_; | 489 std::string instanceId_; |
489 unsigned int frame_; | 490 unsigned int frame_; |
490 unsigned int quality_; | 491 unsigned int quality_; |
491 HttpHeaders headers_; | 492 HttpHeaders headers_; |
492 unsigned int timeout_; | 493 unsigned int timeout_; |
494 Orthanc::PixelFormat expectedFormat_; | |
493 | 495 |
494 std::auto_ptr< OrthancStone::MessageHandler<SuccessMessage> > successCallback_; | 496 std::auto_ptr< OrthancStone::MessageHandler<SuccessMessage> > successCallback_; |
495 std::auto_ptr< OrthancStone::MessageHandler<OracleCommandExceptionMessage> > failureCallback_; | 497 std::auto_ptr< OrthancStone::MessageHandler<OracleCommandExceptionMessage> > failureCallback_; |
496 | 498 |
497 public: | 499 public: |
498 GetOrthancWebViewerJpegCommand() : | 500 GetOrthancWebViewerJpegCommand() : |
499 frame_(0), | 501 frame_(0), |
500 quality_(95), | 502 quality_(95), |
501 timeout_(10) | 503 timeout_(10), |
504 expectedFormat_(Orthanc::PixelFormat_Grayscale8) | |
502 { | 505 { |
503 } | 506 } |
504 | 507 |
505 virtual Type GetType() const | 508 virtual Type GetType() const |
506 { | 509 { |
507 return Type_GetOrthancWebViewerJpeg; | 510 return Type_GetOrthancWebViewerJpeg; |
511 } | |
512 | |
513 void SetExpectedFormat(Orthanc::PixelFormat format) | |
514 { | |
515 expectedFormat_ = format; | |
508 } | 516 } |
509 | 517 |
510 void SetInstance(const std::string& instanceId) | 518 void SetInstance(const std::string& instanceId) |
511 { | 519 { |
512 instanceId_ = instanceId; | 520 instanceId_ = instanceId; |
532 | 540 |
533 void SetHttpHeader(const std::string& key, | 541 void SetHttpHeader(const std::string& key, |
534 const std::string& value) | 542 const std::string& value) |
535 { | 543 { |
536 headers_[key] = value; | 544 headers_[key] = value; |
545 } | |
546 | |
547 Orthanc::PixelFormat GetExpectedFormat() const | |
548 { | |
549 return expectedFormat_; | |
537 } | 550 } |
538 | 551 |
539 const std::string& GetInstanceId() const | 552 const std::string& GetInstanceId() const |
540 { | 553 { |
541 return instanceId_; | 554 return instanceId_; |
574 | 587 |
575 void ProcessHttpAnswer(IMessageEmitter& emitter, | 588 void ProcessHttpAnswer(IMessageEmitter& emitter, |
576 const OrthancStone::IObserver& receiver, | 589 const OrthancStone::IObserver& receiver, |
577 const std::string& answer) const | 590 const std::string& answer) const |
578 { | 591 { |
579 Json::Value value; | 592 // This code comes from older "OrthancSlicesLoader::ParseSliceImageJpeg()" |
580 Json::Reader reader; | 593 |
581 if (!reader.parse(answer, value)) | 594 Json::Value encoded; |
595 | |
596 { | |
597 Json::Reader reader; | |
598 if (!reader.parse(answer, encoded)) | |
599 { | |
600 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
601 } | |
602 } | |
603 | |
604 if (encoded.type() != Json::objectValue || | |
605 !encoded.isMember("Orthanc") || | |
606 encoded["Orthanc"].type() != Json::objectValue) | |
582 { | 607 { |
583 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | 608 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); |
584 } | 609 } |
585 | 610 |
586 //GetOrthancWebViewerJpegCommand::SuccessMessage message(command, image.release(), contentType); | 611 const Json::Value& info = encoded["Orthanc"]; |
587 //emitter.EmitMessage(receiver, message); | 612 if (!info.isMember("PixelData") || |
613 !info.isMember("Stretched") || | |
614 !info.isMember("Compression") || | |
615 info["Compression"].type() != Json::stringValue || | |
616 info["PixelData"].type() != Json::stringValue || | |
617 info["Stretched"].type() != Json::booleanValue || | |
618 info["Compression"].asString() != "Jpeg") | |
619 { | |
620 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
621 } | |
622 | |
623 bool isSigned = false; | |
624 bool isStretched = info["Stretched"].asBool(); | |
625 | |
626 if (info.isMember("IsSigned")) | |
627 { | |
628 if (info["IsSigned"].type() != Json::booleanValue) | |
629 { | |
630 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
631 } | |
632 else | |
633 { | |
634 isSigned = info["IsSigned"].asBool(); | |
635 } | |
636 } | |
637 | |
638 std::auto_ptr<Orthanc::ImageAccessor> reader; | |
639 | |
640 { | |
641 std::string jpeg; | |
642 Orthanc::Toolbox::DecodeBase64(jpeg, info["PixelData"].asString()); | |
643 | |
644 reader.reset(new Orthanc::JpegReader); | |
645 dynamic_cast<Orthanc::JpegReader&>(*reader).ReadFromMemory(jpeg); | |
646 } | |
647 | |
648 if (reader->GetFormat() == Orthanc::PixelFormat_RGB24) // This is a color image | |
649 { | |
650 if (expectedFormat_ != Orthanc::PixelFormat_RGB24) | |
651 { | |
652 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
653 } | |
654 | |
655 if (isSigned || isStretched) | |
656 { | |
657 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
658 } | |
659 else | |
660 { | |
661 SuccessMessage message(*this, reader.release()); | |
662 emitter.EmitMessage(receiver, message); | |
663 return; | |
664 } | |
665 } | |
666 | |
667 if (reader->GetFormat() != Orthanc::PixelFormat_Grayscale8) | |
668 { | |
669 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
670 } | |
671 | |
672 if (!isStretched) | |
673 { | |
674 if (expectedFormat_ != reader->GetFormat()) | |
675 { | |
676 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
677 } | |
678 else | |
679 { | |
680 SuccessMessage message(*this, reader.release()); | |
681 emitter.EmitMessage(receiver, message); | |
682 return; | |
683 } | |
684 } | |
685 | |
686 int32_t stretchLow = 0; | |
687 int32_t stretchHigh = 0; | |
688 | |
689 if (!info.isMember("StretchLow") || | |
690 !info.isMember("StretchHigh") || | |
691 info["StretchLow"].type() != Json::intValue || | |
692 info["StretchHigh"].type() != Json::intValue) | |
693 { | |
694 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
695 } | |
696 | |
697 stretchLow = info["StretchLow"].asInt(); | |
698 stretchHigh = info["StretchHigh"].asInt(); | |
699 | |
700 if (stretchLow < -32768 || | |
701 stretchHigh > 65535 || | |
702 (stretchLow < 0 && stretchHigh > 32767)) | |
703 { | |
704 // This range cannot be represented with a uint16_t or an int16_t | |
705 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); | |
706 } | |
707 | |
708 // Decode a grayscale JPEG 8bpp image coming from the Web viewer | |
709 std::auto_ptr<Orthanc::ImageAccessor> image | |
710 (new Orthanc::Image(expectedFormat_, reader->GetWidth(), reader->GetHeight(), false)); | |
711 | |
712 Orthanc::ImageProcessing::Convert(*image, *reader); | |
713 reader.reset(); | |
714 | |
715 float scaling = static_cast<float>(stretchHigh - stretchLow) / 255.0f; | |
716 | |
717 if (!OrthancStone::LinearAlgebra::IsCloseToZero(scaling)) | |
718 { | |
719 float offset = static_cast<float>(stretchLow) / scaling; | |
720 Orthanc::ImageProcessing::ShiftScale(*image, offset, scaling, true); | |
721 } | |
722 | |
723 SuccessMessage message(*this, image.release()); | |
724 emitter.EmitMessage(receiver, message); | |
588 } | 725 } |
589 }; | 726 }; |
590 | 727 |
591 | 728 |
592 | 729 |
669 { | 806 { |
670 contentEncoding = Orthanc::HttpCompression_Gzip; | 807 contentEncoding = Orthanc::HttpCompression_Gzip; |
671 } | 808 } |
672 else | 809 else |
673 { | 810 { |
674 // TODO - Emit error message? | |
675 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, | 811 throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol, |
676 "Unsupported HTTP Content-Encoding: " + it->second); | 812 "Unsupported HTTP Content-Encoding: " + it->second); |
677 } | 813 } |
678 | 814 |
679 break; | 815 break; |
757 { | 893 { |
758 std::auto_ptr<Orthanc::IDynamicObject> object(queue_.Dequeue(100)); | 894 std::auto_ptr<Orthanc::IDynamicObject> object(queue_.Dequeue(100)); |
759 | 895 |
760 if (object.get() != NULL) | 896 if (object.get() != NULL) |
761 { | 897 { |
898 printf("===========================> REQUEST\n"); | |
899 | |
762 const Item& item = dynamic_cast<Item&>(*object); | 900 const Item& item = dynamic_cast<Item&>(*object); |
763 | 901 |
764 try | 902 try |
765 { | 903 { |
766 switch (item.GetCommand().GetType()) | 904 switch (item.GetCommand().GetType()) |
1461 void Handle(const Refactoring::GetOrthancImageCommand::SuccessMessage& message) | 1599 void Handle(const Refactoring::GetOrthancImageCommand::SuccessMessage& message) |
1462 { | 1600 { |
1463 printf("IMAGE %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); | 1601 printf("IMAGE %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); |
1464 } | 1602 } |
1465 | 1603 |
1604 void Handle(const Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage& message) | |
1605 { | |
1606 printf("WebViewer %dx%d\n", message.GetImage().GetWidth(), message.GetImage().GetHeight()); | |
1607 } | |
1608 | |
1466 void Handle(const Refactoring::OracleCommandExceptionMessage& message) | 1609 void Handle(const Refactoring::OracleCommandExceptionMessage& message) |
1467 { | 1610 { |
1468 printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), message.GetCommand().GetType()); | 1611 printf("EXCEPTION: [%s] on command type %d\n", message.GetException().What(), message.GetCommand().GetType()); |
1469 | 1612 |
1470 switch (message.GetCommand().GetType()) | 1613 switch (message.GetCommand().GetType()) |
1491 (new OrthancStone::Callable | 1634 (new OrthancStone::Callable |
1492 <Toto, Refactoring::GetOrthancImageCommand::SuccessMessage>(*this, &Toto::Handle)); | 1635 <Toto, Refactoring::GetOrthancImageCommand::SuccessMessage>(*this, &Toto::Handle)); |
1493 | 1636 |
1494 oracle.RegisterObserverCallback | 1637 oracle.RegisterObserverCallback |
1495 (new OrthancStone::Callable | 1638 (new OrthancStone::Callable |
1639 <Toto, Refactoring::GetOrthancWebViewerJpegCommand::SuccessMessage>(*this, &Toto::Handle)); | |
1640 | |
1641 oracle.RegisterObserverCallback | |
1642 (new OrthancStone::Callable | |
1496 <Toto, Refactoring::OracleCommandExceptionMessage>(*this, &Toto::Handle)); | 1643 <Toto, Refactoring::OracleCommandExceptionMessage>(*this, &Toto::Handle)); |
1497 } | 1644 } |
1498 }; | 1645 }; |
1499 | 1646 |
1500 | 1647 |
1519 oracle.SetOrthancParameters(p); | 1666 oracle.SetOrthancParameters(p); |
1520 } | 1667 } |
1521 | 1668 |
1522 oracle.Start(); | 1669 oracle.Start(); |
1523 | 1670 |
1524 if (0) | 1671 if (1) |
1525 { | 1672 { |
1526 Json::Value v = Json::objectValue; | 1673 Json::Value v = Json::objectValue; |
1527 v["Level"] = "Series"; | 1674 v["Level"] = "Series"; |
1528 v["Query"] = Json::objectValue; | 1675 v["Query"] = Json::objectValue; |
1529 | 1676 |
1533 command->SetBody(v); | 1680 command->SetBody(v); |
1534 | 1681 |
1535 oracle.Schedule(*toto, command.release()); | 1682 oracle.Schedule(*toto, command.release()); |
1536 } | 1683 } |
1537 | 1684 |
1538 if (0) | 1685 if (1) |
1539 { | 1686 { |
1540 std::auto_ptr<Refactoring::GetOrthancImageCommand> command(new Refactoring::GetOrthancImageCommand); | 1687 std::auto_ptr<Refactoring::GetOrthancImageCommand> command(new Refactoring::GetOrthancImageCommand); |
1541 command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Jpeg))); | 1688 command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Jpeg))); |
1542 command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/preview"); | 1689 command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/preview"); |
1543 oracle.Schedule(*toto, command.release()); | 1690 oracle.Schedule(*toto, command.release()); |
1544 } | 1691 } |
1545 | 1692 |
1546 if (0) | 1693 if (1) |
1547 { | 1694 { |
1548 std::auto_ptr<Refactoring::GetOrthancImageCommand> command(new Refactoring::GetOrthancImageCommand); | 1695 std::auto_ptr<Refactoring::GetOrthancImageCommand> command(new Refactoring::GetOrthancImageCommand); |
1549 command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Png))); | 1696 command->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Png))); |
1550 command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/preview"); | 1697 command->SetUri("/instances/6687cc73-07cae193-52ff29c8-f646cb16-0753ed92/preview"); |
1551 oracle.Schedule(*toto, command.release()); | 1698 oracle.Schedule(*toto, command.release()); |
1588 | 1735 |
1589 // 2017-11-17-Anonymized | 1736 // 2017-11-17-Anonymized |
1590 loader1->LoadSeries(oracle, "cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT | 1737 loader1->LoadSeries(oracle, "cb3ea4d1-d08f3856-ad7b6314-74d88d77-60b05618"); // CT |
1591 loader2->LoadInstance(oracle, "41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE | 1738 loader2->LoadInstance(oracle, "41029085-71718346-811efac4-420e2c15-d39f99b6"); // RT-DOSE |
1592 | 1739 |
1593 boost::this_thread::sleep(boost::posix_time::seconds(1)); | 1740 LOG(WARNING) << "...Waiting for Ctrl-C..."; |
1741 Orthanc::SystemToolbox::ServerBarrier(); | |
1742 //boost::this_thread::sleep(boost::posix_time::seconds(1)); | |
1594 | 1743 |
1595 oracle.Stop(); | 1744 oracle.Stop(); |
1596 } | 1745 } |
1597 | 1746 |
1598 | 1747 |