File: image.h

package info (click to toggle)
mrtrix3 3.0.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 13,712 kB
  • sloc: cpp: 129,776; python: 9,494; sh: 593; makefile: 234; xml: 47
file content (157 lines) | stat: -rw-r--r-- 5,928 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* Copyright (c) 2008-2022 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Covered Software is provided under this License on an "as is"
 * basis, without warranty of any kind, either expressed, implied, or
 * statutory, including, without limitation, warranties that the
 * Covered Software is free of defects, merchantable, fit for a
 * particular purpose or non-infringing.
 * See the Mozilla Public License v. 2.0 for more details.
 *
 * For more details, see http://www.mrtrix.org/.
 */

#ifndef __fixel_legacy_image_h__
#define __fixel_legacy_image_h__

#include <typeinfo>

#include "image.h"
#include "header.h"
#include "types.h"
#include "image_io/sparse.h"
#include "fixel/legacy/keys.h"

#ifndef __image_h__
#error File that #includes "fixel/legacy/image.h" must explicitly #include "image.h" beforehand
#endif


namespace MR
{

  namespace Fixel
  {
    namespace Legacy
    {
      template <typename DataType>
        class Value { MEMALIGN (Value<DataType>)
          public:
            Value (::MR::Image<uint64_t>& offsets, ImageIO::SparseLegacy& io) : offsets (offsets), io (io) { }

          uint32_t size() const { return io.get_numel (offsets.value()); }

          void set_size (const uint32_t n)
          {
            // Handler allocates new memory if necessary, and sets the relevant number of elements flag in the sparse image data
            // It returns the file offset necessary to access the relevant memory, so update the raw image value accordingly
            offsets.value() = (io.set_numel (offsets.value(), n));
          }

          // Handler is responsible for bounds checking
          DataType& operator[] (const size_t i)
          {
            uint8_t* const ptr = io.get (offsets.value(), i);
            return *(reinterpret_cast<DataType* const>(ptr));
          }
          const DataType& operator[] (const size_t i) const
          {
            const uint8_t* const ptr = io.get (offsets.value(), i);
            return *(reinterpret_cast<const DataType* const>(ptr));
          }


          // This should provide image copying capability using the relevant templated functions
          Value& operator= (const Value& that) {
            set_size (that.size());
            for (uint32_t i = 0; i != size(); ++i)
              (*this)[i] = that[i];
            return *this;
          }


          friend std::ostream& operator<< (std::ostream& stream, const Value& value) {
            stream << "Position [ ";
            for (size_t n = 0; n < value.offsets.ndim(); ++n)
              stream << value.offsets.index(n) << " ";
            stream << "], offset = " << value.offsets.value() << ", " << value.size() << " elements";
            return stream;
          }



          protected:
            ::MR::Image<uint64_t>& offsets;
            ImageIO::SparseLegacy& io;
        };







      // A convenience class for wrapping access to sparse images
      template <typename DataType>
        class Image : public ::MR::Image<uint64_t>
      { MEMALIGN (Image<DataType>)
        public:
          Image (const std::string& image_name) :
            ::MR::Image<uint64_t> (::MR::Image<uint64_t>::open (image_name)), io (nullptr) { check(); }

          Image (Header& header) :
            ::MR::Image<uint64_t> (header.get_image<uint64_t>()), io (nullptr) { check(); }

          Image (const Image<DataType>& that) = default;

          Image (const std::string& image_name, const Header& template_header) :
            ::MR::Image<uint64_t> (::MR::Image<uint64_t>::create (image_name, template_header)), io (nullptr) { check(); }

          using value_type = uint64_t;
          using sparse_data_type = DataType;

          Value<DataType> value () { return { *this, *io }; }
          const Value<DataType> value () const { return { *this, *io }; }

        protected:
          ImageIO::SparseLegacy* io;

          void check()
          {
            if (!buffer || !buffer->get_io())
              throw Exception ("cannot create sparse image for image with no handler");
            ImageIO::Base* ptr = buffer->get_io();
            if (typeid (*ptr) != typeid (ImageIO::SparseLegacy))
              throw Exception ("cannot create sparse image to access non-sparse data");
            // Use the header information rather than trying to access this from the handler
            KeyValues::const_iterator name_it = keyval().find (Fixel::Legacy::name_key);
            if (name_it == keyval().end())
              throw Exception ("cannot create sparse image without knowledge of underlying class type in the image header");
            // TODO temporarily disabled this to allow updated_syntax tests to pass with files generated with master branch.
  //          const std::string& class_name = name_it->second;
  //          if (str(typeid(DataType).name()) != class_name)
  //            throw Exception ("class type of sparse image buffer (" + str(typeid(DataType).name()) + ") does not match that in image header (" + class_name + ")");
            KeyValues::const_iterator size_it = keyval().find (Fixel::Legacy::size_key);
            if (size_it == keyval().end())
              throw Exception ("cannot create sparse image without knowledge of underlying class size in the image header");
            const size_t class_size = to<size_t>(size_it->second);
            if (sizeof(DataType) != class_size)
              throw Exception ("class size of sparse image does not match that in image header");
            io = reinterpret_cast<ImageIO::SparseLegacy*> (buffer->get_io());
            DEBUG ("Sparse image verified for accessing " + name() + " using type " + str(typeid(DataType).name()));
          }


      };

    }
  }
}

#endif