File: csa_entry.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 (182 lines) | stat: -rw-r--r-- 6,667 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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* 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 __file_dicom_csa_entry_h__
#define __file_dicom_csa_entry_h__

#include "datatype.h"
#include "raw.h"
#include "types.h"
#include "file/dicom/element.h"

namespace MR {
  namespace File {
    namespace Dicom {

        class CSAEntry { NOMEMALIGN
          public:
            CSAEntry (const uint8_t* start_p, const uint8_t* end_p, bool output_fields = false) :
                start (start_p),
                end (end_p),
                print (output_fields),
                cnum (0)
            {
              if (strncmp ("SV10", (const char*) start, 4)) {
                DEBUG ("Siemens CSA entry does not start with \"SV10\"; ignoring");
                num = 0;
                next = end;
              } else {
                const uint8_t* const unused1 = start+4;
                if (unused1[0] != 0x04U || unused1[1] != 0x03U || unused1[2] != 0x02U || unused1[3] != 0x01U)
                  DEBUG ("WARNING: CSA2 \'unused1\' int8 field contains unexpected data");
                num = Raw::fetch_LE<uint32_t> (start+8);
                const uint32_t unused2 = Raw::fetch_LE<uint32_t> (start+12);
                if (unused2 != 77)
                  DEBUG ("CSA2 \'unused2\' integer field contains " + str(unused2) + "; expected 77");
                next = start + 16;
              }
            }


            bool parse () {
              if (cnum >= num)
                return false;
              start = next;
              if (start >= end + 84)
                return false;
              strncpy (name, (const char*) start, 64);
              Raw::fetch_LE<uint32_t> (start+64); // vm
              strncpy (vr, (const char*) start+68, 4);
              Raw::fetch_LE<uint32_t> (start+72); // syngodt
              nitems = Raw::fetch_LE<uint32_t> (start+76);
              const int32_t xx = Raw::fetch_LE<int32_t> (start+80);
              if (!(xx == 77 || xx == 205))
                DEBUG ("CSA tag \'xx\' integer field contains " + str(xx) + "; expected 77 or 205");
              if (print)
                fprintf (stdout, "    [CSA] %s: ", name);
              next = start + 84;
              if (next + 4 >= end)
                return false;

              for (uint32_t m = 0; m < nitems; m++) {
                uint32_t length = Raw::fetch_LE<uint32_t> (next);
                size_t size = 16 + 4*((length+3)/4);
                if (next + size > end)
                  return false;
                if (print)
                  fprintf (stdout, "%.*s ", length, (const char*) next+16);
                next += size;
              }
              if (print)
                fprintf (stdout, "\n");

              cnum++;
              return true;
            }

            const char* key () const { return name; }

            uint32_t num_items() const { return nitems; }
            uint32_t size() const { return num; }

            int get_int () const {
              const uint8_t* p = start + 84;
              for (uint32_t m = 0; m < nitems; m++) {
                uint32_t length = Raw::fetch_LE<uint32_t> (p);
                if (length)
                  return to<int> (std::string (reinterpret_cast<const char*> (p)+16, 4*((length+3)/4)));
                p += 16 + 4*((length+3)/4);
              }
              return 0;
            }

            default_type get_float () const {
              const uint8_t* p = start + 84;
              for (uint32_t m = 0; m < nitems; m++) {
                uint32_t length = Raw::fetch_LE<uint32_t> (p);
                if (length)
                  return to<default_type> (std::string (reinterpret_cast<const char*> (p)+16, 4*((length+3)/4)));
                p += 16 + 4*((length+3)/4);
              }
              return NaN;
            }

            template <typename Container>
              void get_float (Container& v) const {
                const uint8_t* p = start + 84;
                if (nitems < v.size())
                  DEBUG ("CSA entry contains fewer items than expected - trailing entries will be set to NaN");
                for (uint32_t m = 0; m < std::min<size_t> (nitems, v.size()); m++) {
                  uint32_t length = Raw::fetch_LE<uint32_t> (p);
                  v[m] = length ? to<default_type> (std::string (reinterpret_cast<const char*> (p)+16, 4*((length+3)/4))) : NaN;
                  p += 16 + 4*((length+3)/4);
                }
                for (uint32_t m = nitems; m < v.size(); ++m)
                  v[m] = NaN;
              }

            vector<std::string> get_string () const {
              vector<std::string> result;
              const uint8_t* p = start + 84;
              for (uint32_t m = 0; m < nitems; m++) {
                const uint32_t length = Raw::fetch_LE<uint32_t> (p);
                std::string s (reinterpret_cast<const char*> (p)+16, length);
                result.push_back (std::move (s));
                p += 16 + 4*((length+3)/4);
              }
              return result;
            }

            friend std::ostream& operator<< (std::ostream& stream, const CSAEntry& item) {
              stream << "[CSA] " << item.name << " (" + str(item.nitems) + " items):";
              const uint8_t* next = item.start + 84;

              for (uint32_t m = 0; m < item.nitems; m++) {
                uint32_t length = Raw::fetch_LE<uint32_t> (next);
                size_t size = 16 + 4*((length+3)/4);
                while (length > 0 && !next[16+length-1])
                  length--;
                stream << " ";
                stream.write (reinterpret_cast<const char*> (next)+16, length);
                next += size;
              }
              stream << "\n";

              return stream;
            }


          protected:
            const uint8_t* start;
            const uint8_t* next;
            const uint8_t* end;
            bool print;
            char name[65], vr[5];
            uint32_t nitems, num, cnum;

        };





    }
  }
}

#endif