Mercurial > hg > orthanc-neuro
view Sources/Framework/NiftiWriter.cpp @ 28:b440931aff64 default tip
added CITATION.cff
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sat, 06 Apr 2024 17:25:43 +0200 |
parents | 2c8f8168c1ab |
children |
line wrap: on
line source
/** * Neuroimaging plugin for Orthanc * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ #include "NiftiWriter.h" #include <Compression/GzipCompressor.h> #include <Images/Image.h> #include <OrthancException.h> #include <cassert> namespace Neuro { void NiftiWriter::WriteHeader(const nifti_image& header) { if (hasHeader_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } else { nifti_image fixed; memcpy(&fixed, &header, sizeof(nifti_image)); std::string empty(1, '\0'); fixed.fname = &empty[0]; fixed.iname = NULL; fixed.num_ext = 0; // no extension nifti_set_iname_offset(&fixed); if (fixed.nifti_type != NIFTI_FTYPE_NIFTI1_1) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } nifti_1_header serialized = nifti_convert_nim2nhdr(&fixed); serialized.vox_offset = (348 + 4); // (*) static const uint8_t nope[4] = { 0, 0, 0, 0 }; assert(sizeof(serialized) == 348); buffer_.AddChunk(&serialized, sizeof(serialized)); assert(sizeof(nope) == 4); buffer_.AddChunk(&nope, sizeof(nope)); // because of (*) hasHeader_ = true; } } void NiftiWriter::AddSlice(const Orthanc::ImageAccessor& slice) { if (!hasHeader_) { throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } else if (slice.GetWidth() != 0 && slice.GetHeight() != 0) { Orthanc::Image image(slice.GetFormat(), slice.GetWidth(), slice.GetHeight(), true /* force minimal pitch, as no pitch is allowed in NIfTI */); const size_t rowSize = GetBytesPerPixel(image.GetFormat()) * image.GetWidth(); if (rowSize != image.GetPitch()) { // Should never happen because of minimal pitch throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } assert(image.GetPitch() <= slice.GetPitch()); for (unsigned int y = 0; y < slice.GetHeight(); y++) { const uint8_t *source = reinterpret_cast<const uint8_t*>(slice.GetConstRow(y)); uint8_t *target = reinterpret_cast<uint8_t*>(image.GetRow(image.GetHeight() - 1 - y)); memcpy(target, source, rowSize); } buffer_.AddChunk(image.GetConstBuffer(), rowSize * image.GetHeight()); } } void NiftiWriter::Flatten(std::string& target, bool compress) { if (compress) { std::string uncompressed; buffer_.Flatten(uncompressed); Orthanc::GzipCompressor compressor; Orthanc::IBufferCompressor::Compress(target, compressor, uncompressed); } else { buffer_.Flatten(target); } } }