cgv
Loading...
Searching...
No Matches
sliced_volume.cxx
1#include <cgv/base/base.h>
2#include "sliced_volume.h"
3#include "sliced_volume_io.h"
4#include <fstream>
5#include <stdio.h>
6#include <cgv/utils/file.h>
7#include <cgv/utils/scan.h>
9#include <cgv/utils/tokenizer.h>
10#include <cgv/media/image/image_reader.h>
11#include <cgv/media/image/image_writer.h>
12
13namespace cgv {
14 namespace media {
15 namespace volume {
16
17
18 ooc_sliced_volume::ooc_sliced_volume()
19 {
20 nr_slices = 0;
21 offset = 0;
22 }
23
25 {
26 return
27 df.get_nr_dimensions() > 1 ?
28 dimension_type(int(df.get_width()), int(df.get_height()), nr_slices) :
29 dimension_type(0, 0, 0);
30 }
31
34 {
35 df.set_width(S(0));
36 df.set_height(S(1));
37 nr_slices = S(2);
39 }
40
41
42 std::string ooc_sliced_volume::get_slice_file_name(int i) const
43 {
44 static std::string long_placeholder = "00000000$";
45 std::string file_name = file_name_pattern;
46 std::string number = cgv::utils::to_string(i + offset);
47 std::string placeholder = long_placeholder.substr(long_placeholder.size() - number.size());
48 cgv::utils::replace(file_name, placeholder, number);
49 return file_name;
50 }
51
52 bool ooc_sliced_volume::open_read(const std::string& file_name)
53 {
55 if (!read_sliced_header(file_name, info)) {
56 std::cerr << "could not read header " << file_name << std::endl;
57 return false;
58 }
60 df.set_width(info.dimensions(0));
61 df.set_height(info.dimensions(1));
62 nr_slices = info.dimensions(2);
63 extent = info.extent;
64 offset = info.offset;
65 df.set_component_format(cgv::data::component_format(info.type_id, info.components));
66
67 file_name_pattern = info.file_name_pattern;
68 std::string path = cgv::utils::file::get_path(file_name);
69 if (path.size() > 0)
70 file_name_pattern = path + "/" + file_name_pattern;
71
72 //if (file_name_pattern.find_first_of('*') == std::string::npos && get_slice_file_name(0) == get_slice_file_name(1)) {
73 // std::cerr << "found invalid file name pattern " << file_name_pattern << std::endl;
74 // return false;
75 //}
76 return true;
77 }
78
79 bool ooc_sliced_volume::open_write(const std::string& file_name, const std::string& _file_name_pattern, unsigned nr_slices)
80 {
81 file_name_pattern = _file_name_pattern;
82
83 // pattern to be written in file should be with local path and no backslashes
84 std::string pattern = _file_name_pattern;
85 std::string path = cgv::utils::file::get_path(file_name);
86 if (path.size() > 0) {
87 if (pattern.substr(0, path.size()) == path)
88 pattern = pattern.substr(path.size() + 1);
89 }
90 pattern = cgv::utils::file::clean_path(pattern);
91
92 // writing header
93 if (!write_sliced_header(file_name, *this)) {
94 std::cerr << "could not write header " << file_name << std::endl;
95 return false;
96 }
97
98 return true;
99 }
100
101 bool ooc_sliced_volume::is_open() const
102 {
103 return !file_name_pattern.empty();
104 }
105
106 unsigned ooc_sliced_volume::get_nr_slices() const
107 {
108 return nr_slices;
109 }
110
111 bool ooc_sliced_volume::read_slice(int i, const std::string& slice_file_name)
112 {
113 if (i < 0 || i >= (int)get_nr_slices()) {
114 std::cerr << "slice index " << i << " out of range [0, " << get_nr_slices() << "[" << std::endl;
115 return false;
116 }
117 std::string file_name = slice_file_name.empty() ? get_slice_file_name(i) : slice_file_name;
118
119 // detect special case for binary files
120 if (cgv::utils::file::get_extension(file_name).empty()) {
121 size_t file_size = cgv::utils::file::size(file_name);
122 size_t data_size = df.get_nr_bytes();
123 if (data_size > file_size) {
124 std::cerr << "slice file " << file_name << " too small: only contains " << file_size << " bytes, but " << df.get_nr_bytes() << " bytes needed." << std::endl;
125 return false;
126 }
127 char* content = cgv::utils::file::read(file_name);
128 if (!content) {
129 std::cerr << "could not read slice file " << file_name << "." << std::endl;
130 return false;
131 }
132 size_t offset = file_size - data_size;
133 if (dv.empty())
134 new(&dv) cgv::data::data_view(&df);
135 std::copy(content + offset, content + file_size, dv.get_ptr<char>());
136 delete[] content;
137 return true;
138 }
139 else {
141 if (!ir.open(file_name)) {
142 std::cerr << "could not open slice file " << file_name << std::endl;
143 return false;
144 }
145 if (!ir.read_image(dv)) {
146 std::cerr << "could not read slice file " << file_name << std::endl;
147 return false;
148 }
149 ir.close();
150 return true;
151 }
152 }
153
155 {
156 if (i < 0 || i >= (int)get_nr_slices()) {
157 std::cerr << "slice index " << i << " out of range [0, " << get_nr_slices() << "[" << std::endl;
158 return false;
159 }
160 std::string file_name = get_slice_file_name(i);
162 if (!iw.write_image(dv)) {
163 std::cerr << "could not write slice file " << file_name << std::endl;
164 return false;
165 }
166 iw.close();
167 return true;
168 }
169
170
171 void ooc_sliced_volume::close()
172 {
173 clear();
174 file_name_pattern.clear();
175 nr_slices = 0;
176 };
177
178 sliced_volume_info::sliced_volume_info()
179 {
180 offset = 0;
181 }
182
183 std::string truncate_spaces(const std::string& s)
184 {
185 size_t p = 0;
186 while (p < s.size() && cgv::utils::is_space(s[p]))
187 ++p;
188 size_t q = s.size();
189 while (q >= p && q > 0 && cgv::utils::is_space(s[q - 1]))
190 --q;
191 return s.substr(p, q - p);
192 }
193
194 bool unknown_line_callback(const std::string& line, const std::vector<cgv::utils::token>& toks, volume_info& info)
195 {
196 if (cgv::utils::to_upper(to_string(toks[0])) == "PATTERN") {
197 sliced_volume_info& sinfo = (sliced_volume_info&)info;
198 sinfo.file_name_pattern = truncate_spaces(line.substr(8));
199 return true;
200 }
201 if (cgv::utils::to_upper(to_string(toks[0])) == "OFFSET") {
202 sliced_volume_info& sinfo = (sliced_volume_info&)info;
203 if (!cgv::utils::is_integer(truncate_spaces(line.substr(7)), sinfo.offset)) {
204 std::cerr << "ERROR in OFFSET line: <" << truncate_spaces(line.substr(7)) << "> not defining an integer offset" << std::endl;
205 return false;
206 }
207 return true;
208 }
209 return false;
210 }
211
212 bool read_sliced_header(const std::string& file_name, sliced_volume_info& info)
213 {
214 return read_vox_header(file_name, info, &unknown_line_callback);
215 }
216
217 bool write_sliced_header(const std::string& file_name, const ooc_sliced_volume& V)
218 {
219 if (!write_vox_header(file_name, V))
220 return false;
221 std::ofstream os(file_name, std::ofstream::app);
222 os << "Pattern: " << V.file_name_pattern << std::endl;
223 return !os.fail();
224 }
225
226 }
227 }
228}
the component format inherits the information of a packing_info and adds information on the component...
unsigned get_nr_dimensions() const
return the number of dimensions of the data set
void set_component_format(const component_format &cf)
set component_format by simply assigning to a converted this pointer
void set_height(size_t _height)
set the resolution in the second dimension, add dimensions if necessary
void set_width(size_t _width)
set the resolution in the first dimension, add dimensions if necessary
size_t get_width() const
return the resolution in the first dimension, or 1 if not defined
size_t get_height() const
return the resolution in the second dimension, or 1 if not defined
void set_nr_dimensions(unsigned _d)
set the number of dimensions of the data set
size_t get_nr_bytes() const
return the total number of bytes necessary to store the data
bool empty() const
return whether the data pointer is a null pointer
cgv::type::func::transfer_const< P, S * >::type get_ptr() const
return a data pointer to type S
Definition data_view.h:61
the data view gives access to a data array of one, two, three or four dimensions.
Definition data_view.h:153
the image reader chooses a specific reader automatically based on the extension of the given file nam...
the image writer chooses a specific writer automatically based on the extension of the given file nam...
bool close()
close image file;
bool write_image(const cgv::data::const_data_view &dv, const std::vector< cgv::data::const_data_view > *palettes=0, double duration=0)
write the data stored in the data view to a file with the file name given in the constructor.
extent_type extent
extent of the volume in each coordinate direction
Definition volume.h:29
cgv::data::data_format df
format description of volume data
Definition volume.h:25
void clear()
deallocate all memory and reset data format to "uint8[L]"
Definition volume.h:40
cgv::data::data_view dv
data storage of volume data
Definition volume.h:27
bool empty() const
return whether volume is empty
Definition volume.h:38
Helper functions to convert numeric types into strings using std streams.
unsigned int replace(std::string &s, char c1, char c2)
replace char c1 with c2 in the given string _s and return number of replacements
Definition scan.cxx:159
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
bool is_integer(const char *begin, const char *end, int &value)
check if the text range (begin,end( defines an integer value. If yes, store the value in the passed r...
Definition scan.cxx:367
char to_upper(char c)
convert char to upper case
Definition scan.cxx:106
bool is_space(char c)
check if char is a whitespace
Definition scan.cxx:12
the cgv namespace
Definition print.h:11
Helper functions to process strings.
bool write_slice(int i) const
set the content of the data view through ref_data
bool open_read(const std::string &file_name)
open for read
void resize(const dimension_type &S)
resize the data view to hold a slice and set the total number of slices as well
bool open_write(const std::string &file_name, const std::string &_file_name_pattern, unsigned nr_slices)
open for write, set the data format to the slice format (width, height, components,...
dimension_type get_dimensions() const
overload to compose dimensions from slice format and number dimensions