# HG changeset patch # User Sebastien Jodogne # Date 1558448106 -7200 # Node ID c3bbb130abc42b33c25c36b81406e28fb5d5bf50 # Parent be3671662eecfd74079001d96a758b9afa7bdb99 removing dependencies in ImageBuffer3D diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/FiniteProjectiveCamera.cpp --- a/Framework/Toolbox/FiniteProjectiveCamera.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/FiniteProjectiveCamera.cpp Tue May 21 16:15:06 2019 +0200 @@ -23,6 +23,7 @@ #include "GeometryToolbox.h" #include "SubpixelReader.h" +#include "ParallelSlices.h" #include #include @@ -299,6 +300,7 @@ static void ApplyRaytracerInternal(Orthanc::ImageAccessor& target, const FiniteProjectiveCamera& camera, const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, VolumeProjection projection) { if (source.GetFormat() != SourceFormat || @@ -315,8 +317,8 @@ LOG(WARNING) << "Output image size: " << target.GetWidth() << "x" << target.GetHeight(); LOG(WARNING) << "Output pixel format: " << Orthanc::EnumerationToString(target.GetFormat()); - std::auto_ptr slices(source.GetGeometry(projection)); - const OrthancStone::Vector pixelSpacing = source.GetGeometry().GetVoxelDimensions(projection); + std::auto_ptr slices(OrthancStone::ParallelSlices::FromVolumeImage(geometry, projection)); + const OrthancStone::Vector pixelSpacing = geometry.GetVoxelDimensions(projection); const unsigned int targetWidth = target.GetWidth(); const unsigned int targetHeight = target.GetHeight(); @@ -422,6 +424,7 @@ Orthanc::ImageAccessor* FiniteProjectiveCamera::ApplyRaytracer(const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, Orthanc::PixelFormat targetFormat, unsigned int targetWidth, unsigned int targetHeight, @@ -440,14 +443,14 @@ { ApplyRaytracerInternal - (*target, *this, source, projection); + (*target, *this, source, geometry, projection); } else if (targetFormat == Orthanc::PixelFormat_Grayscale16 && source.GetFormat() == Orthanc::PixelFormat_Grayscale16 && !mip) { ApplyRaytracerInternal - (*target, *this, source, projection); + (*target, *this, source, geometry, projection); } else { diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/FiniteProjectiveCamera.h --- a/Framework/Toolbox/FiniteProjectiveCamera.h Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/FiniteProjectiveCamera.h Tue May 21 16:15:06 2019 +0200 @@ -23,6 +23,7 @@ #include "LinearAlgebra.h" #include "../Volumes/ImageBuffer3D.h" +#include "VolumeImageGeometry.h" namespace OrthancStone { @@ -109,6 +110,7 @@ Vector ApplyGeneral(const Vector& v) const; Orthanc::ImageAccessor* ApplyRaytracer(const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, Orthanc::PixelFormat targetFormat, unsigned int targetWidth, unsigned int targetHeight, diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/OrientedBoundingBox.cpp --- a/Framework/Toolbox/OrientedBoundingBox.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/OrientedBoundingBox.cpp Tue May 21 16:15:06 2019 +0200 @@ -22,6 +22,7 @@ #include "OrientedBoundingBox.h" #include "GeometryToolbox.h" +#include "../Volumes/ImageBuffer3D.h" #include @@ -29,26 +30,25 @@ namespace OrthancStone { - OrientedBoundingBox::OrientedBoundingBox(const ImageBuffer3D& image) + OrientedBoundingBox::OrientedBoundingBox(const VolumeImageGeometry& geometry) { - unsigned int n = image.GetDepth(); + unsigned int n = geometry.GetDepth(); if (n < 1) { throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); } - const CoordinateSystem3D& geometry = image.GetGeometry().GetAxialGeometry(); - Vector dim = image.GetGeometry().GetVoxelDimensions(VolumeProjection_Axial); + Vector dim = geometry.GetVoxelDimensions(VolumeProjection_Axial); + + u_ = geometry.GetAxialGeometry().GetAxisX(); + v_ = geometry.GetAxialGeometry().GetAxisY(); + w_ = geometry.GetAxialGeometry().GetNormal(); - u_ = geometry.GetAxisX(); - v_ = geometry.GetAxisY(); - w_ = geometry.GetNormal(); - - hu_ = static_cast(image.GetWidth() * dim[0] / 2.0); - hv_ = static_cast(image.GetHeight() * dim[1] / 2.0); - hw_ = static_cast(image.GetDepth() * dim[2] / 2.0); + hu_ = static_cast(geometry.GetWidth() * dim[0] / 2.0); + hv_ = static_cast(geometry.GetHeight() * dim[1] / 2.0); + hw_ = static_cast(geometry.GetDepth() * dim[2] / 2.0); - c_ = (geometry.GetOrigin() + + c_ = (geometry.GetAxialGeometry().GetOrigin() + (hu_ - dim[0] / 2.0) * u_ + (hv_ - dim[1] / 2.0) * v_ + (hw_ - dim[2] / 2.0) * w_); diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/OrientedBoundingBox.h --- a/Framework/Toolbox/OrientedBoundingBox.h Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/OrientedBoundingBox.h Tue May 21 16:15:06 2019 +0200 @@ -21,9 +21,10 @@ #pragma once +#include "CoordinateSystem3D.h" #include "Extent2D.h" #include "LinearAlgebra.h" -#include "../Volumes/ImageBuffer3D.h" +#include "VolumeImageGeometry.h" namespace OrthancStone { @@ -39,7 +40,7 @@ double hw_; // half depth public: - OrientedBoundingBox(const ImageBuffer3D& image); + OrientedBoundingBox(const VolumeImageGeometry& geometry); const Vector& GetCenter() const { diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/ParallelSlices.cpp --- a/Framework/Toolbox/ParallelSlices.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/ParallelSlices.cpp Tue May 21 16:15:06 2019 +0200 @@ -22,6 +22,7 @@ #include "ParallelSlices.h" #include "GeometryToolbox.h" +#include "../Volumes/ImageBuffer3D.h" #include #include @@ -30,7 +31,7 @@ { ParallelSlices::ParallelSlices() { - LinearAlgebra::AssignVector(normal_, 0, 0, 1); + Clear(); } @@ -48,7 +49,7 @@ } - ParallelSlices::~ParallelSlices() + void ParallelSlices::Clear() { for (size_t i = 0; i < slices_.size(); i++) { @@ -58,6 +59,15 @@ slices_[i] = NULL; } } + + slices_.clear(); + LinearAlgebra::AssignVector(normal_, 0, 0, 1); + } + + + ParallelSlices::~ParallelSlices() + { + Clear(); } @@ -146,4 +156,60 @@ return reversed.release(); } + + + ParallelSlices* ParallelSlices::FromVolumeImage(const VolumeImageGeometry& geometry, + VolumeProjection projection) + { + const Vector dimensions = geometry.GetVoxelDimensions(VolumeProjection_Axial); + const CoordinateSystem3D& axial = geometry.GetAxialGeometry(); + + std::auto_ptr result(new ParallelSlices); + + switch (projection) + { + case VolumeProjection_Axial: + for (unsigned int z = 0; z < geometry.GetDepth(); z++) + { + Vector origin = axial.GetOrigin(); + origin += static_cast(z) * dimensions[2] * axial.GetNormal(); + + result->AddSlice(origin, + axial.GetAxisX(), + axial.GetAxisY()); + } + break; + + case VolumeProjection_Coronal: + for (unsigned int y = 0; y < geometry.GetHeight(); y++) + { + Vector origin = axial.GetOrigin(); + origin += static_cast(y) * dimensions[1] * axial.GetAxisY(); + origin += static_cast(geometry.GetDepth() - 1) * dimensions[2] * axial.GetNormal(); + + result->AddSlice(origin, + axial.GetAxisX(), + -axial.GetNormal()); + } + break; + + case VolumeProjection_Sagittal: + for (unsigned int x = 0; x < geometry.GetWidth(); x++) + { + Vector origin = axial.GetOrigin(); + origin += static_cast(x) * dimensions[0] * axial.GetAxisX(); + origin += static_cast(geometry.GetDepth() - 1) * dimensions[2] * axial.GetNormal(); + + result->AddSlice(origin, + axial.GetAxisY(), + -axial.GetNormal()); + } + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + return result.release(); + } } diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/ParallelSlices.h --- a/Framework/Toolbox/ParallelSlices.h Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/ParallelSlices.h Tue May 21 16:15:06 2019 +0200 @@ -22,6 +22,7 @@ #pragma once #include "CoordinateSystem3D.h" +#include "VolumeImageGeometry.h" namespace OrthancStone { @@ -33,6 +34,8 @@ ParallelSlices& operator= (const ParallelSlices& other); // Forbidden + void Clear(); + public: ParallelSlices(); @@ -63,5 +66,8 @@ const Vector& origin) const; ParallelSlices* Reverse() const; + + static ParallelSlices* FromVolumeImage(const VolumeImageGeometry& geometry, + VolumeProjection projection); }; } diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/ShearWarpProjectiveTransform.cpp --- a/Framework/Toolbox/ShearWarpProjectiveTransform.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/ShearWarpProjectiveTransform.cpp Tue May 21 16:15:06 2019 +0200 @@ -343,6 +343,7 @@ float& maxValue, const Matrix& M_view, const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, double pixelSpacing, unsigned int countSlices, ImageInterpolation shearInterpolation, @@ -385,8 +386,8 @@ // Compute the "world" matrix that maps the source volume to the // (0,0,0)->(1,1,1) unit cube - Vector origin = source.GetGeometry().GetCoordinates(0, 0, 0); - Vector ps = source.GetGeometry().GetVoxelDimensions(VolumeProjection_Axial); + Vector origin = geometry.GetCoordinates(0, 0, 0); + Vector ps = geometry.GetVoxelDimensions(VolumeProjection_Axial); Matrix world = LinearAlgebra::Product( GeometryToolbox::CreateScalingMatrix(1.0 / ps[0], 1.0 / ps[1], 1.0 / ps[2]), GeometryToolbox::CreateTranslationMatrix(-origin[0], -origin[1], -origin[2])); @@ -598,6 +599,7 @@ float& maxValue, const Matrix& M_view, const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, bool mip, double pixelSpacing, unsigned int countSlices, @@ -607,13 +609,13 @@ if (mip) { ApplyAxialInternal - (target, maxValue, M_view, source, pixelSpacing, + (target, maxValue, M_view, source, geometry, pixelSpacing, countSlices, shearInterpolation, warpInterpolation); } else { ApplyAxialInternal - (target, maxValue, M_view, source, pixelSpacing, + (target, maxValue, M_view, source, geometry, pixelSpacing, countSlices, shearInterpolation, warpInterpolation); } } @@ -623,6 +625,7 @@ ShearWarpProjectiveTransform::ApplyAxial(float& maxValue, const Matrix& M_view, const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, Orthanc::PixelFormat targetFormat, unsigned int targetWidth, unsigned int targetHeight, @@ -640,7 +643,7 @@ { ApplyAxialInternal2 - (*target, maxValue, M_view, source, mip, pixelSpacing, + (*target, maxValue, M_view, source, geometry, mip, pixelSpacing, countSlices, shearInterpolation, warpInterpolation); } else if (source.GetFormat() == Orthanc::PixelFormat_SignedGrayscale16 && @@ -648,7 +651,7 @@ { ApplyAxialInternal2 - (*target, maxValue, M_view, source, mip, pixelSpacing, + (*target, maxValue, M_view, source, geometry, mip, pixelSpacing, countSlices, shearInterpolation, warpInterpolation); } else diff -r be3671662eec -r c3bbb130abc4 Framework/Toolbox/ShearWarpProjectiveTransform.h --- a/Framework/Toolbox/ShearWarpProjectiveTransform.h Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Toolbox/ShearWarpProjectiveTransform.h Tue May 21 16:15:06 2019 +0200 @@ -92,6 +92,7 @@ static Orthanc::ImageAccessor* ApplyAxial(float& maxValue, const Matrix& M_view, // cf. "CalibrateView()" const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, Orthanc::PixelFormat targetFormat, unsigned int targetWidth, unsigned int targetHeight, diff -r be3671662eec -r c3bbb130abc4 Framework/Volumes/ImageBuffer3D.cpp --- a/Framework/Volumes/ImageBuffer3D.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Volumes/ImageBuffer3D.cpp Tue May 21 16:15:06 2019 +0200 @@ -21,8 +21,6 @@ #include "ImageBuffer3D.h" -#include "../Toolbox/GeometryToolbox.h" - #include #include #include @@ -118,8 +116,6 @@ computeRange_(computeRange), hasRange_(false) { - geometry_.SetSize(width, height, depth); - LOG(INFO) << "Created a 3D image of size " << width << "x" << height << "x" << depth << " in " << Orthanc::EnumerationToString(format) << " (" << (GetEstimatedMemorySize() / (1024ll * 1024ll)) << "MB)"; @@ -132,63 +128,6 @@ } - - - ParallelSlices* ImageBuffer3D::GetGeometry(VolumeProjection projection) const - { - const Vector dimensions = geometry_.GetVoxelDimensions(VolumeProjection_Axial); - const CoordinateSystem3D& axial = geometry_.GetAxialGeometry(); - - std::auto_ptr result(new ParallelSlices); - - switch (projection) - { - case VolumeProjection_Axial: - for (unsigned int z = 0; z < depth_; z++) - { - Vector origin = axial.GetOrigin(); - origin += static_cast(z) * dimensions[2] * axial.GetNormal(); - - result->AddSlice(origin, - axial.GetAxisX(), - axial.GetAxisY()); - } - break; - - case VolumeProjection_Coronal: - for (unsigned int y = 0; y < height_; y++) - { - Vector origin = axial.GetOrigin(); - origin += static_cast(y) * dimensions[1] * axial.GetAxisY(); - origin += static_cast(depth_ - 1) * dimensions[2] * axial.GetNormal(); - - result->AddSlice(origin, - axial.GetAxisX(), - -axial.GetNormal()); - } - break; - - case VolumeProjection_Sagittal: - for (unsigned int x = 0; x < width_; x++) - { - Vector origin = axial.GetOrigin(); - origin += static_cast(x) * dimensions[0] * axial.GetAxisX(); - origin += static_cast(depth_ - 1) * dimensions[2] * axial.GetNormal(); - - result->AddSlice(origin, - axial.GetAxisY(), - -axial.GetNormal()); - } - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - return result.release(); - } - - uint64_t ImageBuffer3D::GetEstimatedMemorySize() const { return image_.GetPitch() * image_.GetHeight() * Orthanc::GetBytesPerPixel(format_); diff -r be3671662eec -r c3bbb130abc4 Framework/Volumes/ImageBuffer3D.h --- a/Framework/Volumes/ImageBuffer3D.h Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Volumes/ImageBuffer3D.h Tue May 21 16:15:06 2019 +0200 @@ -22,8 +22,7 @@ #pragma once #include "../StoneEnumerations.h" -#include "../Toolbox/ParallelSlices.h" -#include "../Toolbox/VolumeImageGeometry.h" +#include "../Toolbox/LinearAlgebra.h" #include @@ -32,7 +31,6 @@ class ImageBuffer3D : public boost::noncopyable { private: - VolumeImageGeometry geometry_; // TODO => Move this out of this class Orthanc::Image image_; Orthanc::PixelFormat format_; unsigned int width_; @@ -76,16 +74,6 @@ void Clear(); - VolumeImageGeometry& GetGeometry() - { - return geometry_; - } - - const VolumeImageGeometry& GetGeometry() const - { - return geometry_; - } - const Orthanc::ImageAccessor& GetInternalImage() const { return image_; @@ -111,9 +99,6 @@ return format_; } - // TODO - Remove - ParallelSlices* GetGeometry(VolumeProjection projection) const; - uint64_t GetEstimatedMemorySize() const; bool GetRange(float& minValue, diff -r be3671662eec -r c3bbb130abc4 Framework/Volumes/VolumeReslicer.cpp --- a/Framework/Volumes/VolumeReslicer.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Volumes/VolumeReslicer.cpp Tue May 21 16:15:06 2019 +0200 @@ -745,12 +745,13 @@ void VolumeReslicer::Apply(const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, const CoordinateSystem3D& plane) { // Choose the default voxel size as the finest voxel dimension // of the source volumetric image const OrthancStone::Vector dim = - source.GetGeometry().GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); + geometry.GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); double voxelSize = dim[0]; if (dim[1] < voxelSize) @@ -768,11 +769,12 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } - Apply(source, plane, voxelSize); + Apply(source, geometry, plane, voxelSize); } void VolumeReslicer::Apply(const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, const CoordinateSystem3D& plane, double voxelSize) { @@ -783,7 +785,7 @@ // to 6 vertices. We compute the extent of the intersection // polygon, with respect to the coordinate system of the reslicing // plane. - OrientedBoundingBox box(source); + OrientedBoundingBox box(geometry); if (!box.ComputeExtent(extent_, plane)) { diff -r be3671662eec -r c3bbb130abc4 Framework/Volumes/VolumeReslicer.h --- a/Framework/Volumes/VolumeReslicer.h Tue May 21 15:20:04 2019 +0200 +++ b/Framework/Volumes/VolumeReslicer.h Tue May 21 16:15:06 2019 +0200 @@ -111,9 +111,11 @@ Orthanc::ImageAccessor* ReleaseOutputSlice(); void Apply(const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, const CoordinateSystem3D& plane); void Apply(const ImageBuffer3D& source, + const VolumeImageGeometry& geometry, const CoordinateSystem3D& plane, double voxelSize); }; diff -r be3671662eec -r c3bbb130abc4 Samples/Sdl/Loader.cpp --- a/Samples/Sdl/Loader.cpp Tue May 21 15:20:04 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Tue May 21 16:15:06 2019 +0200 @@ -31,6 +31,7 @@ #include "../../Framework/StoneInitialization.h" #include "../../Framework/Toolbox/GeometryToolbox.h" #include "../../Framework/Toolbox/SlicesSorter.h" +#include "../../Framework/Toolbox/VolumeImageGeometry.h" #include "../../Framework/Volumes/ImageBuffer3D.h" // From Orthanc framework @@ -1269,6 +1270,7 @@ { private: std::auto_ptr image_; + std::auto_ptr geometry_; std::vector slices_; uint64_t revision_; std::vector slicesRevision_; @@ -1336,6 +1338,7 @@ void Clear() { image_.reset(); + geometry_.reset(); for (size_t i = 0; i < slices_.size(); i++) { @@ -1386,6 +1389,8 @@ "Cannot sort the 3D slices of a DICOM series"); } + geometry_.reset(new OrthancStone::VolumeImageGeometry); + if (slices.GetSlicesCount() == 0) { // Empty volume @@ -1417,9 +1422,10 @@ parameters.GetImageInformation().GetHeight(), slices.GetSlicesCount(), false /* don't compute range */)); - image_->GetGeometry().SetAxialGeometry(slices.GetSliceGeometry(0)); - image_->GetGeometry().SetVoxelDimensions(parameters.GetPixelSpacingX(), - parameters.GetPixelSpacingY(), spacingZ); + geometry_->SetSize(image_->GetWidth(), image_->GetHeight(), image_->GetDepth()); + geometry_->SetAxialGeometry(slices.GetSliceGeometry(0)); + geometry_->SetVoxelDimensions(parameters.GetPixelSpacingX(), + parameters.GetPixelSpacingY(), spacingZ); } image_->Clear(); @@ -1434,7 +1440,8 @@ bool HasGeometry() const { - return (image_.get() != NULL); + return (image_.get() != NULL && + geometry_.get() != NULL); } const OrthancStone::ImageBuffer3D& GetImage() const @@ -1449,6 +1456,18 @@ } } + const OrthancStone::VolumeImageGeometry& GetGeometry() const + { + if (!HasGeometry()) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + return *geometry_; + } + } + size_t GetSlicesCount() const { if (!HasGeometry()) @@ -1834,7 +1853,7 @@ return; } - const OrthancStone::VolumeImageGeometry& geometry = source_.GetVolume().GetImage().GetGeometry(); + const OrthancStone::VolumeImageGeometry& geometry = source_.GetVolume().GetGeometry(); OrthancStone::VolumeProjection projection; unsigned int sliceIndex;