Mercurial > hg > orthanc-stone
diff Framework/Layers/OrthancFrameLayerSource.cpp @ 65:885932a893de wasm
OrthancFrameLayerSource
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 16 May 2017 22:12:41 +0200 |
parents | |
children | 298f375dcb68 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Layers/OrthancFrameLayerSource.cpp Tue May 16 22:12:41 2017 +0200 @@ -0,0 +1,213 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017 Osimis, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "OrthancFrameLayerSource.h" + +#include "FrameRenderer.h" +#include "../../Resources/Orthanc/Core/Images/PngReader.h" +#include "../../Resources/Orthanc/Core/Logging.h" +#include "../../Resources/Orthanc/Core/OrthancException.h" +#include "../Toolbox/DicomFrameConverter.h" + +#include <boost/lexical_cast.hpp> + + +namespace OrthancStone +{ + class OrthancFrameLayerSource::Operation : public Orthanc::IDynamicObject + { + private: + Content content_; + SliceGeometry viewportSlice_; + + public: + Operation(Content content) : content_(content) + { + } + + void SetViewportSlice(const SliceGeometry& slice) + { + viewportSlice_ = slice; + } + + const SliceGeometry& GetViewportSlice() const + { + return viewportSlice_; + } + + Content GetContent() const + { + return content_; + } + }; + + + OrthancFrameLayerSource::OrthancFrameLayerSource(IWebService& orthanc, + const std::string& instanceId, + unsigned int frame) : + orthanc_(orthanc), + instanceId_(instanceId), + frame_(frame) + { + orthanc_.ScheduleGetRequest(*this, + "/instances/" + instanceId + "/tags", + new Operation(Content_Tags)); + } + + + void OrthancFrameLayerSource::SetObserver(IObserver& observer) + { + LayerSourceBase::SetObserver(observer); + + if (dataset_.get() != NULL) + { + NotifySourceChange(); + } + } + + void OrthancFrameLayerSource::NotifyError(const std::string& uri, + Orthanc::IDynamicObject* payload) + { + LOG(ERROR) << "Cannot download " << uri; + } + + void OrthancFrameLayerSource::NotifySuccess(const std::string& uri, + const void* answer, + size_t answerSize, + Orthanc::IDynamicObject* payload) + { + std::auto_ptr<Operation> operation(reinterpret_cast<Operation*>(payload)); + + if (operation.get() == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + else if (operation->GetContent() == Content_Tags) + { + dataset_.reset(new OrthancPlugins::FullOrthancDataset(answer, answerSize)); + + DicomFrameConverter converter; + converter.ReadParameters(*dataset_); + format_ = converter.GetExpectedPixelFormat(); + + NotifySourceChange(); + } + else if (operation->GetContent() == Content_Frame) + { + std::auto_ptr<Orthanc::PngReader> image(new Orthanc::PngReader); + image->ReadFromMemory(answer, answerSize); + + if (format_ == Orthanc::PixelFormat_SignedGrayscale16) + { + if (image->GetFormat() == Orthanc::PixelFormat_Grayscale16) + { + image->SetFormat(Orthanc::PixelFormat_SignedGrayscale16); + } + else + { + NotifyLayerReady(NULL, *this, operation->GetViewportSlice()); + } + } + + SliceGeometry frameSlice(*dataset_); + NotifyLayerReady(FrameRenderer::CreateRenderer(image.release(), + operation->GetViewportSlice(), + frameSlice, *dataset_, 1, 1, true), + *this, operation->GetViewportSlice()); + } + else + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + + + bool OrthancFrameLayerSource::GetExtent(double& x1, + double& y1, + double& x2, + double& y2, + const SliceGeometry& viewportSlice /* ignored */) + { + if (dataset_.get() == NULL) + { + return false; + } + else + { + // Assume that PixelSpacingX == PixelSpacingY == 1 + + OrthancPlugins::DicomDatasetReader reader(*dataset_); + + unsigned int width, height; + + if (!reader.GetUnsignedIntegerValue(width, OrthancPlugins::DICOM_TAG_COLUMNS) || + !reader.GetUnsignedIntegerValue(height, OrthancPlugins::DICOM_TAG_ROWS)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + x1 = 0; + y1 = 0; + x2 = static_cast<double>(width); + y2 = static_cast<double>(height); + + return true; + } + } + + + void OrthancFrameLayerSource::ScheduleLayerCreation(const SliceGeometry& viewportSlice) + { + if (dataset_.get() == NULL) + { + NotifyLayerReady(NULL, *this, viewportSlice); + } + else + { + std::string uri = ("/instances/" + instanceId_ + "/frames/" + + boost::lexical_cast<std::string>(frame_)); + + std::string compressed; + + switch (format_) + { + case Orthanc::PixelFormat_RGB24: + uri += "/preview"; + break; + + case Orthanc::PixelFormat_Grayscale16: + uri += "/image-uint16"; + break; + + case Orthanc::PixelFormat_SignedGrayscale16: + uri += "/image-int16"; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + std::auto_ptr<Operation> operation(new Operation(Content_Frame)); + operation->SetViewportSlice(viewportSlice); + orthanc_.ScheduleGetRequest(*this, uri, operation.release()); + } + } +}