comparison Plugins/Engine/OrthancPlugins.cpp @ 3916:0e3849268a55 transcoding

new plugin SDK primitives related to OrthancPluginDicomInstance
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 11 May 2020 21:07:36 +0200
parents f0dd5ded8927
children 6f11b3233a06
comparison
equal deleted inserted replaced
3915:7e33516965f8 3916:0e3849268a55
1759 pluginOutput.Close(error, GetErrorDictionary()); 1759 pluginOutput.Close(error, GetErrorDictionary());
1760 return true; 1760 return true;
1761 } 1761 }
1762 1762
1763 1763
1764 class OrthancPlugins::IDicomInstance : public boost::noncopyable
1765 {
1766 public:
1767 virtual ~IDicomInstance()
1768 {
1769 }
1770
1771 virtual bool CanBeFreed() const = 0;
1772
1773 virtual const DicomInstanceToStore& GetInstance() const = 0;
1774 };
1775
1776
1777 class OrthancPlugins::DicomInstanceFromCallback : public IDicomInstance
1778 {
1779 private:
1780 const DicomInstanceToStore& instance_;
1781
1782 public:
1783 DicomInstanceFromCallback(const DicomInstanceToStore& instance) :
1784 instance_(instance)
1785 {
1786 }
1787
1788 virtual bool CanBeFreed() const ORTHANC_OVERRIDE
1789 {
1790 return false;
1791 }
1792
1793 virtual const DicomInstanceToStore& GetInstance() const ORTHANC_OVERRIDE
1794 {
1795 return instance_;
1796 };
1797 };
1798
1799
1800 class OrthancPlugins::DicomInstanceFromBuffer : public IDicomInstance
1801 {
1802 private:
1803 std::string buffer_;
1804 DicomInstanceToStore instance_;
1805
1806 public:
1807 DicomInstanceFromBuffer(const void* buffer,
1808 size_t size)
1809 {
1810 buffer_.assign(reinterpret_cast<const char*>(buffer), size);
1811 instance_.SetBuffer(buffer_.empty() ? NULL : buffer_.c_str(), buffer_.size());
1812 instance_.SetOrigin(DicomInstanceOrigin::FromPlugins());
1813 }
1814
1815 virtual bool CanBeFreed() const ORTHANC_OVERRIDE
1816 {
1817 return true;
1818 }
1819
1820 virtual const DicomInstanceToStore& GetInstance() const ORTHANC_OVERRIDE
1821 {
1822 return instance_;
1823 };
1824 };
1825
1826
1764 void OrthancPlugins::SignalStoredInstance(const std::string& instanceId, 1827 void OrthancPlugins::SignalStoredInstance(const std::string& instanceId,
1765 DicomInstanceToStore& instance, 1828 const DicomInstanceToStore& instance,
1766 const Json::Value& simplifiedTags) 1829 const Json::Value& simplifiedTags)
1767 { 1830 {
1831 DicomInstanceFromCallback wrapped(instance);
1832
1768 boost::recursive_mutex::scoped_lock lock(pimpl_->storedCallbackMutex_); 1833 boost::recursive_mutex::scoped_lock lock(pimpl_->storedCallbackMutex_);
1769 1834
1770 for (PImpl::OnStoredCallbacks::const_iterator 1835 for (PImpl::OnStoredCallbacks::const_iterator
1771 callback = pimpl_->onStoredCallbacks_.begin(); 1836 callback = pimpl_->onStoredCallbacks_.begin();
1772 callback != pimpl_->onStoredCallbacks_.end(); ++callback) 1837 callback != pimpl_->onStoredCallbacks_.end(); ++callback)
1773 { 1838 {
1774 OrthancPluginErrorCode error = (*callback) 1839 OrthancPluginErrorCode error = (*callback) (
1775 (reinterpret_cast<OrthancPluginDicomInstance*>(&instance), 1840 reinterpret_cast<OrthancPluginDicomInstance*>(&wrapped),
1776 instanceId.c_str()); 1841 instanceId.c_str());
1777 1842
1778 if (error != OrthancPluginErrorCode_Success) 1843 if (error != OrthancPluginErrorCode_Success)
1779 { 1844 {
1780 GetErrorDictionary().LogError(error, true); 1845 GetErrorDictionary().LogError(error, true);
1781 throw OrthancException(static_cast<ErrorCode>(error)); 1846 throw OrthancException(static_cast<ErrorCode>(error));
1785 1850
1786 1851
1787 bool OrthancPlugins::FilterIncomingInstance(const DicomInstanceToStore& instance, 1852 bool OrthancPlugins::FilterIncomingInstance(const DicomInstanceToStore& instance,
1788 const Json::Value& simplified) 1853 const Json::Value& simplified)
1789 { 1854 {
1855 DicomInstanceFromCallback wrapped(instance);
1856
1790 boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); 1857 boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_);
1791 1858
1792 for (PImpl::IncomingDicomInstanceFilters::const_iterator 1859 for (PImpl::IncomingDicomInstanceFilters::const_iterator
1793 filter = pimpl_->incomingDicomInstanceFilters_.begin(); 1860 filter = pimpl_->incomingDicomInstanceFilters_.begin();
1794 filter != pimpl_->incomingDicomInstanceFilters_.end(); ++filter) 1861 filter != pimpl_->incomingDicomInstanceFilters_.end(); ++filter)
1795 { 1862 {
1796 int32_t allowed = (*filter) ( 1863 int32_t allowed = (*filter) (reinterpret_cast<const OrthancPluginDicomInstance*>(&wrapped));
1797 reinterpret_cast<const OrthancPluginDicomInstance*>(&instance));
1798 1864
1799 if (allowed == 0) 1865 if (allowed == 0)
1800 { 1866 {
1801 return false; 1867 return false;
1802 } 1868 }
2449 } 2515 }
2450 } 2516 }
2451 } 2517 }
2452 2518
2453 2519
2454 static void AccessDicomInstance(_OrthancPluginService service, 2520 void OrthancPlugins::AccessDicomInstance(_OrthancPluginService service,
2455 const void* parameters) 2521 const void* parameters)
2456 { 2522 {
2457 const _OrthancPluginAccessDicomInstance& p = 2523 const _OrthancPluginAccessDicomInstance& p =
2458 *reinterpret_cast<const _OrthancPluginAccessDicomInstance*>(parameters); 2524 *reinterpret_cast<const _OrthancPluginAccessDicomInstance*>(parameters);
2459 2525
2526 if (p.instance == NULL)
2527 {
2528 throw OrthancException(ErrorCode_NullPointer);
2529 }
2530
2460 const DicomInstanceToStore& instance = 2531 const DicomInstanceToStore& instance =
2461 *reinterpret_cast<const DicomInstanceToStore*>(p.instance); 2532 reinterpret_cast<const IDicomInstance*>(p.instance)->GetInstance();
2462 2533
2463 switch (service) 2534 switch (service)
2464 { 2535 {
2465 case _OrthancPluginService_GetInstanceRemoteAet: 2536 case _OrthancPluginService_GetInstanceRemoteAet:
2466 *p.resultString = instance.GetOrigin().GetRemoteAetC(); 2537 *p.resultString = instance.GetOrigin().GetRemoteAetC();
2521 2592
2522 case _OrthancPluginService_HasInstancePixelData: // New in Orthanc 1.6.1 2593 case _OrthancPluginService_HasInstancePixelData: // New in Orthanc 1.6.1
2523 *p.resultInt64 = instance.HasPixelData(); 2594 *p.resultInt64 = instance.HasPixelData();
2524 return; 2595 return;
2525 2596
2597 case _OrthancPluginService_GetInstanceFramesCount: // New in Orthanc 1.7.0
2598 *p.resultInt64 = instance.GetParsedDicomFile().GetFramesCount();
2599 return;
2600
2526 default: 2601 default:
2527 throw OrthancException(ErrorCode_InternalError); 2602 throw OrthancException(ErrorCode_InternalError);
2528 } 2603 }
2529 } 2604 }
2530 2605
2600 return reinterpret_cast<OrthancPluginImage*>(copy.release()); 2675 return reinterpret_cast<OrthancPluginImage*>(copy.release());
2601 } 2676 }
2602 else 2677 else
2603 { 2678 {
2604 return reinterpret_cast<OrthancPluginImage*>(image.release()); 2679 return reinterpret_cast<OrthancPluginImage*>(image.release());
2680 }
2681 }
2682
2683
2684 void OrthancPlugins::AccessDicomInstance2(_OrthancPluginService service,
2685 const void* parameters)
2686 {
2687 const _OrthancPluginAccessDicomInstance2& p =
2688 *reinterpret_cast<const _OrthancPluginAccessDicomInstance2*>(parameters);
2689
2690 if (p.instance == NULL)
2691 {
2692 throw OrthancException(ErrorCode_NullPointer);
2693 }
2694
2695 const DicomInstanceToStore& instance =
2696 reinterpret_cast<const IDicomInstance*>(p.instance)->GetInstance();
2697
2698 switch (service)
2699 {
2700 case _OrthancPluginService_GetInstanceFramesCount:
2701 *p.targetUint32 = instance.GetParsedDicomFile().GetFramesCount();
2702 return;
2703
2704 case _OrthancPluginService_GetInstanceRawFrame:
2705 {
2706 if (p.targetBuffer == NULL)
2707 {
2708 throw OrthancException(ErrorCode_NullPointer);
2709 }
2710
2711 p.targetBuffer->data = NULL;
2712 p.targetBuffer->size = 0;
2713
2714 MimeType mime;
2715 std::string frame;
2716 instance.GetParsedDicomFile().GetRawFrame(frame, mime, p.frameIndex);
2717 CopyToMemoryBuffer(*p.targetBuffer, frame);
2718 return;
2719 }
2720
2721 case _OrthancPluginService_GetInstanceDecodedFrame:
2722 {
2723 bool hasDecoderPlugin;
2724
2725 {
2726 boost::mutex::scoped_lock lock(pimpl_->decodeImageCallbackMutex_);
2727 hasDecoderPlugin = !pimpl_->decodeImageCallbacks_.empty();
2728 }
2729
2730 std::unique_ptr<ImageAccessor> decoded;
2731 if (p.targetImage == NULL)
2732 {
2733 throw OrthancException(ErrorCode_NullPointer);
2734 }
2735 else if (hasDecoderPlugin)
2736 {
2737 // TODO - This call could be speeded up the future, if a
2738 // "decoding context" gets introduced in the decoder plugins
2739
2740 decoded.reset(Decode(instance.GetBufferData(), instance.GetBufferSize(), p.frameIndex));
2741 }
2742 else
2743 {
2744 decoded.reset(DicomImageDecoder::Decode(instance.GetParsedDicomFile(), p.frameIndex));
2745 }
2746
2747 *(p.targetImage) = ReturnImage(decoded);
2748 return;
2749 }
2750
2751 default:
2752 throw OrthancException(ErrorCode_InternalError);
2605 } 2753 }
2606 } 2754 }
2607 2755
2608 2756
2609 void OrthancPlugins::UncompressImage(const void* parameters) 2757 void OrthancPlugins::UncompressImage(const void* parameters)
3479 case _OrthancPluginService_GetInstanceTransferSyntaxUid: 3627 case _OrthancPluginService_GetInstanceTransferSyntaxUid:
3480 case _OrthancPluginService_HasInstancePixelData: 3628 case _OrthancPluginService_HasInstancePixelData:
3481 AccessDicomInstance(service, parameters); 3629 AccessDicomInstance(service, parameters);
3482 return true; 3630 return true;
3483 3631
3632 case _OrthancPluginService_GetInstanceFramesCount:
3633 case _OrthancPluginService_GetInstanceRawFrame:
3634 case _OrthancPluginService_GetInstanceDecodedFrame:
3635 AccessDicomInstance2(service, parameters);
3636 return true;
3637
3484 case _OrthancPluginService_SetGlobalProperty: 3638 case _OrthancPluginService_SetGlobalProperty:
3485 { 3639 {
3486 const _OrthancPluginGlobalProperty& p = 3640 const _OrthancPluginGlobalProperty& p =
3487 *reinterpret_cast<const _OrthancPluginGlobalProperty*>(parameters); 3641 *reinterpret_cast<const _OrthancPluginGlobalProperty*>(parameters);
3488 if (p.property < 1024) 3642 if (p.property < 1024)
4025 4179
4026 case _OrthancPluginService_GetTagName: 4180 case _OrthancPluginService_GetTagName:
4027 GetTagName(parameters); 4181 GetTagName(parameters);
4028 return true; 4182 return true;
4029 4183
4184 case _OrthancPluginService_CreateDicomInstance:
4185 {
4186 const _OrthancPluginCreateDicomInstance& p =
4187 *reinterpret_cast<const _OrthancPluginCreateDicomInstance*>(parameters);
4188 *(p.target) = reinterpret_cast<OrthancPluginDicomInstance*>(
4189 new DicomInstanceFromBuffer(p.buffer, p.size));
4190 return true;
4191 }
4192
4193 case _OrthancPluginService_FreeDicomInstance:
4194 {
4195 const _OrthancPluginFreeDicomInstance& p =
4196 *reinterpret_cast<const _OrthancPluginFreeDicomInstance*>(parameters);
4197
4198 if (p.dicom != NULL)
4199 {
4200 IDicomInstance* obj = reinterpret_cast<IDicomInstance*>(p.dicom);
4201
4202 if (obj->CanBeFreed())
4203 {
4204 delete obj;
4205 }
4206 else
4207 {
4208 throw OrthancException(ErrorCode_Plugin, "Cannot free a DICOM instance provided to a callback");
4209 }
4210 }
4211
4212 return true;
4213 }
4214
4030 default: 4215 default:
4031 return false; 4216 return false;
4032 } 4217 }
4033 } 4218 }
4034 4219