Mercurial > hg > orthanc-stl
diff Sources/Plugin.cpp @ 6:c02d12eb34d4
added LoadNifti()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 18 Jul 2023 14:45:20 +0200 |
parents | 5ee4448a8ff8 |
children | e3e59de705f6 |
line wrap: on
line diff
--- a/Sources/Plugin.cpp Tue Jul 18 12:39:50 2023 +0200 +++ b/Sources/Plugin.cpp Tue Jul 18 14:45:20 2023 +0200 @@ -26,6 +26,7 @@ #include <EmbeddedResources.h> +#include <Compression/GzipCompressor.h> #include <ChunkedBuffer.h> #include <DicomParsing/FromDcmtkBridge.h> #include <DicomParsing/ParsedDicomFile.h> @@ -47,6 +48,9 @@ #include <boost/thread/shared_mutex.hpp> +#include <nifti1_io.h> + + // Forward declaration void ReadStaticAsset(std::string& target, const std::string& path); @@ -1111,10 +1115,15 @@ padding->SetInputData(resize->GetOutput()); padding->Update(); + double range[2]; + padding->GetOutput()->GetScalarRange(range); + + const double isoValue = (range[0] + range[1]) / 2.0; + vtkNew<vtkMarchingCubes> surface; surface->SetInputData(padding->GetOutput()); surface->ComputeNormalsOn(); - surface->SetValue(0, 128 /*isoValue*/); + surface->SetValue(0, isoValue); surface->Update(); if (smooth) @@ -1397,6 +1406,95 @@ } + +class NiftiHeader : public boost::noncopyable +{ +private: + nifti_image* image_; + +public: + NiftiHeader(const std::string& nifti) + { + nifti_1_header header; + if (nifti.size() < sizeof(header)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + memcpy(&header, nifti.c_str(), sizeof(header)); + if (!nifti_hdr_looks_good(&header)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + + image_ = nifti_convert_nhdr2nim(header, "dummy_filename"); + if (image_ == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat); + } + } + + ~NiftiHeader() + { + nifti_image_free(image_); + } + + const nifti_image& GetInfo() const + { + assert(image_ != NULL); + return *image_; + } +}; + + +static void LoadNifti(vtkImageData* volume, + std::string& nifti) +{ + if (volume == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + + const uint8_t* p = reinterpret_cast<const uint8_t*>(nifti.c_str()); + + if (nifti.size() >= 2 && + p[0] == 0x1f && + p[1] == 0x8b) + { + Orthanc::GzipCompressor compressor; + std::string uncompressed; + Orthanc::IBufferCompressor::Uncompress(uncompressed, compressor, nifti); + nifti.swap(uncompressed); + } + + NiftiHeader header(nifti); + + if (header.GetInfo().ndim != 3) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, + "Only 3D NIfTI volumes are allowed"); + } + + if (header.GetInfo().datatype != DT_UNSIGNED_CHAR) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); + } + + assert(static_cast<int>(header.GetInfo().nvox) == header.GetInfo().nx * header.GetInfo().ny * header.GetInfo().nz); + + const size_t pixelDataOffset = sizeof(nifti_1_header) + 4 /* extension */; + + if (nifti.size() != pixelDataOffset + header.GetInfo().nvox) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_CorruptedFile); + } + + volume->SetDimensions(header.GetInfo().nx, header.GetInfo().ny, header.GetInfo().nz); + volume->AllocateScalars(VTK_UNSIGNED_CHAR, 1); + volume->SetSpacing(header.GetInfo().dx, header.GetInfo().dy, header.GetInfo().dz); + memcpy(volume->GetScalarPointer(), &nifti[pixelDataOffset], header.GetInfo().nvox * sizeof(unsigned char)); +} + extern "C" { ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)