# HG changeset patch # User Sebastien Jodogne # Date 1495653209 -7200 # Node ID f5f54ed8d30715f6f955908fe8b9e8c5e5497566 # Parent 0aef120d7e1c803378cb0a4d741b71d1af151231 refactoring diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/ColorFrameRenderer.cpp --- a/Framework/Layers/ColorFrameRenderer.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/ColorFrameRenderer.cpp Wed May 24 21:13:29 2017 +0200 @@ -38,12 +38,11 @@ ColorFrameRenderer::ColorFrameRenderer(Orthanc::ImageAccessor* frame, - const SliceGeometry& viewportSlice, const SliceGeometry& frameSlice, double pixelSpacingX, double pixelSpacingY, bool isFullQuality) : - FrameRenderer(viewportSlice, frameSlice, pixelSpacingX, pixelSpacingY, isFullQuality), + FrameRenderer(frameSlice, pixelSpacingX, pixelSpacingY, isFullQuality), frame_(frame) { if (frame == NULL) diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/ColorFrameRenderer.h --- a/Framework/Layers/ColorFrameRenderer.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/ColorFrameRenderer.h Wed May 24 21:13:29 2017 +0200 @@ -35,7 +35,6 @@ public: ColorFrameRenderer(Orthanc::ImageAccessor* frame, // Takes ownership - const SliceGeometry& viewportSlice, const SliceGeometry& frameSlice, double pixelSpacingX, double pixelSpacingY, diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/DicomStructureSetRendererFactory.cpp --- a/Framework/Layers/DicomStructureSetRendererFactory.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/DicomStructureSetRendererFactory.cpp Wed May 24 21:13:29 2017 +0200 @@ -42,7 +42,8 @@ } virtual bool RenderLayer(CairoContext& context, - const ViewportGeometry& view) + const ViewportGeometry& view, + const SliceGeometry& viewportSlice) { if (visible_) { diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/FrameRenderer.cpp --- a/Framework/Layers/FrameRenderer.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/FrameRenderer.cpp Wed May 24 21:13:29 2017 +0200 @@ -76,12 +76,10 @@ } - FrameRenderer::FrameRenderer(const SliceGeometry& viewportSlice, - const SliceGeometry& frameSlice, + FrameRenderer::FrameRenderer(const SliceGeometry& frameSlice, double pixelSpacingX, double pixelSpacingY, bool isFullQuality) : - viewportSlice_(viewportSlice), frameSlice_(frameSlice), pixelSpacingX_(pixelSpacingX), pixelSpacingY_(pixelSpacingY), @@ -138,7 +136,8 @@ bool FrameRenderer::RenderLayer(CairoContext& context, - const ViewportGeometry& view) + const ViewportGeometry& view, + const SliceGeometry& viewportSlice) { if (!style_.visible_) { @@ -147,7 +146,7 @@ if (display_.get() == NULL) { - if (!ComputePixelTransform(transform_, viewportSlice_, frameSlice_, + if (!ComputePixelTransform(transform_, viewportSlice, frameSlice_, pixelSpacingX_, pixelSpacingY_)) { return true; @@ -216,7 +215,6 @@ ILayerRenderer* FrameRenderer::CreateRenderer(Orthanc::ImageAccessor* frame, - const SliceGeometry& viewportSlice, const SliceGeometry& frameSlice, const OrthancPlugins::IDicomDataset& dicom, double pixelSpacingX, @@ -227,15 +225,34 @@ if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) { - return new ColorFrameRenderer(protect.release(), viewportSlice, frameSlice, + return new ColorFrameRenderer(protect.release(), frameSlice, pixelSpacingX, pixelSpacingY, isFullQuality); } else { DicomFrameConverter converter; converter.ReadParameters(dicom); - return new GrayscaleFrameRenderer(protect.release(), converter, viewportSlice, frameSlice, + return new GrayscaleFrameRenderer(protect.release(), converter, frameSlice, pixelSpacingX, pixelSpacingY, isFullQuality); } } + + + ILayerRenderer* FrameRenderer::CreateRenderer(Orthanc::ImageAccessor* frame, + const Slice& slice, + bool isFullQuality) + { + std::auto_ptr protect(frame); + + if (frame->GetFormat() == Orthanc::PixelFormat_RGB24) + { + return new ColorFrameRenderer(protect.release(), slice.GetGeometry(), + slice.GetPixelSpacingX(), slice.GetPixelSpacingY(), isFullQuality); + } + else + { + return new GrayscaleFrameRenderer(protect.release(), slice.GetConverter(), slice.GetGeometry(), + slice.GetPixelSpacingX(), slice.GetPixelSpacingY(), isFullQuality); + } + } } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/FrameRenderer.h --- a/Framework/Layers/FrameRenderer.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/FrameRenderer.h Wed May 24 21:13:29 2017 +0200 @@ -23,14 +23,13 @@ #include "ILayerRenderer.h" -#include "../Toolbox/SliceGeometry.h" +#include "../Toolbox/Slice.h" namespace OrthancStone { class FrameRenderer : public ILayerRenderer { private: - SliceGeometry viewportSlice_; SliceGeometry frameSlice_; double pixelSpacingX_; double pixelSpacingY_; @@ -44,12 +43,12 @@ virtual CairoSurface* GenerateDisplay(const RenderStyle& style) = 0; public: - FrameRenderer(const SliceGeometry& viewportSlice, - const SliceGeometry& frameSlice, + FrameRenderer(const SliceGeometry& frameSlice, double pixelSpacingX, double pixelSpacingY, bool isFullQuality); + // TODO Remove this overload static bool ComputeFrameExtent(double& x1, double& y1, double& x2, @@ -61,8 +60,21 @@ double pixelSpacingX, double pixelSpacingY); + static bool ComputeFrameExtent(double& x1, + double& y1, + double& x2, + double& y2, + const SliceGeometry& viewportSlice, + const Slice& slice) + { + return ComputeFrameExtent(x1, y1, x2, y2, viewportSlice, + slice.GetGeometry(), slice.GetWidth(), slice.GetHeight(), + slice.GetPixelSpacingX(), slice.GetPixelSpacingY()); + } + virtual bool RenderLayer(CairoContext& context, - const ViewportGeometry& view); + const ViewportGeometry& view, + const SliceGeometry& viewportSlice); virtual void SetLayerStyle(const RenderStyle& style); @@ -71,12 +83,16 @@ return isFullQuality_; } + // TODO Remove this overload static ILayerRenderer* CreateRenderer(Orthanc::ImageAccessor* frame, - const SliceGeometry& viewportSlice, const SliceGeometry& frameSlice, const OrthancPlugins::IDicomDataset& dicom, double pixelSpacingX, double pixelSpacingY, bool isFullQuality); + + static ILayerRenderer* CreateRenderer(Orthanc::ImageAccessor* frame, + const Slice& slice, + bool isFullQuality); }; } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/GrayscaleFrameRenderer.cpp --- a/Framework/Layers/GrayscaleFrameRenderer.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/GrayscaleFrameRenderer.cpp Wed May 24 21:13:29 2017 +0200 @@ -107,12 +107,11 @@ GrayscaleFrameRenderer::GrayscaleFrameRenderer(Orthanc::ImageAccessor* frame, const DicomFrameConverter& converter, - const SliceGeometry& viewportSlice, const SliceGeometry& frameSlice, double pixelSpacingX, double pixelSpacingY, bool isFullQuality) : - FrameRenderer(viewportSlice, frameSlice, pixelSpacingX, pixelSpacingY, isFullQuality), + FrameRenderer(frameSlice, pixelSpacingX, pixelSpacingY, isFullQuality), frame_(frame), defaultWindowCenter_(converter.GetDefaultWindowCenter()), defaultWindowWidth_(converter.GetDefaultWindowWidth()) diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/GrayscaleFrameRenderer.h --- a/Framework/Layers/GrayscaleFrameRenderer.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/GrayscaleFrameRenderer.h Wed May 24 21:13:29 2017 +0200 @@ -39,7 +39,6 @@ public: GrayscaleFrameRenderer(Orthanc::ImageAccessor* frame, // Takes ownership const DicomFrameConverter& converter, - const SliceGeometry& viewportSlice, const SliceGeometry& frameSlice, double pixelSpacingX, double pixelSpacingY, diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/ILayerRenderer.h --- a/Framework/Layers/ILayerRenderer.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/ILayerRenderer.h Wed May 24 21:13:29 2017 +0200 @@ -22,6 +22,7 @@ #pragma once #include "../Viewport/CairoContext.h" +#include "../Toolbox/SliceGeometry.h" #include "../Toolbox/ViewportGeometry.h" #include "RenderStyle.h" @@ -35,7 +36,8 @@ } virtual bool RenderLayer(CairoContext& context, - const ViewportGeometry& view) = 0; + const ViewportGeometry& view, + const SliceGeometry& viewportSlice) = 0; virtual void SetLayerStyle(const RenderStyle& style) = 0; diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/ILayerSource.h --- a/Framework/Layers/ILayerSource.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/ILayerSource.h Wed May 24 21:13:29 2017 +0200 @@ -22,7 +22,7 @@ #pragma once #include "ILayerRenderer.h" -#include "../Toolbox/SliceGeometry.h" +#include "../Toolbox/Slice.h" namespace OrthancStone { @@ -40,22 +40,24 @@ // answer to "GetExtent()" virtual void NotifyGeometryReady(ILayerSource& source) = 0; + virtual void NotifyGeometryError(ILayerSource& source) = 0; + // Triggered if the extent or the content of the volume has changed virtual void NotifySourceChange(ILayerSource& source) = 0; - // Triggered if some slice in the source volume has changed + // Triggered if the content of some slice in the source volume has changed virtual void NotifySliceChange(ILayerSource& source, - const SliceGeometry& slice) = 0; + const Slice& slice) = 0; // The layer must be deleted by the observer. "layer" will never // be "NULL", otherwise "NotifyLayerError()" would have been // called. virtual void NotifyLayerReady(ILayerRenderer *layer, ILayerSource& source, - const SliceGeometry& viewportSlice) = 0; + const Slice& slice) = 0; virtual void NotifyLayerError(ILayerSource& source, - const SliceGeometry& viewportSlice) = 0; + const SliceGeometry& slice) = 0; }; virtual ~ILayerSource() diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/LayerSourceBase.cpp --- a/Framework/Layers/LayerSourceBase.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/LayerSourceBase.cpp Wed May 24 21:13:29 2017 +0200 @@ -38,6 +38,19 @@ } } + void LayerSourceBase::NotifyGeometryError() + { + if (!started_) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + + if (observer_ != NULL) + { + observer_->NotifyGeometryError(*this); + } + } + void LayerSourceBase::NotifySourceChange() { if (!started_) @@ -51,7 +64,7 @@ } } - void LayerSourceBase::NotifySliceChange(const SliceGeometry& slice) + void LayerSourceBase::NotifySliceChange(const Slice& slice) { if (!started_) { @@ -65,7 +78,7 @@ } void LayerSourceBase::NotifyLayerReady(ILayerRenderer* layer, - const SliceGeometry& viewportSlice) + const Slice& slice) { std::auto_ptr tmp(layer); @@ -81,11 +94,11 @@ if (observer_ != NULL) { - observer_->NotifyLayerReady(tmp.release(), *this, viewportSlice); + observer_->NotifyLayerReady(tmp.release(), *this, slice); } } - void LayerSourceBase::NotifyLayerError(const SliceGeometry& viewportSlice) + void LayerSourceBase::NotifyLayerError(const SliceGeometry& slice) { if (!started_) { @@ -94,7 +107,7 @@ if (observer_ != NULL) { - observer_->NotifyLayerError(*this, viewportSlice); + observer_->NotifyLayerError(*this, slice); } } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/LayerSourceBase.h --- a/Framework/Layers/LayerSourceBase.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/LayerSourceBase.h Wed May 24 21:13:29 2017 +0200 @@ -39,15 +39,17 @@ void NotifyGeometryReady(); + void NotifyGeometryError(); + void NotifySourceChange(); - void NotifySliceChange(const SliceGeometry& slice); + void NotifySliceChange(const Slice& slice); // Takes ownership of "layer" (that cannot be "NULL") void NotifyLayerReady(ILayerRenderer* layer, - const SliceGeometry& viewportSlice); + const Slice& slice); - void NotifyLayerError(const SliceGeometry& viewportSlice); + void NotifyLayerError(const SliceGeometry& slice); virtual void StartInternal() = 0; diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/LineLayerRenderer.cpp --- a/Framework/Layers/LineLayerRenderer.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/LineLayerRenderer.cpp Wed May 24 21:13:29 2017 +0200 @@ -38,7 +38,8 @@ bool LineLayerRenderer::RenderLayer(CairoContext& context, - const ViewportGeometry& view) + const ViewportGeometry& view, + const SliceGeometry& slice) { if (visible_) { diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/LineLayerRenderer.h --- a/Framework/Layers/LineLayerRenderer.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/LineLayerRenderer.h Wed May 24 21:13:29 2017 +0200 @@ -42,7 +42,8 @@ double y2); virtual bool RenderLayer(CairoContext& context, - const ViewportGeometry& view); + const ViewportGeometry& view, + const SliceGeometry& slice); virtual void SetLayerStyle(const RenderStyle& style); diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/OrthancFrameLayerSource.cpp --- a/Framework/Layers/OrthancFrameLayerSource.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/OrthancFrameLayerSource.cpp Wed May 24 21:13:29 2017 +0200 @@ -32,44 +32,63 @@ namespace OrthancStone { - class OrthancFrameLayerSource::Operation : public Orthanc::IDynamicObject + void OrthancFrameLayerSource::NotifyGeometryReady(const OrthancSlicesLoader& loader) { - private: - Content content_; - SliceGeometry viewportSlice_; - - public: - Operation(Content content) : content_(content) + if (loader.GetSliceCount() > 0) { + // Make sure all the slices are parallel. TODO Alleviate this constraint + for (size_t i = 1; i < loader.GetSliceCount(); i++) + { + if (!GeometryToolbox::IsParallel(loader.GetSlice(i).GetGeometry().GetNormal(), + loader.GetSlice(0).GetGeometry().GetNormal())) + { + LayerSourceBase::NotifyGeometryError(); + return; + } + } } - void SetViewportSlice(const SliceGeometry& slice) - { - viewportSlice_ = slice; - } - - const SliceGeometry& GetViewportSlice() const + if (observer2_ != NULL) { - return viewportSlice_; - } + ParallelSlices slices; + + for (size_t i = 0; i < loader.GetSliceCount(); i++) + { + slices.AddSlice(loader.GetSlice(i).GetGeometry()); + } + + observer2_->NotifySlicesAvailable(slices); + } + + LayerSourceBase::NotifyGeometryReady(); + } - Content GetContent() const - { - return content_; - } - }; - + void OrthancFrameLayerSource::NotifyGeometryError(const OrthancSlicesLoader& loader) + { + LayerSourceBase::NotifyGeometryError(); + } + + void OrthancFrameLayerSource::NotifySliceImageReady(const OrthancSlicesLoader& loader, + unsigned int sliceIndex, + const Slice& slice, + Orthanc::ImageAccessor* image) + { + LayerSourceBase::NotifyLayerReady(FrameRenderer::CreateRenderer(image, slice, true), slice); + } + + void OrthancFrameLayerSource::NotifySliceImageError(const OrthancSlicesLoader& loader, + unsigned int sliceIndex, + const Slice& slice) + { + LayerSourceBase::NotifyLayerError(slice.GetGeometry()); + } OrthancFrameLayerSource::OrthancFrameLayerSource(IWebService& orthanc, const std::string& instanceId, unsigned int frame) : - orthanc_(orthanc), instanceId_(instanceId), frame_(frame), - frameWidth_(0), - frameHeight_(0), - pixelSpacingX_(1), - pixelSpacingY_(1), + loader_(*this, orthanc), observer2_(NULL) { } @@ -77,23 +96,10 @@ void OrthancFrameLayerSource::StartInternal() { - orthanc_.ScheduleGetRequest(*this, - "/instances/" + instanceId_ + "/tags", - new Operation(Content_Tags)); + loader_.ScheduleLoadInstance(instanceId_, frame_); } - void OrthancFrameLayerSource::SetObserver(IObserver& observer) - { - LayerSourceBase::SetObserver(observer); - - if (dataset_.get() != NULL) - { - NotifySourceChange(); - } - } - - void OrthancFrameLayerSource::SetObserver(IVolumeSlicesObserver& observer) { if (IsStarted()) @@ -112,96 +118,6 @@ } } - - void OrthancFrameLayerSource::NotifyError(const std::string& uri, - Orthanc::IDynamicObject* payload) - { - std::auto_ptr operation(reinterpret_cast(payload)); - - LOG(ERROR) << "Cannot download " << uri; - NotifyLayerError(operation->GetViewportSlice()); - } - - - void OrthancFrameLayerSource::NotifySuccess(const std::string& uri, - const void* answer, - size_t answerSize, - Orthanc::IDynamicObject* payload) - { - std::auto_ptr operation(reinterpret_cast(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(); - GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, *dataset_); - - OrthancPlugins::DicomDatasetReader reader(*dataset_); - if (!reader.GetUnsignedIntegerValue(frameWidth_, OrthancPlugins::DICOM_TAG_COLUMNS) || - !reader.GetUnsignedIntegerValue(frameHeight_, OrthancPlugins::DICOM_TAG_ROWS)) - { - frameWidth_ = 0; - frameHeight_ = 0; - LOG(WARNING) << "Missing tags in a DICOM image: Columns or Rows"; - } - - if (observer2_ != NULL) - { - ParallelSlices slices; - slices.AddSlice(SliceGeometry(*dataset_)); - observer2_->NotifySlicesAvailable(slices); - } - - NotifyGeometryReady(); - } - else if (operation->GetContent() == Content_Frame) - { - std::auto_ptr image(new Orthanc::PngReader); - image->ReadFromMemory(answer, answerSize); - - bool ok = (image->GetWidth() == frameWidth_ || - image->GetHeight() == frameHeight_); - - if (ok && - format_ == Orthanc::PixelFormat_SignedGrayscale16) - { - if (image->GetFormat() == Orthanc::PixelFormat_Grayscale16) - { - image->SetFormat(Orthanc::PixelFormat_SignedGrayscale16); - } - else - { - ok = false; - } - } - - if (ok) - { - SliceGeometry frameSlice(*dataset_); - NotifyLayerReady(FrameRenderer::CreateRenderer(image.release(), - operation->GetViewportSlice(), - frameSlice, *dataset_, - pixelSpacingX_, pixelSpacingY_, true), - operation->GetViewportSlice()); - } - else - { - NotifyLayerError(operation->GetViewportSlice()); - } - } - else - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); - } - } - bool OrthancFrameLayerSource::GetExtent(double& x1, double& y1, @@ -209,61 +125,57 @@ double& y2, const SliceGeometry& viewportSlice /* ignored */) { - if (!IsStarted() || - dataset_.get() == NULL) - { - return false; - } - else + bool ok = false; + + if (IsStarted() && + loader_.IsGeometryReady()) { - SliceGeometry frameSlice(*dataset_); - return FrameRenderer::ComputeFrameExtent(x1, y1, x2, y2, - viewportSlice, frameSlice, - frameWidth_, frameHeight_, - pixelSpacingX_, pixelSpacingY_); + double tx1, ty1, tx2, ty2; + + for (size_t i = 0; i < loader_.GetSliceCount(); i++) + { + if (FrameRenderer::ComputeFrameExtent(tx1, ty1, tx2, ty2, viewportSlice, loader_.GetSlice(i))) + { + if (ok) + { + x1 = std::min(x1, tx1); + y1 = std::min(y1, ty1); + x2 = std::min(x2, tx2); + y2 = std::min(y2, ty2); + } + else + { + // This is the first slice parallel to the viewport + x1 = tx1; + y1 = ty1; + x2 = tx2; + y2 = ty2; + ok = true; + } + } + } } + + return ok; } void OrthancFrameLayerSource::ScheduleLayerCreation(const SliceGeometry& viewportSlice) { - if (!IsStarted()) + size_t index; + + if (!IsStarted() || + !loader_.IsGeometryReady()) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } - - if (dataset_.get() == NULL) + else if (loader_.LookupSlice(index, viewportSlice)) { - NotifyLayerError(viewportSlice); + loader_.ScheduleLoadSliceImage(index); } else { - std::string uri = ("/instances/" + instanceId_ + "/frames/" + - boost::lexical_cast(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(new Operation(Content_Frame)); - operation->SetViewportSlice(viewportSlice); - orthanc_.ScheduleGetRequest(*this, uri, operation.release()); + LayerSourceBase::NotifyLayerError(viewportSlice); } } } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/OrthancFrameLayerSource.h --- a/Framework/Layers/OrthancFrameLayerSource.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/OrthancFrameLayerSource.h Wed May 24 21:13:29 2017 +0200 @@ -24,54 +24,45 @@ #include "LayerSourceBase.h" #include "../Toolbox/IWebService.h" #include "../Toolbox/IVolumeSlicesObserver.h" -#include "../../Resources/Orthanc/Plugins/Samples/Common/FullOrthancDataset.h" +#include "../Toolbox/OrthancSlicesLoader.h" namespace OrthancStone { class OrthancFrameLayerSource : public LayerSourceBase, - public IWebService::ICallback // TODO move this into a PImpl + private OrthancSlicesLoader::ICallback { private: - enum Content - { - Content_Tags, - Content_Frame - }; + std::string instanceId_; + unsigned int frame_; + OrthancSlicesLoader loader_; + IVolumeSlicesObserver* observer2_; + + virtual void NotifyGeometryReady(const OrthancSlicesLoader& loader); + + virtual void NotifyGeometryError(const OrthancSlicesLoader& loader); - class Operation; - - IWebService& orthanc_; - std::string instanceId_; - unsigned int frame_; - std::auto_ptr dataset_; - unsigned int frameWidth_; - unsigned int frameHeight_; - Orthanc::PixelFormat format_; - double pixelSpacingX_; - double pixelSpacingY_; - IVolumeSlicesObserver* observer2_; + virtual void NotifySliceImageReady(const OrthancSlicesLoader& loader, + unsigned int sliceIndex, + const Slice& slice, + Orthanc::ImageAccessor* image); + + virtual void NotifySliceImageError(const OrthancSlicesLoader& loader, + unsigned int sliceIndex, + const Slice& slice); protected: virtual void StartInternal(); public: + using LayerSourceBase::SetObserver; + OrthancFrameLayerSource(IWebService& orthanc, const std::string& instanceId, unsigned int frame); - virtual void SetObserver(IObserver& observer); - void SetObserver(IVolumeSlicesObserver& observer); - virtual void NotifyError(const std::string& uri, - Orthanc::IDynamicObject* payload); - - virtual void NotifySuccess(const std::string& uri, - const void* answer, - size_t answerSize, - Orthanc::IDynamicObject* payload); - virtual bool GetExtent(double& x1, double& y1, double& x2, diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/SeriesFrameRendererFactory.cpp --- a/Framework/Layers/SeriesFrameRendererFactory.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/SeriesFrameRendererFactory.cpp Wed May 24 21:13:29 2017 +0200 @@ -155,7 +155,6 @@ { SliceGeometry frameSlice(*currentDataset_); return FrameRenderer::CreateRenderer(loader_->DownloadFrame(closest), - viewportSlice, frameSlice, *currentDataset_, spacingX, spacingY, diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Layers/SingleFrameRendererFactory.cpp --- a/Framework/Layers/SingleFrameRendererFactory.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Layers/SingleFrameRendererFactory.cpp Wed May 24 21:13:29 2017 +0200 @@ -76,7 +76,7 @@ { SliceGeometry frameSlice(*dicom_); return FrameRenderer::CreateRenderer(MessagingToolbox::DecodeFrame(orthanc_, instance_, frame_, format_), - viewportSlice, frameSlice, *dicom_, 1, 1, true); + frameSlice, *dicom_, 1, 1, true); } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/OrthancAsynchronousWebService.cpp --- a/Framework/Toolbox/OrthancAsynchronousWebService.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/OrthancAsynchronousWebService.cpp Wed May 24 21:13:29 2017 +0200 @@ -90,6 +90,7 @@ catch (Orthanc::OrthancException&) { callback_.NotifyError(uri_, payload_.release()); + return; } callback_.NotifySuccess(uri_, answer.c_str(), answer.size(), payload_.release()); @@ -220,14 +221,15 @@ for (size_t i = 0; i < threads_.size(); i++) { - assert(threads_[i] != NULL); - - if (threads_[i]->joinable()) + if (threads_[i] != NULL) { - threads_[i]->join(); + if (threads_[i]->joinable()) + { + threads_[i]->join(); + } + + delete threads_[i]; } - - delete threads_[i]; } } }; diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/OrthancSlicesLoader.cpp --- a/Framework/Toolbox/OrthancSlicesLoader.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/OrthancSlicesLoader.cpp Wed May 24 21:13:29 2017 +0200 @@ -335,6 +335,12 @@ } + bool OrthancSlicesLoader::IsGeometryReady() const + { + return state_ == State_GeometryReady; + } + + size_t OrthancSlicesLoader::GetSliceCount() const { if (state_ != State_GeometryReady) @@ -357,6 +363,18 @@ } + bool OrthancSlicesLoader::LookupSlice(size_t& index, + const SliceGeometry& plane) const + { + if (state_ != State_GeometryReady) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + + return slices_.LookupSlice(index, plane); + } + + void OrthancSlicesLoader::ScheduleLoadSliceImage(size_t index) { if (state_ != State_GeometryReady) diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/OrthancSlicesLoader.h --- a/Framework/Toolbox/OrthancSlicesLoader.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/OrthancSlicesLoader.h Wed May 24 21:13:29 2017 +0200 @@ -101,10 +101,15 @@ void ScheduleLoadInstance(const std::string& instanceId, unsigned int frame); + bool IsGeometryReady() const; + size_t GetSliceCount() const; const Slice& GetSlice(size_t index) const; + bool LookupSlice(size_t& index, + const SliceGeometry& plane) const; + void ScheduleLoadSliceImage(size_t index); }; } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/Slice.h --- a/Framework/Toolbox/Slice.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/Slice.h Wed May 24 21:13:29 2017 +0200 @@ -78,5 +78,10 @@ unsigned int GetHeight() const; const DicomFrameConverter& GetConverter() const; + + bool ContainsPlane(const SliceGeometry& plane) const + { + return geometry_.IsSamePlane(plane, thickness_); + } }; } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/SliceGeometry.h --- a/Framework/Toolbox/SliceGeometry.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/SliceGeometry.h Wed May 24 21:13:29 2017 +0200 @@ -89,7 +89,7 @@ double& offsetY, const Vector& point) const; - bool IsSamePlane(const SliceGeometry& other, + bool IsSamePlane(const SliceGeometry& slice, double sliceThickness) const; }; } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/SlicesSorter.cpp --- a/Framework/Toolbox/SlicesSorter.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/SlicesSorter.cpp Wed May 24 21:13:29 2017 +0200 @@ -192,4 +192,23 @@ return found; } + + + bool SlicesSorter::LookupSlice(size_t& index, + const SliceGeometry& slice) const + { + // TODO Turn this linear-time lookup into a log-time lookup, + // keeping track of whether the slices are sorted along the normal + + for (size_t i = 0; i < slices_.size(); i++) + { + if (slices_[i]->GetSlice().ContainsPlane(slice)) + { + index = i; + return true; + } + } + + return false; + } } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Toolbox/SlicesSorter.h --- a/Framework/Toolbox/SlicesSorter.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Toolbox/SlicesSorter.h Wed May 24 21:13:29 2017 +0200 @@ -64,5 +64,8 @@ void FilterNormal(const Vector& normal); bool SelectNormal(Vector& normal) const; + + bool LookupSlice(size_t& index, + const SliceGeometry& slice) const; }; } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Volumes/VolumeImage.cpp --- a/Framework/Volumes/VolumeImage.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Volumes/VolumeImage.cpp Wed May 24 21:13:29 2017 +0200 @@ -387,7 +387,6 @@ } return FrameRenderer::CreateRenderer(frame.release(), - viewportSlice, frameSlice, *that_.referenceDataset_, spacing[0], spacing[1], diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Widgets/LayerWidget.cpp --- a/Framework/Widgets/LayerWidget.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Widgets/LayerWidget.cpp Wed May 24 21:13:29 2017 +0200 @@ -105,7 +105,7 @@ for (size_t i = 0; i < renderers_.size(); i++) { if (renderers_[i] != NULL && - !renderers_[i]->RenderLayer(context, view)) + !renderers_[i]->RenderLayer(context, view, slice_)) { return false; } @@ -257,7 +257,7 @@ void LayerWidget::UpdateLayer(size_t index, ILayerRenderer* renderer, - const SliceGeometry& slice) + const Slice& slice) { LOG(INFO) << "Updating layer " << index; @@ -277,13 +277,13 @@ renderer->SetLayerStyle(styles_[index]); if (currentScene_.get() != NULL && - currentScene_->IsSamePlane(slice, sliceThickness_)) + currentScene_->IsSamePlane(slice.GetGeometry(), sliceThickness_)) { currentScene_->SetLayer(index, tmp.release()); NotifyChange(); } else if (pendingScene_.get() != NULL && - pendingScene_->IsSamePlane(slice, sliceThickness_)) + pendingScene_->IsSamePlane(slice.GetGeometry(), sliceThickness_)) { pendingScene_->SetLayer(index, tmp.release()); @@ -397,6 +397,12 @@ } + void LayerWidget::NotifyGeometryError(ILayerSource& source) + { + LOG(ERROR) << "Cannot get geometry"; + } + + void LayerWidget::NotifySourceChange(ILayerSource& source) { source.ScheduleLayerCreation(slice_); @@ -404,9 +410,9 @@ void LayerWidget::NotifySliceChange(ILayerSource& source, - const SliceGeometry& slice) + const Slice& slice) { - if (slice_.IsSamePlane(slice, sliceThickness_)) + if (slice.ContainsPlane(slice_)) { source.ScheduleLayerCreation(slice_); } @@ -415,18 +421,15 @@ void LayerWidget::NotifyLayerReady(ILayerRenderer* renderer, ILayerSource& source, - const SliceGeometry& viewportSlice) + const Slice& slice) { std::auto_ptr tmp(renderer); - size_t i; - if (LookupLayer(i, source)) - LOG(INFO) << "Renderer ready for layer " << i; - size_t index; if (LookupLayer(index, source)) { - UpdateLayer(index, tmp.release(), viewportSlice); + LOG(INFO) << "Renderer ready for layer " << index; + UpdateLayer(index, tmp.release(), slice); } } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Widgets/LayerWidget.h --- a/Framework/Widgets/LayerWidget.h Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Widgets/LayerWidget.h Wed May 24 21:13:29 2017 +0200 @@ -30,7 +30,7 @@ { class LayerWidget : public WorldSceneWidget, - public ILayerSource::IObserver // TODO move this as PImpl + private ILayerSource::IObserver { private: class Scene; @@ -50,6 +50,23 @@ bool LookupLayer(size_t& index /* out */, ILayerSource& layer) const; + + virtual void NotifyGeometryReady(ILayerSource& source); + + virtual void NotifyGeometryError(ILayerSource& source); + + virtual void NotifySourceChange(ILayerSource& source); + + virtual void NotifySliceChange(ILayerSource& source, + const Slice& slice); + + virtual void NotifyLayerReady(ILayerRenderer* renderer, + ILayerSource& source, + const Slice& slice); + + virtual void NotifyLayerError(ILayerSource& source, + const SliceGeometry& slice); + protected: virtual void GetSceneExtent(double& x1, @@ -64,7 +81,7 @@ void UpdateLayer(size_t index, ILayerRenderer* renderer, - const SliceGeometry& slice); + const Slice& slice); public: LayerWidget(); @@ -79,20 +96,6 @@ void SetSlice(const SliceGeometry& slice, double sliceThickness); - virtual void NotifyGeometryReady(ILayerSource& source); - - virtual void NotifySourceChange(ILayerSource& source); - - virtual void NotifySliceChange(ILayerSource& source, - const SliceGeometry& slice); - - virtual void NotifyLayerReady(ILayerRenderer* renderer, - ILayerSource& source, - const SliceGeometry& viewportSlice); - - virtual void NotifyLayerError(ILayerSource& source, - const SliceGeometry& viewportSlice); - virtual void Start(); }; } diff -r 0aef120d7e1c -r f5f54ed8d307 Framework/Widgets/LayeredSceneWidget.cpp --- a/Framework/Widgets/LayeredSceneWidget.cpp Wed May 24 12:42:08 2017 +0200 +++ b/Framework/Widgets/LayeredSceneWidget.cpp Wed May 24 21:13:29 2017 +0200 @@ -100,7 +100,8 @@ } bool RenderScene(CairoContext& context, - const ViewportGeometry& view) + const ViewportGeometry& view, + const SliceGeometry& slice) { boost::mutex::scoped_lock lock(mutex_); @@ -109,7 +110,7 @@ for (size_t i = 0; i < renderers_.size(); i++) { if (renderers_[i] != NULL && - !renderers_[i]->RenderLayer(context, view)) + !renderers_[i]->RenderLayer(context, view, slice)) { return false; } @@ -395,7 +396,7 @@ bool LayeredSceneWidget::RenderScene(CairoContext& context, const ViewportGeometry& view) { - return renderers_->RenderScene(context, view); + return renderers_->RenderScene(context, view, slice_); } diff -r 0aef120d7e1c -r f5f54ed8d307 UnitTestsSources/UnitTestsMain.cpp --- a/UnitTestsSources/UnitTestsMain.cpp Wed May 24 12:42:08 2017 +0200 +++ b/UnitTestsSources/UnitTestsMain.cpp Wed May 24 21:13:29 2017 +0200 @@ -77,9 +77,9 @@ OrthancStone::Tata tata; OrthancStone::OrthancSlicesLoader loader(tata, orthanc); //loader.ScheduleLoadSeries("c1c4cb95-05e3bd11-8da9f5bb-87278f71-0b2b43f5"); - loader.ScheduleLoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); + //loader.ScheduleLoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5"); - //loader.ScheduleLoadInstance("19816330-cb02e1cf-df3a8fe8-bf510623-ccefe9f5", 0); + loader.ScheduleLoadInstance("19816330-cb02e1cf-df3a8fe8-bf510623-ccefe9f5", 0); /*printf(">> %d\n", loader.GetSliceCount()); loader.ScheduleLoadSliceImage(31);*/