38 template <
typename ValueType>
40 public ImageBase<Image<ValueType>, ValueType>
75 for (
size_t n = 0; n <
ndim(); ++n)
99 stream <<
"\"" << V.
name() <<
"\", datatype " << DataType::from<Image::value_type>().specifier() <<
", index [ ";
100 for (
size_t n = 0; n < V.
ndim(); ++n) stream << V.index(n) <<
" ";
101 stream <<
"], current offset = " << V.
offset() <<
", ";
102 if (is_out_of_bounds(V))
103 stream <<
"outside FoV";
105 stream <<
"value = " << V.value();
107 else stream <<
" (using direct IO, data at " << V.
data_pointer <<
")";
186 assert (
data_pointer !=
nullptr &&
"Image::address() can only be used when image access is via direct RAM access");
189 static Image open (
const std::string& image_name,
bool read_write_if_existing =
false) {
190 return Header::open (image_name).get_image<ValueType> (read_write_if_existing);
192 static Image create (
const std::string& image_name,
const Header& template_header,
bool add_to_command_history =
true) {
193 return Header::create (image_name, template_header, add_to_command_history).get_image<ValueType>();
196 return Header::scratch (template_header, label).get_image<ValueType>();
219 template <
typename ValueType>
229 Header (b), fetch_func (b.fetch_func), store_func (b.store_func) { }
233 ssize_t nseg =
offset / io->segment_size();
234 return fetch_func (io->segment (nseg),
offset - nseg*io->segment_size(), intensity_offset(), intensity_scale());
238 ssize_t nseg =
offset / io->segment_size();
239 store_func (val, io->segment (nseg),
offset - nseg*io->segment_size(), intensity_offset(), intensity_scale());
275 template <
typename ValueType>
277 public ImageBase<TmpImage<ValueType>, ValueType>
283 b (b), data (data), x (x), strides (strides),
offset (
offset) { }
285 const typename Image<ValueType>::Buffer& b;
291 bool valid ()
const {
return true; }
292 const std::string
name ()
const {
return "direct IO buffer"; }
301 FORCE_INLINE void set_value (ValueType val) { Raw::store_native<ValueType> (val, data,
offset); }
315 template <
typename ValueType>
318 assert (
H.valid() &&
"IO handler must be set when creating an Image");
322 io->set_readwrite_if_existing (read_write_if_existing);
323 io->open (*
this, footprint<ValueType> (voxel_count (*
this)));
324 if (
io->is_file_backed())
333 template <
typename ValueType>
337 return data_buffer.get();
339 assert (io &&
"data pointer will only be set for valid Images");
340 if (!io->is_file_backed())
341 return io->segment(0);
345 if (io->nsegments() == 1 && datatype() == DataType::from<ValueType>() && intensity_offset() == 0.0 && intensity_scale() == 1.0)
346 return io->segment(0);
354 template <
typename ValueType>
355 Image<ValueType> Header::get_image (
bool read_write_if_existing)
358 throw Exception (
"FIXME: don't invoke get_image() with invalid Header!");
359 std::shared_ptr<typename Image<ValueType>::Buffer>
buffer (
new typename Image<ValueType>::Buffer (*
this, read_write_if_existing));
368 template <
typename ValueType>
373 template <
typename ValueType>
384 +
", using " + (
is_direct_io() ?
"" :
"in" ) +
"direct IO");
391 template <
typename ValueType>
397 if (
buffer->get_io()->is_image_readwrite() &&
buffer->data_buffer) {
398 auto data_buffer = std::move (
buffer->data_buffer);
400 Image<ValueType> dest (
buffer);
409 template <
typename ValueType>
413 throw Exception (
"FIXME: don't invoke 'with_direct_io()' on images already using direct IO!");
415 throw Exception (
"FIXME: don't invoke 'with_direct_io()' on non-validated images!");
417 throw Exception (
"FIXME: don't invoke 'with_direct_io()' on images if other copies exist!");
419 bool preload = (
buffer->datatype() != DataType::from<ValueType>() ) || (
buffer->get_io()->files.size() > 1 );
420 if (with_strides.size()) {
423 with_strides = new_strides;
429 return std::move (*
this);
434 const auto buffer_size = footprint<ValueType> (voxel_count (*
this));
435 buffer->data_buffer = std::unique_ptr<uint8_t[]> (
new uint8_t [buffer_size]);
437 if (
buffer->get_io()->is_image_new()) {
439 memset (
buffer->data_buffer.get(), 0, buffer_size);
443 TmpImage<ValueType> dest = { *
buffer,
buffer->data_buffer.get(), vector<ssize_t> (
ndim(), 0), with_strides,
Stride::offset (with_strides, *
this) };
454 template <
typename ValueType>
458 throw Exception (
"FIXME: image not suitable for use with 'Image::dump_to_mrtrix_file()'");
464 DEBUG (
"dumping image \"" +
name() +
"\" to file \"" + filename +
"\"...");
466 File::OFStream out (filename, std::ios::out | std::ios::binary);
467 out <<
"mrtrix image\n";
471 std::string data_filename = filename;
476 offset = int64_t(out.tellp()) + int64_t(18);
478 out <<
". " <<
offset <<
"\nEND\n";
481 data_filename = filename.substr (0, filename.size()-4) +
".dat";
484 out.open (data_filename, std::ios::out | std::ios::binary);
487 const int64_t data_size = footprint (*
buffer);
488 out.seekp (
offset, out.beg);
491 throw Exception (
"error writing back contents of file \"" + data_filename +
"\": " + strerror(errno));
508 template <
class ImageType>
509 std::string __save_generic (ImageType&
x,
const std::string& filename,
bool use_multi_threading) {
511 if (use_multi_threading)
521 template <
class ImageType>
522 typename std::enable_if<is_adapter_type<typename std::remove_reference<ImageType>::type>
::value, std::string>::type
523 save (ImageType&&
x,
const std::string& filename,
bool use_multi_threading =
true)
525 return __save_generic (
x, filename, use_multi_threading);
529 template <
class ImageType>
530 typename std::enable_if<is_pure_image<typename std::remove_reference<ImageType>::type>
::value, std::string>::type
531 save (ImageType&&
x,
const std::string& filename,
bool use_multi_threading =
true)
533 try {
return x.dump_to_mrtrix_file (filename, use_multi_threading); }
535 return __save_generic (
x, filename, use_multi_threading);
540 template <
class ImageType>
541 typename enable_if_image_type<ImageType,void>::type
display (ImageType&
x) {
542 std::string filename =
save (
x,
"-");
543 CONSOLE (
"displaying image \"" + filename +
"\"");
544 if (system ((
"bash -c \"mrview " + filename +
"\"").c_str()))
545 WARN (std::string(
"error invoking viewer: ") + strerror(errno));
void * get_data_pointer()
std::function< ValueType(const void *, size_t, default_type, default_type)> fetch_func
ValueType get_value(size_t offset) const
void set_fetch_store_functions()
Buffer(Header &H, bool read_write_if_existing=false)
construct a Buffer object to access the data in the image specified
ImageIO::Base * get_io() const
void set_value(size_t offset, ValueType val) const
Buffer(Buffer &&)=default
std::unique_ptr< uint8_t[]> data_buffer
std::function< void(ValueType, void *, size_t, default_type, default_type)> store_func
functions and classes related to image data input/output
Image with_direct_io(Stride::List with_strides=Stride::List())
return a new Image using direct IO
Image with_direct_io(int axis)
return a new Image using direct IO
bool is_direct_io() const
static Image scratch(const Header &template_header, const std::string &label="scratch image")
static Image create(const std::string &image_name, const Header &template_header, bool add_to_command_history=true)
size_t offset() const
offset to current voxel from start of data
ValueType get_value() const
get voxel value at current location
void set_value(ValueType val)
set voxel value at current location
const std::string & name() const
ssize_t get_index(size_t axis) const
get position of current voxel location along axis
std::shared_ptr< Buffer > buffer
shared reference to header/buffer
const KeyValues & keyval() const
get generic key/value text attributes
const transform_type & transform() const
ValueType * address() const
return RAM address of current voxel
friend std::ostream & operator<<(std::ostream &stream, const Image &V)
use for debugging
std::string dump_to_mrtrix_file(std::string filename, bool use_multi_threading=true) const
write out the contents of a direct IO image to file
size_t data_offset
offset to currently pointed-to voxel
Image(const std::shared_ptr< Buffer > &, const Stride::List &=Stride::List())
used internally to instantiate Image objects
default_type spacing(size_t axis) const
Stride::List strides
voxel indices
void move_index(size_t axis, ssize_t increment)
move position of current voxel location along axis
static Image open(const std::string &image_name, bool read_write_if_existing=false)
void reset()
reset index to zero (origin)
Image(const Image &)=default
ssize_t stride(size_t axis) const
Image & operator=(const Image &image)=default
void * data_pointer
pointer to data address whether in RAM or MMap
vector< ssize_t > x
voxel indices
ssize_t size(size_t axis) const
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
std::unique_ptr< ImageIO::Base > create(Header &H)
void resize(const std::string &filename, int64_t size)
std::string create_tempfile(int64_t size=0, const char *suffix=NULL)
MR::default_type value_type
std::string basename(const std::string &name)
bool has_suffix(const std::string &name, const std::string &suffix)
List contiguous_along_axis(size_t axis)
convenience function to get volume-contiguous strides
List contiguous_along_spatial_axes(const HeaderType &header)
convenience function to get spatially contiguous strides
List get_nearest_match(const HeaderType ¤t, const List &desired)
produce strides from current that match those specified in desired
List get_actual(HeaderType &header)
get actual strides:
size_t offset(const HeaderType &header)
calculate offset to start of data
List get(const HeaderType &header)
return the strides of header as a vector<ssize_t>
std::map< std::string, std::string > KeyValues
used in various places for storing key-value pairs
constexpr int SpatiallyContiguous
enable_if_image_type< ImageType, void >::type display(ImageType &x)
display the contents of an image in MRView (for debugging only)
double default_type
the default type used throughout MRtrix
std::string str(const T &value, int precision=0)
Eigen::Transform< default_type, 3, Eigen::AffineCompact > transform_type
the type for the affine transform of an image:
std::enable_if<!is_data_type< ValueType >::value, void >::type __set_fetch_store_functions(std::function< ValueType(const void *, size_t, default_type, default_type)> &, std::function< void(ValueType, void *, size_t, default_type, default_type)> &, DataType)
void copy(InputImageType &&source, OutputImageType &&destination, size_t from_axis=0, size_t to_axis=std::numeric_limits< size_t >::max())
void threaded_copy(InputImageType &source, OutputImageType &destination, const vector< size_t > &axes, size_t num_axes_in_thread=1)
size_t is_dash(const std::string &arg)
match whole string to a dash or any Unicode character that looks like one
std::enable_if< is_adapter_type< typenamestd::remove_reference< ImageType >::type >::value, std::string >::type save(ImageType &&x, const std::string &filename, bool use_multi_threading=true)
save contents of an existing image to file (for debugging only)
void threaded_copy_with_progress_message(const std::string &message, InputImageType &source, OutputImageType &destination, const vector< size_t > &axes, size_t num_axes_in_thread=1)