Developer documentation
Version 3.0.3-105-gd3941f44
image.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __fixel_legacy_image_h__
18#define __fixel_legacy_image_h__
19
20#include <typeinfo>
21
22#include "image.h"
23#include "header.h"
24#include "types.h"
25#include "image_io/sparse.h"
26#include "fixel/legacy/keys.h"
27
28#ifndef __image_h__
29#error File that #includes "fixel/legacy/image.h" must explicitly #include "image.h" beforehand
30#endif
31
32
33namespace MR
34{
35
36 namespace Fixel
37 {
38 namespace Legacy
39 {
40 template <typename DataType>
41 class Value { MEMALIGN (Value<DataType>)
42 public:
44
45 uint32_t size() const { return io.get_numel (offsets.value()); }
46
47 void set_size (const uint32_t n)
48 {
49 // Handler allocates new memory if necessary, and sets the relevant number of elements flag in the sparse image data
50 // It returns the file offset necessary to access the relevant memory, so update the raw image value accordingly
51 offsets.value() = (io.set_numel (offsets.value(), n));
52 }
53
54 // Handler is responsible for bounds checking
55 DataType& operator[] (const size_t i)
56 {
57 uint8_t* const ptr = io.get (offsets.value(), i);
58 return *(reinterpret_cast<DataType* const>(ptr));
59 }
60 const DataType& operator[] (const size_t i) const
61 {
62 const uint8_t* const ptr = io.get (offsets.value(), i);
63 return *(reinterpret_cast<const DataType* const>(ptr));
64 }
65
66
67 // This should provide image copying capability using the relevant templated functions
68 Value& operator= (const Value& that) {
69 set_size (that.size());
70 for (uint32_t i = 0; i != size(); ++i)
71 (*this)[i] = that[i];
72 return *this;
73 }
74
75
76 friend std::ostream& operator<< (std::ostream& stream, const Value& value) {
77 stream << "Position [ ";
78 for (size_t n = 0; n < value.offsets.ndim(); ++n)
79 stream << value.offsets.index(n) << " ";
80 stream << "], offset = " << value.offsets.value() << ", " << value.size() << " elements";
81 return stream;
82 }
83
84
85
86 protected:
89 };
90
91
92
93
94
95
96
97 // A convenience class for wrapping access to sparse images
98 template <typename DataType>
99 class Image : public ::MR::Image<uint64_t>
100 { MEMALIGN (Image<DataType>)
101 public:
102 Image (const std::string& image_name) :
103 ::MR::Image<uint64_t> (::MR::Image<uint64_t>::open (image_name)), io (nullptr) { check(); }
104
105 Image (Header& header) :
106 ::MR::Image<uint64_t> (header.get_image<uint64_t>()), io (nullptr) { check(); }
107
108 Image (const Image<DataType>& that) = default;
109
110 Image (const std::string& image_name, const Header& template_header) :
111 ::MR::Image<uint64_t> (::MR::Image<uint64_t>::create (image_name, template_header)), io (nullptr) { check(); }
112
113 using value_type = uint64_t;
115
116 Value<DataType> value () { return { *this, *io }; }
117 const Value<DataType> value () const { return { *this, *io }; }
118
119 protected:
121
122 void check()
123 {
124 if (!buffer || !buffer->get_io())
125 throw Exception ("cannot create sparse image for image with no handler");
126 ImageIO::Base* ptr = buffer->get_io();
127 if (typeid (*ptr) != typeid (ImageIO::SparseLegacy))
128 throw Exception ("cannot create sparse image to access non-sparse data");
129 // Use the header information rather than trying to access this from the handler
130 KeyValues::const_iterator name_it = keyval().find (Fixel::Legacy::name_key);
131 if (name_it == keyval().end())
132 throw Exception ("cannot create sparse image without knowledge of underlying class type in the image header");
133 // TODO temporarily disabled this to allow updated_syntax tests to pass with files generated with master branch.
134 // const std::string& class_name = name_it->second;
135 // if (str(typeid(DataType).name()) != class_name)
136 // throw Exception ("class type of sparse image buffer (" + str(typeid(DataType).name()) + ") does not match that in image header (" + class_name + ")");
137 KeyValues::const_iterator size_it = keyval().find (Fixel::Legacy::size_key);
138 if (size_it == keyval().end())
139 throw Exception ("cannot create sparse image without knowledge of underlying class size in the image header");
140 const size_t class_size = to<size_t>(size_it->second);
141 if (sizeof(DataType) != class_size)
142 throw Exception ("class size of sparse image does not match that in image header");
143 io = reinterpret_cast<ImageIO::SparseLegacy*> (buffer->get_io());
144 DEBUG ("Sparse image verified for accessing " + name() + " using type " + str(typeid(DataType).name()));
145 }
146
147
148 };
149
150 }
151 }
152}
153
154#endif
155
156
157
ImageIO::SparseLegacy * io
Definition: image.h:120
::MR::Image< uint64_t > & offsets
Definition: image.h:87
ImageIO::SparseLegacy & io
Definition: image.h:88
friend std::ostream & operator<<(std::ostream &stream, const Value &value)
Definition: image.h:76
const std::string & name() const
Definition: image.h:62
std::shared_ptr< Buffer > buffer
shared reference to header/buffer
Definition: image.h:200
const KeyValues & keyval() const
get generic key/value text attributes
Definition: image.h:60
#define DEBUG(msg)
Definition: exception.h:75
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
Definition: SH.h:233
const std::string size_key("sparse_data_size")
const std::string name_key("sparse_data_name")
@ Value
Definition: linear.h:87
Definition: base.h:24
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247