| hdf5impex.hxx | | hdf5impex.hxx | |
| | | | |
| skipping to change at line 79 | | skipping to change at line 79 | |
| #else | | #else | |
| # include <hdf5_hl.h> | | # include <hdf5_hl.h> | |
| #endif | | #endif | |
| | | | |
| #include "impex.hxx" | | #include "impex.hxx" | |
| #include "multi_array.hxx" | | #include "multi_array.hxx" | |
| #include "multi_impex.hxx" | | #include "multi_impex.hxx" | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "error.hxx" | | #include "error.hxx" | |
| | | | |
|
| | | #include <algorithm> | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup VigraHDF5Impex Import/Export of Images and Arrays in HDF5 F
ormat | | /** \addtogroup VigraHDF5Impex Import/Export of Images and Arrays in HDF5 F
ormat | |
| | | | |
| Supports arrays with arbitrary element types and arbitrary many dimensi
ons. | | Supports arrays with arbitrary element types and arbitrary many dimensi
ons. | |
| See the <a href="http://www.hdfgroup.org/HDF5/">HDF5 Website</a> for mo
re | | See the <a href="http://www.hdfgroup.org/HDF5/">HDF5 Website</a> for mo
re | |
| information on the HDF5 file format. | | information on the HDF5 file format. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /** \brief Wrapper for hid_t objects. | | /** \brief Wrapper for hid_t objects. | |
| | | | |
| Newly created or opened HDF5 handles are usually stored as objects of t
ype 'hid_t'. When the handle | | Newly created or opened HDF5 handles are usually stored as objects of t
ype 'hid_t'. When the handle | |
| is no longer needed, the appropriate close function must be called. How
ever, if a function is | | is no longer needed, the appropriate close function must be called. How
ever, if a function is | |
| aborted by an exception, this is difficult to ensure. Class HDF5Handle
is a smart pointer that | | aborted by an exception, this is difficult to ensure. Class HDF5Handle
is a smart pointer that | |
| solves this problem by calling the close function in the destructor (Th
is is analogous to how | | solves this problem by calling the close function in the destructor (Th
is is analogous to how | |
|
| std::auto_ptr calls 'delete' on the contained pointer). A pointer to th
e close function must be | | VIGRA_UNIQUE_PTR calls 'delete' on the contained pointer). A pointer to
the close function must be | |
| passed to the constructor, along with an error message that is raised w
hen creation/opening fails. | | passed to the constructor, along with an error message that is raised w
hen creation/opening fails. | |
| | | | |
| Since HDF5Handle objects are convertible to hid_t, they can be used in
the code in place | | Since HDF5Handle objects are convertible to hid_t, they can be used in
the code in place | |
| of the latter. | | of the latter. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| | | | |
| \code | | \code | |
| HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | | HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | |
| &H5Fclose, | | &H5Fclose, | |
| | | | |
| skipping to change at line 161 | | skipping to change at line 163 | |
| */ | | */ | |
| HDF5Handle(hid_t h, Destructor destructor, const char * error_message) | | HDF5Handle(hid_t h, Destructor destructor, const char * error_message) | |
| : handle_( h ), | | : handle_( h ), | |
| destructor_(destructor) | | destructor_(destructor) | |
| { | | { | |
| if(handle_ < 0) | | if(handle_ < 0) | |
| vigra_fail(error_message); | | vigra_fail(error_message); | |
| } | | } | |
| | | | |
| /** \brief Copy constructor. | | /** \brief Copy constructor. | |
|
| Hands over ownership of the RHS handle (analogous to std::auto_
ptr). | | Hands over ownership of the RHS handle (analogous to VIGRA_UNIQ
UE_PTR). | |
| */ | | */ | |
| HDF5Handle(HDF5Handle const & h) | | HDF5Handle(HDF5Handle const & h) | |
| : handle_( h.handle_ ), | | : handle_( h.handle_ ), | |
| destructor_(h.destructor_) | | destructor_(h.destructor_) | |
| { | | { | |
| const_cast<HDF5Handle &>(h).handle_ = 0; | | const_cast<HDF5Handle &>(h).handle_ = 0; | |
| } | | } | |
| | | | |
| /** \brief Assignment. | | /** \brief Assignment. | |
| Calls close() for the LHS handle and hands over ownership of th
e | | Calls close() for the LHS handle and hands over ownership of th
e | |
|
| RHS handle (analogous to std::auto_ptr). | | RHS handle (analogous to VIGRA_UNIQUE_PTR). | |
| */ | | */ | |
| HDF5Handle & operator=(HDF5Handle const & h) | | HDF5Handle & operator=(HDF5Handle const & h) | |
| { | | { | |
| if(h.handle_ != handle_) | | if(h.handle_ != handle_) | |
| { | | { | |
| close(); | | close(); | |
| handle_ = h.handle_; | | handle_ = h.handle_; | |
| destructor_ = h.destructor_; | | destructor_ = h.destructor_; | |
| const_cast<HDF5Handle &>(h).handle_ = 0; | | const_cast<HDF5Handle &>(h).handle_ = 0; | |
| } | | } | |
| | | | |
| skipping to change at line 312 | | skipping to change at line 314 | |
| | | | |
| /** Get a handle to the dataset represented by this info object. | | /** Get a handle to the dataset represented by this info object. | |
| */ | | */ | |
| VIGRA_EXPORT hid_t getDatasetHandle() const; | | VIGRA_EXPORT hid_t getDatasetHandle() const; | |
| | | | |
| /** Get the number of dimensions of the dataset represented by this
info object. | | /** Get the number of dimensions of the dataset represented by this
info object. | |
| */ | | */ | |
| VIGRA_EXPORT MultiArrayIndex numDimensions() const; | | VIGRA_EXPORT MultiArrayIndex numDimensions() const; | |
| | | | |
| /** Get the shape of the dataset represented by this info object. | | /** Get the shape of the dataset represented by this info object. | |
|
| | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This function therefore | |
| | | reverses the axis | |
| | | order relative to the file contents. That is, when the axes in | |
| | | the file are | |
| | | ordered as 'z', 'y', 'x', this function will return the shape i | |
| | | n the order | |
| | | 'x', 'y', 'z'. | |
| */ | | */ | |
| VIGRA_EXPORT ArrayVector<hsize_t> const & shape() const | | VIGRA_EXPORT ArrayVector<hsize_t> const & shape() const | |
| { | | { | |
| return m_dims; | | return m_dims; | |
| } | | } | |
| | | | |
| /** Get the shape (length) of the dataset along dimension \a dim. | | /** Get the shape (length) of the dataset along dimension \a dim. | |
|
| | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This function therefore | |
| | | reverses the axis | |
| | | order relative to the file contents. That is, when the axes in | |
| | | the file are | |
| | | ordered as 'z', 'y', 'x', this function will return the shape i | |
| | | n the order | |
| | | 'x', 'y', 'z'. | |
| */ | | */ | |
| VIGRA_EXPORT MultiArrayIndex shapeOfDimension(const int dim) const; | | VIGRA_EXPORT MultiArrayIndex shapeOfDimension(const int dim) const; | |
| | | | |
| /** Query the pixel type of the dataset. | | /** Query the pixel type of the dataset. | |
| | | | |
| Possible values are: | | Possible values are: | |
| <DL> | | <DL> | |
| <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char) | | <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char) | |
| <DT>"INT16"<DD> 16-bit signed integer (short) | | <DT>"INT16"<DD> 16-bit signed integer (short) | |
| <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) | | <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) | |
| | | | |
| skipping to change at line 473 | | skipping to change at line 487 | |
| | | | |
| /** \brief Access to HDF5 files | | /** \brief Access to HDF5 files | |
| | | | |
| HDF5File provides a convenient way of accessing data in HDF5 files. vigra::
MultiArray | | HDF5File provides a convenient way of accessing data in HDF5 files. vigra::
MultiArray | |
| structures of any dimension can be stored to / loaded from HDF5 files. Typi
cal | | structures of any dimension can be stored to / loaded from HDF5 files. Typi
cal | |
| HDF5 features like subvolume access, chunks and data compression are availa
ble, | | HDF5 features like subvolume access, chunks and data compression are availa
ble, | |
| string attributes can be attached to any dataset or group. Group- or datase
t-handles | | string attributes can be attached to any dataset or group. Group- or datase
t-handles | |
| are encapsulated in the class and managed automatically. The internal file-
system like | | are encapsulated in the class and managed automatically. The internal file-
system like | |
| structure can be accessed by functions like "cd()" or "mkdir()". | | structure can be accessed by functions like "cd()" or "mkdir()". | |
| | | | |
|
| | | Note that the memory order between VIGRA and HDF5 files differs: VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA MultiArray, | |
| | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that order, is reve | |
| | | rsed | |
| | | upon writing to an HDF5 file, i.e. in the file the axis order is 'z', 'y', | |
| | | 'x'. | |
| | | Likewise, the order is reversed upon reading. | |
| | | | |
| <b>Example:</b> | | <b>Example:</b> | |
| Write the MultiArray out_multi_array to file. Change the current directory
to | | Write the MultiArray out_multi_array to file. Change the current directory
to | |
| "/group" and read in the same MultiArray as in_multi_array. | | "/group" and read in the same MultiArray as in_multi_array. | |
| \code | | \code | |
| HDF5File file("/path/to/file",HDF5File::New); | | HDF5File file("/path/to/file",HDF5File::New); | |
| file.mkdir("group"); | | file.mkdir("group"); | |
| file.write("/group/dataset", out_multi_array); | | file.write("/group/dataset", out_multi_array); | |
| | | | |
| file.cd("/group"); | | file.cd("/group"); | |
| file.read("dataset", in_multi_array); | | file.read("dataset", in_multi_array); | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | | <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| class HDF5File | | class HDF5File | |
| { | | { | |
|
| private: | | protected: | |
| HDF5Handle fileHandle_; | | HDF5Handle fileHandle_; | |
| | | | |
| // current group handle | | // current group handle | |
| HDF5Handle cGroupHandle_; | | HDF5Handle cGroupHandle_; | |
| | | | |
|
| | | private: | |
| // time tagging of datasets, turned off (= 0) by default. | | // time tagging of datasets, turned off (= 0) by default. | |
| int track_time; | | int track_time; | |
| | | | |
| // helper class for ls() | | // helper class for ls() | |
| struct ls_closure | | struct ls_closure | |
| { | | { | |
| virtual void insert(const std::string &) = 0; | | virtual void insert(const std::string &) = 0; | |
| virtual ~ls_closure() {} | | virtual ~ls_closure() {} | |
| }; | | }; | |
| // datastructure to hold a list of dataset and group names | | // datastructure to hold a list of dataset and group names | |
| | | | |
| skipping to change at line 530 | | skipping to change at line 551 | |
| Container & objects; | | Container & objects; | |
| ls_container_data(Container & o) : objects(o) {} | | ls_container_data(Container & o) : objects(o) {} | |
| void insert(const std::string & x) | | void insert(const std::string & x) | |
| { | | { | |
| objects.insert(std::string(x)); | | objects.insert(std::string(x)); | |
| } | | } | |
| }; | | }; | |
| | | | |
| public: | | public: | |
| | | | |
|
| // helper for callback HDF5_ls_inserter_callback(), used by ls() | | // helper for callback HDF5_ls_inserter_callback(), used by ls() | |
| friend void HDF5_ls_insert(void*, const std::string &); | | friend void HDF5_ls_insert(void*, const std::string &); | |
| | | | |
|
| /** \brief Set how a file is opened. | | /** \brief Set how a file is opened. | |
| OpenMode::New creates a new file. If the file already exists, overwri | | | |
| te it. | | | |
| | | | |
|
| OpenMode::Open opens a file for reading/writing. The file will be cre | | OpenMode::New creates a new file. If the file already exists, o | |
| ated, | | verwrite it. | |
| if necessary. | | | |
| */ | | OpenMode::Open opens a file for reading/writing. The file will | |
| | | be created, | |
| | | if necessary. | |
| | | */ | |
| enum OpenMode { | | enum OpenMode { | |
| New, // Create new empty file (existing file will be dele
ted). | | New, // Create new empty file (existing file will be dele
ted). | |
|
| Open // Open file. Create if not existing. | | Open, // Open file. Create if not existing. | |
| | | OpenReadOnly // Open file in read-only mode. | |
| }; | | }; | |
| | | | |
|
| /** \brief Create an HDF5File object. | | /** \brief Default constructor. | |
| | | | |
| | | A file can later be opened via the open() function. | |
| | | | |
|
| Creates or opens HDF5 file at position filename. The current group is s | | If \a track_creation_times is non-zero, time tagging of datasets wi | |
| et | | ll be enabled (it is disabled | |
| to "/". | | by default). | |
| */ | | */ | |
| | | HDF5File(int track_creation_times = 0) | |
| | | : track_time(track_creation_times) | |
| | | {} | |
| | | | |
| | | /** \brief Open or create an HDF5File object. | |
| | | | |
| | | Creates or opens HDF5 file with given filename. | |
| | | The current group is set to "/". | |
| | | | |
| | | Note that the HDF5File class is not copyable (the copy constructor | |
| | | is | |
| | | private to enforce this). | |
| | | */ | |
| HDF5File(std::string filename, OpenMode mode, int track_creation_times
= 0) | | HDF5File(std::string filename, OpenMode mode, int track_creation_times
= 0) | |
| : track_time(track_creation_times) | | : track_time(track_creation_times) | |
| { | | { | |
|
| std::string errorMessage = "HDF5File: Could not create file '" + fi | | open(filename, mode); | |
| lename + "'."; | | | |
| fileHandle_ = HDF5Handle(createFile_(filename, mode), &H5Fclose, er | | | |
| rorMessage.c_str()); | | | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_("/"), &H5Gclose, "HDF5F | | | |
| ile(): Failed to open root group."); | | | |
| } | | } | |
| | | | |
|
| /** \brief Destructor to make sure that all data is flushed before clos | | /** \brief The destructor flushes and closes the file. | |
| ing the file. | | */ | |
| */ | | | |
| ~HDF5File() | | ~HDF5File() | |
| { | | { | |
|
| //Write everything to disk before closing | | // The members fileHandle_ and cGroupHandle_ are automatically clos | |
| H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); | | ed | |
| | | // as they are of type HDF5Handle and are properly initialised. | |
| | | // The closing of fileHandle_ implies flushing the file to | |
| | | // the operating system, see | |
| | | // http://www.hdfgroup.org/HDF5/doc/RM/RM_H5F.html#File-Close . | |
| } | | } | |
| | | | |
|
| /** \brief Change current group to "/". | | // copying is not permitted. | |
| */ | | private: | |
| | | HDF5File(const HDF5File &); | |
| | | void operator=(const HDF5File &); | |
| | | | |
| | | public: | |
| | | | |
| | | /** \brief Open or create the given file in the given mode and set | |
| | | the group to "/". | |
| | | If another file is currently open, it is first closed. | |
| | | */ | |
| | | void open(std::string filename, OpenMode mode) | |
| | | { | |
| | | close(); | |
| | | | |
| | | std::string errorMessage = "HDF5File.open(): Could not open or crea | |
| | | te file '" + filename + "'."; | |
| | | fileHandle_ = HDF5Handle(createFile_(filename, mode), &H5Fclose, er | |
| | | rorMessage.c_str()); | |
| | | cGroupHandle_ = HDF5Handle(openCreateGroup_("/"), &H5Gclose, "HDF5F | |
| | | ile.open(): Failed to open root group."); | |
| | | } | |
| | | | |
| | | /** \brief Close the current file. | |
| | | */ | |
| | | void close() | |
| | | { | |
| | | bool success = cGroupHandle_.close() >= 0 && fileHandle_.close() >= | |
| | | 0; | |
| | | vigra_postcondition(success, "HDF5File.close() failed."); | |
| | | } | |
| | | | |
| | | /** \brief Change current group to "/". | |
| | | */ | |
| inline void root() | | inline void root() | |
| { | | { | |
| std::string message = "HDF5File::root(): Could not open group '/'."
; | | std::string message = "HDF5File::root(): Could not open group '/'."
; | |
| cGroupHandle_ = HDF5Handle(H5Gopen(fileHandle_, "/", H5P_DEFAULT),&
H5Gclose,message.c_str()); | | cGroupHandle_ = HDF5Handle(H5Gopen(fileHandle_, "/", H5P_DEFAULT),&
H5Gclose,message.c_str()); | |
| } | | } | |
| | | | |
|
| /** \brief Change the current group. | | /** \brief Change the current group. | |
| Both absolute and relative group names are allowed. | | Both absolute and relative group names are allowed. | |
| */ | | */ | |
| inline void cd(std::string groupName) | | inline void cd(std::string groupName) | |
| { | | { | |
| std::string message = "HDF5File::cd(): Could not open group '" + gr
oupName + "'.\n"; | | std::string message = "HDF5File::cd(): Could not open group '" + gr
oupName + "'.\n"; | |
| | | | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
|
| if(groupName == "/"){ | | if(groupName == "/") | |
| | | { | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_("/"),&H5Gclose,mess
age.c_str()); | | cGroupHandle_ = HDF5Handle(openCreateGroup_("/"),&H5Gclose,mess
age.c_str()); | |
|
| return; | | | |
| } | | } | |
|
| else{ | | else | |
| if (H5Lexists(fileHandle_, groupName.c_str(), H5P_DEFAULT) == 0 | | { | |
| ) | | vigra_precondition(H5Lexists(fileHandle_, groupName.c_str(), H5 | |
| { | | P_DEFAULT) != 0, message); | |
| std::cerr << message; | | | |
| return; | | | |
| } | | | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName),&H5Gclos
e,message.c_str()); | | cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName),&H5Gclos
e,message.c_str()); | |
| } | | } | |
| } | | } | |
| | | | |
|
| /** \brief Change the current group to its parent group. | | /** \brief Change the current group to its parent group. | |
| returns true if successful, false otherwise. | | Returns true if successful, false otherwise. If unsuccessful, | |
| */ | | the group will not change. | |
| | | */ | |
| inline bool cd_up() | | inline bool cd_up() | |
| { | | { | |
| std::string groupName = currentGroupName_(); | | std::string groupName = currentGroupName_(); | |
| | | | |
| //do not try to move up if we already in "/" | | //do not try to move up if we already in "/" | |
| if(groupName == "/"){ | | if(groupName == "/"){ | |
| return false; | | return false; | |
| } | | } | |
| | | | |
| size_t lastSlash = groupName.find_last_of('/'); | | size_t lastSlash = groupName.find_last_of('/'); | |
| | | | |
| std::string parentGroup (groupName.begin(), groupName.begin()+lastS
lash+1); | | std::string parentGroup (groupName.begin(), groupName.begin()+lastS
lash+1); | |
| | | | |
| cd(parentGroup); | | cd(parentGroup); | |
| | | | |
| return true; | | return true; | |
| } | | } | |
|
| inline void cd_up(int levels) | | | |
| | | /** \brief Change the current group to its parent group. | |
| | | Returns true if successful, false otherwise. If unsuccessful, | |
| | | the group will not change. | |
| | | */ | |
| | | inline bool cd_up(int levels) | |
| { | | { | |
|
| | | std::string groupName = currentGroupName_(); | |
| | | | |
| for(int i = 0; i<levels; i++) | | for(int i = 0; i<levels; i++) | |
|
| cd_up(); | | { | |
| | | if(!cd_up()) | |
| | | { | |
| | | // restore old group if neccessary | |
| | | if(groupName != currentGroupName_()) | |
| | | cd(groupName); | |
| | | return false; | |
| | | } | |
| | | } | |
| | | return true; | |
| } | | } | |
| | | | |
|
| /** \brief Create a new group. | | /** \brief Create a new group. | |
| If the first character is a "/", the path will be interpreted as abso | | If the first character is a "/", the path will be interpreted | |
| lute path, | | as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curre | |
| p. | | nt group. | |
| */ | | */ | |
| inline void mkdir(std::string groupName) | | inline void mkdir(std::string groupName) | |
| { | | { | |
|
| | | std::string message = "HDF5File::mkdir(): Could not create group '" | |
| | | + groupName + "'.\n"; | |
| | | | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
|
| hid_t handle = openCreateGroup_(groupName.c_str()); | | HDF5Handle(openCreateGroup_(groupName.c_str()),&H5Gclose,message.c_ | |
| if (handle != cGroupHandle_){ | | str()); | |
| H5Gclose(handle); | | | |
| } | | | |
| } | | } | |
| | | | |
|
| /** \brief Change the current group; create it if necessary. | | /** \brief Change the current group; create it if necessary. | |
| If the first character is a "/", the path will be interpreted as abso | | If the first character is a "/", the path will be interpreted | |
| lute path, | | as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curre | |
| p. | | nt group. | |
| */ | | */ | |
| inline void cd_mk(std::string groupName) | | inline void cd_mk(std::string groupName) | |
| { | | { | |
|
| | | std::string message = "HDF5File::cd_mk(): Could not create group ' | |
| | | " + groupName + "'."; | |
| | | | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
|
| std::string message = "HDF5File::cd_mk(): Could not create group '
" + groupName + "'."; | | | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName.c_str()),&H5G
close,message.c_str()); | | cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName.c_str()),&H5G
close,message.c_str()); | |
| } | | } | |
| | | | |
|
| // helper function for the various ls() variants. | | // helper function for the various ls() variants. | |
| void ls_H5Literate(ls_closure & data) | | void ls_H5Literate(ls_closure & data) const | |
| { | | { | |
| H5Literate(cGroupHandle_, H5_INDEX_NAME, H5_ITER_NATIVE, NULL, | | H5Literate(cGroupHandle_, H5_INDEX_NAME, H5_ITER_NATIVE, NULL, | |
| HDF5_ls_inserter_callback, static_cast<void*>(&data)); | | HDF5_ls_inserter_callback, static_cast<void*>(&data)); | |
| } | | } | |
| | | | |
|
| /** \brief List the contents of the current group. | | /** \brief List the contents of the current group. | |
| The function returns a vector of strings holding the entries of the | | The function returns a vector of strings holding the entries of | |
| current group. Only datasets and groups are listed, other objects | | the | |
| (e.g. datatypes) are ignored. Group names always have an ending "/". | | current group. Only datasets and groups are listed, other objec | |
| */ | | ts | |
| /** | | (e.g. datatypes) are ignored. Group names always have a trailin | |
| * | | g "/". | |
| */ | | */ | |
| inline std::vector<std::string> ls() | | inline std::vector<std::string> ls() const | |
| { | | { | |
| std::vector<std::string> list; | | std::vector<std::string> list; | |
| lsOpData data(list); | | lsOpData data(list); | |
| ls_H5Literate(data); | | ls_H5Literate(data); | |
| return list; | | return list; | |
| } | | } | |
| | | | |
|
| /** \brief List the contents of the current group into a container-like | | /** \brief List the contents of the current group into a container- | |
| object via insert(). Only datasets and groups are inserted, | | like | |
| other | | object via insert(). | |
| objects (e.g., datatypes) are ignored. Group names always ha | | | |
| ve an | | Only datasets and groups are inserted, other objects (e.g., dat | |
| ending "/". | | atypes) are ignored. | |
| | | Group names always have a trailing "/". | |
| The argument cont is presumably an associative container, however, | | | |
| only its member function <tt>cont.insert(std::string)</tt> will be | | The argument cont is presumably an associative container, howev | |
| called. | | er, | |
| \param cont reference to a container supplying a member functi | | only its member function <tt>cont.insert(std::string)</tt> will | |
| on | | be | |
| <tt>insert(const i_type &)</tt>, where <tt>i_type< | | called. | |
| /tt> | | \param cont reference to a container supplying a member fu | |
| is convertible to <tt>std::string</tt>. | | nction | |
| */ | | <tt>insert(const i_type &)</tt>, where <tt>i_t | |
| | | ype</tt> | |
| | | is convertible to <tt>std::string</tt>. | |
| | | */ | |
| template<class Container> | | template<class Container> | |
|
| void ls(Container & cont) | | void ls(Container & cont) const | |
| { | | { | |
| ls_container_data<Container> data(cont); | | ls_container_data<Container> data(cont); | |
| ls_H5Literate(data); | | ls_H5Literate(data); | |
| } | | } | |
| | | | |
|
| /** \brief Get the path of the current group. | | /** \brief Get the path of the current group. | |
| */ | | */ | |
| inline std::string pwd() | | inline std::string pwd() const | |
| { | | { | |
| return currentGroupName_(); | | return currentGroupName_(); | |
| } | | } | |
| | | | |
|
| /** \brief Get the name of the associated file. | | /** \brief Get the name of the associated file. | |
| */ | | */ | |
| inline std::string filename() | | inline std::string filename() const | |
| { | | { | |
| return fileName_(); | | return fileName_(); | |
| } | | } | |
| | | | |
|
| /** \brief Get the number of dimensions of a certain dataset | | /** \brief Get the number of dimensions of a certain dataset | |
| If the first character is a "/", the path will be interpreted as abso | | If the first character is a "/", the path will be interpreted | |
| lute path, | | as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curre | |
| p. | | nt group. | |
| */ | | */ | |
| inline hssize_t getDatasetDimensions(std::string datasetName) | | inline hssize_t getDatasetDimensions(std::string datasetName) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| //Open dataset and dataspace | | //Open dataset and dataspace | |
| std::string errorMessage = "HDF5File::getDatasetDimensions(): Unabl
e to open dataset '" + datasetName + "'."; | | std::string errorMessage = "HDF5File::getDatasetDimensions(): Unabl
e to open dataset '" + datasetName + "'."; | |
| HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName
), &H5Dclose, errorMessage.c_str()); | | HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName
), &H5Dclose, errorMessage.c_str()); | |
| | | | |
| errorMessage = "HDF5File::getDatasetDimensions(): Unable to access
dataspace."; | | errorMessage = "HDF5File::getDatasetDimensions(): Unable to access
dataspace."; | |
| HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose,
errorMessage.c_str()); | | HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose,
errorMessage.c_str()); | |
| | | | |
| //return dimension information | | //return dimension information | |
| return H5Sget_simple_extent_ndims(dataspaceHandle); | | return H5Sget_simple_extent_ndims(dataspaceHandle); | |
| } | | } | |
| | | | |
|
| /** \brief Get the shape of each dimension of a certain dataset. | | /** \brief Get the shape of each dimension of a certain dataset. | |
| Normally, this function is called after determining the dimension of | | | |
| the | | Normally, this function is called after determining the dimensio | |
| dataset using \ref getDatasetDimensions(). | | n of the | |
| If the first character is a "/", the path will be interpreted as abso | | dataset using \ref getDatasetDimensions(). | |
| lute path, | | If the first character is a "/", the path will be interpreted a | |
| otherwise it will be interpreted as path relative to the current grou | | s absolute path, | |
| p. | | otherwise it will be interpreted as path relative to the curren | |
| */ | | t group. | |
| | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This function therefore | |
| | | reverses the axis | |
| | | order relative to the file contents. That is, when the axes in | |
| | | the file are | |
| | | ordered as 'z', 'y', 'x', this function will return the shape i | |
| | | n the order | |
| | | 'x', 'y', 'z'. | |
| | | */ | |
| inline ArrayVector<hsize_t> getDatasetShape(std::string datasetName) | | inline ArrayVector<hsize_t> getDatasetShape(std::string datasetName) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| //Open dataset and dataspace | | //Open dataset and dataspace | |
| std::string errorMessage = "HDF5File::getDatasetShape(): Unable to
open dataset '" + datasetName + "'."; | | std::string errorMessage = "HDF5File::getDatasetShape(): Unable to
open dataset '" + datasetName + "'."; | |
| HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName
), &H5Dclose, errorMessage.c_str()); | | HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName
), &H5Dclose, errorMessage.c_str()); | |
| | | | |
| errorMessage = "HDF5File::getDatasetShape(): Unable to access datas
pace."; | | errorMessage = "HDF5File::getDatasetShape(): Unable to access datas
pace."; | |
| HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose,
errorMessage.c_str()); | | HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose,
errorMessage.c_str()); | |
| | | | |
| //get dimension information | | //get dimension information | |
| ArrayVector<hsize_t>::size_type dimensions = H5Sget_simple_extent_n
dims(dataspaceHandle); | | ArrayVector<hsize_t>::size_type dimensions = H5Sget_simple_extent_n
dims(dataspaceHandle); | |
| | | | |
| ArrayVector<hsize_t> shape(dimensions); | | ArrayVector<hsize_t> shape(dimensions); | |
| ArrayVector<hsize_t> maxdims(dimensions); | | ArrayVector<hsize_t> maxdims(dimensions); | |
| H5Sget_simple_extent_dims(dataspaceHandle, shape.data(), maxdims.da
ta()); | | H5Sget_simple_extent_dims(dataspaceHandle, shape.data(), maxdims.da
ta()); | |
| | | | |
|
| // invert the dimensions to guarantee c-order | | // invert the dimensions to guarantee VIGRA-compatible order. | |
| ArrayVector<hsize_t> shape_inv(dimensions); | | std::reverse(shape.begin(), shape.end()); | |
| for(ArrayVector<hsize_t>::size_type i=0; i<shape.size(); i++) { | | return shape; | |
| shape_inv[i] = shape[dimensions-1-i]; | | | |
| } | | | |
| | | | |
| return shape_inv; | | | |
| } | | } | |
| | | | |
|
| /** \brief Obtain the HDF5 handle of a dataset. | | /** \brief Obtain the HDF5 handle of a dataset. | |
| */ | | */ | |
| inline hid_t getDatasetHandle(std::string dataset_name) | | inline HDF5Handle getDatasetHandle(std::string dataset_name) | |
| { | | { | |
|
| return getDatasetHandle_(dataset_name); | | std::string errorMessage = "HDF5File::getDatasetHandle(): Unable to | |
| | | open dataset '" + dataset_name + "'."; | |
| | | return HDF5Handle(getDatasetHandle_(dataset_name), &H5Dclose, error | |
| | | Message.c_str()); | |
| } | | } | |
| | | | |
|
| /** \brief Obtain the HDF5 handle of a group. | | /** \brief Obtain the HDF5 handle of a group. | |
| */ | | */ | |
| inline hid_t getGroupHandle(std::string group_name) | | inline HDF5Handle getGroupHandle(std::string group_name) | |
| { | | { | |
|
| | | std::string errorMessage = "HDF5File::getGroupHandle(): Group '" + | |
| | | group_name + "' not found."; | |
| | | | |
| // make group_name clean | | // make group_name clean | |
| group_name = get_absolute_path(group_name); | | group_name = get_absolute_path(group_name); | |
| | | | |
| // group must exist | | // group must exist | |
|
| vigra_precondition((H5Lexists(fileHandle_, group_name.c_str(), H5P_ | | vigra_precondition(H5Lexists(fileHandle_, group_name.c_str(), H5P_D | |
| DEFAULT) == 1), "Error: Group '" + group_name + "' does not exist."); | | EFAULT) == 1, | |
| | | errorMessage.c_str()); | |
| | | | |
|
| //open group and return group handle | | // open group and return group handle | |
| return openCreateGroup_( group_name); | | return HDF5Handle(openCreateGroup_(group_name), &H5Gclose, "Interna | |
| | | l error"); | |
| } | | } | |
| | | | |
|
| /** \brief Obtain the HDF5 handle of a attribute. | | /** \brief Obtain the HDF5 handle of a attribute. | |
| */ | | */ | |
| inline hid_t getAttributeHandle(std::string dataset_name, std::string a | | inline HDF5Handle getAttributeHandle(std::string dataset_name, std::str | |
| ttribute_name) | | ing attribute_name) | |
| { | | { | |
|
| HDF5Handle dset (getDatasetHandle_(dataset_name),&H5Dclose,std::str | | std::string message = "HDF5File::getAttributeHandle(): Attribute '" | |
| ing("Error: Dataset '"+dataset_name+"' not found.").c_str()); | | + attribute_name + "' not found."; | |
| | | return HDF5Handle(H5Aopen(getDatasetHandle(dataset_name), attribute | |
| return H5Aopen(dset, attribute_name.c_str(),H5P_DEFAULT); | | _name.c_str(), H5P_DEFAULT), | |
| | | &H5Aclose, message.c_str()); | |
| } | | } | |
| | | | |
| /* Writing Attributes */ | | /* Writing Attributes */ | |
| | | | |
|
| /** \brief Write MultiArray Attributes. | | /** \brief Write MultiArray Attributes. | |
| * In contrast to datasets, subarray access, chunks and compression ar | | * In contrast to datasets, subarray access, chunks and compressio | |
| e not available. | | n are not available. | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeAttribute(std::string object_name, std::string attribu
te_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) | | inline void writeAttribute(std::string object_name, std::string attribu
te_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) | |
| { | | { | |
| // make object_name clean | | // make object_name clean | |
| object_name = get_absolute_path(object_name); | | object_name = get_absolute_path(object_name); | |
| | | | |
| write_attribute_(object_name, attribute_name, array, detail::getH5D
ataType<T>(), 1); | | write_attribute_(object_name, attribute_name, array, detail::getH5D
ataType<T>(), 1); | |
| } | | } | |
| | | | |
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE> | |
| | | | |
| skipping to change at line 823 | | skipping to change at line 907 | |
| | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 3); | | write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 3); | |
| } | | } | |
| | | | |
|
| /** \brief Write a single value. | | /** \brief Write a single value. | |
| Specialization of the write function for simple datatypes | | Specialization of the write function for simple datatypes | |
| */ | | */ | |
| inline void writeAttribute(std::string object_name, std::string attribu
te_name, char data) | | inline void writeAttribute(std::string object_name, std::string attribu
te_name, char data) | |
| { writeAtomicAttribute(object_name,attribute_name,data); } | | { writeAtomicAttribute(object_name,attribute_name,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed char data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed char data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed short data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed short data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed int data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed int data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed long data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, signed long data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| | | | |
| skipping to change at line 859 | | skipping to change at line 943 | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, double data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, double data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, long double data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, long double data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, const char* data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, const char* data) | |
| { writeAtomicAttribute(datasetName,attributeName,data); } | | { writeAtomicAttribute(datasetName,attributeName,data); } | |
| inline void writeAttribute(std::string datasetName, std::string attribu
teName, std::string const & data) | | inline void writeAttribute(std::string datasetName, std::string attribu
teName, std::string const & data) | |
| { writeAtomicAttribute(datasetName,attributeName,data.c_str()); } | | { writeAtomicAttribute(datasetName,attributeName,data.c_str()); } | |
| | | | |
|
| /** \brief Test if attribute exists. | | /** \brief Test if attribute exists. | |
| | | */ | |
| */ | | | |
| bool existsAttribute(std::string object_name, std::string attribute_nam
e) | | bool existsAttribute(std::string object_name, std::string attribute_nam
e) | |
| { | | { | |
| std::string obj_path = get_absolute_path(object_name); | | std::string obj_path = get_absolute_path(object_name); | |
| htri_t exists = H5Aexists_by_name(fileHandle_, obj_path.c_str(), | | htri_t exists = H5Aexists_by_name(fileHandle_, obj_path.c_str(), | |
| attribute_name.c_str(), H5P_DEFAU
LT); | | attribute_name.c_str(), H5P_DEFAU
LT); | |
| vigra_precondition(exists >= 0, "HDF5File::existsAttribute(): " | | vigra_precondition(exists >= 0, "HDF5File::existsAttribute(): " | |
|
| "object \"" + object_name + "\" " | | "object '" + object_name + "' " | |
| "not found."); | | "not found."); | |
| return exists != 0; | | return exists != 0; | |
| } | | } | |
| | | | |
| // Reading Attributes | | // Reading Attributes | |
| | | | |
|
| /** \brief Read MultiArray Attributes. | | /** \brief Read MultiArray Attributes. | |
| * In contrast to datasets, subarray access is not available. | | * In contrast to datasets, subarray access is not available. | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readAttribute(std::string object_name, std::string attribut
e_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) | | inline void readAttribute(std::string object_name, std::string attribut
e_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) | |
| { | | { | |
| // make object_name clean | | // make object_name clean | |
| object_name = get_absolute_path(object_name); | | object_name = get_absolute_path(object_name); | |
| | | | |
| read_attribute_(object_name, attribute_name, array, detail::getH5Da
taType<T>(), 1); | | read_attribute_(object_name, attribute_name, array, detail::getH5Da
taType<T>(), 1); | |
| } | | } | |
| | | | |
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE> | |
| | | | |
| skipping to change at line 905 | | skipping to change at line 988 | |
| | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), 3); | | read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), 3); | |
| } | | } | |
| | | | |
|
| /** \brief Read a single value. | | /** \brief Read a single value. | |
| Specialization of the read function for simple datatypes | | Specialization of the read function for simple datatypes | |
| */ | | */ | |
| inline void readAttribute(std::string object_name, std::string attribut
e_name, char &data) | | inline void readAttribute(std::string object_name, std::string attribut
e_name, char &data) | |
| { readAtomicAttribute(object_name,attribute_name,data); } | | { readAtomicAttribute(object_name,attribute_name,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, signed char &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, signed char &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, signed short &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, signed short &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, signed int &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, signed int &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, signed long &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, signed long &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| | | | |
| skipping to change at line 941 | | skipping to change at line 1024 | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, double &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, double &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, long double &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, long double &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, std::string &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, std::string &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| | | | |
| // Writing data | | // Writing data | |
| | | | |
|
| /** \brief Write multi arrays. | | /** \brief Write multi arrays. | |
| | | | |
| | | Chunks can be activated by setting | |
| | | \code iChunkSize = size; //size \> 0 | |
| | | \endcode . | |
| | | The chunks will be hypercubes with edge length size. | |
| | | | |
| | | Compression can be activated by setting | |
| | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| | | \endcode | |
| | | where 0 stands for no compression and 9 for maximum compression | |
| | | . | |
| | | | |
| | | If the first character of datasetName is a "/", the path will b | |
| | | e interpreted as absolute path, | |
| | | otherwise it will be interpreted as path relative to the curren | |
| | | t group. | |
| | | | |
|
| Chunks can be activated by setting | | Note that the memory order between VIGRA and HDF5 files differs | |
| \code iChunkSize = size; //size \> 0 | | : VIGRA uses | |
| \endcode . | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA | |
| The chunks will be hypercubes with edge length size. | | MultiArray, | |
| | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or | |
| Compression can be activated by setting | | der, is reversed | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | upon writing to an HDF5 file, i.e. in the file the axis order i | |
| \endcode | | s 'z', 'y', 'x'. | |
| where 0 stands for no compression and 9 for maximum compression. | | */ | |
| | | | |
| If the first character of datasetName is a "/", the path will be inte | | | |
| rpreted as absolute path, | | | |
| otherwise it will be interpreted as path relative to the current grou | | | |
| p. | | | |
| */ | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void write(std::string datasetName, const MultiArrayView<N, T, U
nstridedArrayTag> & array, int iChunkSize = 0, int compression = 0) | | inline void write(std::string datasetName, const MultiArrayView<N, T, U
nstridedArrayTag> & array, int iChunkSize = 0, int compression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<N>::type chunkSize; | | typename MultiArrayShape<N>::type chunkSize; | |
|
| for(int i = 0; i < N; i++){ | | for(unsigned int i = 0; i < N; i++){ | |
| chunkSize[i] = iChunkSize; | | chunkSize[i] = iChunkSize; | |
| } | | } | |
| write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | |
| } | | } | |
| | | | |
|
| /** \brief Write multi arrays. | | /** \brief Write multi arrays. | |
| Chunks can be activated by providing a MultiArrayShape as chunkSize. | | Chunks can be activated by providing a MultiArrayShape as chunk | |
| chunkSize must have equal dimension as array. | | Size. | |
| | | chunkSize must have equal dimension as array. | |
| Compression can be activated by setting | | | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | Compression can be activated by setting | |
| \endcode | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| where 0 stands for no compression and 9 for maximum compression. | | \endcode | |
| | | where 0 stands for no compression and 9 for maximum compression | |
| If the first character of datasetName is a "/", the path will be inte | | . | |
| rpreted as absolute path, | | | |
| otherwise it will be interpreted as path relative to the current grou | | If the first character of datasetName is a "/", the path will b | |
| p. | | e interpreted as absolute path, | |
| */ | | otherwise it will be interpreted as path relative to the curren | |
| | | t group. | |
| | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA | |
| | | MultiArray, | |
| | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or | |
| | | der, is reversed | |
| | | upon writing to an HDF5 file, i.e. in the file the axis order i | |
| | | s 'z', 'y', 'x'. | |
| | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void write(std::string datasetName, const MultiArrayView<N, T, U
nstridedArrayTag> & array, typename MultiArrayShape<N>::type chunkSize, int
compression = 0) | | inline void write(std::string datasetName, const MultiArrayView<N, T, U
nstridedArrayTag> & array, typename MultiArrayShape<N>::type chunkSize, int
compression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | |
| } | | } | |
| | | | |
|
| /** \brief Write a multi array into a larger volume. | | /** \brief Write a multi array into a larger volume. | |
| blockOffset determines the position, where array is written. | | blockOffset determines the position, where array is written. | |
| | | | |
| | | Chunks can be activated by providing a MultiArrayShape as chunk | |
| | | Size. | |
| | | chunkSize must have equal dimension as array. | |
| | | | |
| | | Compression can be activated by setting | |
| | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| | | \endcode | |
| | | where 0 stands for no compression and 9 for maximum compression | |
| | | . | |
| | | | |
|
| Chunks can be activated by providing a MultiArrayShape as chunkSize. | | If the first character of datasetName is a "/", the path will b | |
| chunkSize must have equal dimension as array. | | e interpreted as absolute path, | |
| | | otherwise it will be interpreted as path relative to the curren | |
| | | t group. | |
| | | | |
|
| Compression can be activated by setting | | Note that the memory order between VIGRA and HDF5 files differs | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | : VIGRA uses | |
| \endcode | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA | |
| where 0 stands for no compression and 9 for maximum compression. | | MultiArray, | |
| | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or | |
| If the first character of datasetName is a "/", the path will be inte | | der, is reversed | |
| rpreted as absolute path, | | upon writing to an HDF5 file, i.e. in the file the axis order i | |
| otherwise it will be interpreted as path relative to the current grou | | s 'z', 'y', 'x'. | |
| p. | | */ | |
| */ | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeBlock(std::string datasetName, typename MultiArrayShap
e<N>::type blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & arr
ay) | | inline void writeBlock(std::string datasetName, typename MultiArrayShap
e<N>::type blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & arr
ay) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| writeBlock_(datasetName, blockOffset, array, detail::getH5DataType<
T>(), 1); | | writeBlock_(datasetName, blockOffset, array, detail::getH5DataType<
T>(), 1); | |
| } | | } | |
| | | | |
| // non-scalar (TinyVector) and unstrided multi arrays | | // non-scalar (TinyVector) and unstrided multi arrays | |
| | | | |
| skipping to change at line 1036 | | skipping to change at line 1134 | |
| | | | |
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE> | |
| inline void write(std::string datasetName, const MultiArrayView<N, Tiny
Vector<T, SIZE>, UnstridedArrayTag> & array, typename MultiArrayShape<N>::t
ype chunkSize, int compression = 0) | | inline void write(std::string datasetName, const MultiArrayView<N, Tiny
Vector<T, SIZE>, UnstridedArrayTag> & array, typename MultiArrayShape<N>::t
ype chunkSize, int compression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS
ize, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS
ize, compression); | |
| } | | } | |
| | | | |
|
| /** \brief Write array vectors. | | /** \brief Write array vectors. | |
| | | | |
| | | Compression can be activated by setting | |
| | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| | | \endcode | |
| | | where 0 stands for no compression and 9 for maximum compression | |
| | | . | |
| | | | |
|
| Compression can be activated by setting | | If the first character of datasetName is a "/", the path will b | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | e interpreted as absolute path, | |
| \endcode | | otherwise it will be interpreted as path relative to the curren | |
| where 0 stands for no compression and 9 for maximum compression. | | t group. | |
| | | */ | |
| If the first character of datasetName is a "/", the path will be inte | | | |
| rpreted as absolute path, | | | |
| otherwise it will be interpreted as path relative to the current grou | | | |
| p. | | | |
| */ | | | |
| template<class T> | | template<class T> | |
| void write(const std::string & datasetName, | | void write(const std::string & datasetName, | |
| const ArrayVectorView<T> & array, | | const ArrayVectorView<T> & array, | |
| int compression = 0) | | int compression = 0) | |
| { | | { | |
| // convert to a (trivial) MultiArrayView and forward. | | // convert to a (trivial) MultiArrayView and forward. | |
| MultiArrayShape<1>::type shape(array.size()); | | MultiArrayShape<1>::type shape(array.size()); | |
| const MultiArrayView<1, T> m_array(shape, const_cast<T*>(array.data
())); | | const MultiArrayView<1, T> m_array(shape, const_cast<T*>(array.data
())); | |
| write(datasetName, m_array, compression); | | write(datasetName, m_array, compression); | |
| } | | } | |
| | | | |
| skipping to change at line 1098 | | skipping to change at line 1196 | |
| | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeBlock(std::string datasetName, typename MultiArrayShap
e<N>::type blockOffset, const MultiArrayView<N, RGBValue<T>, UnstridedArray
Tag> & array) | | inline void writeBlock(std::string datasetName, typename MultiArrayShap
e<N>::type blockOffset, const MultiArrayView<N, RGBValue<T>, UnstridedArray
Tag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| writeBlock_(datasetName, blockOffset, array, detail::getH5DataType<
T>(), 3); | | writeBlock_(datasetName, blockOffset, array, detail::getH5DataType<
T>(), 3); | |
| } | | } | |
| | | | |
|
| /** \brief Write a single value. | | /** \brief Write a single value. | |
| Specialization of the write function for simple datatypes | | Specialization of the write function for simple datatypes | |
| */ | | */ | |
| inline void write(std::string datasetName, char data) { writeAtomic(dat
asetName,data); } | | inline void write(std::string datasetName, char data) { writeAtomic(dat
asetName,data); } | |
| inline void write(std::string datasetName, signed char data) { writeAto
mic(datasetName,data); } | | inline void write(std::string datasetName, signed char data) { writeAto
mic(datasetName,data); } | |
| inline void write(std::string datasetName, signed short data) { writeAt
omic(datasetName,data); } | | inline void write(std::string datasetName, signed short data) { writeAt
omic(datasetName,data); } | |
| inline void write(std::string datasetName, signed int data) { writeAtom
ic(datasetName,data); } | | inline void write(std::string datasetName, signed int data) { writeAtom
ic(datasetName,data); } | |
| inline void write(std::string datasetName, signed long data) { writeAto
mic(datasetName,data); } | | inline void write(std::string datasetName, signed long data) { writeAto
mic(datasetName,data); } | |
| inline void write(std::string datasetName, signed long long data) { wri
teAtomic(datasetName,data); } | | inline void write(std::string datasetName, signed long long data) { wri
teAtomic(datasetName,data); } | |
| inline void write(std::string datasetName, unsigned char data) { writeA
tomic(datasetName,data); } | | inline void write(std::string datasetName, unsigned char data) { writeA
tomic(datasetName,data); } | |
| inline void write(std::string datasetName, unsigned short data) { write
Atomic(datasetName,data); } | | inline void write(std::string datasetName, unsigned short data) { write
Atomic(datasetName,data); } | |
| inline void write(std::string datasetName, unsigned int data) { writeAt
omic(datasetName,data); } | | inline void write(std::string datasetName, unsigned int data) { writeAt
omic(datasetName,data); } | |
| inline void write(std::string datasetName, unsigned long data) { writeA
tomic(datasetName,data); } | | inline void write(std::string datasetName, unsigned long data) { writeA
tomic(datasetName,data); } | |
| inline void write(std::string datasetName, unsigned long long data) { w
riteAtomic(datasetName,data); } | | inline void write(std::string datasetName, unsigned long long data) { w
riteAtomic(datasetName,data); } | |
| inline void write(std::string datasetName, float data) { writeAtomic(da
tasetName,data); } | | inline void write(std::string datasetName, float data) { writeAtomic(da
tasetName,data); } | |
| inline void write(std::string datasetName, double data) { writeAtomic(d
atasetName,data); } | | inline void write(std::string datasetName, double data) { writeAtomic(d
atasetName,data); } | |
| inline void write(std::string datasetName, long double data) { writeAto
mic(datasetName,data); } | | inline void write(std::string datasetName, long double data) { writeAto
mic(datasetName,data); } | |
| inline void write(std::string datasetName, const char* data) { writeAto
mic(datasetName,data); } | | inline void write(std::string datasetName, const char* data) { writeAto
mic(datasetName,data); } | |
| inline void write(std::string datasetName, std::string const & data) {
writeAtomic(datasetName,data.c_str()); } | | inline void write(std::string datasetName, std::string const & data) {
writeAtomic(datasetName,data.c_str()); } | |
| | | | |
| // Reading data | | // Reading data | |
| | | | |
|
| /** \brief Read data into a multi array. | | /** \brief Read data into a multi array. | |
| If the first character of datasetName is a "/", the path will be inte | | If the first character of datasetName is a "/", the path will b | |
| rpreted as absolute path, | | e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curren | |
| p. | | t group. | |
| */ | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This means that a HDF5 | |
| | | dataset, | |
| | | whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or | |
| | | der, is reversed | |
| | | upon reading into a MultiArrayView, i.e. in the array axis orde | |
| | | r must be 'x', 'y', 'z'. | |
| | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void read(std::string datasetName, MultiArrayView<N, T, Unstride
dArrayTag> & array) | | inline void read(std::string datasetName, MultiArrayView<N, T, Unstride
dArrayTag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 1); | | read_(datasetName, array, detail::getH5DataType<T>(), 1); | |
| } | | } | |
| | | | |
|
| /** \brief Read data into a MultiArray. Resize MultiArray to the correc | | /** \brief Read data into a MultiArray. Resize MultiArray to the co | |
| t size. | | rrect size. | |
| If the first character of datasetName is a "/", the path will be inte | | If the first character of datasetName is a "/", the path will b | |
| rpreted as absolute path, | | e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curren | |
| p. | | t group. | |
| */ | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This means that a HDF5 | |
| | | dataset, | |
| | | whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or | |
| | | der, is reversed | |
| | | upon reading into a MultiArray, i.e. in the array axis order wi | |
| | | ll be 'x', 'y', 'z'. | |
| | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readAndResize(std::string datasetName, MultiArray<N, T> & a
rray) | | inline void readAndResize(std::string datasetName, MultiArray<N, T> & a
rray) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
|
| hssize_t dimensions = getDatasetDimensions(datasetName); | | | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
|
| vigra_precondition((N == MultiArrayIndex(dimensions)), // the ob
ject in the HDF5 file may have one additional dimension which we then inter
pret as the pixel type bands | | vigra_precondition(N == MultiArrayIndex(dimshape.size()), // the ob
ject in the HDF5 file may have one additional dimension which we then inter
pret as the pixel type bands | |
| "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | | "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | |
|
| typename MultiArrayShape<N>::type shape; | | | |
| | | | |
| for(int k=0; k< MultiArrayIndex(dimensions); ++k) { | | | |
| shape[k] = MultiArrayIndex(dimshape[k]); | | | |
| } | | | |
| | | | |
| // reshape target MultiArray | | // reshape target MultiArray | |
|
| | | typename MultiArrayShape<N>::type shape; | |
| | | for(int k=0; k < (int)dimshape.size(); ++k) | |
| | | shape[k] = (MultiArrayIndex)dimshape[k]; | |
| array.reshape(shape); | | array.reshape(shape); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 1); | | read_(datasetName, array, detail::getH5DataType<T>(), 1); | |
| } | | } | |
| | | | |
|
| /** \brief Read data into an array vector. | | /** \brief Read data into an array vector. | |
| If the first character of datasetName is a "/", the path will be inte | | If the first character of datasetName is a "/", the path will be | |
| rpreted as absolute path, | | interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the current | |
| p. | | group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| inline void read(const std::string & datasetName, ArrayVectorView<T> &
array) | | inline void read(const std::string & datasetName, ArrayVectorView<T> &
array) | |
| { | | { | |
| // convert to a (trivial) MultiArrayView and forward. | | // convert to a (trivial) MultiArrayView and forward. | |
| MultiArrayShape<1>::type shape(array.size()); | | MultiArrayShape<1>::type shape(array.size()); | |
| MultiArrayView<1, T> m_array(shape, (array.data())); | | MultiArrayView<1, T> m_array(shape, (array.data())); | |
| read(datasetName, m_array); | | read(datasetName, m_array); | |
| } | | } | |
| | | | |
|
| /** \brief Read data into an array vector. Resize the array vector to t | | /** \brief Read data into an array vector. Resize the array vector | |
| he correct size. | | to the correct size. | |
| If the first character of datasetName is a "/", the path will be inte | | If the first character of datasetName is a "/", the path will b | |
| rpreted as absolute path, | | e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curren | |
| p. | | t group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| inline void readAndResize(std::string datasetName, | | inline void readAndResize(std::string datasetName, | |
| ArrayVector<T> & array) | | ArrayVector<T> & array) | |
| { | | { | |
| // make dataset name clean | | // make dataset name clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
|
| hssize_t dimensions = getDatasetDimensions(datasetName); | | | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
|
| vigra_precondition((1 == MultiArrayIndex(dimensions)), | | vigra_precondition(1 == MultiArrayIndex(dimshape.size()), | |
| "HDF5File::readAndResize(): Array dimension disagrees with Data
set dimension must equal one for vigra::ArrayVector."); | | "HDF5File::readAndResize(): Array dimension disagrees with Data
set dimension must equal one for vigra::ArrayVector."); | |
|
| | | | |
| // resize target array vector | | // resize target array vector | |
| array.resize((typename ArrayVector<T>::size_type)dimshape[0]); | | array.resize((typename ArrayVector<T>::size_type)dimshape[0]); | |
| // convert to a (trivial) MultiArrayView and forward. | | // convert to a (trivial) MultiArrayView and forward. | |
| MultiArrayShape<1>::type shape(array.size()); | | MultiArrayShape<1>::type shape(array.size()); | |
| MultiArrayView<1, T> m_array(shape, (array.data())); | | MultiArrayView<1, T> m_array(shape, (array.data())); | |
| | | | |
| read_(datasetName, m_array, detail::getH5DataType<T>(), 1); | | read_(datasetName, m_array, detail::getH5DataType<T>(), 1); | |
| } | | } | |
| | | | |
|
| /** \brief Read a block of data into a multi array. | | /** \brief Read a block of data into a multi array. | |
| This function allows to read a small block out of a larger volume sto | | This function allows to read a small block out of a larger volu | |
| red | | me stored | |
| in an HDF5 dataset. | | in an HDF5 dataset. | |
| | | | |
| blockOffset determines the position of the block. | | blockOffset determines the position of the block. | |
| blockSize determines the size in each dimension of the block. | | blockSize determines the size in each dimension of the block. | |
| | | | |
| If the first character of datasetName is a "/", the path will be inte | | If the first character of datasetName is a "/", the path will b | |
| rpreted as absolute path, | | e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the curren | |
| p. | | t group. | |
| */ | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This means that a HDF5 | |
| | | dataset, | |
| | | whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or | |
| | | der, is reversed | |
| | | upon reading into a MultiArray, i.e. in the array axis order wi | |
| | | ll be 'x', 'y', 'z'. | |
| | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readBlock(std::string datasetName, typename MultiArrayShape
<N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA
rrayView<N, T, UnstridedArrayTag> & array) | | inline void readBlock(std::string datasetName, typename MultiArrayShape
<N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA
rrayView<N, T, UnstridedArrayTag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| readBlock_(datasetName, blockOffset, blockShape, array, detail::get
H5DataType<T>(), 1); | | readBlock_(datasetName, blockOffset, blockShape, array, detail::get
H5DataType<T>(), 1); | |
| } | | } | |
| | | | |
| // non-scalar (TinyVector) and unstrided target MultiArrayView | | // non-scalar (TinyVector) and unstrided target MultiArrayView | |
| | | | |
| skipping to change at line 1240 | | skipping to change at line 1350 | |
| | | | |
| // non-scalar (TinyVector) MultiArray | | // non-scalar (TinyVector) MultiArray | |
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE> | |
| inline void readAndResize(std::string datasetName, MultiArray<N, TinyVe
ctor<T, SIZE> > & array) | | inline void readAndResize(std::string datasetName, MultiArray<N, TinyVe
ctor<T, SIZE> > & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
|
| hssize_t dimensions = getDatasetDimensions(datasetName); | | | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
|
| vigra_precondition(((N+1) == MultiArrayIndex(dimensions)), // the | | vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) && | |
| object in the HDF5 file may have one additional dimension which we then int | | SIZE == dimshape[0], // the object in the HDF5 f | |
| erpret as the pixel type bands | | ile must have one additional dimension which we interpret as the pixel type | |
| | | bands | |
| "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | | "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | |
|
| typename MultiArrayShape<N>::type shape; | | | |
| | | | |
| for(int k=1; k< MultiArrayIndex(dimensions); ++k) { | | | |
| shape[k-1] = MultiArrayIndex(dimshape[k]); | | | |
| } | | | |
| | | | |
| // reshape target MultiArray | | // reshape target MultiArray | |
|
| | | typename MultiArrayShape<N>::type shape; | |
| | | for(int k=1; k < (int)dimshape.size(); ++k) | |
| | | shape[k-1] = (MultiArrayIndex)dimshape[k]; | |
| array.reshape(shape); | | array.reshape(shape); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), SIZE); | | read_(datasetName, array, detail::getH5DataType<T>(), SIZE); | |
| } | | } | |
| | | | |
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE> | |
| inline void readBlock(std::string datasetName, typename MultiArrayShape
<N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA
rrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & array) | | inline void readBlock(std::string datasetName, typename MultiArrayShape
<N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA
rrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| skipping to change at line 1285 | | skipping to change at line 1393 | |
| | | | |
| // non-scalar (RGBValue) MultiArray | | // non-scalar (RGBValue) MultiArray | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readAndResize(std::string datasetName, MultiArray<N, RGBVal
ue<T> > & array) | | inline void readAndResize(std::string datasetName, MultiArray<N, RGBVal
ue<T> > & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
|
| hssize_t dimensions = getDatasetDimensions(datasetName); | | | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
|
| vigra_precondition(((N+1) == MultiArrayIndex(dimensions)), // the | | vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) && | |
| object in the HDF5 file may have one additional dimension which we then int | | 3 == dimshape[0], // the object in the HDF5 file | |
| erpret as the pixel type bands | | must have one additional dimension which we interpret as the pixel type ba | |
| | | nds | |
| "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | | "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | |
|
| typename MultiArrayShape<N>::type shape; | | | |
| | | | |
| for(int k=1; k< MultiArrayIndex(dimensions); ++k) { | | | |
| shape[k-1] = MultiArrayIndex(dimshape[k]); | | | |
| } | | | |
| | | | |
| // reshape target MultiArray | | // reshape target MultiArray | |
|
| | | typename MultiArrayShape<N>::type shape; | |
| | | for(int k=1; k < (int)dimshape.size(); ++k) | |
| | | shape[k-1] = (MultiArrayIndex)dimshape[k]; | |
| array.reshape(shape); | | array.reshape(shape); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 3); | | read_(datasetName, array, detail::getH5DataType<T>(), 3); | |
| } | | } | |
| | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readBlock(std::string datasetName, typename MultiArrayShape
<N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA
rrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | inline void readBlock(std::string datasetName, typename MultiArrayShape
<N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA
rrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| readBlock_(datasetName, blockOffset, blockShape, array, detail::get
H5DataType<T>(), 3); | | readBlock_(datasetName, blockOffset, blockShape, array, detail::get
H5DataType<T>(), 3); | |
| } | | } | |
| | | | |
|
| /** \brief Read a single value. | | /** \brief Read a single value. | |
| Specialization of the read function for simple datatypes | | Specialization of the read function for simple datatypes | |
| */ | | */ | |
| inline void read(std::string datasetName, char &data) { readAtomic(data
setName,data); } | | inline void read(std::string datasetName, char &data) { readAtomic(data
setName,data); } | |
| inline void read(std::string datasetName, signed char &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, signed char &data) { readAtom
ic(datasetName,data); } | |
| inline void read(std::string datasetName, signed short &data) { readAto
mic(datasetName,data); } | | inline void read(std::string datasetName, signed short &data) { readAto
mic(datasetName,data); } | |
| inline void read(std::string datasetName, signed int &data) { readAtomi
c(datasetName,data); } | | inline void read(std::string datasetName, signed int &data) { readAtomi
c(datasetName,data); } | |
| inline void read(std::string datasetName, signed long &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, signed long &data) { readAtom
ic(datasetName,data); } | |
| inline void read(std::string datasetName, signed long long &data) { rea
dAtomic(datasetName,data); } | | inline void read(std::string datasetName, signed long long &data) { rea
dAtomic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned char &data) { readAt
omic(datasetName,data); } | | inline void read(std::string datasetName, unsigned char &data) { readAt
omic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned short &data) { readA
tomic(datasetName,data); } | | inline void read(std::string datasetName, unsigned short &data) { readA
tomic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned int &data) { readAto
mic(datasetName,data); } | | inline void read(std::string datasetName, unsigned int &data) { readAto
mic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned long &data) { readAt
omic(datasetName,data); } | | inline void read(std::string datasetName, unsigned long &data) { readAt
omic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned long long &data) { r
eadAtomic(datasetName,data); } | | inline void read(std::string datasetName, unsigned long long &data) { r
eadAtomic(datasetName,data); } | |
| inline void read(std::string datasetName, float &data) { readAtomic(dat
asetName,data); } | | inline void read(std::string datasetName, float &data) { readAtomic(dat
asetName,data); } | |
| inline void read(std::string datasetName, double &data) { readAtomic(da
tasetName,data); } | | inline void read(std::string datasetName, double &data) { readAtomic(da
tasetName,data); } | |
| inline void read(std::string datasetName, long double &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, long double &data) { readAtom
ic(datasetName,data); } | |
| inline void read(std::string datasetName, std::string &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, std::string &data) { readAtom
ic(datasetName,data); } | |
| | | | |
|
| /** \brief Create a new dataset. | | /** \brief Create a new dataset. | |
| This function can be used to create a dataset filled with a default v | | This function can be used to create a dataset filled with a def | |
| alue, | | ault value, | |
| for example before writing data into it using \ref writeBlock(). | | for example before writing data into it using \ref writeBlock() | |
| Attention: only atomic datatypes are provided. For spectral data, add | | . | |
| an | | Attention: only atomic datatypes are provided. For spectral dat | |
| dimension (case RGB: add one dimension of size 3). | | a, add an | |
| | | dimension (case RGB: add one dimension of size 3). | |
| shape determines the dimension and the size of the dataset. | | | |
| | | shape determines the dimension and the size of the dataset. | |
| Chunks can be activated by providing a MultiArrayShape as chunkSize. | | | |
| chunkSize must have equal dimension as array. | | Chunks can be activated by providing a MultiArrayShape as chunk | |
| | | Size. | |
| Compression can be activated by setting | | chunkSize must have equal dimension as array. | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | | |
| \endcode | | Compression can be activated by setting | |
| where 0 stands for no compression and 9 for maximum compression. | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| | | \endcode | |
| If the first character of datasetName is a "/", the path will be inte | | where 0 stands for no compression and 9 for maximum compression | |
| rpreted as absolute path, | | . | |
| otherwise it will be interpreted as path relative to the current grou | | | |
| p. | | If the first character of datasetName is a "/", the path will b | |
| */ | | e interpreted as absolute path, | |
| | | otherwise it will be interpreted as path relative to the curren | |
| | | t group. | |
| | | | |
| | | Note that the memory order between VIGRA and HDF5 files differs | |
| | | : VIGRA uses | |
| | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA | |
| | | MultiArray, | |
| | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or | |
| | | der, is reversed | |
| | | upon writing to an HDF5 file, i.e. in the file the axis order i | |
| | | s 'z', 'y', 'x'. | |
| | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
|
| inline void createDataset(std::string datasetName, typename MultiArrayS | | inline void createDataset(std::string datasetName, | |
| hape<N>::type shape, T init = T(), int iChunkSize = 0, int compressionParam | | typename MultiArrayShape<N>::type shape, | |
| eter = 0) | | T init = T(), | |
| | | int iChunkSize = 0, | |
| | | int compressionParameter = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<N>::type chunkSize; | | typename MultiArrayShape<N>::type chunkSize; | |
| for(int i = 0; i < N; i++){ | | for(int i = 0; i < N; i++){ | |
| chunkSize[i] = iChunkSize; | | chunkSize[i] = iChunkSize; | |
| } | | } | |
| createDataset<N,T>(datasetName, shape, init, chunkSize, compression
Parameter); | | createDataset<N,T>(datasetName, shape, init, chunkSize, compression
Parameter); | |
| } | | } | |
| | | | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
|
| inline void createDataset(std::string datasetName, typename MultiArrayS | | inline void createDataset(std::string datasetName, | |
| hape<N>::type shape, T init, typename MultiArrayShape<N>::type chunkSize, i | | typename MultiArrayShape<N>::type shape, | |
| nt compressionParameter = 0) | | T init, | |
| | | typename MultiArrayShape<N>::type chunkSize, | |
| | | int compressionParameter = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| std::string groupname = SplitString(datasetName).first(); | | std::string groupname = SplitString(datasetName).first(); | |
| std::string setname = SplitString(datasetName).last(); | | std::string setname = SplitString(datasetName).last(); | |
| | | | |
| hid_t parent = openCreateGroup_(groupname); | | hid_t parent = openCreateGroup_(groupname); | |
| | | | |
| // delete the dataset if it already exists | | // delete the dataset if it already exists | |
| | | | |
| skipping to change at line 1420 | | skipping to change at line 1539 | |
| H5Pset_deflate(plist, compressionParameter); | | H5Pset_deflate(plist, compressionParameter); | |
| } | | } | |
| | | | |
| //create the dataset. | | //create the dataset. | |
| HDF5Handle datasetHandle ( H5Dcreate(parent, setname.c_str(), detai
l::getH5DataType<T>(), dataspaceHandle, H5P_DEFAULT, plist, H5P_DEFAULT), | | HDF5Handle datasetHandle ( H5Dcreate(parent, setname.c_str(), detai
l::getH5DataType<T>(), dataspaceHandle, H5P_DEFAULT, plist, H5P_DEFAULT), | |
| &H5Dclose, "HDF5File::createDataset(): un
able to create dataset."); | | &H5Dclose, "HDF5File::createDataset(): un
able to create dataset."); | |
| if(parent != cGroupHandle_) | | if(parent != cGroupHandle_) | |
| H5Gclose(parent); | | H5Gclose(parent); | |
| } | | } | |
| | | | |
|
| /** \brief Immediately write all data to disk | | /** \brief Immediately write all data to disk | |
| */ | | */ | |
| inline void flushToDisk() | | inline void flushToDisk() | |
| { | | { | |
| H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); | | H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); | |
| } | | } | |
| | | | |
| private: | | private: | |
| | | | |
|
| /* Simple extension of std::string for splitting into two parts | | /* Simple extension of std::string for splitting into two parts | |
| * | | * | |
| * Strings (in particular: file/dataset paths) will be split into two | | * Strings (in particular: file/dataset paths) will be split into | |
| * parts. The split is made at the last occurrence of the delimiter. | | two | |
| * | | * parts. The split is made at the last occurrence of the delimite | |
| * For example, "/path/to/some/file" will be split (delimiter = "/") i | | r. | |
| nto | | * | |
| * first() = "/path/to/some" and last() = "file". | | * For example, "/path/to/some/file" will be split (delimiter = "/ | |
| */ | | ") into | |
| | | * first() = "/path/to/some" and last() = "file". | |
| | | */ | |
| class SplitString: public std::string { | | class SplitString: public std::string { | |
| public: | | public: | |
| SplitString(std::string &sstring): std::string(sstring) {}; | | SplitString(std::string &sstring): std::string(sstring) {}; | |
| | | | |
| // return the part of the string before the delimiter | | // return the part of the string before the delimiter | |
| std::string first(char delimiter = '/') | | std::string first(char delimiter = '/') | |
| { | | { | |
| size_t last = find_last_of(delimiter); | | size_t last = find_last_of(delimiter); | |
| if(last == std::string::npos) // delimiter not found --> no fir
st | | if(last == std::string::npos) // delimiter not found --> no fir
st | |
| return ""; | | return ""; | |
| | | | |
| skipping to change at line 1463 | | skipping to change at line 1582 | |
| { | | { | |
| size_t last = find_last_of(delimiter); | | size_t last = find_last_of(delimiter); | |
| if(last == std::string::npos) // delimiter not found --> only l
ast | | if(last == std::string::npos) // delimiter not found --> only l
ast | |
| return std::string(*this); | | return std::string(*this); | |
| return std::string(begin()+last+1, end()); | | return std::string(begin()+last+1, end()); | |
| } | | } | |
| }; | | }; | |
| | | | |
| public: | | public: | |
| | | | |
|
| /** \brief takes any path and converts it into an absolute path | | /** \brief takes any path and converts it into an absolute path | |
| in the current file. | | in the current file. | |
| | | | |
|
| Elements like "." and ".." are treated as expected. | | Elements like "." and ".." are treated as expected. | |
| Links are not supported or resolved. | | Links are not supported or resolved. | |
| */ | | */ | |
| inline std::string get_absolute_path(std::string path) { | | inline std::string get_absolute_path(std::string path) const { | |
| // check for empty input or "." and return the current folder | | // check for empty input or "." and return the current folder | |
| if(path.length() == 0 || path == "."){ | | if(path.length() == 0 || path == "."){ | |
| return currentGroupName_(); | | return currentGroupName_(); | |
| } | | } | |
| | | | |
| std::string str; | | std::string str; | |
| // convert to absolute path | | // convert to absolute path | |
| if(relativePath_(path)){ | | if(relativePath_(path)){ | |
| std::string cname = currentGroupName_(); | | std::string cname = currentGroupName_(); | |
| if (cname == "/") | | if (cname == "/") | |
| | | | |
| skipping to change at line 1530 | | skipping to change at line 1649 | |
| // find second slash before ".." | | // find second slash before ".." | |
| std::string::size_type begin = str.rfind("/",prev_slash-1); | | std::string::size_type begin = str.rfind("/",prev_slash-1); | |
| | | | |
| // cut out part of the string | | // cut out part of the string | |
| str = str.substr(0,begin+1) + str.substr(end,str.length()-end); | | str = str.substr(0,begin+1) + str.substr(end,str.length()-end); | |
| } | | } | |
| | | | |
| return str; | | return str; | |
| } | | } | |
| | | | |
|
| private: | | protected: | |
| | | | |
|
| /* checks if the given path is a relative path. | | /* checks if the given path is a relative path. | |
| */ | | */ | |
| inline bool relativePath_(std::string & path) | | inline bool relativePath_(std::string & path) const | |
| { | | { | |
| std::string::size_type pos = path.find('/') ; | | std::string::size_type pos = path.find('/') ; | |
| if(pos == 0) | | if(pos == 0) | |
| return false; | | return false; | |
| | | | |
| return true; | | return true; | |
| } | | } | |
| | | | |
|
| /* return the name of the current group | | /* return the name of the current group | |
| */ | | */ | |
| inline std::string currentGroupName_() | | inline std::string currentGroupName_() const | |
| { | | { | |
| int len = H5Iget_name(cGroupHandle_,NULL,1000); | | int len = H5Iget_name(cGroupHandle_,NULL,1000); | |
| ArrayVector<char> name (len+1,0); | | ArrayVector<char> name (len+1,0); | |
| H5Iget_name(cGroupHandle_,name.begin(),len+1); | | H5Iget_name(cGroupHandle_,name.begin(),len+1); | |
| | | | |
| return std::string(name.begin()); | | return std::string(name.begin()); | |
| } | | } | |
| | | | |
|
| /* return the name of the current file | | /* return the name of the current file | |
| */ | | */ | |
| inline std::string fileName_() | | inline std::string fileName_() const | |
| { | | { | |
| int len = H5Fget_name(fileHandle_,NULL,1000); | | int len = H5Fget_name(fileHandle_,NULL,1000); | |
| ArrayVector<char> name (len+1,0); | | ArrayVector<char> name (len+1,0); | |
| H5Fget_name(fileHandle_,name.begin(),len+1); | | H5Fget_name(fileHandle_,name.begin(),len+1); | |
| | | | |
| return std::string(name.begin()); | | return std::string(name.begin()); | |
| } | | } | |
| | | | |
|
| /* create an empty file and open is | | /* create an empty file and open is | |
| */ | | */ | |
| inline hid_t createFile_(std::string filePath, OpenMode mode = Open) | | inline hid_t createFile_(std::string filePath, OpenMode mode = Open) | |
| { | | { | |
| // try to open file | | // try to open file | |
| FILE * pFile; | | FILE * pFile; | |
| pFile = fopen ( filePath.c_str(), "r" ); | | pFile = fopen ( filePath.c_str(), "r" ); | |
| hid_t fileId; | | hid_t fileId; | |
| | | | |
| // check if opening was successful (= file exists) | | // check if opening was successful (= file exists) | |
| if ( pFile == NULL ) | | if ( pFile == NULL ) | |
| { | | { | |
| fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT
, H5P_DEFAULT); | | fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT
, H5P_DEFAULT); | |
| } | | } | |
| else if(mode == Open) | | else if(mode == Open) | |
| { | | { | |
| fclose( pFile ); | | fclose( pFile ); | |
| fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); | | fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); | |
| } | | } | |
|
| | | else if(mode == OpenReadOnly) { | |
| | | fclose( pFile ); | |
| | | fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT) | |
| | | ; | |
| | | } | |
| else | | else | |
| { | | { | |
| fclose(pFile); | | fclose(pFile); | |
| std::remove(filePath.c_str()); | | std::remove(filePath.c_str()); | |
| fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT
, H5P_DEFAULT); | | fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT
, H5P_DEFAULT); | |
| } | | } | |
| return fileId; | | return fileId; | |
| } | | } | |
| | | | |
|
| /* open a group and subgroups. Create if necessary. | | /* open a group and subgroups. Create if necessary. | |
| */ | | */ | |
| inline hid_t openCreateGroup_(std::string groupName) | | inline hid_t openCreateGroup_(std::string groupName) | |
| { | | { | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
| // open root group | | // open root group | |
| hid_t parent = H5Gopen(fileHandle_, "/", H5P_DEFAULT); | | hid_t parent = H5Gopen(fileHandle_, "/", H5P_DEFAULT); | |
| if(groupName == "/") | | if(groupName == "/") | |
| { | | { | |
| return parent; | | return parent; | |
| | | | |
| skipping to change at line 1616 | | skipping to change at line 1739 | |
| | | | |
| // remove leading / | | // remove leading / | |
| groupName = std::string(groupName.begin()+1, groupName.end()); | | groupName = std::string(groupName.begin()+1, groupName.end()); | |
| | | | |
| // check if the groupName has finishing slash | | // check if the groupName has finishing slash | |
| if( groupName.size() != 0 && *groupName.rbegin() != '/') | | if( groupName.size() != 0 && *groupName.rbegin() != '/') | |
| { | | { | |
| groupName = groupName + '/'; | | groupName = groupName + '/'; | |
| } | | } | |
| | | | |
|
| //open or create subgroups one by one | | // open or create subgroups one by one | |
| std::string::size_type begin = 0, end = groupName.find('/'); | | std::string::size_type begin = 0, end = groupName.find('/'); | |
|
| int ii = 0; | | | |
| while (end != std::string::npos) | | while (end != std::string::npos) | |
| { | | { | |
| std::string group(groupName.begin()+begin, groupName.begin()+en
d); | | std::string group(groupName.begin()+begin, groupName.begin()+en
d); | |
| hid_t prevParent = parent; | | hid_t prevParent = parent; | |
| | | | |
| if(H5LTfind_dataset(parent, group.c_str()) == 0) | | if(H5LTfind_dataset(parent, group.c_str()) == 0) | |
| { | | { | |
| parent = H5Gcreate(prevParent, group.c_str(), H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT); | | parent = H5Gcreate(prevParent, group.c_str(), H5P_DEFAULT,
H5P_DEFAULT, H5P_DEFAULT); | |
| } else { | | } else { | |
| parent = H5Gopen(prevParent, group.c_str(), H5P_DEFAULT); | | parent = H5Gopen(prevParent, group.c_str(), H5P_DEFAULT); | |
| } | | } | |
|
| | | H5Gclose(prevParent); | |
| | | | |
|
| if(ii != 0) | | | |
| { | | | |
| H5Gclose(prevParent); | | | |
| } | | | |
| if(parent < 0) | | if(parent < 0) | |
| { | | { | |
| return parent; | | return parent; | |
| } | | } | |
|
| ++ii; | | | |
| begin = end + 1; | | begin = end + 1; | |
| end = groupName.find('/', begin); | | end = groupName.find('/', begin); | |
| } | | } | |
| | | | |
| return parent; | | return parent; | |
| } | | } | |
| | | | |
|
| /* delete a dataset by unlinking it from the file structure. This does | | /* delete a dataset by unlinking it from the file structure. This d | |
| not | | oes not | |
| delete the data! | | delete the data! | |
| */ | | */ | |
| inline void deleteDataset_(hid_t parent, std::string datasetName) | | inline void deleteDataset_(hid_t parent, std::string datasetName) | |
| { | | { | |
| // delete existing data and create new dataset | | // delete existing data and create new dataset | |
| if(H5LTfind_dataset(parent, datasetName.c_str())) | | if(H5LTfind_dataset(parent, datasetName.c_str())) | |
| { | | { | |
| | | | |
| #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6) | | #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6) | |
| if(H5Gunlink(parent, datasetName.c_str()) < 0) | | if(H5Gunlink(parent, datasetName.c_str()) < 0) | |
| { | | { | |
| vigra_postcondition(false, "HDF5File::deleteDataset_(): Una
ble to delete existing data."); | | vigra_postcondition(false, "HDF5File::deleteDataset_(): Una
ble to delete existing data."); | |
| } | | } | |
| #else | | #else | |
| if(H5Ldelete(parent, datasetName.c_str(), H5P_DEFAULT ) < 0) | | if(H5Ldelete(parent, datasetName.c_str(), H5P_DEFAULT ) < 0) | |
| { | | { | |
| vigra_postcondition(false, "HDF5File::deleteDataset_(): Una
ble to delete existing data."); | | vigra_postcondition(false, "HDF5File::deleteDataset_(): Una
ble to delete existing data."); | |
| } | | } | |
| #endif | | #endif | |
| } | | } | |
| } | | } | |
| | | | |
|
| /* get the handle of a dataset specified by a string | | /* get the handle of a dataset specified by a string | |
| */ | | */ | |
| inline hid_t getDatasetHandle_(std::string datasetName) | | inline hid_t getDatasetHandle_(std::string datasetName) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| std::string groupname = SplitString(datasetName).first(); | | std::string groupname = SplitString(datasetName).first(); | |
| std::string setname = SplitString(datasetName).last(); | | std::string setname = SplitString(datasetName).last(); | |
| | | | |
|
| if (H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) <= 0) | | if(H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) <= 0) | |
| { | | { | |
| std::cerr << "HDF5File::getDatasetHandle_(): Dataset '" << data
setName << "' does not exist.\n"; | | std::cerr << "HDF5File::getDatasetHandle_(): Dataset '" << data
setName << "' does not exist.\n"; | |
| return -1; | | return -1; | |
| } | | } | |
| | | | |
|
| //Open parent group | | // Open parent group | |
| hid_t groupHandle = openCreateGroup_(groupname); | | HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, "Int | |
| | | ernal error"); | |
| hid_t datasetHandle = H5Dopen(groupHandle, setname.c_str(), H5P_DEF | | | |
| AULT); | | | |
| | | | |
| if(groupHandle != cGroupHandle_) | | | |
| { | | | |
| H5Gclose(groupHandle); | | | |
| } | | | |
| | | | |
| //return dataset handle | | | |
| return datasetHandle; | | | |
| | | | |
|
| | | return H5Dopen(groupHandle, setname.c_str(), H5P_DEFAULT); | |
| } | | } | |
| | | | |
|
| /* get the type of an object specified by a string | | /* get the type of an object specified by a string | |
| */ | | */ | |
| H5O_type_t get_object_type_(std::string name) | | H5O_type_t get_object_type_(std::string name) | |
| { | | { | |
| name = get_absolute_path(name); | | name = get_absolute_path(name); | |
| std::string group_name = SplitString(name).first(); | | std::string group_name = SplitString(name).first(); | |
| std::string object_name = SplitString(name).last(); | | std::string object_name = SplitString(name).last(); | |
| if (!object_name.size()) | | if (!object_name.size()) | |
| return H5O_TYPE_GROUP; | | return H5O_TYPE_GROUP; | |
| | | | |
| htri_t exists = H5Lexists(fileHandle_, name.c_str(), H5P_DEFAULT); | | htri_t exists = H5Lexists(fileHandle_, name.c_str(), H5P_DEFAULT); | |
| vigra_precondition(exists > 0, "HDF5File::get_object_type_(): " | | vigra_precondition(exists > 0, "HDF5File::get_object_type_(): " | |
| "object \"" + name + "\" " | | "object \"" + name + "\" " | |
| "not found."); | | "not found."); | |
| // open parent group | | // open parent group | |
|
| hid_t group_handle = openCreateGroup_(group_name); | | HDF5Handle group_handle(openCreateGroup_(group_name), &H5Gclose, "I | |
| H5O_type_t h5_type = HDF5_get_type(group_handle, name.c_str()); | | nternal error"); | |
| if (group_handle != cGroupHandle_) | | return HDF5_get_type(group_handle, name.c_str()); | |
| { | | | |
| H5Gclose(group_handle); | | | |
| } | | | |
| return h5_type; | | | |
| } | | } | |
| | | | |
|
| /* low-level write function to write vigra MultiArray data as an attrib | | /* low-level write function to write vigra MultiArray data as an at | |
| ute | | tribute | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| void write_attribute_(std::string name, const std::string & attribute_n
ame, | | void write_attribute_(std::string name, const std::string & attribute_n
ame, | |
| const MultiArrayView<N, T, UnstridedArrayTag> & a
rray, | | const MultiArrayView<N, T, UnstridedArrayTag> & a
rray, | |
|
| const hid_t datatype, const int numBandsOfType) | | const hid_t datatype, | |
| | | const int numBandsOfType) | |
| { | | { | |
|
| | | | |
| // shape of the array. Add one dimension, if array contains non-sca
lars. | | // shape of the array. Add one dimension, if array contains non-sca
lars. | |
|
| ArrayVector<hsize_t> shape(N + (numBandsOfType > 1),0); | | ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end | |
| for(unsigned int i = 0; i < N; i++){ | | ()); | |
| shape[N-1-i] = array.shape(i); // reverse order | | std::reverse(shape.begin(), shape.end()); | |
| } | | | |
| | | | |
| if(numBandsOfType > 1) | | if(numBandsOfType > 1) | |
|
| shape[N] = numBandsOfType; | | shape.push_back(numBandsOfType); | |
| | | | |
|
| HDF5Handle dataspace(H5Screate_simple(N + (numBandsOfType > 1), | | HDF5Handle dataspace(H5Screate_simple(shape.size(), | |
| shape.begin(), NULL), | | shape.begin(), NULL), | |
| &H5Sclose, "HDF5File::writeAttribute(): Can no
t" | | &H5Sclose, "HDF5File::writeAttribute(): Can no
t" | |
| " create dataspace."); | | " create dataspace."); | |
| | | | |
| std::string errorMessage ("HDF5File::writeAttribute(): can not find
" | | std::string errorMessage ("HDF5File::writeAttribute(): can not find
" | |
| "object '" + name + "'."); | | "object '" + name + "'."); | |
| | | | |
| H5O_type_t h5_type = get_object_type_(name); | | H5O_type_t h5_type = get_object_type_(name); | |
| bool is_group = h5_type == H5O_TYPE_GROUP; | | bool is_group = h5_type == H5O_TYPE_GROUP; | |
| if (!is_group && h5_type != H5O_TYPE_DATASET) | | if (!is_group && h5_type != H5O_TYPE_DATASET) | |
| | | | |
| skipping to change at line 1782 | | skipping to change at line 1883 | |
| dataspace, H5P_DEFAULT, | | dataspace, H5P_DEFAULT, | |
| H5P_DEFAULT), | | H5P_DEFAULT), | |
| &H5Aclose, | | &H5Aclose, | |
| "HDF5File::writeAttribute(): Can not cre
ate" | | "HDF5File::writeAttribute(): Can not cre
ate" | |
| " attribute."); | | " attribute."); | |
| | | | |
| // Write the data to the HDF5 object | | // Write the data to the HDF5 object | |
| H5Awrite(attributeHandle, datatype, array.data()); | | H5Awrite(attributeHandle, datatype, array.data()); | |
| } | | } | |
| | | | |
|
| /* Write single value attribute | | /* Write single value attribute | |
| This function allows to write data of atomic datatypes (int, long, do | | This function allows to write data of atomic datatypes (int, lon | |
| uble) | | g, double) | |
| as an attribute in the HDF5 file. So it is not necessary to create a | | as an attribute in the HDF5 file. So it is not necessary to crea | |
| MultiArray | | te a MultiArray | |
| of size 1 to write a single number. | | of size 1 to write a single number. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| inline void writeAtomicAttribute(std::string datasetName, std::string a
ttributeName, const T data) | | inline void writeAtomicAttribute(std::string datasetName, std::string a
ttributeName, const T data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<1>::type chunkSize; | | typename MultiArrayShape<1>::type chunkSize; | |
| chunkSize[0] = 0; | | chunkSize[0] = 0; | |
| MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | |
| array[0] = data; | | array[0] = data; | |
| write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 1); | | write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 1); | |
| } | | } | |
| | | | |
|
| /* low-level read function to write vigra MultiArray data from attribut | | /* low-level read function to write vigra MultiArray data from attr | |
| es | | ibutes | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void read_attribute_(std::string datasetName, std::string attrib
uteName, MultiArrayView<N, T, UnstridedArrayTag> array, const hid_t datatyp
e, const int numBandsOfType) | | inline void read_attribute_(std::string datasetName, std::string attrib
uteName, MultiArrayView<N, T, UnstridedArrayTag> array, const hid_t datatyp
e, const int numBandsOfType) | |
| { | | { | |
| std::string dataset_path = get_absolute_path(datasetName); | | std::string dataset_path = get_absolute_path(datasetName); | |
| // open Attribute handle | | // open Attribute handle | |
| std::string message = "Error: could not get handle for attribute '"
+attributeName+"'' of object '"+dataset_path+"'."; | | std::string message = "Error: could not get handle for attribute '"
+attributeName+"'' of object '"+dataset_path+"'."; | |
| HDF5Handle attr_handle (H5Aopen_by_name(fileHandle_,dataset_path.c_
str(),attributeName.c_str(),H5P_DEFAULT,H5P_DEFAULT),&H5Aclose, message.c_s
tr()); | | HDF5Handle attr_handle (H5Aopen_by_name(fileHandle_,dataset_path.c_
str(),attributeName.c_str(),H5P_DEFAULT,H5P_DEFAULT),&H5Aclose, message.c_s
tr()); | |
| | | | |
| // get Attribute dataspace | | // get Attribute dataspace | |
| message = "Error: could not get dataspace for attribute '"+attribut
eName+"'' of object '"+dataset_path+"'."; | | message = "Error: could not get dataspace for attribute '"+attribut
eName+"'' of object '"+dataset_path+"'."; | |
| HDF5Handle attr_dataspace_handle (H5Aget_space(attr_handle),&H5Sclo
se,message.c_str()); | | HDF5Handle attr_dataspace_handle (H5Aget_space(attr_handle),&H5Sclo
se,message.c_str()); | |
| | | | |
| // obtain Attribute shape | | // obtain Attribute shape | |
| int dims = H5Sget_simple_extent_ndims(attr_dataspace_handle); | | int dims = H5Sget_simple_extent_ndims(attr_dataspace_handle); | |
|
| ArrayVector<hsize_t> shape_inv(dims); | | | |
| H5Sget_simple_extent_dims(attr_dataspace_handle, shape_inv.data(), | | | |
| NULL); | | | |
| | | | |
| // invert the dimensions to guarantee c-order | | | |
| ArrayVector<hsize_t> dimshape(dims); | | ArrayVector<hsize_t> dimshape(dims); | |
|
| for(ArrayVector<hsize_t>::size_type i=0; i<shape_inv.size(); i++) { | | H5Sget_simple_extent_dims(attr_dataspace_handle, dimshape.data(), N | |
| dimshape[i] = shape_inv[dims-1-i]; | | ULL); | |
| } | | | |
| | | | |
|
| int offset = (numBandsOfType > 1); | | // invert the dimensions to guarantee VIGRA-compatible order | |
| | | std::reverse(dimshape.begin(), dimshape.end()); | |
| | | | |
| | | int offset = (numBandsOfType > 1) | |
| | | ? 1 | |
| | | : 0; | |
| message = "Error: Array dimension disagrees with dataset dimension.
"; | | message = "Error: Array dimension disagrees with dataset dimension.
"; | |
| // the object in the HDF5 file may have one additional dimension wh
ich we then interpret as the pixel type bands | | // the object in the HDF5 file may have one additional dimension wh
ich we then interpret as the pixel type bands | |
|
| vigra_precondition( ( (N + offset ) == MultiArrayIndex(dims)), mes
sage); | | vigra_precondition((N + offset) == MultiArrayIndex(dims), message); | |
| | | | |
| typename MultiArrayShape<N>::type shape; | | typename MultiArrayShape<N>::type shape; | |
|
| for(int k=offset; k< MultiArrayIndex(dims); ++k) { | | for(int k=offset; k < (int)dimshape.size(); ++k) | |
| shape[k-offset] = MultiArrayIndex(dimshape[k]); | | shape[k-offset] = (MultiArrayIndex)dimshape[k]; | |
| } | | | |
| | | | |
| message = "Error: Array shape disagrees with dataset shape"; | | message = "Error: Array shape disagrees with dataset shape"; | |
|
| vigra_precondition(shape == array.shape(),message); | | vigra_precondition(shape == array.shape(), message); | |
| | | | |
| // simply read in the data as is | | // simply read in the data as is | |
| H5Aread( attr_handle, datatype, array.data()); | | H5Aread( attr_handle, datatype, array.data()); | |
| } | | } | |
| | | | |
|
| /* Read a single value attribute. | | /* Read a single value attribute. | |
| This functions allows to read a single value attribute of atomic data | | This functions allows to read a single value attribute of atomic | |
| type (int, long, double) | | datatype (int, long, double) | |
| from the HDF5 file. So it is not necessary to create a MultiArray | | from the HDF5 file. So it is not necessary to create a MultiArra | |
| of size 1 to read a single number. | | y | |
| */ | | of size 1 to read a single number. | |
| | | */ | |
| template<class T> | | template<class T> | |
| inline void readAtomicAttribute(std::string datasetName, std::string at
tributeName, T & data) | | inline void readAtomicAttribute(std::string datasetName, std::string at
tributeName, T & data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | |
| read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), 1); | | read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), 1); | |
| data = array[0]; | | data = array[0]; | |
| } | | } | |
| | | | |
| skipping to change at line 1868 | | skipping to change at line 1967 | |
| inline void readAtomicAttribute(std::string datasetName, std::string at
tributeName, std::string & data) | | inline void readAtomicAttribute(std::string datasetName, std::string at
tributeName, std::string & data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | |
| read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<const char *>(), 1); | | read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<const char *>(), 1); | |
| data = std::string(array[0]); | | data = std::string(array[0]); | |
| } | | } | |
| | | | |
|
| /* low-level write function to write vigra unstrided MultiArray data | | /* low-level write function to write vigra unstrided MultiArray dat | |
| */ | | a | |
| | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
|
| inline void write_(std::string &datasetName, const MultiArrayView<N, T, | | inline void write_(std::string &datasetName, | |
| UnstridedArrayTag> & array, const hid_t datatype, const int numBandsOfType | | const MultiArrayView<N, T, UnstridedArrayTag> & arra | |
| , typename MultiArrayShape<N>::type &chunkSize, int compressionParameter = | | y, | |
| 0) | | const hid_t datatype, | |
| | | const int numBandsOfType, | |
| | | typename MultiArrayShape<N>::type &chunkSize, | |
| | | int compressionParameter = 0) | |
| { | | { | |
| std::string groupname = SplitString(datasetName).first(); | | std::string groupname = SplitString(datasetName).first(); | |
| std::string setname = SplitString(datasetName).last(); | | std::string setname = SplitString(datasetName).last(); | |
| | | | |
| // shape of the array. Add one dimension, if array contains non-sca
lars. | | // shape of the array. Add one dimension, if array contains non-sca
lars. | |
|
| ArrayVector<hsize_t> shape(N + (numBandsOfType > 1),0); | | ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end | |
| for(unsigned int i = 0; i < N; i++){ | | ()); | |
| shape[N-1-i] = array.shape(i); // reverse order | | std::reverse(shape.begin(), shape.end()); | |
| } | | | |
| | | | |
| if(numBandsOfType > 1) | | if(numBandsOfType > 1) | |
|
| shape[N] = numBandsOfType; | | shape.push_back(numBandsOfType); | |
| | | | |
|
| HDF5Handle dataspace ( H5Screate_simple(N + (numBandsOfType > 1), s | | HDF5Handle dataspace(H5Screate_simple(shape.size(), shape.begin(), | |
| hape.begin(), NULL), &H5Sclose, "HDF5File::write(): Can not create dataspac | | NULL), &H5Sclose, | |
| e."); | | "HDF5File::write(): Can not create dataspace." | |
| | | ); | |
| | | | |
| // create and open group: | | // create and open group: | |
| std::string errorMessage ("HDF5File::write(): can not create group
'" + groupname + "'."); | | std::string errorMessage ("HDF5File::write(): can not create group
'" + groupname + "'."); | |
|
| hid_t groupHandle = openCreateGroup_(groupname); | | HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, erro | |
| if(groupHandle <= 0) | | rMessage.c_str()); | |
| { | | | |
| std::cerr << errorMessage << "\n"; | | | |
| } | | | |
| | | | |
| // delete dataset, if it already exists | | // delete dataset, if it already exists | |
| deleteDataset_(groupHandle, setname.c_str()); | | deleteDataset_(groupHandle, setname.c_str()); | |
| | | | |
| // set up properties list | | // set up properties list | |
|
| HDF5Handle plist ( H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, "HDF5F | | HDF5Handle plist(H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, | |
| ile::write(): unable to create property list." ); | | "HDF5File::write(): unable to create property list | |
| | | ." ); | |
| | | | |
| // turn off time tagging of datasets by default. | | // turn off time tagging of datasets by default. | |
| H5Pset_obj_track_times(plist, track_time); | | H5Pset_obj_track_times(plist, track_time); | |
| | | | |
| // enable chunks | | // enable chunks | |
| if(chunkSize[0] > 0) | | if(chunkSize[0] > 0) | |
| { | | { | |
|
| ArrayVector<hsize_t> cSize(N + (numBandsOfType > 1),0); | | ArrayVector<hsize_t> cSize(chunkSize.begin(), chunkSize.end()); | |
| for(unsigned int i = 0; i<N; i++) | | std::reverse(cSize.begin(), cSize.end()); | |
| { | | | |
| cSize[i] = chunkSize[N-1-i]; | | | |
| } | | | |
| if(numBandsOfType > 1) | | if(numBandsOfType > 1) | |
|
| cSize[N] = numBandsOfType; | | cSize.push_back(numBandsOfType); | |
| | | | |
|
| H5Pset_chunk (plist, N + (numBandsOfType > 1), cSize.begin()); | | H5Pset_chunk (plist, cSize.size(), cSize.begin()); | |
| } | | } | |
| | | | |
| // enable compression | | // enable compression | |
| if(compressionParameter > 0) | | if(compressionParameter > 0) | |
| { | | { | |
| H5Pset_deflate(plist, compressionParameter); | | H5Pset_deflate(plist, compressionParameter); | |
| } | | } | |
| | | | |
| // create dataset | | // create dataset | |
|
| HDF5Handle datasetHandle (H5Dcreate(groupHandle, setname.c_str(), d | | HDF5Handle datasetHandle(H5Dcreate(groupHandle, setname.c_str(), da | |
| atatype, dataspace,H5P_DEFAULT, plist, H5P_DEFAULT), &H5Dclose, "HDF5File:: | | tatype, dataspace,H5P_DEFAULT, plist, H5P_DEFAULT), | |
| write(): Can not create dataset."); | | &H5Dclose, "HDF5File::write(): Can not cre | |
| | | ate dataset."); | |
| | | | |
| // Write the data to the HDF5 dataset as is | | // Write the data to the HDF5 dataset as is | |
| herr_t write_status = H5Dwrite(datasetHandle, datatype, H5S_ALL, | | herr_t write_status = H5Dwrite(datasetHandle, datatype, H5S_ALL, | |
| H5S_ALL, H5P_DEFAULT, array.data()); | | H5S_ALL, H5P_DEFAULT, array.data()); | |
| vigra_precondition(write_status >= 0, "HDF5File::write_(): write to
" | | vigra_precondition(write_status >= 0, "HDF5File::write_(): write to
" | |
| "dataset \"" + datasetName + "\" " | | "dataset \"" + datasetName + "\" " | |
| "failed."); | | "failed."); | |
|
| | | | |
| if(groupHandle != cGroupHandle_) | | | |
| { | | | |
| H5Gclose(groupHandle); | | | |
| } | | | |
| } | | } | |
| | | | |
|
| /* Write single value as dataset. | | /* Write single value as dataset. | |
| This functions allows to write data of atomic datatypes (int, long, d | | This functions allows to write data of atomic datatypes (int, lo | |
| ouble) | | ng, double) | |
| as a dataset in the HDF5 file. So it is not necessary to create a Mul | | as a dataset in the HDF5 file. So it is not necessary to create | |
| tiArray | | a MultiArray | |
| of size 1 to write a single number. | | of size 1 to write a single number. | |
| | | | |
|
| If the first character of datasetName is a "/", the path will be inte | | If the first character of datasetName is a "/", the path will be | |
| rpreted as absolute path, | | interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current grou | | otherwise it will be interpreted as path relative to the current | |
| p. | | group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| inline void writeAtomic(std::string datasetName, const T data) | | inline void writeAtomic(std::string datasetName, const T data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<1>::type chunkSize; | | typename MultiArrayShape<1>::type chunkSize; | |
| chunkSize[0] = 0; | | chunkSize[0] = 0; | |
| MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | |
| array[0] = data; | | array[0] = data; | |
| write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
,0); | | write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
,0); | |
| } | | } | |
| | | | |
|
| /* low-level read function to read vigra unstrided MultiArray data | | /* low-level read function to read vigra unstrided MultiArray data | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
|
| inline void read_(std::string datasetName, MultiArrayView<N, T, Unstrid | | inline void read_(std::string datasetName, | |
| edArrayTag> array, const hid_t datatype, const int numBandsOfType) | | MultiArrayView<N, T, UnstridedArrayTag> array, | |
| | | const hid_t datatype, const int numBandsOfType) | |
| { | | { | |
| //Prepare to read without using HDF5ImportInfo | | //Prepare to read without using HDF5ImportInfo | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
|
| hssize_t dimensions = getDatasetDimensions(datasetName); | | | |
| | | | |
| std::string errorMessage ("HDF5File::read(): Unable to open dataset
'" + datasetName + "'."); | | std::string errorMessage ("HDF5File::read(): Unable to open dataset
'" + datasetName + "'."); | |
|
| HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose
, errorMessage.c_str()); | | HDF5Handle datasetHandle(getDatasetHandle_(datasetName), &H5Dclose,
errorMessage.c_str()); | |
| | | | |
|
| int offset = (numBandsOfType > 1); | | int offset = (numBandsOfType > 1) | |
| | | ? 1 | |
| | | : 0; | |
| | | | |
|
| vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions))
, // the object in the HDF5 file may have one additional dimension which we
then interpret as the pixel type bands | | vigra_precondition((N + offset ) == MultiArrayIndex(dimshape.size()
), // the object in the HDF5 file may have one additional dimension which w
e then interpret as the pixel type bands | |
| "HDF5File::read(): Array dimension disagrees with dataset dimen
sion."); | | "HDF5File::read(): Array dimension disagrees with dataset dimen
sion."); | |
| | | | |
| typename MultiArrayShape<N>::type shape; | | typename MultiArrayShape<N>::type shape; | |
|
| for(int k=offset; k< MultiArrayIndex(dimensions); ++k) { | | for(int k=offset; k < (int)dimshape.size(); ++k) | |
| shape[k-offset] = MultiArrayIndex(dimshape[k]); | | shape[k-offset] = (MultiArrayIndex)dimshape[k]; | |
| } | | | |
| | | | |
| vigra_precondition(shape == array.shape(), | | vigra_precondition(shape == array.shape(), | |
| "HDF5File::read(): Array shape disagrees with da
taset shape."); | | "HDF5File::read(): Array shape disagrees with da
taset shape."); | |
|
| | | if (offset) | |
| | | vigra_precondition(dimshape[0] == static_cast<hsize_t>(numBands | |
| | | OfType), | |
| | | "HDF5File::read(): Band count doesn't match | |
| | | destination array compound type."); | |
| | | | |
| // simply read in the data as is | | // simply read in the data as is | |
| H5Dread( datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ar
ray.data() ); // .data() possible since void pointer! | | H5Dread( datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ar
ray.data() ); // .data() possible since void pointer! | |
| } | | } | |
| | | | |
|
| /* Read a single value. | | /* Read a single value. | |
| This functions allows to read a single datum of atomic datatype (int, | | This functions allows to read a single datum of atomic datatype | |
| long, double) | | (int, long, double) | |
| from the HDF5 file. So it is not necessary to create a MultiArray | | from the HDF5 file. So it is not necessary to create a MultiArra | |
| of size 1 to read a single number. | | y | |
| | | of size 1 to read a single number. | |
| If the first character of datasetName is a "/", the path will be inte | | | |
| rpreted as absolute path, | | If the first character of datasetName is a "/", the path will be | |
| otherwise it will be interpreted as path relative to the current grou | | interpreted as absolute path, | |
| p. | | otherwise it will be interpreted as path relative to the current | |
| */ | | group. | |
| | | */ | |
| template<class T> | | template<class T> | |
| inline void readAtomic(std::string datasetName, T & data) | | inline void readAtomic(std::string datasetName, T & data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | |
| read_(datasetName, array, detail::getH5DataType<T>(), 1); | | read_(datasetName, array, detail::getH5DataType<T>(), 1); | |
| data = array[0]; | | data = array[0]; | |
| } | | } | |
|
| | | | |
| inline void readAtomic(std::string datasetName, std::string & data) | | inline void readAtomic(std::string datasetName, std::string & data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | |
| read_(datasetName, array, detail::getH5DataType<const char *>(), 1)
; | | read_(datasetName, array, detail::getH5DataType<const char *>(), 1)
; | |
| data = std::string(array[0]); | | data = std::string(array[0]); | |
| } | | } | |
| | | | |
|
| /* low-level write function to write vigra unstrided MultiArray data in | | /* low-level write function to write vigra unstrided MultiArray data | |
| to a sub-block of a dataset | | into a sub-block of a dataset | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeBlock_(std::string datasetName, typename MultiArraySha
pe<N>::type &blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & a
rray, const hid_t datatype, const int numBandsOfType) | | inline void writeBlock_(std::string datasetName, typename MultiArraySha
pe<N>::type &blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & a
rray, const hid_t datatype, const int numBandsOfType) | |
| { | | { | |
| // open dataset if it exists | | // open dataset if it exists | |
| std::string errorMessage = "HDF5File::writeBlock(): Error opening d
ataset '" + datasetName + "'."; | | std::string errorMessage = "HDF5File::writeBlock(): Error opening d
ataset '" + datasetName + "'."; | |
| HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose
, errorMessage.c_str()); | | HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose
, errorMessage.c_str()); | |
| | | | |
| // hyperslab parameters for position, size, ... | | // hyperslab parameters for position, size, ... | |
| hsize_t boffset [N]; | | hsize_t boffset [N]; | |
| hsize_t bshape [N]; | | hsize_t bshape [N]; | |
| | | | |
| skipping to change at line 2049 | | skipping to change at line 2148 | |
| HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo
se,"Unable to get origin dataspace"); | | HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo
se,"Unable to get origin dataspace"); | |
| | | | |
| // get file dataspace and select the desired block | | // get file dataspace and select the desired block | |
| HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose,"
Unable to create target dataspace"); | | HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose,"
Unable to create target dataspace"); | |
| H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones
, bones, bshape); | | H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones
, bones, bshape); | |
| | | | |
| // Write the data to the HDF5 dataset as is | | // Write the data to the HDF5 dataset as is | |
| H5Dwrite( datasetHandle, datatype, memspace_handle, dataspaceHandle
, H5P_DEFAULT, array.data()); // .data() possible since void pointer! | | H5Dwrite( datasetHandle, datatype, memspace_handle, dataspaceHandle
, H5P_DEFAULT, array.data()); // .data() possible since void pointer! | |
| } | | } | |
| | | | |
|
| /* low-level read function to read vigra unstrided MultiArray data from | | /* low-level read function to read vigra unstrided MultiArray data | |
| a sub-block of a dataset | | from a sub-block of a dataset | |
| */ | | */ | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readBlock_(std::string datasetName, typename MultiArrayShap
e<N>::type &blockOffset, typename MultiArrayShape<N>::type &blockShape, Mul
tiArrayView<N, T, UnstridedArrayTag> &array, const hid_t datatype, const in
t numBandsOfType) | | inline void readBlock_(std::string datasetName, typename MultiArrayShap
e<N>::type &blockOffset, typename MultiArrayShape<N>::type &blockShape, Mul
tiArrayView<N, T, UnstridedArrayTag> &array, const hid_t datatype, const in
t numBandsOfType) | |
| { | | { | |
| //Prepare to read without using HDF5ImportInfo | | //Prepare to read without using HDF5ImportInfo | |
| //ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName) ; | | //ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName) ; | |
| hssize_t dimensions = getDatasetDimensions(datasetName); | | hssize_t dimensions = getDatasetDimensions(datasetName); | |
| | | | |
| std::string errorMessage ("HDF5File::readBlock(): Unable to open da
taset '" + datasetName + "'."); | | std::string errorMessage ("HDF5File::readBlock(): Unable to open da
taset '" + datasetName + "'."); | |
| HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose
, errorMessage.c_str()); | | HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose
, errorMessage.c_str()); | |
| | | | |
|
| int offset = (numBandsOfType > 1); | | int offset = (numBandsOfType > 1) | |
| | | ? 1 | |
| | | : 0; | |
| | | | |
| vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions))
, // the object in the HDF5 file may have one additional dimension which we
then interpret as the pixel type bands | | vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions))
, // the object in the HDF5 file may have one additional dimension which we
then interpret as the pixel type bands | |
| "readHDF5_block(): Array dimension disagrees with data dimensio
n."); | | "readHDF5_block(): Array dimension disagrees with data dimensio
n."); | |
| | | | |
| vigra_precondition(blockShape == array.shape(), | | vigra_precondition(blockShape == array.shape(), | |
| "readHDF5_block(): Array shape disagrees with block size."); | | "readHDF5_block(): Array shape disagrees with block size."); | |
| | | | |
| // hyperslab parameters for position, size, ... | | // hyperslab parameters for position, size, ... | |
| hsize_t boffset [N]; | | hsize_t boffset [N]; | |
| hsize_t bshape [N]; | | hsize_t bshape [N]; | |
| | | | |
| skipping to change at line 2084 | | skipping to change at line 2185 | |
| for(int i = 0; i < N; i++){ | | for(int i = 0; i < N; i++){ | |
| // vigra and hdf5 use different indexing | | // vigra and hdf5 use different indexing | |
| boffset[i] = blockOffset[N-1-i]; | | boffset[i] = blockOffset[N-1-i]; | |
| //bshape[i] = blockShape[i]; | | //bshape[i] = blockShape[i]; | |
| bshape[i] = blockShape[N-1-i]; | | bshape[i] = blockShape[N-1-i]; | |
| //boffset[i] = blockOffset[N-1-i]; | | //boffset[i] = blockOffset[N-1-i]; | |
| bones[i] = 1; | | bones[i] = 1; | |
| } | | } | |
| | | | |
| // create a target dataspace in memory with the shape of the desire
d block | | // create a target dataspace in memory with the shape of the desire
d block | |
|
| HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo | | HDF5Handle memspace_handle(H5Screate_simple(N,bshape,NULL),&H5Sclos | |
| se,"Unable to create target dataspace"); | | e, | |
| | | "Unable to create target dataspace"); | |
| | | | |
| // get file dataspace and select the desired block | | // get file dataspace and select the desired block | |
|
| HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose," | | HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle),&H5Sclose, | |
| Unable to get dataspace"); | | "Unable to get dataspace"); | |
| H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones
, bones, bshape); | | H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones
, bones, bshape); | |
| | | | |
| // now read the data | | // now read the data | |
| H5Dread( datasetHandle, datatype, memspace_handle, dataspaceHandle,
H5P_DEFAULT, array.data() ); // .data() possible since void pointer! | | H5Dread( datasetHandle, datatype, memspace_handle, dataspaceHandle,
H5P_DEFAULT, array.data() ); // .data() possible since void pointer! | |
| } | | } | |
| | | | |
| }; /* class HDF5File */ | | }; /* class HDF5File */ | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| | | | |
| skipping to change at line 2166 | | skipping to change at line 2269 | |
| counter++; | | counter++; | |
| | | | |
| //std::cout << "numBandsOfType: " << numBandsOfType << std::endl; | | //std::cout << "numBandsOfType: " << numBandsOfType << std::endl; | |
| DestIterator dend = d + shape[0]; | | DestIterator dend = d + shape[0]; | |
| int k = 0; | | int k = 0; | |
| for(; d < dend; ++d, k++) | | for(; d < dend; ++d, k++) | |
| { | | { | |
| *d = buffer[k]; | | *d = buffer[k]; | |
| //std::cout << buffer[k] << "| "; | | //std::cout << buffer[k] << "| "; | |
| } | | } | |
|
| | | | |
| } | | } | |
| | | | |
| template <class DestIterator, class Shape, class T, int N> | | template <class DestIterator, class Shape, class T, int N> | |
| void | | void | |
| readHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, c
onst hid_t datatype, ArrayVector<T> & buffer, int & counter, const int elem
ents, const int numBandsOfType, MetaInt<N>) | | readHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, c
onst hid_t datatype, ArrayVector<T> & buffer, int & counter, const int elem
ents, const int numBandsOfType, MetaInt<N>) | |
| { | | { | |
| DestIterator dend = d + shape[N]; | | DestIterator dend = d + shape[N]; | |
| for(; d < dend; ++d) | | for(; d < dend; ++d) | |
| { | | { | |
| readHDF5Impl(d.begin(), shape, dataset_id, datatype, buffer, counte
r, elements, numBandsOfType, MetaInt<N-1>()); | | readHDF5Impl(d.begin(), shape, dataset_id, datatype, buffer, counte
r, elements, numBandsOfType, MetaInt<N-1>()); | |
| | | | |
| skipping to change at line 2188 | | skipping to change at line 2290 | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /** \brief Read the data specified by the given \ref vigra::HDF5ImportInfo
object | | /** \brief Read the data specified by the given \ref vigra::HDF5ImportInfo
object | |
| and write the into the given 'array'. | | and write the into the given 'array'. | |
| | | | |
| The array must have the correct number of dimensions and shape for the
dataset | | The array must have the correct number of dimensions and shape for the
dataset | |
| represented by 'info'. When the element type of 'array' differs from th
e stored element | | represented by 'info'. When the element type of 'array' differs from th
e stored element | |
| type, HDF5 will convert the type on the fly (except when the HDF5 versi
on is 1.6 or below, | | type, HDF5 will convert the type on the fly (except when the HDF5 versi
on is 1.6 or below, | |
|
| in which case an error will result). Multi-channel element types (i.e. | | in which case an error will result). Multi-channel element types (i.e. | |
| \ref vigra::RGBValue | | \ref vigra::RGBValue, | |
| and \ref vigra::TinyVector) are recognized and handled correctly. | | \ref vigra::TinyVector, and \ref vigra::FFTWComplex) are recognized and | |
| | | handled correctly. | |
| | | | |
| <b> Declaration:</b> | | <b> Declaration:</b> | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template<unsigned int N, class T, class StrideTag> | | template<unsigned int N, class T, class StrideTag> | |
| void | | void | |
| readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, StrideTag
> array); | | readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, StrideTag
> array); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
| skipping to change at line 2240 | | skipping to change at line 2342 | |
| readHDF5(info, array, detail::getH5DataType<T>(), SIZE); | | readHDF5(info, array, detail::getH5DataType<T>(), SIZE); | |
| } | | } | |
| | | | |
| // non-scalar (RGBValue) and unstrided target multi array | | // non-scalar (RGBValue) and unstrided target multi array | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, RGBValue
<T>, UnstridedArrayTag> array) | | inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, RGBValue
<T>, UnstridedArrayTag> array) | |
| { | | { | |
| readHDF5(info, array, detail::getH5DataType<T>(), 3); | | readHDF5(info, array, detail::getH5DataType<T>(), 3); | |
| } | | } | |
| | | | |
|
| | | // non-scalar (FFTWComplex) and unstrided target multi array | |
| | | template<unsigned int N, class T> | |
| | | inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, FFTWComp | |
| | | lex<T>, UnstridedArrayTag> array) | |
| | | { | |
| | | readHDF5(info, array, detail::getH5DataType<T>(), 2); | |
| | | } | |
| | | | |
| // unstrided target multi array | | // unstrided target multi array | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, UnstridedArr
ayTag> array, const hid_t datatype, const int numBandsOfType) | | void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, UnstridedArr
ayTag> array, const hid_t datatype, const int numBandsOfType) | |
| { | | { | |
| int offset = (numBandsOfType > 1); | | int offset = (numBandsOfType > 1); | |
| | | | |
| //std::cout << "offset: " << offset << ", N: " << N << ", dims: " << in
fo.numDimensions() << std::endl; | | //std::cout << "offset: " << offset << ", N: " << N << ", dims: " << in
fo.numDimensions() << std::endl; | |
| vigra_precondition(( (N + offset ) == info.numDimensions()), // the obj
ect in the HDF5 file may have one additional dimension which we then interp
ret as the pixel type bands | | vigra_precondition(( (N + offset ) == info.numDimensions()), // the obj
ect in the HDF5 file may have one additional dimension which we then interp
ret as the pixel type bands | |
| "readHDF5(): Array dimension disagrees with HDF5ImportInfo.numDimen
sions()."); | | "readHDF5(): Array dimension disagrees with HDF5ImportInfo.numDimen
sions()."); | |
| | | | |
| | | | |
| skipping to change at line 2514 | | skipping to change at line 2623 | |
| } | | } | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /** \brief Store array data in an HDF5 file. | | /** \brief Store array data in an HDF5 file. | |
| | | | |
| The number of dimensions, shape and element type of the stored dataset
is automatically | | The number of dimensions, shape and element type of the stored dataset
is automatically | |
| determined from the properties of the given \a array. Strided arrays ar
e stored in an | | determined from the properties of the given \a array. Strided arrays ar
e stored in an | |
| unstrided way, i.e. in contiguous scan-order. Multi-channel element typ
es | | unstrided way, i.e. in contiguous scan-order. Multi-channel element typ
es | |
|
| (i.e. \ref vigra::RGBValue and \ref vigra::TinyVector) are recognized a | | (i.e. \ref vigra::RGBValue, \ref vigra::TinyVector and \ref vigra::FFTW | |
| nd handled correctly | | Complex) | |
| | | are recognized and handled correctly | |
| (in particular, the will form the innermost dimension of the stored dat
aset). | | (in particular, the will form the innermost dimension of the stored dat
aset). | |
| \a pathInFile may contain '/'-separated group names, but must end with
the name | | \a pathInFile may contain '/'-separated group names, but must end with
the name | |
| of the dataset to be created. | | of the dataset to be created. | |
| | | | |
| <b> Declaration:</b> | | <b> Declaration:</b> | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template<unsigned int N, class T, class StrideTag> | | template<unsigned int N, class T, class StrideTag> | |
| void | | void | |
| | | | |
| skipping to change at line 2608 | | skipping to change at line 2718 | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), SIZE
); | | writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), SIZE
); | |
| } | | } | |
| | | | |
| // non-scalar (RGBValue) and strided multi arrays | | // non-scalar (RGBValue) and strided multi arrays | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M
ultiArrayView<N, RGBValue<T>, StridedArrayTag> & array) | | inline void writeHDF5(const char* filePath, const char* pathInFile, const M
ultiArrayView<N, RGBValue<T>, StridedArrayTag> & array) | |
| { | | { | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 3); | | writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 3); | |
| } | | } | |
| | | | |
|
| // non-scalar (RGBValue) and strided multi arrays | | // non-scalar (FFTWComplex) and strided multi arrays | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M
ultiArrayView<N, FFTWComplex<T>, StridedArrayTag> & array) | | inline void writeHDF5(const char* filePath, const char* pathInFile, const M
ultiArrayView<N, FFTWComplex<T>, StridedArrayTag> & array) | |
| { | | { | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 2); | | writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 2); | |
| } | | } | |
| | | | |
| // strided multi arrays | | // strided multi arrays | |
| template<unsigned int N, class T> | | template<unsigned int N, class T> | |
| void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr
ayView<N, T, StridedArrayTag> & array, const hid_t datatype, const int numB
andsOfType) | | void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr
ayView<N, T, StridedArrayTag> & array, const hid_t datatype, const int numB
andsOfType) | |
| { | | { | |
| | | | |
End of changes. 162 change blocks. |
| 510 lines changed or deleted | | 693 lines changed or added | |
|
| impex.hxx | | impex.hxx | |
| /************************************************************************/ | | /************************************************************************/ | |
| /* */ | | /* */ | |
| /* Copyright 2001-2002 by Gunnar Kedenburg */ | | /* Copyright 2001-2002 by Gunnar Kedenburg */ | |
|
| | | /* Copyright 2012 Christoph Spiel and Ullrich Koethe */ | |
| /* */ | | /* */ | |
| /* This file is part of the VIGRA computer vision library. */ | | /* This file is part of the VIGRA computer vision library. */ | |
| /* The VIGRA Website is */ | | /* The VIGRA Website is */ | |
| /* http://hci.iwr.uni-heidelberg.de/vigra/ */ | | /* http://hci.iwr.uni-heidelberg.de/vigra/ */ | |
| /* Please direct questions, bug reports, and contributions to */ | | /* Please direct questions, bug reports, and contributions to */ | |
| /* ullrich.koethe@iwr.uni-heidelberg.de or */ | | /* ullrich.koethe@iwr.uni-heidelberg.de or */ | |
| /* vigra@informatik.uni-hamburg.de */ | | /* vigra@informatik.uni-hamburg.de */ | |
| /* */ | | /* */ | |
| /* Permission is hereby granted, free of charge, to any person */ | | /* Permission is hereby granted, free of charge, to any person */ | |
| /* obtaining a copy of this software and associated documentation */ | | /* obtaining a copy of this software and associated documentation */ | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 36 | |
| /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ | | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ | |
| /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ | | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ | |
| /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ | | /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ | |
| /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ | | /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ | |
| /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ | | /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ | |
| /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | | /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | |
| /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | | /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
|
| /* Modifications by Pablo d'Angelo | | | |
| * updated to vigra 1.4 by Douglas Wilkins | | | |
| * as of 18 February 2006: | | | |
| * - Added import/export of UINT16 and UINT32 image types. | | | |
| * Modifications by Andrew Mihal | | | |
| * updated to vigra 1.4 by Douglas Wilkins | | | |
| * as of 18 February 2006: | | | |
| * - Moved some RowIterator declarations around to avoid using default cto | | | |
| rs | | | |
| * (cachedfileimages do not have default ctors for row iterators). | | | |
| * - Added some case-specific optimizations | | | |
| */ | | | |
| | | | |
| /*! | | /*! | |
|
| \file impex.hxx | | * \file impex.hxx | |
| \brief image import and export functions | | * \brief image import and export functions | |
| | | * | |
| this file provides the declarations and implementations of importImage() | | * This module implements functions importImage() and exportImage(). | |
| and exportImage(). the matching implementation for the given datatype is | | * The matching implementation for any given datatype is selected by | |
| selected by template metacode. | | * template meta code. | |
| */ | | * | |
| | | */ | |
| | | | |
| #ifndef VIGRA_IMPEX_HXX | | #ifndef VIGRA_IMPEX_HXX | |
| #define VIGRA_IMPEX_HXX | | #define VIGRA_IMPEX_HXX | |
| | | | |
|
| #include "sized_int.hxx" | | | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
|
| #include "tinyvector.hxx" | | | |
| #include "imageinfo.hxx" | | #include "imageinfo.hxx" | |
|
| #include "numerictraits.hxx" | | #include "impexbase.hxx" | |
| #include "codec.hxx" | | | |
| #include "accessor.hxx" | | | |
| #include "inspectimage.hxx" | | | |
| #include "transformimage.hxx" | | | |
| #include "copyimage.hxx" | | | |
| #include "multi_array.hxx" | | | |
| #include <typeinfo> | | | |
| #include <iostream> | | | |
| | | | |
| // TODO | | | |
| // next refactoring: pluggable conversion algorithms | | | |
| | | | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| /** \addtogroup VigraImpex | | /** \addtogroup VigraImpex | |
|
| **/ | | * @{ | |
| //@{ | | */ | |
| | | namespace detail | |
| /*! | | { | |
| \brief used for reading bands after the source data type has been fig | | template <class ValueType, | |
| ured out. | | class ImageIterator, class ImageAccessor> | |
| | | void | |
| <b>\#include</b> \<vigra/impex.hxx\><br> | | read_image_band(Decoder* decoder, | |
| Namespace: vigra | | ImageIterator image_iterator, ImageAccessor image_a | |
| | | ccessor) | |
| | | { | |
| | | typedef typename ImageIterator::row_iterator ImageRowIterator; | |
| | | | |
|
| <b> Declaration:</b> | | const unsigned width(decoder->getWidth()); | |
| | | const unsigned height(decoder->getHeight()); | |
| | | const unsigned offset(decoder->getOffset()); | |
| | | | |
|
| \code | | for (unsigned y = 0U; y != height; ++y) | |
| namespace vigra { | | { | |
| template< class ImageIterator, class Accessor, class SrcValueTy | | decoder->nextScanline(); | |
| pe > | | | |
| void read_bands( Decoder * dec, ImageIterator ys, Accessor a, S | | | |
| rcValueType ) | | | |
| } | | | |
| \endcode | | | |
| | | | |
|
| \param dec decoder object through which the source data will be acces | | const ValueType* scanline = static_cast<const ValueType*>(d | |
| sed | | ecoder->currentScanlineOfBand(0)); | |
| \param ys image iterator referencing the upper left pixel of the des | | | |
| tination image | | | |
| \param a image accessor for the destination image | | | |
| */ | | | |
| template< class ImageIterator, class Accessor, class SrcValueType > | | | |
| void read_bands( Decoder * dec, ImageIterator ys, Accessor a, SrcValueT | | | |
| ype ) | | | |
| { | | | |
| | | | |
|
| typedef unsigned int size_type; | | ImageRowIterator is(image_iterator.rowIterator()); | |
| typedef typename ImageIterator::row_iterator DstRowIterator; | | const ImageRowIterator is_end(is + width); | |
| typedef typename Accessor::value_type AccessorValueType; | | | |
| typedef typename AccessorValueType::value_type DstValueType; | | | |
| | | | |
| const size_type width = dec->getWidth(); | | | |
| const size_type height = dec->getHeight(); | | | |
| const size_type num_bands = dec->getNumBands(); | | | |
| | | | |
| vigra_precondition(num_bands == (size_type)a.size(ys), | | | |
| "importImage(): number of bands (color channels) in file and de | | | |
| stination image differ."); | | | |
| | | | |
| SrcValueType const * scanline; | | | |
| // MIHAL no default constructor available for cachedfileimages. | | | |
| DstRowIterator xs = ys.rowIterator(); | | | |
| | | | |
|
| // iterate | | while (is != is_end) | |
| if (num_bands == 4) | | | |
| { | | | |
| // Speedup for this particular case | | | |
| unsigned int offset = dec->getOffset(); | | | |
| SrcValueType const * scanline0; | | | |
| SrcValueType const * scanline1; | | | |
| SrcValueType const * scanline2; | | | |
| SrcValueType const * scanline3; | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) | | | |
| { | | | |
| dec->nextScanline(); | | | |
| xs = ys.rowIterator(); | | | |
| scanline0 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(0)); | | | |
| scanline1 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(1)); | | | |
| scanline2 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(2)); | | | |
| scanline3 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(3)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) | | | |
| { | | { | |
|
| a.setComponent( *scanline0, xs, 0); | | image_accessor.set(*scanline, is); | |
| a.setComponent( *scanline1, xs, 1); | | scanline += offset; | |
| a.setComponent( *scanline2, xs, 2); | | ++is; | |
| a.setComponent( *scanline3, xs, 3); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| scanline2 += offset; | | | |
| scanline3 += offset; | | | |
| } | | } | |
|
| } | | | |
| } | | | |
| else | | | |
| { | | | |
| // General case | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) | | | |
| { | | | |
| dec->nextScanline(); | | | |
| for( size_type b = 0; b < num_bands; ++b ) | | | |
| { | | | |
| xs = ys.rowIterator(); | | | |
| scanline = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(b)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) | | | |
| { | | | |
| a.setComponent( *scanline, xs, b ); | | | |
| scanline += dec->getOffset(); | | | |
| } | | | |
| } | | | |
| } | | | |
| } | | | |
| } // read_bands() | | | |
| | | | |
| // specialization for speed-up (the standard version would also work, | | | |
| // but causes a stupid gcc waring) | | | |
| template< class ImageIterator, class RGBType, | | | |
| class SrcValueType > | | | |
| void read_bands( Decoder * dec, ImageIterator ys, | | | |
| RGBAccessor<RGBType> a, SrcValueType ) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| typedef typename ImageIterator::row_iterator DstRowIterator; | | | |
| typedef RGBType AccessorValueType; | | | |
| typedef typename AccessorValueType::value_type DstValueType; | | | |
| | | | |
| const size_type width = dec->getWidth(); | | | |
| const size_type height = dec->getHeight(); | | | |
| const size_type num_bands = dec->getNumBands(); | | | |
| | | | |
| vigra_precondition(num_bands == (size_type)a.size(ys), | | | |
| "importImage(): number of bands (color channels) in file and des | | | |
| tination image differ."); | | | |
| | | | |
| // MIHAL no default constructor available for cachedfileimages. | | | |
| DstRowIterator xs = ys.rowIterator(); | | | |
| | | | |
| // Speedup for this particular case | | | |
| unsigned int offset = dec->getOffset(); | | | |
| SrcValueType const * scanline0; | | | |
| SrcValueType const * scanline1; | | | |
| SrcValueType const * scanline2; | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) | | | |
| { | | | |
| dec->nextScanline(); | | | |
| xs = ys.rowIterator(); | | | |
| scanline0 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(0)); | | | |
| scanline1 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(1)); | | | |
| scanline2 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(2)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) | | | |
| { | | | |
| a.setComponent( *scanline0, xs, 0); | | | |
| a.setComponent( *scanline1, xs, 1); | | | |
| a.setComponent( *scanline2, xs, 2); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| scanline2 += offset; | | | |
| } | | | |
| } | | | |
| } // read_bands() | | | |
| | | | |
|
| // specialization for speed-up (the standard version would also work, | | ++image_iterator.y; | |
| // but causes a stupid gcc waring) | | | |
| template< class ImageIterator, class ComponentType, class SrcValueType | | | |
| > | | | |
| void read_bands( Decoder * dec, ImageIterator ys, | | | |
| VectorAccessor<TinyVector<ComponentType, 3> > a, SrcVa | | | |
| lueType ) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| typedef typename ImageIterator::row_iterator DstRowIterator; | | | |
| typedef TinyVector<ComponentType, 3> AccessorValueType; | | | |
| typedef typename AccessorValueType::value_type DstValueType; | | | |
| | | | |
| const size_type width = dec->getWidth(); | | | |
| const size_type height = dec->getHeight(); | | | |
| const size_type num_bands = dec->getNumBands(); | | | |
| | | | |
| vigra_precondition(num_bands == (size_type)a.size(ys), | | | |
| "importImage(): number of bands (color channels) in file and des | | | |
| tination image differ."); | | | |
| | | | |
| // MIHAL no default constructor available for cachedfileimages. | | | |
| DstRowIterator xs = ys.rowIterator(); | | | |
| | | | |
| // Speedup for this particular case | | | |
| unsigned int offset = dec->getOffset(); | | | |
| SrcValueType const * scanline0; | | | |
| SrcValueType const * scanline1; | | | |
| SrcValueType const * scanline2; | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) | | | |
| { | | | |
| dec->nextScanline(); | | | |
| xs = ys.rowIterator(); | | | |
| scanline0 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(0)); | | | |
| scanline1 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(1)); | | | |
| scanline2 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(2)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) | | | |
| { | | | |
| a.setComponent( *scanline0, xs, 0); | | | |
| a.setComponent( *scanline1, xs, 1); | | | |
| a.setComponent( *scanline2, xs, 2); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| scanline2 += offset; | | | |
| } | | } | |
| } | | } | |
|
| } // read_bands() | | | |
| | | | |
|
| // specialization for speed-up (the standard version would also work, | | template <class ValueType, | |
| // but causes a stupid gcc waring) | | class ImageIterator, class ImageAccessor> | |
| template< class ImageIterator, class ComponentType, class SrcValueType | | void | |
| > | | read_image_bands(Decoder* decoder, | |
| void read_bands( Decoder * dec, ImageIterator ys, | | ImageIterator image_iterator, ImageAccessor image_ | |
| VectorAccessor<TinyVector<ComponentType, 4> > a, SrcVa | | accessor) | |
| lueType ) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| typedef typename ImageIterator::row_iterator DstRowIterator; | | | |
| typedef TinyVector<ComponentType, 4> AccessorValueType; | | | |
| typedef typename AccessorValueType::value_type DstValueType; | | | |
| | | | |
| const size_type width = dec->getWidth(); | | | |
| const size_type height = dec->getHeight(); | | | |
| const size_type num_bands = dec->getNumBands(); | | | |
| | | | |
| vigra_precondition(num_bands == (size_type)a.size(ys), | | | |
| "importImage(): number of bands (color channels) in file and des | | | |
| tination image differ."); | | | |
| | | | |
| // MIHAL no default constructor available for cachedfileimages. | | | |
| DstRowIterator xs = ys.rowIterator(); | | | |
| | | | |
| // Speedup for this particular case | | | |
| unsigned int offset = dec->getOffset(); | | | |
| SrcValueType const * scanline0; | | | |
| SrcValueType const * scanline1; | | | |
| SrcValueType const * scanline2; | | | |
| SrcValueType const * scanline3; | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) | | | |
| { | | { | |
|
| dec->nextScanline(); | | typedef typename ImageIterator::row_iterator ImageRowIterator; | |
| xs = ys.rowIterator(); | | | |
| scanline0 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(0)); | | | |
| scanline1 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(1)); | | | |
| scanline2 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(2)); | | | |
| scanline3 = static_cast< SrcValueType const * > | | | |
| (dec->currentScanlineOfBand(3)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) | | | |
| { | | | |
| a.setComponent( *scanline0, xs, 0); | | | |
| a.setComponent( *scanline1, xs, 1); | | | |
| a.setComponent( *scanline2, xs, 2); | | | |
| a.setComponent( *scanline3, xs, 3); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| scanline2 += offset; | | | |
| scanline3 += offset; | | | |
| } | | | |
| } | | | |
| } // read_bands() | | | |
| | | | |
| /*! | | | |
| \brief used for reading bands after the source data type has been fig | | | |
| ured out. | | | |
| | | | |
| <b>\#include</b> \<vigra/impex.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| <b> Declaration:</b> | | | |
| | | | |
| \code | | | |
| namespace vigra { | | | |
| template< class ImageIterator, class Accessor, class SrcValueTy | | | |
| pe > | | | |
| void read_band( Decoder * dec, ImageIterator ys, Accessor a, Sr | | | |
| cValueType ) | | | |
| } | | | |
| \endcode | | | |
| | | | |
| \param dec decoder object through which the source data will be acces | | | |
| sed | | | |
| \param ys image iterator referencing the upper left pixel of the des | | | |
| tination image | | | |
| \param a image accessor for the destination image | | | |
| */ | | | |
| template< class ImageIterator, class Accessor, class SrcValueType > | | | |
| void read_band( Decoder * dec, ImageIterator ys, Accessor a, SrcValueTy | | | |
| pe ) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| typedef typename ImageIterator::row_iterator DstRowIterator; | | | |
| typedef typename Accessor::value_type DstValueType; | | | |
| const size_type width = dec->getWidth(); | | | |
| const size_type height = dec->getHeight(); | | | |
| | | | |
| SrcValueType const * scanline; | | | |
| // MIHAL no default constructor available for cachedfileimages. | | | |
| DstRowIterator xs = ys.rowIterator(); | | | |
| | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) { | | | |
| dec->nextScanline(); | | | |
| xs = ys.rowIterator(); | | | |
| scanline = static_cast< SrcValueType const * >(dec->currentScan | | | |
| lineOfBand(0)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) | | | |
| a.set( scanline[x], xs ); | | | |
| } | | | |
| } // read_band() | | | |
| | | | |
| /*! | | | |
| \brief used for reading images of vector type, such as integer of flo | | | |
| at rgb. | | | |
| | | | |
| <b>\#include</b> \<vigra/impex.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| <b> Declaration:</b> | | | |
| | | | |
| \code | | | |
| namespace vigra { | | | |
| template< class ImageIterator, class Accessor > | | | |
| void importVectorImage( const ImageImportInfo & info, ImageIter | | | |
| ator iter, Accessor a ) | | | |
| } | | | |
| \endcode | | | |
| | | | |
|
| <b> Parameters:</b> | | const unsigned width(decoder->getWidth()); | |
| | | const unsigned height(decoder->getHeight()); | |
| | | const unsigned offset(decoder->getOffset()); | |
| | | const unsigned accessor_size(image_accessor.size(image_iterator | |
| | | )); | |
| | | | |
|
| <DL> | | // OPTIMIZATION: Specialization for the most common case | |
| <DT>ImageIterator<DD> the image iterator type for the destination i | | // of an RGB-image, i.e. 3 channels. | |
| mage | | if (accessor_size == 3U) | |
| <DT>Accessor<DD> the image accessor type for the destination image | | { | |
| <DT>info<DD> user supplied image import information | | const ValueType* scanline_0; | |
| <DT>iter<DD> image iterator referencing the upper left pixel of the | | const ValueType* scanline_1; | |
| destination image | | const ValueType* scanline_2; | |
| <DT>a<DD> image accessor for the destination image | | | |
| </DL> | | | |
| */ | | | |
| doxygen_overloaded_function(template <...> void importVectorImage) | | | |
| | | | |
| template< class ImageIterator, class Accessor > | | | |
| void importVectorImage( const ImageImportInfo & info, ImageIterator ite | | | |
| r, Accessor a ) | | | |
| { | | | |
| std::auto_ptr<Decoder> dec = decoder(info); | | | |
| std::string pixeltype = dec->getPixelType(); | | | |
| | | | |
| if ( pixeltype == "UINT8" ) | | | |
| read_bands( dec.get(), iter, a, (UInt8)0 ); | | | |
| else if ( pixeltype == "INT16" ) | | | |
| read_bands( dec.get(), iter, a, Int16() ); | | | |
| else if ( pixeltype == "UINT16" ) | | | |
| read_bands( dec.get(), iter, a, (UInt16)0 ); | | | |
| else if ( pixeltype == "INT32" ) | | | |
| read_bands( dec.get(), iter, a, Int32() ); | | | |
| else if ( pixeltype == "UINT32" ) | | | |
| read_bands( dec.get(), iter, a, (UInt32)0 ); | | | |
| else if ( pixeltype == "FLOAT" ) | | | |
| read_bands( dec.get(), iter, a, float() ); | | | |
| else if ( pixeltype == "DOUBLE" ) | | | |
| read_bands( dec.get(), iter, a, double() ); | | | |
| else | | | |
| vigra_precondition( false, "invalid pixeltype" ); | | | |
| | | | |
| // close the decoder | | | |
| dec->close(); | | | |
| } | | | |
| | | | |
|
| /*! | | for (unsigned y = 0U; y != height; ++y) | |
| \brief used for reading images of scalar type, such as integer and f | | { | |
| loat grayscale. | | decoder->nextScanline(); | |
| | | | |
|
| <b>\#include</b> \<vigra/impex.hxx\><br> | | scanline_0 = static_cast<const ValueType*>(decoder->cur | |
| Namespace: vigra | | rentScanlineOfBand(0)); | |
| | | scanline_1 = static_cast<const ValueType*>(decoder->cur | |
| | | rentScanlineOfBand(1)); | |
| | | scanline_2 = static_cast<const ValueType*>(decoder->cur | |
| | | rentScanlineOfBand(2)); | |
| | | | |
|
| <b> Declaration:</b> | | ImageRowIterator is(image_iterator.rowIterator()); | |
| | | const ImageRowIterator is_end(is + width); | |
| | | | |
|
| \code | | while (is != is_end) | |
| namespace vigra { | | { | |
| template < class ImageIterator, class Accessor > | | image_accessor.setComponent(*scanline_0, is, 0); | |
| void importScalarImage( const ImageImportInfo & info, ImageIter | | image_accessor.setComponent(*scanline_1, is, 1); | |
| ator iter, Accessor a ) | | image_accessor.setComponent(*scanline_2, is, 2); | |
| } | | | |
| \endcode | | scanline_0 += offset; | |
| | | scanline_1 += offset; | |
| | | scanline_2 += offset; | |
| | | | |
|
| <b> Parameters:</b> | | ++is; | |
| | | } | |
| | | | |
|
| <DL> | | ++image_iterator.y; | |
| <DT>ImageIterator<DD> the image iterator type for the destination i | | } | |
| mage | | } | |
| <DT>Accessor<DD> the image accessor type for the destination image | | else | |
| <DT>info<DD> user supplied image import information | | { | |
| <DT>iter<DD> image iterator referencing the upper left pixel of the | | std::vector<const ValueType*> scanlines(accessor_size); | |
| destination image | | | |
| <DT>a<DD> image accessor for the destination image | | | |
| </DL> | | | |
| */ | | | |
| doxygen_overloaded_function(template <...> void importScalarImage) | | | |
| | | | |
|
| template < class ImageIterator, class Accessor > | | for (unsigned y = 0U; y != height; ++y) | |
| void importScalarImage( const ImageImportInfo & info, ImageIterator ite | | { | |
| r, Accessor a ) | | decoder->nextScanline(); | |
| { | | | |
| std::auto_ptr<Decoder> dec = decoder(info); | | | |
| std::string pixeltype = dec->getPixelType(); | | | |
| | | | |
|
| if ( pixeltype == "UINT8" ) | | for (unsigned i = 0U; i != accessor_size; ++i) | |
| read_band( dec.get(), iter, a, (UInt8)0 ); | | { | |
| else if ( pixeltype == "INT16" ) | | scanlines[i] = static_cast<const ValueType*>(decode | |
| read_band( dec.get(), iter, a, Int16() ); | | r->currentScanlineOfBand(i)); | |
| else if ( pixeltype == "UINT16" ) | | } | |
| read_band( dec.get(), iter, a, (UInt16)0 ); | | | |
| else if ( pixeltype == "INT32" ) | | | |
| read_band( dec.get(), iter, a, Int32() ); | | | |
| else if ( pixeltype == "UINT32" ) | | | |
| read_band( dec.get(), iter, a, (UInt32)0 ); | | | |
| else if ( pixeltype == "FLOAT" ) | | | |
| read_band( dec.get(), iter, a, float() ); | | | |
| else if ( pixeltype == "DOUBLE" ) | | | |
| read_band( dec.get(), iter, a, double() ); | | | |
| else | | | |
| vigra_precondition( false, "invalid pixeltype" ); | | | |
| | | | |
|
| // close the decoder | | ImageRowIterator is(image_iterator.rowIterator()); | |
| dec->close(); | | const ImageRowIterator is_end(is + width); | |
| } | | | |
| | | | |
|
| /********************************************************/ | | while (is != is_end) | |
| /* */ | | { | |
| /* importImage */ | | for (unsigned i = 0U; i != accessor_size; ++i) | |
| /* */ | | { | |
| /********************************************************/ | | image_accessor.setComponent(*scanlines[i], is, | |
| | | static_cast<int>(i)); | |
| /** \brief Read the image specified by the given \ref vigra::ImageImpor | | scanlines[i] += offset; | |
| tInfo object. | | } | |
| | | ++is; | |
| <b> Declarations:</b> | | } | |
| | | | |
| pass arguments explicitly: | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class ImageIterator, class Accessor> | | | |
| void | | | |
| importImage(ImageImportInfo const & image, ImageIterator iter, | | | |
| Accessor a) | | | |
| } | | | |
| \endcode | | | |
| | | | |
|
| use argument objects in conjunction with \ref ArgumentObjectFactori | | ++image_iterator.y; | |
| es : | | } | |
| \code | | } | |
| namespace vigra { | | | |
| template <class ImageIterator, class Accessor> | | | |
| inline void | | | |
| importImage(ImageImportInfo const & image, pair<ImageIterator, | | | |
| Accessor> dest) | | | |
| } | | } | |
|
| \endcode | | | |
| | | | |
| <b> Usage:</b> | | | |
| | | | |
| <b>\#include</b> \<vigra/impex.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| \code | | | |
| | | | |
|
| vigra::ImageImportInfo info("myimage.gif"); | | template <class ImageIterator, class ImageAccessor> | |
| | | void | |
| if(info.isGrayscale()) | | importImage(const ImageImportInfo& import_info, | |
| | | ImageIterator image_iterator, ImageAccessor image_acces | |
| | | sor, | |
| | | /* isScalar? */ VigraTrueType) | |
| { | | { | |
|
| // create byte image of appropriate size | | VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info)); | |
| vigra::BImage in(info.width(), info.height()); | | | |
| | | | |
|
| vigra::importImage(info, destImage(in)); // read the image | | switch (pixel_t_of_string(decoder->getPixelType())) | |
| ... | | { | |
| } | | case UNSIGNED_INT_8: | |
| else | | read_image_band<UInt8>(decoder.get(), image_iterator, image | |
| | | _accessor); | |
| | | break; | |
| | | case UNSIGNED_INT_16: | |
| | | read_image_band<UInt16>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | case UNSIGNED_INT_32: | |
| | | read_image_band<UInt32>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | case SIGNED_INT_16: | |
| | | read_image_band<Int16>(decoder.get(), image_iterator, image | |
| | | _accessor); | |
| | | break; | |
| | | case SIGNED_INT_32: | |
| | | read_image_band<Int32>(decoder.get(), image_iterator, image | |
| | | _accessor); | |
| | | break; | |
| | | case IEEE_FLOAT_32: | |
| | | read_image_band<float>(decoder.get(), image_iterator, image | |
| | | _accessor); | |
| | | break; | |
| | | case IEEE_FLOAT_64: | |
| | | read_image_band<double>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | default: | |
| | | vigra_fail("detail::importImage<scalar>: not reached"); | |
| | | } | |
| | | | |
| | | decoder->close(); | |
| | | } | |
| | | | |
| | | template <class ImageIterator, class ImageAccessor> | |
| | | void | |
| | | importImage(const ImageImportInfo& import_info, | |
| | | ImageIterator image_iterator, ImageAccessor image_acces | |
| | | sor, | |
| | | /* isScalar? */ VigraFalseType) | |
| { | | { | |
|
| // create byte RGB image of appropriate size | | VIGRA_UNIQUE_PTR<Decoder> decoder(vigra::decoder(import_info)); | |
| vigra::BRGBImage in(info.width(), info.height()); | | | |
| | | | |
|
| vigra::importImage(info, destImage(in)); // read the image | | switch (pixel_t_of_string(decoder->getPixelType())) | |
| ... | | { | |
| } | | case UNSIGNED_INT_8: | |
| | | read_image_bands<UInt8>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | case UNSIGNED_INT_16: | |
| | | read_image_bands<UInt16>(decoder.get(), image_iterator, ima | |
| | | ge_accessor); | |
| | | break; | |
| | | case UNSIGNED_INT_32: | |
| | | read_image_bands<UInt32>(decoder.get(), image_iterator, ima | |
| | | ge_accessor); | |
| | | break; | |
| | | case SIGNED_INT_16: | |
| | | read_image_bands<Int16>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | case SIGNED_INT_32: | |
| | | read_image_bands<Int32>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | case IEEE_FLOAT_32: | |
| | | read_image_bands<float>(decoder.get(), image_iterator, imag | |
| | | e_accessor); | |
| | | break; | |
| | | case IEEE_FLOAT_64: | |
| | | read_image_bands<double>(decoder.get(), image_iterator, ima | |
| | | ge_accessor); | |
| | | break; | |
| | | default: | |
| | | vigra_fail("vigra::detail::importImage<non-scalar>: not rea | |
| | | ched"); | |
| | | } | |
| | | | |
| | | decoder->close(); | |
| | | } | |
| | | | |
| | | template<class ValueType, | |
| | | class ImageIterator, class ImageAccessor, class ImageScale | |
| | | r> | |
| | | void | |
| | | write_image_band(Encoder* encoder, | |
| | | ImageIterator image_upper_left, ImageIterator imag | |
| | | e_lower_right, ImageAccessor image_accessor, | |
| | | const ImageScaler& image_scaler) | |
| | | { | |
| | | typedef typename ImageIterator::row_iterator ImageRowIterator; | |
| | | typedef typename ImageAccessor::value_type ImageValueType; | |
| | | | |
| | | typedef RequiresExplicitCast<ValueType> explicit_cast; | |
| | | | |
| | | vigra_precondition(image_lower_right.x >= image_upper_left.x, | |
| | | "vigra::detail::write_image_band: negative w | |
| | | idth"); | |
| | | vigra_precondition(image_lower_right.y >= image_upper_left.y, | |
| | | "vigra::detail::write_image_band: negative h | |
| | | eight"); | |
| | | | |
| | | const unsigned width(static_cast<unsigned>(image_lower_right.x | |
| | | - image_upper_left.x)); | |
| | | const unsigned height(static_cast<unsigned>(image_lower_right.y | |
| | | - image_upper_left.y)); | |
| | | | |
| | | encoder->setWidth(width); | |
| | | encoder->setHeight(height); | |
| | | encoder->setNumBands(1); | |
| | | encoder->finalizeSettings(); | |
| | | | |
| | | const unsigned offset(encoder->getOffset()); // correct offset | |
| | | only _after_ finalizeSettings() | |
| | | | |
| | | // IMPLEMENTATION NOTE: We avoid calling the default | |
| | | // constructor to allow classes ImageIterator that do not | |
| | | // define one. | |
| | | ImageIterator image_iterator(image_upper_left); | |
| | | | |
|
| \endcode | | for (unsigned y = 0U; y != height; ++y) | |
| | | { | |
| | | ValueType* scanline = static_cast<ValueType*>(encoder->curr | |
| | | entScanlineOfBand(0)); | |
| | | | |
|
| <b> Preconditions:</b> | | ImageRowIterator is(image_iterator.rowIterator()); | |
| | | const ImageRowIterator is_end(is + width); | |
| | | | |
|
| <UL> | | while (is != is_end) | |
| | | { | |
| | | *scanline = explicit_cast::cast(image_scaler(image_acce | |
| | | ssor(is))); | |
| | | scanline += offset; | |
| | | ++is; | |
| | | } | |
| | | | |
|
| <LI> the image file must be readable | | encoder->nextScanline(); | |
| <LI> the file type must be one of | | | |
| | | | |
|
| <DL> | | ++image_iterator.y; | |
| <DT>"BMP"<DD> Microsoft Windows bitmap image file. | | } | |
| <DT>"EXR"<DD> OpenEXR high dynamic range image format. | | } | |
| (only available if libopenexr is installed) | | | |
| <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit col | | | |
| or. | | | |
| <DT>"HDR"<DD> Radiance RGBE high dynamic range image format. | | | |
| <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; | | | |
| compressed 24-bit color (only available if libjpeg is installed | | | |
| ). | | | |
| <DT>"PNG"<DD> Portable Network Graphic | | | |
| (only available if libpng is installed). | | | |
| <DT>"PBM"<DD> Portable bitmap format (black and white). | | | |
| <DT>"PGM"<DD> Portable graymap format (gray scale). | | | |
| <DT>"PNM"<DD> Portable anymap. | | | |
| <DT>"PPM"<DD> Portable pixmap format (color). | | | |
| <DT>"SUN"<DD> SUN Rasterfile. | | | |
| <DT>"TIFF"<DD> Tagged Image File Format. | | | |
| (only available if libtiff is installed.) | | | |
| <DT>"VIFF"<DD> Khoros Visualization image file. | | | |
| </DL> | | | |
| </UL> | | | |
| **/ | | | |
| doxygen_overloaded_function(template <...> void importImage) | | | |
| | | | |
|
| template < class ImageIterator, class Accessor > | | template<class ValueType, | |
| void importImage( const ImageImportInfo & info, ImageIterator iter, Acc | | class ImageIterator, class ImageAccessor, class ImageScale | |
| essor a ) | | r> | |
| { | | void | |
| typedef typename NumericTraits<typename Accessor::value_type>::isSc | | write_image_bands(Encoder* encoder, | |
| alar is_scalar; | | ImageIterator image_upper_left, ImageIterator ima | |
| importImage( info, iter, a, is_scalar() ); | | ge_lower_right, ImageAccessor image_accessor, | |
| } | | const ImageScaler& image_scaler) | |
| | | { | |
| | | typedef typename ImageIterator::row_iterator ImageRowIterator; | |
| | | typedef RequiresExplicitCast<ValueType> explicit_cast; | |
| | | | |
|
| template < class ImageIterator, class Accessor > | | vigra_precondition(image_lower_right.x >= image_upper_left.x, | |
| void importImage( const ImageImportInfo & info, pair< ImageIterator, Ac | | "vigra::detail::write_image_bands: negative | |
| cessor > dest ) | | width"); | |
| { | | vigra_precondition(image_lower_right.y >= image_upper_left.y, | |
| importImage( info, dest.first, dest.second ); | | "vigra::detail::write_image_bands: negative | |
| } | | height"); | |
| | | | |
|
| template < class ImageIterator, class Accessor > | | const unsigned width(static_cast<unsigned>(image_lower_right.x | |
| void importImage( const ImageImportInfo & info, ImageIterator iter, Acc | | - image_upper_left.x)); | |
| essor a, VigraFalseType ) | | const unsigned height(static_cast<unsigned>(image_lower_right.y | |
| { | | - image_upper_left.y)); | |
| importVectorImage( info, iter, a ); | | const unsigned accessor_size(image_accessor.size(image_upper_le | |
| } | | ft)); | |
| | | | |
|
| template < class ImageIterator, class Accessor > | | encoder->setWidth(width); | |
| void importImage( const ImageImportInfo & info, ImageIterator iter, Acc | | encoder->setHeight(height); | |
| essor a, VigraTrueType ) | | encoder->setNumBands(accessor_size); | |
| { | | encoder->finalizeSettings(); | |
| importScalarImage( info, iter, a ); | | | |
| } | | | |
| | | | |
|
| /*! | | const unsigned offset(encoder->getOffset()); // correct offset | |
| \brief used for writing bands after the source data type has been fig | | only _after_ finalizeSettings() | |
| ured out. | | | |
| | | | |
|
| <b>\#include</b> \<vigra/impex.hxx\><br> | | // IMPLEMENTATION NOTE: We avoid calling the default | |
| Namespace: vigra | | // constructor to allow classes ImageIterator that do not | |
| | | // define one. | |
| | | ImageIterator image_iterator(image_upper_left); | |
| | | | |
|
| <b> Declaration:</b> | | // OPTIMIZATION: Specialization for the most common case | |
| | | // of an RGB-image, i.e. 3 channels. | |
| | | if (accessor_size == 3U) | |
| | | { | |
| | | ValueType* scanline_0; | |
| | | ValueType* scanline_1; | |
| | | ValueType* scanline_2; | |
| | | | |
|
| \code | | for (unsigned y = 0U; y != height; ++y) | |
| namespace vigra { | | { | |
| template< class ImageIterator, class Accessor, class DstValueTy | | scanline_0 = static_cast<ValueType*>(encoder->currentSc | |
| pe > | | anlineOfBand(0)); | |
| void write_bands( Encoder * enc, ImageIterator ul, ImageIterato | | scanline_1 = static_cast<ValueType*>(encoder->currentSc | |
| r lr, Accessor a, DstValueType ) | | anlineOfBand(1)); | |
| } | | scanline_2 = static_cast<ValueType*>(encoder->currentSc | |
| \endcode | | anlineOfBand(2)); | |
| | | | |
|
| \param enc encoder object through which the destination data will be | | ImageRowIterator is(image_iterator.rowIterator()); | |
| accessed | | const ImageRowIterator is_end(is + width); | |
| \param ul image iterator referencing the upper left pixel of the sou | | | |
| rce image | | | |
| \param lr image iterator referencing the lower right pixel of the so | | | |
| urce image | | | |
| \param a image accessor for the source image | | | |
| */ | | | |
| template< class ImageIterator, class Accessor, class DstValueType > | | | |
| void write_bands( Encoder * enc, ImageIterator ul, ImageIterator lr, Ac | | | |
| cessor a, DstValueType) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| typedef typename ImageIterator::row_iterator SrcRowIterator; | | | |
| typedef typename Accessor::value_type AccessorValueType; | | | |
| typedef typename AccessorValueType::value_type SrcValueType; | | | |
| | | | |
| // complete decoder settings | | | |
| const size_type width = lr.x - ul.x; | | | |
| const size_type height = lr.y - ul.y; | | | |
| enc->setWidth(width); | | | |
| enc->setHeight(height); | | | |
| const size_type num_bands = a.size(ul); | | | |
| enc->setNumBands(num_bands); | | | |
| enc->finalizeSettings(); | | | |
| | | | |
| DstValueType * scanline; | | | |
| | | | |
| // iterate | | | |
| ImageIterator ys(ul); | | | |
| // MIHAL no default constructor available for cachedfileimages | | | |
| SrcRowIterator xs = ys.rowIterator(); | | | |
| | | | |
|
| // Speedup for the common cases | | while (is != is_end) | |
| switch (num_bands) | | { | |
| { | | *scanline_0 = explicit_cast::cast(image_scaler(imag | |
| case 2: | | e_accessor.getComponent(is, 0))); | |
| { | | *scanline_1 = explicit_cast::cast(image_scaler(imag | |
| unsigned int offset = enc->getOffset(); | | e_accessor.getComponent(is, 1))); | |
| DstValueType * scanline0; | | *scanline_2 = explicit_cast::cast(image_scaler(imag | |
| DstValueType * scanline1; | | e_accessor.getComponent(is, 2))); | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) { | | | |
| xs = ys.rowIterator(); | | scanline_0 += offset; | |
| scanline0 = static_cast< DstValueType * > | | scanline_1 += offset; | |
| (enc->currentScanlineOfBand(0)); | | scanline_2 += offset; | |
| scanline1 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(1)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs) { | | | |
| *scanline0 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 0)); | | | |
| *scanline1 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 1)); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| } | | | |
| enc->nextScanline(); | | | |
| | | | |
|
| } | | ++is; | |
| break; | | | |
| } | | | |
| case 3: | | | |
| { | | | |
| unsigned int offset = enc->getOffset(); | | | |
| DstValueType * scanline0; | | | |
| DstValueType * scanline1; | | | |
| DstValueType * scanline2; | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) { | | | |
| xs = ys.rowIterator(); | | | |
| scanline0 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(0)); | | | |
| scanline1 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(1)); | | | |
| scanline2 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(2)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs) { | | | |
| *scanline0 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 0)); | | | |
| *scanline1 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 1)); | | | |
| *scanline2 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 2)); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| scanline2 += offset; | | | |
| } | | | |
| enc->nextScanline(); | | | |
| } | | | |
| break; | | | |
| } | | | |
| case 4: | | | |
| { | | | |
| unsigned int offset = enc->getOffset(); | | | |
| DstValueType * scanline0; | | | |
| DstValueType * scanline1; | | | |
| DstValueType * scanline2; | | | |
| DstValueType * scanline3; | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) { | | | |
| xs = ys.rowIterator(); | | | |
| scanline0 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(0)); | | | |
| scanline1 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(1)); | | | |
| scanline2 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(2)); | | | |
| scanline3 = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(3)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs) { | | | |
| *scanline0 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 0)); | | | |
| *scanline1 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 1)); | | | |
| *scanline2 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 2)); | | | |
| *scanline3 = detail::RequiresExplicitCast<DstValueType> | | | |
| ::cast(a.getComponent( xs, 3)); | | | |
| scanline0 += offset; | | | |
| scanline1 += offset; | | | |
| scanline2 += offset; | | | |
| scanline3 += offset; | | | |
| } | | | |
| enc->nextScanline(); | | | |
| } | | | |
| break; | | | |
| } | | | |
| default: | | | |
| { | | | |
| // General case | | | |
| for( size_type y = 0; y < height; ++y, ++ys.y ) { | | | |
| for( size_type b = 0; b < num_bands; ++b ) { | | | |
| xs = ys.rowIterator(); | | | |
| scanline = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(b)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs ) { | | | |
| *scanline = detail::RequiresExplicitCast<DstValueTy | | | |
| pe>::cast(a.getComponent( xs, b )); | | | |
| scanline += enc->getOffset(); | | | |
| } | | } | |
|
| } | | | |
| enc->nextScanline(); | | | |
| } | | | |
| } | | | |
| } | | | |
| } // write_bands() | | | |
| | | | |
|
| template< class MArray, class DstValueType > | | encoder->nextScanline(); | |
| void write_bands( Encoder * enc, MArray const & array, DstValueType) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| | | | |
|
| // complete decoder settings | | ++image_iterator.y; | |
| const size_type width = array.shape(0); | | | |
| const size_type height = array.shape(1); | | | |
| enc->setWidth(width); | | | |
| enc->setHeight(height); | | | |
| const size_type num_bands = array.shape(2); | | | |
| enc->setNumBands(num_bands); | | | |
| enc->finalizeSettings(); | | | |
| | | | |
| DstValueType * scanline; | | | |
| | | | |
| // iterate | | | |
| for( size_type y = 0; y < height; ++y ) { | | | |
| for( size_type b = 0; b < num_bands; ++b ) { | | | |
| scanline = static_cast< DstValueType * > | | | |
| (enc->currentScanlineOfBand(b)); | | | |
| for( size_type x = 0; x < width; ++x) { | | | |
| *scanline = array(x, y, b); | | | |
| scanline += enc->getOffset(); | | | |
| } | | } | |
| } | | } | |
|
| enc->nextScanline(); | | else | |
| } | | { | |
| } // write_bands() | | std::vector<ValueType*> scanlines(accessor_size); | |
| | | | |
|
| /*! | | for (unsigned y = 0U; y != height; ++y) | |
| \brief used for writing bands after the source data type has been fig | | { | |
| ured out. | | for (unsigned i = 0U; i != accessor_size; ++i) | |
| | | { | |
| | | scanlines[i] = static_cast<ValueType*>(encoder->cur | |
| | | rentScanlineOfBand(i)); | |
| | | } | |
| | | | |
|
| <b>\#include</b> \<vigra/impex.hxx\><br> | | ImageRowIterator is(image_iterator.rowIterator()); | |
| Namespace: vigra | | const ImageRowIterator is_end(is + width); | |
| | | | |
|
| <b> Declaration:</b> | | while (is != is_end) | |
| | | { | |
| | | for (unsigned i = 0U; i != accessor_size; ++i) | |
| | | { | |
| | | *scanlines[i] = explicit_cast::cast(image_scale | |
| | | r(image_accessor.getComponent(is, static_cast<int>(i)))); | |
| | | scanlines[i] += offset; | |
| | | } | |
| | | ++is; | |
| | | } | |
| | | | |
|
| \code | | encoder->nextScanline(); | |
| namespace vigra { | | | |
| template< class ImageIterator, class Accessor, class DstValueTy | | | |
| pe > | | | |
| void write_band( Encoder * enc, ImageIterator ul, ImageIterator | | | |
| lr, Accessor a, DstValueType ) | | | |
| } | | | |
| \endcode | | | |
| | | | |
|
| \param enc encoder object through which the destination data will be | | ++image_iterator.y; | |
| accessed | | } | |
| \param ul image iterator referencing the upper left pixel of the sou | | } | |
| rce image | | | |
| \param lr image iterator referencing the lower right pixel of the so | | | |
| urce image | | | |
| \param a image accessor for the source image | | | |
| */ | | | |
| template< class ImageIterator, class Accessor, class DstValueType > | | | |
| void write_band( Encoder * enc, ImageIterator ul, ImageIterator lr, Acc | | | |
| essor a, DstValueType) | | | |
| { | | | |
| typedef unsigned int size_type; | | | |
| typedef typename ImageIterator::row_iterator SrcRowIterator; | | | |
| typedef typename Accessor::value_type SrcValueType; | | | |
| | | | |
| // complete decoder settings | | | |
| const size_type width = size_type(lr.x - ul.x); | | | |
| const size_type height = size_type(lr.y - ul.y); | | | |
| enc->setWidth(width); | | | |
| enc->setHeight(height); | | | |
| enc->setNumBands(1); | | | |
| enc->finalizeSettings(); | | | |
| | | | |
| DstValueType * scanline; | | | |
| | | | |
| // iterate | | | |
| ImageIterator ys(ul); | | | |
| // MIHAL no default constructor available for cachedfileimages. | | | |
| SrcRowIterator xs = ys.rowIterator(); | | | |
| size_type y; | | | |
| for( y = 0; y < height; ++y, ++ys.y ) { | | | |
| xs = ys.rowIterator(); | | | |
| scanline = static_cast< DstValueType * >(enc->currentScanlineOf | | | |
| Band(0)); | | | |
| for( size_type x = 0; x < width; ++x, ++xs, ++scanline ) | | | |
| *scanline = detail::RequiresExplicitCast<DstValueType>::cas | | | |
| t(a(xs)); | | | |
| enc->nextScanline(); | | | |
| } | | } | |
|
| } // write_band() | | | |
| | | | |
|
| namespace detail { | | template <class ImageIterator, class ImageAccessor> | |
| | | void | |
| | | exportImage(ImageIterator image_upper_left, ImageIterator image_low | |
| | | er_right, ImageAccessor image_accessor, | |
| | | const ImageExportInfo& export_info, | |
| | | /* isScalar? */ VigraTrueType) | |
| | | { | |
| | | typedef typename ImageAccessor::value_type ImageValueType; | |
| | | | |
|
| // export scalar images without conversion | | VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info)); | |
| template < class SrcIterator, class SrcAccessor, class T > | | | |
| void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg | | | |
| et, | | | |
| Encoder * enc, T zero) | | | |
| { | | | |
| write_band( enc, sul, slr, sget, zero ); | | | |
| } | | | |
| | | | |
|
| // export scalar images with conversion | | std::string pixel_type(export_info.getPixelType()); | |
| template < class SrcIterator, class SrcAccessor, class T > | | const bool downcast(negotiatePixelType(encoder->getFileType(), | |
| void exportScalarImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg | | TypeAsString<ImageValueType>::result(), pixel_type)); | |
| et, | | const pixel_t type(pixel_t_of_string(pixel_type)); | |
| Encoder * enc, | | | |
| const ImageExportInfo & info, | | | |
| T zero) | | | |
| { | | | |
| double fromMin, fromMax, toMin, toMax; | | | |
| if(info.getFromMin() < info.getFromMax()) | | | |
| { | | | |
| fromMin = info.getFromMin(); | | | |
| fromMax = info.getFromMax(); | | | |
| } | | | |
| else | | | |
| { | | | |
| typedef typename SrcAccessor::value_type SrcValue; | | | |
| FindMinMax<SrcValue> minmax; | | | |
| inspectImage( sul, slr, sget, minmax ); | | | |
| | | | |
| fromMin = (double)minmax.min; | | | |
| fromMax = (double)minmax.max; | | | |
| if(fromMax <= fromMin) | | | |
| fromMax = fromMin + 1.0; | | | |
| } | | | |
| | | | |
|
| if(info.getToMin() < info.getToMax()) | | encoder->setPixelType(pixel_type); | |
| { | | | |
| toMin = info.getToMin(); | | | |
| toMax = info.getToMax(); | | | |
| } | | | |
| else | | | |
| { | | | |
| toMin = (double)NumericTraits<T>::min(); | | | |
| toMax = (double)NumericTraits<T>::max(); | | | |
| } | | | |
| | | | |
|
| double scale = (toMax - toMin) / (fromMax - fromMin); | | const range_t image_source_range(find_source_value_range(export | |
| double offset = (toMin / scale) - fromMin; | | _info, | |
| BasicImage<T> image(slr-sul); | | image_ | |
| transformImage( sul, slr, sget, image.upperLeft(), image.accessor() | | upper_left, image_lower_right, image_accessor)); | |
| , | | const range_t destination_range(find_destination_value_range(ex | |
| linearIntensityTransform(scale, offset)); | | port_info, type)); | |
| write_band( enc, image.upperLeft(), | | | |
| image.lowerRight(), image.accessor(), zero ); | | | |
| } | | | |
| | | | |
|
| // export vector images without conversion | | if ((downcast || export_info.hasForcedRangeMapping()) && | |
| template < class SrcIterator, class SrcAccessor, class T > | | (image_source_range.first != destination_range.first || ima | |
| void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg | | ge_source_range.second != destination_range.second)) | |
| et, | | { | |
| Encoder * enc, T zero) | | const linear_transform image_rescaler(image_source_range, d | |
| { | | estination_range); | |
| int bands = sget.size(sul); | | | |
| vigra_precondition(isBandNumberSupported(enc->getFileType(), bands) | | | |
| , | | | |
| "exportImage(): file format does not support requested number of | | | |
| bands (color channels)"); | | | |
| write_bands( enc, sul, slr, sget, zero ); | | | |
| } | | | |
| | | | |
|
| // export vector images with conversion | | switch (type) | |
| template < class SrcIterator, class SrcAccessor, class T > | | { | |
| void exportVectorImage(SrcIterator sul, SrcIterator slr, SrcAccessor sg | | case UNSIGNED_INT_8: | |
| et, | | write_image_band<UInt8>(encoder.get(), | |
| Encoder * enc, | | image_upper_left, image_lower_r | |
| const ImageExportInfo & info, | | ight, image_accessor, image_rescaler); | |
| T zero) | | break; | |
| { | | case UNSIGNED_INT_16: | |
| unsigned int bands = sget.size(sul); | | write_image_band<UInt16>(encoder.get(), | |
| vigra_precondition(isBandNumberSupported(enc->getFileType(), bands) | | image_upper_left, image_lower_ | |
| , | | right, image_accessor, image_rescaler); | |
| "exportImage(): file format does not support requested number of | | break; | |
| bands (color channels)"); | | case UNSIGNED_INT_32: | |
| | | write_image_band<UInt32>(encoder.get(), | |
| typedef typename SrcAccessor::ElementAccessor SrcElementAccessor; | | image_upper_left, image_lower_ | |
| typedef typename SrcElementAccessor::value_type SrcComponent; | | right, image_accessor, image_rescaler); | |
| double fromMin, fromMax, toMin, toMax; | | break; | |
| if(info.getFromMin() < info.getFromMax()) | | case SIGNED_INT_16: | |
| { | | write_image_band<Int16>(encoder.get(), | |
| fromMin = info.getFromMin(); | | image_upper_left, image_lower_r | |
| fromMax = info.getFromMax(); | | ight, image_accessor, image_rescaler); | |
| } | | break; | |
| else | | case SIGNED_INT_32: | |
| { | | write_image_band<Int32>(encoder.get(), | |
| FindMinMax<SrcComponent> minmax; | | image_upper_left, image_lower_r | |
| for(unsigned int i=0; i<bands; ++i) | | ight, image_accessor, image_rescaler); | |
| | | break; | |
| | | case IEEE_FLOAT_32: | |
| | | write_image_band<float>(encoder.get(), | |
| | | image_upper_left, image_lower_r | |
| | | ight, image_accessor, image_rescaler); | |
| | | break; | |
| | | case IEEE_FLOAT_64: | |
| | | write_image_band<double>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, image_rescaler); | |
| | | break; | |
| | | default: | |
| | | vigra_fail("vigra::detail::exportImage<scalar>: not rea | |
| | | ched"); | |
| | | } | |
| | | } | |
| | | else | |
| { | | { | |
|
| SrcElementAccessor band(i, sget); | | switch (type) | |
| inspectImage( sul, slr, band, minmax ); | | { | |
| | | case UNSIGNED_INT_8: | |
| | | write_image_band<UInt8>(encoder.get(), | |
| | | image_upper_left, image_lower_r | |
| | | ight, image_accessor, identity()); | |
| | | break; | |
| | | case UNSIGNED_INT_16: | |
| | | write_image_band<UInt16>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | case UNSIGNED_INT_32: | |
| | | write_image_band<UInt32>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | case SIGNED_INT_16: | |
| | | write_image_band<Int16>(encoder.get(), | |
| | | image_upper_left, image_lower_r | |
| | | ight, image_accessor, identity()); | |
| | | break; | |
| | | case SIGNED_INT_32: | |
| | | write_image_band<Int32>(encoder.get(), | |
| | | image_upper_left, image_lower_r | |
| | | ight, image_accessor, identity()); | |
| | | break; | |
| | | case IEEE_FLOAT_32: | |
| | | write_image_band<float>(encoder.get(), | |
| | | image_upper_left, image_lower_r | |
| | | ight, image_accessor, identity()); | |
| | | break; | |
| | | case IEEE_FLOAT_64: | |
| | | write_image_band<double>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | default: | |
| | | vigra_fail("vigra::detail::exportImage<scalar>: not rea | |
| | | ched"); | |
| | | } | |
| } | | } | |
| | | | |
|
| fromMin = (double)minmax.min; | | encoder->close(); | |
| fromMax = (double)minmax.max; | | | |
| if(fromMax <= fromMin) | | | |
| fromMax = fromMin + 1.0; | | | |
| } | | } | |
| | | | |
|
| if(info.getToMin() < info.getToMax()) | | template <class ImageIterator, class ImageAccessor> | |
| | | void | |
| | | exportImage(ImageIterator image_upper_left, ImageIterator image_low | |
| | | er_right, ImageAccessor image_accessor, | |
| | | const ImageExportInfo& export_info, | |
| | | /* isScalar? */ VigraFalseType) | |
| { | | { | |
|
| toMin = info.getToMin(); | | typedef typename ImageAccessor::value_type ImageBaseType; | |
| toMax = info.getToMax(); | | typedef typename ImageBaseType::value_type ImageValueType; | |
| } | | | |
| else | | | |
| { | | | |
| toMin = (double)NumericTraits<T>::min(); | | | |
| toMax = (double)NumericTraits<T>::max(); | | | |
| } | | | |
| | | | |
| double scale = (toMax - toMin) / (fromMax - fromMin); | | | |
| double offset = (toMin / scale) - fromMin; | | | |
| int w = slr.x - sul.x; | | | |
| int h = slr.y - sul.y; | | | |
| | | | |
| typedef vigra::MultiArray<3, T> MArray; | | | |
| MArray array(typename MArray::difference_type(w, h, bands)); | | | |
| | | | |
| for(unsigned int i=0; i<bands; ++i) | | | |
| { | | | |
| BasicImageView<T> subImage = makeBasicImageView(array.bindOuter | | | |
| (i)); | | | |
| SrcElementAccessor band(i, sget); | | | |
| transformImage( sul, slr, band, subImage.upperLeft(), subImage. | | | |
| accessor(), | | | |
| linearIntensityTransform( scale, offset ) ); | | | |
| } | | | |
| write_bands( enc, array, zero ); | | | |
| } | | | |
| | | | |
|
| } // namespace detail | | VIGRA_UNIQUE_PTR<Encoder> encoder(vigra::encoder(export_info)); | |
| | | | |
|
| /*! | | std::string pixel_type(export_info.getPixelType()); | |
| \brief Deprecated. | | const bool downcast(negotiatePixelType(encoder->getFileType(), | |
| | | TypeAsString<ImageValueType>::result(), pixel_type)); | |
| | | const pixel_t type(pixel_t_of_string(pixel_type)); | |
| | | | |
|
| Use \ref exportImage() instead. | | encoder->setPixelType(pixel_type); | |
| | | | |
|
| <b> Declaration:</b> | | vigra_precondition(isBandNumberSupported(encoder->getFileType() | |
| | | , image_accessor.size(image_upper_left)), | |
| | | "exportImage(): file format does not support | |
| | | requested number of bands (color channels)"); | |
| | | | |
|
| \code | | const range_t image_source_range(find_source_value_range(export | |
| namespace vigra { | | _info, | |
| template < class SrcIterator, class SrcAccessor > | | image_ | |
| void exportFloatingVectorImage( SrcIterator sul, SrcIterator sl | | upper_left, image_lower_right, image_accessor)); | |
| r, SrcAccessor sget, | | const range_t destination_range(find_destination_value_range(ex | |
| const ImageExportInfo & info ) | | port_info, pixel_t_of_string(pixel_type))); | |
| } | | | |
| \endcode | | | |
| */ | | | |
| doxygen_overloaded_function(template <...> void exportFloatingVectorImage) | | | |
| | | | |
| template < class SrcIterator, class SrcAccessor > | | | |
| void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAc | | | |
| cessor sget, | | | |
| const ImageExportInfo & info ) | | | |
| { | | | |
| exportImage(sul, slr, sget, info); | | | |
| } | | | |
| | | | |
|
| /*! | | if ((downcast || export_info.hasForcedRangeMapping()) && | |
| \brief Deprecated. | | (image_source_range.first != destination_range.first || ima | |
| | | ge_source_range.second != destination_range.second)) | |
| Use \ref exportImage() instead. | | { | |
| | | const linear_transform image_rescaler(image_source_range, d | |
| | | estination_range); | |
| | | | |
|
| <b> Declaration:</b> | | switch (type) | |
| | | { | |
| | | case UNSIGNED_INT_8: | |
| | | write_image_bands<UInt8>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, image_rescaler); | |
| | | break; | |
| | | case UNSIGNED_INT_16: | |
| | | write_image_bands<UInt16>(encoder.get(), | |
| | | image_upper_left, image_lower | |
| | | _right, image_accessor, image_rescaler); | |
| | | break; | |
| | | case UNSIGNED_INT_32: | |
| | | write_image_bands<UInt32>(encoder.get(), | |
| | | image_upper_left, image_lower | |
| | | _right, image_accessor, image_rescaler); | |
| | | break; | |
| | | case SIGNED_INT_16: | |
| | | write_image_bands<Int16>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, image_rescaler); | |
| | | break; | |
| | | case SIGNED_INT_32: | |
| | | write_image_bands<Int32>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, image_rescaler); | |
| | | break; | |
| | | case IEEE_FLOAT_32: | |
| | | write_image_bands<float>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, image_rescaler); | |
| | | break; | |
| | | case IEEE_FLOAT_64: | |
| | | write_image_bands<double>(encoder.get(), | |
| | | image_upper_left, image_lower | |
| | | _right, image_accessor, image_rescaler); | |
| | | break; | |
| | | default: | |
| | | vigra_fail("vigra::detail::exportImage<non-scalar>: not | |
| | | reached"); | |
| | | } | |
| | | } | |
| | | else | |
| | | { | |
| | | switch (type) | |
| | | { | |
| | | case UNSIGNED_INT_8: | |
| | | write_image_bands<UInt8>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | case UNSIGNED_INT_16: | |
| | | write_image_bands<UInt16>(encoder.get(), | |
| | | image_upper_left, image_lower | |
| | | _right, image_accessor, identity()); | |
| | | break; | |
| | | case UNSIGNED_INT_32: | |
| | | write_image_bands<UInt32>(encoder.get(), | |
| | | image_upper_left, image_lower | |
| | | _right, image_accessor, identity()); | |
| | | break; | |
| | | case SIGNED_INT_16: | |
| | | write_image_bands<Int16>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | case SIGNED_INT_32: | |
| | | write_image_bands<Int32>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | case IEEE_FLOAT_32: | |
| | | write_image_bands<float>(encoder.get(), | |
| | | image_upper_left, image_lower_ | |
| | | right, image_accessor, identity()); | |
| | | break; | |
| | | case IEEE_FLOAT_64: | |
| | | write_image_bands<double>(encoder.get(), | |
| | | image_upper_left, image_lower | |
| | | _right, image_accessor, identity()); | |
| | | break; | |
| | | default: | |
| | | vigra_fail("vigra::detail::exportImage<non-scalar>: not | |
| | | reached"); | |
| | | } | |
| | | } | |
| | | | |
|
| \code | | encoder->close(); | |
| namespace vigra { | | | |
| template < class SrcIterator, class SrcAccessor > | | | |
| void exportIntegralVectorImage( SrcIterator sul, SrcIterator sl | | | |
| r, SrcAccessor sget, | | | |
| const ImageExportInfo & info ) | | | |
| } | | } | |
|
| \endcode | | } // end namespace detail | |
| */ | | | |
| doxygen_overloaded_function(template <...> void exportIntegralVectorImage) | | | |
| | | | |
| template < class SrcIterator, class SrcAccessor > | | | |
| void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAc | | | |
| cessor sget, | | | |
| const ImageExportInfo & info ) | | | |
| { | | | |
| exportImage(sul, slr, sget, info); | | | |
| } | | | |
| | | | |
| /*! | | /*! | |
|
| \brief Deprecated. | | * \brief Read the image specified by the given \ref | |
| | | * vigra::ImageImportInfo object. | |
| Use \ref exportImage() instead. | | * | |
| | | * <B>Declarations</B> | |
| <b> Declaration:</b> | | * | |
| | | * Pass arguments explicitly: | |
| \code | | * \code | |
| namespace vigra { | | * namespace vigra { | |
| template < class SrcIterator, class SrcAccessor > | | * template <class ImageIterator, class Accessor> | |
| void exportFloatingScalarImage( SrcIterator sul, SrcIterator sl | | * void | |
| r, SrcAccessor sget, | | * importImage(const ImageImportInfo& importInfo, | |
| const ImageExportInfo & info ) | | * ImageIterator imageIterator, Accessor imageAccessor) | |
| } | | * } | |
| \endcode | | * \endcode | |
| */ | | * | |
| doxygen_overloaded_function(template <...> void exportFloatingScalarImage) | | * Use argument objects in conjunction with \ref ArgumentObjectFactorie | |
| | | s : | |
| template < class SrcIterator, class SrcAccessor > | | * \code | |
| void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAc | | * namespace vigra { | |
| cessor sget, | | * template <class ImageIterator, class Accessor> | |
| const ImageExportInfo & info ) | | * inline void | |
| | | * importImage(const ImageImportInfo& importInfo, | |
| | | * const pair<ImageIterator, Accessor>& image) | |
| | | * } | |
| | | * \endcode | |
| | | * | |
| | | * <B>Usage</B> | |
| | | * | |
| | | * <B>\#include \<vigra/impex.hxx\></B> | |
| | | * | |
| | | * Namespace: vigra | |
| | | * | |
| | | * \code | |
| | | * ImageImportInfo info("myimage.gif"); | |
| | | * | |
| | | * if (info.isGrayscale()) | |
| | | * { | |
| | | * // create byte image of appropriate size | |
| | | * BImage image(info.width(), info.height()); | |
| | | * | |
| | | * importImage(info, destImage(image)); | |
| | | * ... | |
| | | * } | |
| | | * else | |
| | | * { | |
| | | * // create byte RGB image of appropriate size | |
| | | * BRGBImage image(info.width(), info.height()); | |
| | | * | |
| | | * importImage(info, destImage(image)); | |
| | | * ... | |
| | | * } | |
| | | * \endcode | |
| | | * | |
| | | * <B>Preconditions</B> | |
| | | * | |
| | | * - The image file must be readable and | |
| | | * - the file type must be one of the following: | |
| | | * | |
| | | * | Type | Extension | Name | |
| | | | Support Library | | |
| | | * |------|-----------|------------------------------------------------ | |
| | | ------------|-----------------| | |
| | | * | BMP | bmp | Microsoft Windows bitmap image file | |
| | | | | | |
| | | * | EXR | exr | OpenEXR high dynamic range image format | |
| | | | libopenexr | | |
| | | * | GIF | gif | CompuServe graphics interchange format, 8-bit c | |
| | | olor | | | |
| | | * | HDR | hdr | Radiance RGBE high dynamic range image format | |
| | | | libexr? | | |
| | | * | JPEG | jpg, jpeg | Joint Photographic Experts Group JFIF format, 2 | |
| | | 4-bit color | libjpeg | | |
| | | * | PBM | pbm | Portable bitmap format (black and white) | |
| | | | | | |
| | | * | PGM | pgm | Portable graymap format (gray scale) | |
| | | | | | |
| | | * | PNG | png | Portable Network Graphic | |
| | | | libpng | | |
| | | * | PNM | pnm | Portable anymap | |
| | | | | | |
| | | * | PPM | ppm | Portable pixmap format (color) | |
| | | | | | |
| | | * | SUN | ras | SUN Rasterfile | |
| | | | | | |
| | | * | TIFF | tif, tiff | Tagged Image File Format | |
| | | | libtiff | | |
| | | * | VIFF | xv | Khoros Visualization image file | |
| | | | | | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> inline void importImage) | |
| | | | |
| | | template <class ImageIterator, class ImageAccessor> | |
| | | inline void | |
| | | importImage(const ImageImportInfo& import_info, | |
| | | ImageIterator image_iterator, ImageAccessor image_accessor) | |
| | | { | |
| | | typedef typename ImageAccessor::value_type ImageValueType; | |
| | | typedef typename NumericTraits<ImageValueType>::isScalar is_scalar; | |
| | | | |
| | | detail::importImage(import_info, | |
| | | image_iterator, image_accessor, | |
| | | is_scalar()); | |
| | | } | |
| | | | |
| | | template <class ImageIterator, class ImageAccessor> | |
| | | inline void | |
| | | importImage(const ImageImportInfo& import_info, | |
| | | const vigra::pair<ImageIterator, ImageAccessor>& image) | |
| { | | { | |
|
| exportImage(sul, slr, sget, info); | | importImage(import_info, | |
| | | image.first, image.second); | |
| } | | } | |
| | | | |
| /*! | | /*! | |
|
| \brief Deprecated. | | * \brief Write an image given a \ref vigra::ImageExportInfo object. | |
| | | * | |
| Use \ref exportImage() instead. | | * If the file format to be exported to supports the pixel type of | |
| | | * the source image, the pixel type will be kept | |
| <b> Declaration:</b> | | * (e.g. <tt>float</tt> can be stored as TIFF without conversion, | |
| | | * in contrast to most other image export toolkits). Otherwise, | |
| \code | | * the pixel values are transformed to the range 0..255 and | |
| namespace vigra { | | * converted to <tt>unsigned char</tt>. Currently, the following | |
| template < class SrcIterator, class SrcAccessor > | | * file formats are supported. The pixel types given in brackets | |
| void exportIntegralScalarImage( SrcIterator sul, SrcIterator sl | | * are those that are written without conversion: | |
| r, SrcAccessor sget, | | * - BMP: Microsoft Windows bitmap image file (pixel types: UINT8 a | |
| const ImageExportInfo & info ) | | s gray and RGB); | |
| } | | * - GIF: CompuServe graphics interchange format, 8-bit color (pixe | |
| \endcode | | l types: UINT8 as gray and RGB); | |
| */ | | * - JPEG: Joint Photographic Experts Group JFIF format, compressed | |
| doxygen_overloaded_function(template <...> void exportIntegralScalarImage) | | 24-bit color | |
| | | * (pixel types: UINT8 as gray and RGB), only available if | |
| template < class SrcIterator, class SrcAccessor > | | libjpeg is installed; | |
| void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAc | | * - PNG: Portable Network Graphic (pixel types: UINT8 and UINT16 w | |
| cessor sget, | | ith up to 4 channels), | |
| const ImageExportInfo & info ) | | * only available if libpng is installed; | |
| { | | * - PBM: Portable bitmap format (black and white); | |
| exportImage(sul, slr, sget, info); | | * - PGM: Portable graymap format (pixel types: UINT8, INT16, INT32 | |
| } | | as gray scale); | |
| | | * - PNM: Portable anymap (pixel types: UINT8, INT16, INT32 as gray | |
| /********************************************************/ | | and RGB); | |
| /* */ | | * - PPM: Portable pixmap format (pixel types: UINT8, INT16, INT32 | |
| /* exportImage */ | | as RGB); | |
| /* */ | | * - SUN: SUN Rasterfile (pixel types: UINT8 as gray and RGB); | |
| /********************************************************/ | | * - TIFF: Tagged Image File Format | |
| | | * (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up t | |
| /** \brief Write an image, given an \ref vigra::ImageExportInfo object. | | o 4 channels), | |
| | | * only available if libtiff is installed; | |
| If the file format to be exported to supports the pixel type of the | | * - VIFF: Khoros Visualization image file | |
| source image, the pixel type will be kept (e.g. <tt>float</tt> | | * (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbi | |
| can be stored as TIFF without conversion, in contrast to most other | | trary many channels); | |
| image export toolkits). Otherwise, the pixel values are transformed | | * | |
| to the range 0.255 and converted to <tt>unsigned char</tt>. Currently, | | * <B>Declarations</B> | |
| the following file formats are supported. The pixel types given in | | * | |
| brackets are those that are written without conversion: | | * Pass arguments explicitly: | |
| | | * \code | |
| <DL> | | * namespace vigra { | |
| <DT>"BMP"<DD> Microsoft Windows bitmap image file (pixel types: UINT8 a | | * template <class ImageIterator, class ImageAccessor> | |
| s gray and RGB). | | * void | |
| <DT>"GIF"<DD> CompuServe graphics interchange format; 8-bit color (pixe | | * exportImage(ImageIterator imageUpperLeft, ImageIterator imageLow | |
| l types: UINT8 as gray and RGB). | | erRight, ImageAccessor imageAccessor, | |
| <DT>"JPEG"<DD> Joint Photographic Experts Group JFIF format; compressed | | * const ImageExportInfo& exportInfo) | |
| 24-bit color | | * } | |
| (pixel types: UINT8 as gray and RGB). (only available if | | * \endcode | |
| libjpeg is installed) | | * | |
| <DT>"PNG"<DD> Portable Network Graphic (pixel types: UINT8 and UINT16 w | | * Use argument objects in conjunction with \ref ArgumentObjectFactorie | |
| ith up to 4 channels). | | s : | |
| (only available if libpng is installed) | | * \code | |
| <DT>"PBM"<DD> Portable bitmap format (black and white). | | * namespace vigra { | |
| <DT>"PGM"<DD> Portable graymap format (pixel types: UINT8, INT16, INT32 | | * template <class ImageIterator, class ImageAccessor> | |
| as gray scale)). | | * void exportImage(ImageIterator imageUpperLeft, ImageIterator | |
| <DT>"PNM"<DD> Portable anymap (pixel types: UINT8, INT16, INT32 as gray | | imageLowerRight, ImageAccessor imageAccessor, | |
| and RGB). | | * const ImageExportInfo& exportInfo) | |
| <DT>"PPM"<DD> Portable pixmap format (pixel types: UINT8, INT16, INT32 | | * } | |
| as RGB). | | * \endcode | |
| <DT>"SUN"<DD> SUN Rasterfile (pixel types: UINT8 as gray and RGB). | | * | |
| <DT>"TIFF"<DD> Tagged Image File Format | | * <B>Usage</B> | |
| (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to | | * | |
| 4 channels). | | * <B>\#include \<vigra/impex.hxx\></B> | |
| (only available if libtiff is installed.) | | * | |
| <DT>"VIFF"<DD> Khoros Visualization image file | | * Namespace: vigra | |
| (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary man | | * \code | |
| y channels). | | * BRGBImage image(width, height); | |
| </DL> | | * ... | |
| | | * | |
| <b> Declarations:</b> | | * // write as JPEG image, using compression quality 80 | |
| | | * exportImage(srcImageRange(image), | |
| pass arguments explicitly: | | * ImageExportInfo("my-image.jpg").setCompression("80") | |
| \code | | ); | |
| namespace vigra { | | * | |
| template <class SrcIterator, class SrcAccessor> | | * // Force it to a particular pixel type. The pixel type must be | |
| void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget | | supported by the | |
| , | | * // desired image file format, otherwise an \ref vigra::Precondit | |
| ImageExportInfo const & info) | | ionViolation | |
| } | | * // exception will be thrown. | |
| \endcode | | * exportImage(srcImageRange(image), | |
| | | * ImageExportInfo("my-INT16-image.tif").setPixelType(" | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | INT16")); | |
| \code | | * \endcode | |
| namespace vigra { | | * | |
| template <class SrcIterator, class SrcAccessor> | | * <B>Preconditions</B> | |
| void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget | | * | |
| , | | * - The image file must be writable and | |
| ImageExportInfo const & info) | | * - the file type must be one of the supported file types. | |
| } | | */ | |
| \endcode | | doxygen_overloaded_function(template <...> inline void exportImage) | |
| | | | |
| <b> Usage:</b> | | template <class ImageIterator, class ImageAccessor> | |
| | | inline void | |
| <b>\#include</b> \<vigra/impex.hxx\><br> | | exportImage(ImageIterator image_upper_left, ImageIterator image_lower_r | |
| Namespace: vigra | | ight, ImageAccessor image_accessor, | |
| | | const ImageExportInfo& export_info) | |
| \code | | | |
| | | | |
| vigra::BRGBImage out(w, h); | | | |
| ... | | | |
| | | | |
| // write as JPEG image, using compression quality 80 | | | |
| vigra::exportImage(srcImageRange(out), | | | |
| vigra::ImageExportInfo("myimage.jpg").setCompression( | | | |
| "80")); | | | |
| | | | |
| // force it to a particular pixel type (the pixel type must be supporte | | | |
| d by the | | | |
| // desired image file format, otherwise an \ref vigra::PreconditionViol | | | |
| ation exception will be thrown) | | | |
| vigra::exportImage(srcImageRange(out), | | | |
| vigra::ImageExportInfo("myINT16image.tif").setPixelTy | | | |
| pe("INT16")); | | | |
| \endcode | | | |
| | | | |
| <b> Preconditions:</b> | | | |
| | | | |
| <UL> | | | |
| | | | |
| <LI> the image file must be writable. | | | |
| <LI> the file type must be one of the supported file types. | | | |
| | | | |
| </UL> | | | |
| **/ | | | |
| doxygen_overloaded_function(template <...> void exportImage) | | | |
| | | | |
| template < class SrcIterator, class SrcAccessor > | | | |
| void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget, | | | |
| const ImageExportInfo & info ) | | | |
| { | | { | |
|
| typedef typename NumericTraits<typename SrcAccessor::value_type>::i | | typedef typename ImageAccessor::value_type ImageValueType; | |
| sScalar is_scalar; | | typedef typename NumericTraits<ImageValueType>::isScalar is_scalar; | |
| | | | |
| try | | try | |
| { | | { | |
|
| exportImage( sul, slr, sget, info, is_scalar() ); | | detail::exportImage(image_upper_left, image_lower_right, image_ | |
| | | accessor, | |
| | | export_info, | |
| | | is_scalar()); | |
| } | | } | |
|
| catch(Encoder::TIFFCompressionException &) | | catch (Encoder::TIFFCompressionException&) | |
| { | | { | |
|
| const_cast<ImageExportInfo &>(info).setCompression(""); | | ImageExportInfo info(export_info); | |
| exportImage( sul, slr, sget, info, is_scalar() ); | | | |
| } | | | |
| } | | | |
| | | | |
|
| template < class SrcIterator, class SrcAccessor > | | info.setCompression(""); | |
| inline | | detail::exportImage(image_upper_left, image_lower_right, image_ | |
| void exportImage( triple<SrcIterator, SrcIterator, SrcAccessor> src, | | accessor, | |
| const ImageExportInfo & info ) | | info, | |
| { | | is_scalar()); | |
| exportImage( src.first, src.second, src.third, info ); | | | |
| } | | | |
| | | | |
| template < class SrcIterator, class SrcAccessor > | | | |
| void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget, | | | |
| const ImageExportInfo & info, VigraFalseType /*not sc | | | |
| alar */) | | | |
| { | | | |
| typedef typename SrcAccessor::value_type AccessorValueType; | | | |
| typedef typename AccessorValueType::value_type SrcValueType; | | | |
| std::string pixeltype = info.getPixelType(); | | | |
| std::auto_ptr<Encoder> enc = encoder(info); | | | |
| bool downcast = negotiatePixelType(enc->getFileType(), | | | |
| TypeAsString<SrcValueType>::result(), pixeltype); | | | |
| enc->setPixelType(pixeltype); | | | |
| if(downcast || info.hasForcedRangeMapping()) | | | |
| { | | | |
| if(pixeltype == "UINT8") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| (UInt8)0); | | | |
| else if(pixeltype == "INT16") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| Int16()); | | | |
| else if(pixeltype == "UINT16") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| (UInt16)0); | | | |
| else if(pixeltype == "INT32") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| Int32()); | | | |
| else if(pixeltype == "UINT32") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| (UInt32)0); | | | |
| else if(pixeltype == "FLOAT") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| float()); | | | |
| else if(pixeltype == "DOUBLE") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), info, | | | |
| double()); | | | |
| } | | } | |
|
| else | | | |
| { | | | |
| if(pixeltype == "UINT8") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt | | | |
| 8)0); | | | |
| else if(pixeltype == "INT16") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), Int16 | | | |
| ()); | | | |
| else if(pixeltype == "UINT16") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt | | | |
| 16)0); | | | |
| else if(pixeltype == "INT32") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), Int32 | | | |
| ()); | | | |
| else if(pixeltype == "UINT32") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), (UInt | | | |
| 32)0); | | | |
| else if(pixeltype == "FLOAT") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), float | | | |
| ()); | | | |
| else if(pixeltype == "DOUBLE") | | | |
| detail::exportVectorImage( sul, slr, sget, enc.get(), doubl | | | |
| e()); | | | |
| } | | | |
| enc->close(); | | | |
| } | | } | |
| | | | |
|
| template < class SrcIterator, class SrcAccessor > | | template <class ImageIterator, class ImageAccessor> | |
| void exportImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget, | | inline void | |
| const ImageExportInfo & info, VigraTrueType /*scalar* | | exportImage(const vigra::triple<ImageIterator, ImageIterator, ImageAcce | |
| / ) | | ssor>& image, | |
| | | const ImageExportInfo& export_info) | |
| { | | { | |
|
| typedef typename SrcAccessor::value_type SrcValueType; | | exportImage(image.first, image.second, image.third, | |
| std::string pixeltype = info.getPixelType(); | | export_info); | |
| std::auto_ptr<Encoder> enc = encoder(info); | | | |
| bool downcast = negotiatePixelType(enc->getFileType(), | | | |
| TypeAsString<SrcValueType>::result(), pixeltype) | | | |
| ; | | | |
| enc->setPixelType(pixeltype); | | | |
| if(downcast || info.hasForcedRangeMapping()) | | | |
| { | | | |
| if(pixeltype == "UINT8") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| (UInt8)0); | | | |
| else if(pixeltype == "INT16") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| Int16()); | | | |
| else if(pixeltype == "UINT16") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| (UInt16)0); | | | |
| else if(pixeltype == "INT32") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| Int32()); | | | |
| else if(pixeltype == "UINT32") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| (UInt32)0); | | | |
| else if(pixeltype == "FLOAT") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| float()); | | | |
| else if(pixeltype == "DOUBLE") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), info, | | | |
| double()); | | | |
| } | | | |
| else | | | |
| { | | | |
| if(pixeltype == "UINT8") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt | | | |
| 8)0); | | | |
| else if(pixeltype == "INT16") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), Int16 | | | |
| ()); | | | |
| else if(pixeltype == "UINT16") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt | | | |
| 16)0); | | | |
| else if(pixeltype == "INT32") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), Int32 | | | |
| ()); | | | |
| else if(pixeltype == "UINT32") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), (UInt | | | |
| 32)0); | | | |
| else if(pixeltype == "FLOAT") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), float | | | |
| ()); | | | |
| else if(pixeltype == "DOUBLE") | | | |
| detail::exportScalarImage( sul, slr, sget, enc.get(), doubl | | | |
| e()); | | | |
| } | | | |
| enc->close(); | | | |
| } | | } | |
| | | | |
|
| //@} | | /** @} */ | |
| | | | |
|
| } // namespace vigra | | } // end namespace vigra | |
| | | | |
|
| #endif /* VIGRA_IMPEX_HXX */ | | #endif // VIGRA_IMPEX_HXX | |
| | | | |
End of changes. 97 change blocks. |
| 1237 lines changed or deleted | | 800 lines changed or added | |
|
| multi_array.hxx | | multi_array.hxx | |
| | | | |
| skipping to change at line 147 | | skipping to change at line 147 | |
| { | | { | |
| template <int N> | | template <int N> | |
| static void | | static void | |
| exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape
*/, | | exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape
*/, | |
| TinyVector <MultiArrayIndex, N> & result) | | TinyVector <MultiArrayIndex, N> & result) | |
| { | | { | |
| result[N-1] = d; | | result[N-1] = d; | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| template <int K> | | | |
| struct CoordinateToScanOrder | | | |
| { | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(const TinyVector <MultiArrayIndex, N> &shape, | | | |
| const TinyVector <MultiArrayIndex, N> & coordinate) | | | |
| { | | | |
| return coordinate[N-K] + shape[N-K] * CoordinateToScanOrder<K-1>::e | | | |
| xec(shape, coordinate); | | | |
| } | | | |
| }; | | | |
| | | | |
| template <> | | | |
| struct CoordinateToScanOrder<1> | | | |
| { | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(const TinyVector <MultiArrayIndex, N> & /*shape*/, | | | |
| const TinyVector <MultiArrayIndex, N> & coordinate) | | | |
| { | | | |
| return coordinate[N-1]; | | | |
| } | | | |
| }; | | | |
| | | | |
| template <class C> | | template <class C> | |
| struct CoordinatesToOffest | | struct CoordinatesToOffest | |
| { | | { | |
| template <int N> | | template <int N> | |
| static MultiArrayIndex | | static MultiArrayIndex | |
| exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x) | | exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x) | |
| { | | { | |
| return stride[0] * x; | | return stride[0] * x; | |
| } | | } | |
| template <int N> | | template <int N> | |
| | | | |
| skipping to change at line 332 | | skipping to change at line 308 | |
| void | | void | |
| initMultiArrayData(DestIterator d, Shape const & shape, T const & init, Met
aInt<N>) | | initMultiArrayData(DestIterator d, Shape const & shape, T const & init, Met
aInt<N>) | |
| { | | { | |
| DestIterator dend = d + shape[N]; | | DestIterator dend = d + shape[N]; | |
| for(; d < dend; ++d) | | for(; d < dend; ++d) | |
| { | | { | |
| initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); | | initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); | |
| } | | } | |
| } | | } | |
| | | | |
|
| | | // FIXME: the explicit overload for MultiIterator<1, UInt8, ... > works aro
und a compiler crash in VisualStudio 2010 | |
| #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \ | | #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \ | |
| template <class SrcIterator, class Shape, class DestIterator> \ | | template <class SrcIterator, class Shape, class DestIterator> \ | |
| inline void \ | | inline void \ | |
| name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<0>) \ | | name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<0>) \ | |
| { \ | | { \ | |
| SrcIterator send = s + shape[0]; \ | | SrcIterator send = s + shape[0]; \ | |
| for(; s < send; ++s, ++d) \ | | for(; s < send; ++s, ++d) \ | |
| { \ | | { \ | |
| *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \ | | *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \ | |
| } \ | | } \ | |
| } \ | | } \ | |
| \ | | \ | |
|
| | | template <class Ref, class Ptr, class Shape, class DestIterator> \ | |
| | | inline void \ | |
| | | name##MultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & sh | |
| | | ape, DestIterator d, MetaInt<0>) \ | |
| | | { \ | |
| | | Ptr s = &(*si), send = s + shape[0]; \ | |
| | | for(; s < send; ++s, ++d) \ | |
| | | { \ | |
| | | *d op detail::RequiresExplicitCast<typename DestIterator::value_typ | |
| | | e>::cast(*s); \ | |
| | | } \ | |
| | | } \ | |
| | | \ | |
| template <class SrcIterator, class Shape, class DestIterator, int N> \ | | template <class SrcIterator, class Shape, class DestIterator, int N> \ | |
| void \ | | void \ | |
| name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<N>) \ | | name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<N>) \ | |
| { \ | | { \ | |
| SrcIterator send = s + shape[N]; \ | | SrcIterator send = s + shape[N]; \ | |
| for(; s < send; ++s, ++d) \ | | for(; s < send; ++s, ++d) \ | |
| { \ | | { \ | |
| name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>());
\ | | name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>());
\ | |
| } \ | | } \ | |
| } \ | | } \ | |
| | | | |
| skipping to change at line 396 | | skipping to change at line 384 | |
| inline void | | inline void | |
| uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d
, ALLOC & a, MetaInt<0>) | | uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d
, ALLOC & a, MetaInt<0>) | |
| { | | { | |
| SrcIterator send = s + shape[0]; | | SrcIterator send = s + shape[0]; | |
| for(; s < send; ++s, ++d) | | for(; s < send; ++s, ++d) | |
| { | | { | |
| a.construct(d, static_cast<T const &>(*s)); | | a.construct(d, static_cast<T const &>(*s)); | |
| } | | } | |
| } | | } | |
| | | | |
|
| | | // FIXME: this overload works around a compiler crash in VisualStudio 2010 | |
| | | template <class Ref, class Ptr, class Shape, class T, class ALLOC> | |
| | | inline void | |
| | | uninitializedCopyMultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape | |
| | | const & shape, T * & d, ALLOC & a, MetaInt<0>) | |
| | | { | |
| | | Ptr s = &(*si), send = s + shape[0]; | |
| | | for(; s < send; ++s, ++d) | |
| | | { | |
| | | a.construct(d, static_cast<T const &>(*s)); | |
| | | } | |
| | | } | |
| | | | |
| template <class SrcIterator, class Shape, class T, class ALLOC, int N> | | template <class SrcIterator, class Shape, class T, class ALLOC, int N> | |
| void | | void | |
| uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d
, ALLOC & a, MetaInt<N>) | | uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d
, ALLOC & a, MetaInt<N>) | |
| { | | { | |
| SrcIterator send = s + shape[N]; | | SrcIterator send = s + shape[N]; | |
| for(; s < send; ++s) | | for(; s < send; ++s) | |
| { | | { | |
| uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1
>()); | | uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1
>()); | |
| } | | } | |
| } | | } | |
| | | | |
| skipping to change at line 938 | | skipping to change at line 938 | |
| */ | | */ | |
| template<class U, class C1> | | template<class U, class C1> | |
| MultiArrayView & operator=(MultiArrayView<N, U, C1> const & rhs) | | MultiArrayView & operator=(MultiArrayView<N, U, C1> const & rhs) | |
| { | | { | |
| vigra_precondition(this->shape() == rhs.shape(), | | vigra_precondition(this->shape() == rhs.shape(), | |
| "MultiArrayView::operator=() size mismatch."); | | "MultiArrayView::operator=() size mismatch."); | |
| this->copyImpl(rhs); | | this->copyImpl(rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | /** Assignment of a scalar. Equivalent to MultiArrayView::init(v). | |
| | | */ | |
| | | MultiArrayView & operator=(value_type const & v) | |
| | | { | |
| | | return init(v); | |
| | | } | |
| | | | |
| /** Add-assignment of a compatible MultiArrayView. Fails with | | /** Add-assignment of a compatible MultiArrayView. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class U, class C1> | | template<class U, class C1> | |
| MultiArrayView & operator+=(MultiArrayView<N, U, C1> const & rhs); | | MultiArrayView & operator+=(MultiArrayView<N, U, C1> const & rhs); | |
| | | | |
| /** Subtract-assignment of a compatible MultiArrayView. Fails with | | /** Subtract-assignment of a compatible MultiArrayView. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class U, class C1> | | template<class U, class C1> | |
| | | | |
| skipping to change at line 1062 | | skipping to change at line 1069 | |
| /** array access. | | /** array access. | |
| */ | | */ | |
| const_reference operator[] (const difference_type &d) const | | const_reference operator[] (const difference_type &d) const | |
| { | | { | |
| VIGRA_ASSERT_INSIDE(d); | | VIGRA_ASSERT_INSIDE(d); | |
| return m_ptr [dot (d, m_stride)]; | | return m_ptr [dot (d, m_stride)]; | |
| } | | } | |
| | | | |
| /** equivalent to bindInner(), when M < N. | | /** equivalent to bindInner(), when M < N. | |
| */ | | */ | |
|
| template <unsigned int M> | | template <int M> | |
| MultiArrayView <N-M, T, StridedArrayTag> operator[] (const TinyVector<M
ultiArrayIndex, M> &d) const | | MultiArrayView <N-M, T, StridedArrayTag> operator[] (const TinyVector<M
ultiArrayIndex, M> &d) const | |
| { | | { | |
| return bindInner(d); | | return bindInner(d); | |
| } | | } | |
| | | | |
| /** Array access in scan-order sense. | | /** Array access in scan-order sense. | |
| Mostly useful to support standard indexing for 1-dimensional mu
lti-arrays, | | Mostly useful to support standard indexing for 1-dimensional mu
lti-arrays, | |
| but works for any N. Use scanOrderIndexToCoordinate() and | | but works for any N. Use scanOrderIndexToCoordinate() and | |
| coordinateToScanOrderIndex() for conversion between indices and
coordinates. | | coordinateToScanOrderIndex() for conversion between indices and
coordinates. | |
| | | | |
| | | | |
| skipping to change at line 1205 | | skipping to change at line 1212 | |
| { | | { | |
| VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v)); | | VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v)); | |
| return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str
ide[3]*u + m_stride[4]*v]; | | return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_str
ide[3]*u + m_stride[4]*v]; | |
| } | | } | |
| | | | |
| /** Init with a constant. | | /** Init with a constant. | |
| */ | | */ | |
| template <class U> | | template <class U> | |
| MultiArrayView & init(const U & init) | | MultiArrayView & init(const U & init) | |
| { | | { | |
|
| detail::copyScalarMultiArrayData(traverser_begin(), shape(), init, | | if(hasData()) | |
| MetaInt<actual_dimension-1>()); | | detail::copyScalarMultiArrayData(traverser_begin(), shape(), in | |
| | | it, MetaInt<actual_dimension-1>()); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Copy the data of the right-hand array (array shapes must match)
. | | /** Copy the data of the right-hand array (array shapes must match)
. | |
| */ | | */ | |
| void copy(const MultiArrayView & rhs) | | void copy(const MultiArrayView & rhs) | |
| { | | { | |
| if(this == &rhs) | | if(this == &rhs) | |
| return; | | return; | |
| this->copyImpl(rhs); | | this->copyImpl(rhs); | |
| | | | |
| skipping to change at line 1274 | | skipping to change at line 1282 | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| MultiArray<3, double> array3(Shape(40, 30, 20)); | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| // get a 1D array by fixing index 1 to 12, and index 2 to 10 | | // get a 1D array by fixing index 1 to 12, and index 2 to 10 | |
| MultiArrayView <1, double> array1 = array3.bindOuter(TinyVector
<MultiArrayIndex, 2>(12, 10)); | | MultiArrayView <1, double> array1 = array3.bindOuter(TinyVector
<MultiArrayIndex, 2>(12, 10)); | |
| \endcode | | \endcode | |
| */ | | */ | |
|
| template <unsigned int M> | | template <int M, class Index> | |
| MultiArrayView <N-M, T, StrideTag> bindOuter (const TinyVector <MultiAr | | MultiArrayView <N-M, T, StrideTag> bindOuter(const TinyVector <Index, M | |
| rayIndex, M> &d) const; | | > &d) const; | |
| | | | |
| /** bind the M innermost dimensions to certain indices. | | /** bind the M innermost dimensions to certain indices. | |
| this reduces the dimensionality of the image to | | this reduces the dimensionality of the image to | |
| max { 1, N-M }. | | max { 1, N-M }. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| MultiArray<3, double> array3(Shape(40, 30, 20)); | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| // get a 1D array by fixing index 0 to 12, and index 1 to 10 | | // get a 1D array by fixing index 0 to 12, and index 1 to 10 | |
| MultiArrayView <1, double, StridedArrayTag> array1 = array3.bin
dInner(TinyVector<MultiArrayIndex, 2>(12, 10)); | | MultiArrayView <1, double, StridedArrayTag> array1 = array3.bin
dInner(TinyVector<MultiArrayIndex, 2>(12, 10)); | |
| \endcode | | \endcode | |
| */ | | */ | |
|
| template <unsigned int M> | | template <int M, class Index> | |
| MultiArrayView <N-M, T, StridedArrayTag> | | MultiArrayView <N-M, T, StridedArrayTag> bindInner(const TinyVector <In | |
| bindInner (const TinyVector <MultiArrayIndex, M> &d) const; | | dex, M> &d) const; | |
| | | | |
| /** bind dimension M to index d. | | /** bind dimension M to index d. | |
| this reduces the dimensionality of the image to | | this reduces the dimensionality of the image to | |
| max { 1, N-1 }. | | max { 1, N-1 }. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| MultiArray<3, double> array3(Shape(40, 30, 20)); | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| skipping to change at line 1441 | | skipping to change at line 1448 | |
| | | | |
| // temporarily add a singleton dimension to the destination arr
ay | | // temporarily add a singleton dimension to the destination arr
ay | |
| transformMultiArray(srcMultiArrayRange(original), | | transformMultiArray(srcMultiArrayRange(original), | |
| destMultiArrayRange(rowAverages.insertSingl
etonDimension(0)), | | destMultiArrayRange(rowAverages.insertSingl
etonDimension(0)), | |
| FindAverage<double>()); | | FindAverage<double>()); | |
| \endcode | | \endcode | |
| */ | | */ | |
| MultiArrayView <N+1, T, StrideTag> | | MultiArrayView <N+1, T, StrideTag> | |
| insertSingletonDimension (difference_type_1 i) const; | | insertSingletonDimension (difference_type_1 i) const; | |
| | | | |
|
| | | /** Create a view to the diagonal elements of the array. | |
| | | | |
| | | This produces a 1D array view whose size equals the size | |
| | | of the shortest dimension of the original array. | |
| | | | |
| | | <b>Usage:</b> | |
| | | \code | |
| | | // create a 3D array of size 40x30x20 | |
| | | typedef MultiArray<3, double>::difference_type Shape; | |
| | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| | | // get a view to the diagonal elements | |
| | | MultiArrayView <1, double, StridedArrayTag> diagonal = array3.d | |
| | | iagonal(); | |
| | | assert(diagonal.shape(0) == 20); | |
| | | \endcode | |
| | | */ | |
| | | MultiArrayView<1, T, StridedArrayTag> diagonal() const | |
| | | { | |
| | | return MultiArrayView<1, T, StridedArrayTag>(Shape1(vigra::min(m_sh | |
| | | ape)), | |
| | | Shape1(vigra::sum(m_st | |
| | | ride)), m_ptr); | |
| | | } | |
| | | | |
| /** create a rectangular subarray that spans between the | | /** create a rectangular subarray that spans between the | |
| points p and q, where p is in the subarray, q not. | | points p and q, where p is in the subarray, q not. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| MultiArray<3, double> array3(Shape(40, 30, 20)); | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| // get a subarray set is smaller by one element at all sides | | // get a subarray set is smaller by one element at all sides | |
| | | | |
| skipping to change at line 1656 | | skipping to change at line 1685 | |
| { | | { | |
| bool res = false; | | bool res = false; | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::AnyTrueReduceFunctor(), | | detail::AnyTrueReduceFunctor(), | |
| MetaInt<actual_dimension-1>()); | | MetaInt<actual_dimension-1>()); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| /** Find the minimum and maximum element in this array. | | /** Find the minimum and maximum element in this array. | |
|
| | | See \ref FeatureAccumulators for a general feature | |
| | | extraction framework. | |
| */ | | */ | |
| void minmax(T * minimum, T * maximum) const | | void minmax(T * minimum, T * maximum) const | |
| { | | { | |
| std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min(
)); | | std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min(
)); | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::MinmaxReduceFunctor(), | | detail::MinmaxReduceFunctor(), | |
| MetaInt<actual_dimension-1>()); | | MetaInt<actual_dimension-1>()); | |
| *minimum = res.first; | | *minimum = res.first; | |
| *maximum = res.second; | | *maximum = res.second; | |
| } | | } | |
| | | | |
| /** Compute the mean and variance of the values in this array. | | /** Compute the mean and variance of the values in this array. | |
|
| | | See \ref FeatureAccumulators for a general feature | |
| | | extraction framework. | |
| */ | | */ | |
| template <class U> | | template <class U> | |
| void meanVariance(U * mean, U * variance) const | | void meanVariance(U * mean, U * variance) const | |
| { | | { | |
| typedef typename NumericTraits<U>::RealPromote R; | | typedef typename NumericTraits<U>::RealPromote R; | |
|
| triple<R, R, R> res(0.0, 0.0, 0.0); | | R zero; | |
| | | triple<double, R, R> res(0.0, zero, zero); | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::MeanVarianceReduceFunctor(), | | detail::MeanVarianceReduceFunctor(), | |
| MetaInt<actual_dimension-1>()); | | MetaInt<actual_dimension-1>()); | |
| *mean = res.second; | | *mean = res.second; | |
| *variance = res.third / res.first; | | *variance = res.third / res.first; | |
| } | | } | |
| | | | |
| /** Compute the sum of the array elements. | | /** Compute the sum of the array elements. | |
| | | | |
| | | | |
| skipping to change at line 1793 | | skipping to change at line 1827 | |
| typename NormTraits<MultiArrayView>::NormType | | typename NormTraits<MultiArrayView>::NormType | |
| norm(int type = 2, bool useSquaredNorm = true) const; | | norm(int type = 2, bool useSquaredNorm = true) const; | |
| | | | |
| /** return the pointer to the image data | | /** return the pointer to the image data | |
| */ | | */ | |
| pointer data () const | | pointer data () const | |
| { | | { | |
| return m_ptr; | | return m_ptr; | |
| } | | } | |
| | | | |
|
| | | pointer & unsafePtr() | |
| | | { | |
| | | return m_ptr; | |
| | | } | |
| | | | |
| /** | | /** | |
| * returns true iff this view refers to valid data, | | * returns true iff this view refers to valid data, | |
| * i.e. data() is not a NULL pointer. (this is false after | | * i.e. data() is not a NULL pointer. (this is false after | |
| * default construction.) | | * default construction.) | |
| */ | | */ | |
| bool hasData () const | | bool hasData () const | |
| { | | { | |
| return m_ptr != 0; | | return m_ptr != 0; | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 2053 | | skipping to change at line 2092 | |
| MultiArrayView <N, T, StridedArrayTag> | | MultiArrayView <N, T, StridedArrayTag> | |
| MultiArrayView <N, T, StrideTag>::permuteStridesDescending() const | | MultiArrayView <N, T, StrideTag>::permuteStridesDescending() const | |
| { | | { | |
| difference_type ordering(strideOrdering(m_stride)), permutation; | | difference_type ordering(strideOrdering(m_stride)), permutation; | |
| for(MultiArrayIndex k=0; k<N; ++k) | | for(MultiArrayIndex k=0; k<N; ++k) | |
| permutation[ordering[N-1-k]] = k; | | permutation[ordering[N-1-k]] = k; | |
| return permuteDimensions(permutation); | | return permuteDimensions(permutation); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
|
| template <unsigned int M> | | template <int M, class Index> | |
| MultiArrayView <N-M, T, StrideTag> | | MultiArrayView <N-M, T, StrideTag> | |
|
| MultiArrayView <N, T, StrideTag>::bindOuter (const TinyVector <MultiArrayIn
dex, M> &d) const | | MultiArrayView <N, T, StrideTag>::bindOuter (const TinyVector <Index, M> &d
) const | |
| { | | { | |
| TinyVector <MultiArrayIndex, M> stride; | | TinyVector <MultiArrayIndex, M> stride; | |
| stride.init (m_stride.begin () + N-M, m_stride.end ()); | | stride.init (m_stride.begin () + N-M, m_stride.end ()); | |
| pointer ptr = m_ptr + dot (d, stride); | | pointer ptr = m_ptr + dot (d, stride); | |
| static const int NNew = (N-M == 0) ? 1 : N-M; | | static const int NNew = (N-M == 0) ? 1 : N-M; | |
| TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; | | TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; | |
| if (N-M == 0) | | if (N-M == 0) | |
| { | | { | |
| inner_shape [0] = 1; | | inner_shape [0] = 1; | |
| inner_stride [0] = 0; | | inner_stride [0] = 0; | |
| } | | } | |
| else | | else | |
| { | | { | |
| inner_shape.init (m_shape.begin (), m_shape.end () - M); | | inner_shape.init (m_shape.begin (), m_shape.end () - M); | |
| inner_stride.init (m_stride.begin (), m_stride.end () - M); | | inner_stride.init (m_stride.begin (), m_stride.end () - M); | |
| } | | } | |
| return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, p
tr); | | return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, p
tr); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
|
| template <unsigned int M> | | template <int M, class Index> | |
| MultiArrayView <N - M, T, StridedArrayTag> | | MultiArrayView <N - M, T, StridedArrayTag> | |
|
| MultiArrayView <N, T, StrideTag>::bindInner (const TinyVector <MultiArrayIn
dex, M> &d) const | | MultiArrayView <N, T, StrideTag>::bindInner (const TinyVector <Index, M> &d
) const | |
| { | | { | |
| TinyVector <MultiArrayIndex, M> stride; | | TinyVector <MultiArrayIndex, M> stride; | |
| stride.init (m_stride.begin (), m_stride.end () - N + M); | | stride.init (m_stride.begin (), m_stride.end () - N + M); | |
| pointer ptr = m_ptr + dot (d, stride); | | pointer ptr = m_ptr + dot (d, stride); | |
| static const int NNew = (N-M == 0) ? 1 : N-M; | | static const int NNew = (N-M == 0) ? 1 : N-M; | |
| TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; | | TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; | |
| if (N-M == 0) | | if (N-M == 0) | |
| { | | { | |
| outer_shape [0] = 1; | | outer_shape [0] = 1; | |
| outer_stride [0] = 0; | | outer_stride [0] = 0; | |
| | | | |
| skipping to change at line 2461 | | skipping to change at line 2500 | |
| {} | | {} | |
| | | | |
| /** construct with given allocator | | /** construct with given allocator | |
| */ | | */ | |
| MultiArray (allocator_type const & alloc) | | MultiArray (allocator_type const & alloc) | |
| : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), | | : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), | |
| difference_type (diff_zero_t(0)), 0), | | difference_type (diff_zero_t(0)), 0), | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| {} | | {} | |
| | | | |
|
| | | /** construct with given length | |
| | | | |
| | | Use only for 1-dimensional arrays (<tt>N==1</tt>). | |
| | | */ | |
| | | explicit MultiArray (difference_type_1 length, | |
| | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** construct with given shape | | /** construct with given shape | |
| */ | | */ | |
| explicit MultiArray (const difference_type &shape, | | explicit MultiArray (const difference_type &shape, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** construct from shape with an initial value | | /** construct from shape with an initial value | |
| */ | | */ | |
| MultiArray (const difference_type &shape, const_reference init, | | MultiArray (const difference_type &shape, const_reference init, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| | | | |
| skipping to change at line 2527 | | skipping to change at line 2573 | |
| the data are copied. Otherwise, new storage is allocated, which
invalidates all | | the data are copied. Otherwise, new storage is allocated, which
invalidates all | |
| objects (array views, iterators) depending on the lhs array. | | objects (array views, iterators) depending on the lhs array. | |
| */ | | */ | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray &operator= (const MultiArrayView<N, U, StrideTag> &rhs) | | MultiArray &operator= (const MultiArrayView<N, U, StrideTag> &rhs) | |
| { | | { | |
| this->copyOrReshape(rhs); | | this->copyOrReshape(rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | /** assignment from scalar.<br> | |
| | | Equivalent to MultiArray::init(v). | |
| | | */ | |
| | | MultiArray & operator=(value_type const & v) | |
| | | { | |
| | | return this->init(v); | |
| | | } | |
| | | | |
| /** Add-assignment from arbitrary MultiArrayView. Fails with | | /** Add-assignment from arbitrary MultiArrayView. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
|
| | | If the left array has no data (hasData() is false), this functi | |
| | | on is | |
| | | equivalent to a normal assignment (i.e. an empty | |
| | | array is interpreted as a zero-array of appropriate size). | |
| */ | | */ | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray &operator+= (const MultiArrayView<N, U, StrideTag> &rhs) | | MultiArray &operator+= (const MultiArrayView<N, U, StrideTag> &rhs) | |
| { | | { | |
|
| view_type::operator+=(rhs); | | if(this->hasData()) | |
| | | view_type::operator+=(rhs); | |
| | | else | |
| | | *this = rhs; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Subtract-assignment from arbitrary MultiArrayView. Fails with | | /** Subtract-assignment from arbitrary MultiArrayView. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
|
| | | If the left array has no data (hasData() is false), this functi | |
| | | on is | |
| | | equivalent to an assignment of the negated rhs (i.e. an empty | |
| | | array is interpreted as a zero-array of appropriate size). | |
| */ | | */ | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray &operator-= (const MultiArrayView<N, U, StrideTag> &rhs) | | MultiArray &operator-= (const MultiArrayView<N, U, StrideTag> &rhs) | |
| { | | { | |
|
| | | if(!this->hasData()) | |
| | | this->reshape(rhs.shape()); | |
| view_type::operator-=(rhs); | | view_type::operator-=(rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Multiply-assignment from arbitrary MultiArrayView. Fails with | | /** Multiply-assignment from arbitrary MultiArrayView. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
|
| | | If the left array has no data (hasData() is false), this functi | |
| | | on is | |
| | | equivalent to reshape(rhs.shape()) with zero initialisation (i. | |
| | | e. an empty | |
| | | array is interpreted as a zero-array of appropriate size). | |
| */ | | */ | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray &operator*= (const MultiArrayView<N, U, StrideTag> &rhs) | | MultiArray &operator*= (const MultiArrayView<N, U, StrideTag> &rhs) | |
| { | | { | |
|
| view_type::operator*=(rhs); | | if(this->hasData()) | |
| | | view_type::operator*=(rhs); | |
| | | else | |
| | | this->reshape(rhs.shape()); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Divide-assignment from arbitrary MultiArrayView. Fails with | | /** Divide-assignment from arbitrary MultiArrayView. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
|
| | | If the left array has no data (hasData() is false), this functi | |
| | | on is | |
| | | equivalent to reshape(rhs.shape()) with zero initialisation (i. | |
| | | e. an empty | |
| | | array is interpreted as a zero-array of appropriate size). | |
| */ | | */ | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray &operator/= (const MultiArrayView<N, U, StrideTag> &rhs) | | MultiArray &operator/= (const MultiArrayView<N, U, StrideTag> &rhs) | |
| { | | { | |
|
| view_type::operator/=(rhs); | | if(this->hasData()) | |
| | | view_type::operator/=(rhs); | |
| | | else | |
| | | this->reshape(rhs.shape()); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Add-assignment of a scalar. | | /** Add-assignment of a scalar. | |
| */ | | */ | |
| MultiArray &operator+= (const T &rhs) | | MultiArray &operator+= (const T &rhs) | |
| { | | { | |
| view_type::operator+=(rhs); | | view_type::operator+=(rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| skipping to change at line 2724 | | skipping to change at line 2801 | |
| | | | |
| /** get the allocator. | | /** get the allocator. | |
| */ | | */ | |
| allocator_type const & allocator () const | | allocator_type const & allocator () const | |
| { | | { | |
| return m_alloc; | | return m_alloc; | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
|
| | | MultiArray <N, T, A>::MultiArray (difference_type_1 length, | |
| | | allocator_type const & alloc) | |
| | | : MultiArrayView <N, T> (difference_type(length), | |
| | | detail::defaultStride <1> (difference_type(length) | |
| | | ), | |
| | | 0), | |
| | | m_alloc(alloc) | |
| | | { | |
| | | allocate (this->m_ptr, this->elementCount (), T()); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class A> | |
| MultiArray <N, T, A>::MultiArray (const difference_type &shape, | | MultiArray <N, T, A>::MultiArray (const difference_type &shape, | |
| allocator_type const & alloc) | | allocator_type const & alloc) | |
| : MultiArrayView <N, T> (shape, | | : MultiArrayView <N, T> (shape, | |
| detail::defaultStride <MultiArrayView<N,T>::actual
_dimension> (shape), | | detail::defaultStride <MultiArrayView<N,T>::actual
_dimension> (shape), | |
| 0), | | 0), | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| { | | { | |
| if (N == 0) | | if (N == 0) | |
| { | | { | |
| this->m_shape [0] = 1; | | this->m_shape [0] = 1; | |
| | | | |
| skipping to change at line 3259 | | skipping to change at line 3347 | |
| vigra_precondition ( | | vigra_precondition ( | |
| array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3
."); | | array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3
."); | |
| return BasicImageView <RGBValue<T> > ( | | return BasicImageView <RGBValue<T> > ( | |
| reinterpret_cast <RGBValue <T> *> (array.data ()), | | reinterpret_cast <RGBValue <T> *> (array.data ()), | |
| array.shape (1), array.shape (2)); | | array.shape (1), array.shape (2)); | |
| } | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
|
| | | | |
| #undef VIGRA_ASSERT_INSIDE | | #undef VIGRA_ASSERT_INSIDE | |
|
| | | | |
| #endif // VIGRA_MULTI_ARRAY_HXX | | #endif // VIGRA_MULTI_ARRAY_HXX | |
| | | | |
End of changes. 31 change blocks. |
| 42 lines changed or deleted | | 145 lines changed or added | |
|
| multi_iterator.hxx | | multi_iterator.hxx | |
| | | | |
| skipping to change at line 65 | | skipping to change at line 65 | |
| <p> | | <p> | |
| <UL style="list-style-image:url(documents/bullet.gif)"> | | <UL style="list-style-image:url(documents/bullet.gif)"> | |
| <LI> \ref vigra::MultiArrayShape | | <LI> \ref vigra::MultiArrayShape | |
| <BR> <em>Difference type for \ref vigra::MultiArrayVi
ew or \ref vigra::MultiIterator</em> | | <BR> <em>Difference type for \ref vigra::MultiArrayVi
ew or \ref vigra::MultiIterator</em> | |
| <LI> \ref vigra::MultiIterator | | <LI> \ref vigra::MultiIterator | |
| <BR> <em>Iterator for unstrided \ref vigra::MultiArra
yView</em> | | <BR> <em>Iterator for unstrided \ref vigra::MultiArra
yView</em> | |
| <LI> \ref vigra::StridedMultiIterator | | <LI> \ref vigra::StridedMultiIterator | |
| <BR> <em>Iterator for strided \ref vigra::MultiArrayV
iew</em> | | <BR> <em>Iterator for strided \ref vigra::MultiArrayV
iew</em> | |
| <LI> \ref vigra::StridedScanOrderIterator | | <LI> \ref vigra::StridedScanOrderIterator | |
| <BR> <em>STL-compatible random access iterator for \r
ef vigra::MultiArrayView</em> | | <BR> <em>STL-compatible random access iterator for \r
ef vigra::MultiArrayView</em> | |
|
| | | <LI> \ref vigra::CoupledScanOrderIterator | |
| | | <BR> <em>Iterate over multiple images simultaneously | |
| | | in scan order</em> | |
| </UL> | | </UL> | |
| </p> | | </p> | |
| | | | |
| <p> | | <p> | |
| The Multidimensional Iterator concept allows navigation on arrays | | The Multidimensional Iterator concept allows navigation on arrays | |
| of arbitrary dimension. It provides two modes of iteration: | | of arbitrary dimension. It provides two modes of iteration: | |
| <em>direct traversal</em>, and <em>hierarchical traversal</em>. | | <em>direct traversal</em>, and <em>hierarchical traversal</em>. | |
| In general, hierarchical traversal will be faster, while only | | In general, hierarchical traversal will be faster, while only | |
| direct traversal allows for true random access in all dimensions. | | direct traversal allows for true random access in all dimensions. | |
| Via the <tt>dim<K>()</tt> function, operations applying to a particular | | Via the <tt>dim<K>()</tt> function, operations applying to a particular | |
| | | | |
| skipping to change at line 364 | | skipping to change at line 366 | |
| */ | | */ | |
| typedef TinyVector<MultiArrayIndex, N> type; | | typedef TinyVector<MultiArrayIndex, N> type; | |
| }; | | }; | |
| | | | |
| typedef MultiArrayShape<1>::type Shape1; ///< shape type for MultiArray<1,
T> | | typedef MultiArrayShape<1>::type Shape1; ///< shape type for MultiArray<1,
T> | |
| typedef MultiArrayShape<2>::type Shape2; ///< shape type for MultiArray<2,
T> | | typedef MultiArrayShape<2>::type Shape2; ///< shape type for MultiArray<2,
T> | |
| typedef MultiArrayShape<3>::type Shape3; ///< shape type for MultiArray<3,
T> | | typedef MultiArrayShape<3>::type Shape3; ///< shape type for MultiArray<3,
T> | |
| typedef MultiArrayShape<4>::type Shape4; ///< shape type for MultiArray<4,
T> | | typedef MultiArrayShape<4>::type Shape4; ///< shape type for MultiArray<4,
T> | |
| typedef MultiArrayShape<5>::type Shape5; ///< shape type for MultiArray<5,
T> | | typedef MultiArrayShape<5>::type Shape5; ///< shape type for MultiArray<5,
T> | |
| | | | |
|
| | | template <class POINTER> | |
| | | struct MultiIteratorStrideTraits | |
| | | { | |
| | | typedef MultiArrayIndex stride_type; | |
| | | typedef const stride_type* stride_array_type; | |
| | | typedef stride_array_type shape_array_type; | |
| | | static stride_array_type shift(stride_array_type s, unsigned d) | |
| | | { | |
| | | return s + d; | |
| | | } | |
| | | }; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* MultiIterator */ | | /* MultiIterator */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <unsigned int N, class T, class REFERENCE, class POINTER> | | template <unsigned int N, class T, class REFERENCE, class POINTER> | |
| class MultiIterator; | | class MultiIterator; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| skipping to change at line 391 | | skipping to change at line 405 | |
| class MultiIterator<1, T, REFERENCE, POINTER> | | class MultiIterator<1, T, REFERENCE, POINTER> | |
| { | | { | |
| public: | | public: | |
| enum { level = 0 }; | | enum { level = 0 }; | |
| typedef T value_type; | | typedef T value_type; | |
| typedef REFERENCE reference; | | typedef REFERENCE reference; | |
| typedef const value_type &const_reference; | | typedef const value_type &const_reference; | |
| typedef POINTER pointer; | | typedef POINTER pointer; | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| typedef typename MultiArrayShape<1>::type multi_difference_type; | | typedef typename MultiArrayShape<1>::type multi_difference_type; | |
|
| typedef MultiArrayIndex difference_type; | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| | | typedef typename stride_traits::shape_array_type shape_array_type; | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | |
| typedef std::random_access_iterator_tag iterator_category; | | typedef std::random_access_iterator_tag iterator_category; | |
| | | | |
| protected: | | protected: | |
| pointer m_ptr; | | pointer m_ptr; | |
| | | | |
| public: | | public: | |
| MultiIterator () | | MultiIterator () | |
| : m_ptr (0) | | : m_ptr (0) | |
| {} | | {} | |
| | | | |
| MultiIterator (pointer ptr, | | MultiIterator (pointer ptr, | |
|
| const difference_type *, | | const difference_array_type &, | |
| const difference_type *) | | const shape_array_type &) | |
| : m_ptr (ptr) | | : m_ptr (ptr) | |
| {} | | {} | |
| | | | |
| void operator++ () | | void operator++ () | |
| { | | { | |
| ++m_ptr; | | ++m_ptr; | |
| } | | } | |
| | | | |
| void operator-- () | | void operator-- () | |
| { | | { | |
| | | | |
| skipping to change at line 595 | | skipping to change at line 612 | |
| public: | | public: | |
| | | | |
| typedef MultiIterator<1, T, REFERENCE, POINTER> base_type; | | typedef MultiIterator<1, T, REFERENCE, POINTER> base_type; | |
| enum { level = 1 }; | | enum { level = 1 }; | |
| typedef T value_type; | | typedef T value_type; | |
| typedef REFERENCE reference; | | typedef REFERENCE reference; | |
| typedef const value_type &const_reference; | | typedef const value_type &const_reference; | |
| typedef POINTER pointer; | | typedef POINTER pointer; | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| typedef typename MultiArrayShape<2>::type multi_difference_type; | | typedef typename MultiArrayShape<2>::type multi_difference_type; | |
|
| typedef MultiArrayIndex difference_type; | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| | | typedef typename stride_traits::shape_array_type shape_array_type; | |
| typedef base_type next_type; | | typedef base_type next_type; | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | |
| typedef multi_dimensional_traverser_tag iterator_category; | | typedef multi_dimensional_traverser_tag iterator_category; | |
| | | | |
| protected: | | protected: | |
|
| const difference_type *m_stride; | | difference_array_type m_stride; | |
| const difference_type *m_shape; | | shape_array_type m_shape; | |
| | | | |
| public: | | public: | |
| /* use default copy constructor and assignment operator */ | | /* use default copy constructor and assignment operator */ | |
| | | | |
| MultiIterator () | | MultiIterator () | |
| : base_type (), | | : base_type (), | |
| m_stride (0), m_shape (0) | | m_stride (0), m_shape (0) | |
| {} | | {} | |
| | | | |
| MultiIterator (pointer ptr, | | MultiIterator (pointer ptr, | |
|
| const difference_type *stride, | | const difference_array_type & stride, | |
| const difference_type *shape) | | const shape_array_type & shape) | |
| : base_type (ptr, stride, shape), | | : base_type (ptr, stride, shape), | |
| m_stride (stride), m_shape (shape) | | m_stride (stride), m_shape (shape) | |
| {} | | {} | |
| | | | |
| void operator++ () | | void operator++ () | |
| { | | { | |
| this->m_ptr += m_stride [level]; | | this->m_ptr += m_stride [level]; | |
| } | | } | |
| | | | |
| void operator-- () | | void operator-- () | |
| | | | |
| skipping to change at line 726 | | skipping to change at line 746 | |
| { | | { | |
| next_type ret = *this; | | next_type ret = *this; | |
| ret += m_shape [level-1]; | | ret += m_shape [level-1]; | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| iterator iteratorForDimension(unsigned int d) const | | iterator iteratorForDimension(unsigned int d) const | |
| { | | { | |
| vigra_precondition(d <= level, | | vigra_precondition(d <= level, | |
| "MultiIterator<N>::iteratorForDimension(d): d < N required"); | | "MultiIterator<N>::iteratorForDimension(d): d < N required"); | |
|
| return iterator(this->m_ptr, &m_stride [d], 0); | | return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0); | |
| } | | } | |
| | | | |
| template <unsigned int K> | | template <unsigned int K> | |
| MultiIterator<K+1, T, REFERENCE, POINTER> & | | MultiIterator<K+1, T, REFERENCE, POINTER> & | |
| dim() | | dim() | |
| { | | { | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| MultiIterator<1, T, REFERENCE, POINTER> & | | MultiIterator<1, T, REFERENCE, POINTER> & | |
| | | | |
| skipping to change at line 808 | | skipping to change at line 828 | |
| */ | | */ | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| | | | |
| /** multi difference type | | /** multi difference type | |
| (used for offsetting along all axes simultaneously) | | (used for offsetting along all axes simultaneously) | |
| */ | | */ | |
| typedef typename MultiArrayShape<N>::type multi_difference_type; | | typedef typename MultiArrayShape<N>::type multi_difference_type; | |
| | | | |
| /** difference type (used for offsetting) | | /** difference type (used for offsetting) | |
| */ | | */ | |
|
| | | #ifndef DOXYGEN | |
| | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| | | typedef typename stride_traits::shape_array_type shape_array_type; | |
| | | #else | |
| typedef MultiArrayIndex difference_type; | | typedef MultiArrayIndex difference_type; | |
|
| | | #endif | |
| | | | |
| /** the MultiIterator for the next lower dimension. | | /** the MultiIterator for the next lower dimension. | |
| */ | | */ | |
| typedef base_type next_type; | | typedef base_type next_type; | |
| | | | |
| /** the 1-dimensional iterator for this iterator hierarchy | | /** the 1-dimensional iterator for this iterator hierarchy | |
| (result of iteratorForDimension()). | | (result of iteratorForDimension()). | |
| */ | | */ | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | |
| | | | |
| | | | |
| skipping to change at line 834 | | skipping to change at line 861 | |
| | | | |
| /** default constructor. | | /** default constructor. | |
| */ | | */ | |
| MultiIterator () | | MultiIterator () | |
| {} | | {} | |
| | | | |
| /** construct from pointer, strides (offset of a sample to the | | /** construct from pointer, strides (offset of a sample to the | |
| next) for every dimension, and the shape. | | next) for every dimension, and the shape. | |
| */ | | */ | |
| MultiIterator (pointer ptr, | | MultiIterator (pointer ptr, | |
|
| const difference_type *stride, | | const difference_array_type & stride, | |
| const difference_type *shape) | | const shape_array_type & shape) | |
| : base_type (ptr, stride, shape) | | : base_type (ptr, stride, shape) | |
| {} | | {} | |
| | | | |
|
| /** prefix-increment the iterator in it's current dimension | | /** prefix-increment the iterator in its current dimension | |
| */ | | */ | |
| void operator++ () | | void operator++ () | |
| { | | { | |
| this->m_ptr += this->m_stride [level]; | | this->m_ptr += this->m_stride [level]; | |
| } | | } | |
| | | | |
|
| /** prefix-decrement the iterator in it's current dimension | | /** prefix-decrement the iterator in its current dimension | |
| */ | | */ | |
| void operator-- () | | void operator-- () | |
| { | | { | |
| this->m_ptr -= this->m_stride [level]; | | this->m_ptr -= this->m_stride [level]; | |
| } | | } | |
| | | | |
|
| /** postfix-increment the iterator in it's current dimension | | /** postfix-increment the iterator in its current dimension | |
| */ | | */ | |
| MultiIterator operator++ (int) | | MultiIterator operator++ (int) | |
| { | | { | |
| MultiIterator ret = *this; | | MultiIterator ret = *this; | |
| ++(*this); | | ++(*this); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
|
| /** postfix-decrement the iterator in it's current dimension | | /** postfix-decrement the iterator in its current dimension | |
| */ | | */ | |
| MultiIterator operator-- (int) | | MultiIterator operator-- (int) | |
| { | | { | |
| MultiIterator ret = *this; | | MultiIterator ret = *this; | |
| --(*this); | | --(*this); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
|
| /** increment the iterator in it's current dimension | | /** increment the iterator in its current dimension | |
| by the given value. | | by the given value. | |
| */ | | */ | |
| MultiIterator & operator+= (difference_type n) | | MultiIterator & operator+= (difference_type n) | |
| { | | { | |
| this->m_ptr += n * this->m_stride [level]; | | this->m_ptr += n * this->m_stride [level]; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** increment the iterator in all dimensions | | /** increment the iterator in all dimensions | |
| by the given offset. | | by the given offset. | |
| */ | | */ | |
| MultiIterator & operator+= (multi_difference_type const & d) | | MultiIterator & operator+= (multi_difference_type const & d) | |
| { | | { | |
| this->m_ptr += total_stride(d.begin()); | | this->m_ptr += total_stride(d.begin()); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| /** decrement the iterator in it's current dimension | | /** decrement the iterator in its current dimension | |
| by the given value. | | by the given value. | |
| */ | | */ | |
| MultiIterator & operator-= (difference_type n) | | MultiIterator & operator-= (difference_type n) | |
| { | | { | |
| this->m_ptr -= n * this->m_stride [level]; | | this->m_ptr -= n * this->m_stride [level]; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** decrement the iterator in all dimensions | | /** decrement the iterator in all dimensions | |
| by the given offset. | | by the given offset. | |
| | | | |
| skipping to change at line 1062 | | skipping to change at line 1089 | |
| for(; i != end; ++i) | | for(; i != end; ++i) | |
| { | | { | |
| // go down the current column starting at the location of '
outer' | | // go down the current column starting at the location of '
outer' | |
| } | | } | |
| \endcode | | \endcode | |
| */ | | */ | |
| iterator iteratorForDimension(unsigned int d) const | | iterator iteratorForDimension(unsigned int d) const | |
| { | | { | |
| vigra_precondition(d <= level, | | vigra_precondition(d <= level, | |
| "MultiIterator<N>::iteratorForDimension(d): d < N required"); | | "MultiIterator<N>::iteratorForDimension(d): d < N required"); | |
|
| return iterator(this->m_ptr, &this->m_stride [d], 0); | | return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d
),0); | |
| } | | } | |
| /** Return the multi-iterator that operates on dimension K in order | | /** Return the multi-iterator that operates on dimension K in order | |
| to manipulate this dimension directly. Usage: | | to manipulate this dimension directly. Usage: | |
| | | | |
| \code | | \code | |
| | | | |
| MultiIterator<3, int> i3 = ...; | | MultiIterator<3, int> i3 = ...; | |
| | | | |
| i3.template dim<2>()++; // increment outer dimension | | i3.template dim<2>()++; // increment outer dimension | |
| i3.template dim<0>()++; // increment inner dimension | | i3.template dim<0>()++; // increment inner dimension | |
| | | | |
| skipping to change at line 1141 | | skipping to change at line 1168 | |
| class StridedMultiIterator<1, T, REFERENCE, POINTER> | | class StridedMultiIterator<1, T, REFERENCE, POINTER> | |
| { | | { | |
| public: | | public: | |
| enum { level = 0 }; | | enum { level = 0 }; | |
| typedef T value_type; | | typedef T value_type; | |
| typedef REFERENCE reference; | | typedef REFERENCE reference; | |
| typedef const value_type &const_reference; | | typedef const value_type &const_reference; | |
| typedef POINTER pointer; | | typedef POINTER pointer; | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| typedef typename MultiArrayShape<1>::type multi_difference_type; | | typedef typename MultiArrayShape<1>::type multi_difference_type; | |
|
| typedef MultiArrayIndex difference_type; | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| | | typedef typename stride_traits::shape_array_type shape_array_type; | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | |
| typedef std::random_access_iterator_tag iterator_category; | | typedef std::random_access_iterator_tag iterator_category; | |
| | | | |
| protected: | | protected: | |
| pointer m_ptr; | | pointer m_ptr; | |
| difference_type m_stride; | | difference_type m_stride; | |
| | | | |
| /* use default copy constructor and assignment operator */ | | /* use default copy constructor and assignment operator */ | |
| | | | |
| public: | | public: | |
| StridedMultiIterator () | | StridedMultiIterator () | |
| : m_ptr (0), m_stride (0) | | : m_ptr (0), m_stride (0) | |
| {} | | {} | |
| | | | |
| StridedMultiIterator (pointer ptr, | | StridedMultiIterator (pointer ptr, | |
|
| const difference_type *stride, | | const difference_array_type & stride, | |
| const difference_type *) | | const shape_array_type &) | |
| : m_ptr (ptr), m_stride (stride [level]) | | : m_ptr (ptr), m_stride (stride [level]) | |
| {} | | {} | |
| | | | |
| void operator++ () | | void operator++ () | |
| { | | { | |
| m_ptr += m_stride; | | m_ptr += m_stride; | |
| } | | } | |
| | | | |
| void operator-- () | | void operator-- () | |
| { | | { | |
| | | | |
| skipping to change at line 1348 | | skipping to change at line 1378 | |
| public: | | public: | |
| | | | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type; | |
| enum { level = 1 }; | | enum { level = 1 }; | |
| typedef T value_type; | | typedef T value_type; | |
| typedef REFERENCE reference; | | typedef REFERENCE reference; | |
| typedef const value_type &const_reference; | | typedef const value_type &const_reference; | |
| typedef POINTER pointer; | | typedef POINTER pointer; | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| typedef typename MultiArrayShape<2>::type multi_difference_type; | | typedef typename MultiArrayShape<2>::type multi_difference_type; | |
|
| typedef MultiArrayIndex difference_type; | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| | | typedef typename stride_traits::shape_array_type shape_array_type; | |
| typedef base_type next_type; | | typedef base_type next_type; | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | |
| typedef multi_dimensional_traverser_tag iterator_category; | | typedef multi_dimensional_traverser_tag iterator_category; | |
| | | | |
| protected: | | protected: | |
|
| const difference_type *m_stride; | | difference_array_type m_stride; | |
| const difference_type *m_shape; | | shape_array_type m_shape; | |
| | | | |
| public: | | public: | |
| /* use default copy constructor and assignment operator */ | | /* use default copy constructor and assignment operator */ | |
| | | | |
| StridedMultiIterator () | | StridedMultiIterator () | |
| : base_type (), | | : base_type (), | |
| m_stride (0), m_shape (0) | | m_stride (0), m_shape (0) | |
| {} | | {} | |
| | | | |
| StridedMultiIterator (pointer ptr, | | StridedMultiIterator (pointer ptr, | |
|
| const difference_type *stride, | | const difference_array_type & stride, | |
| const difference_type *shape) | | const shape_array_type & shape) | |
| : base_type (ptr, stride, shape), | | : base_type (ptr, stride, shape), | |
| m_stride (stride), m_shape (shape) | | m_stride (stride), m_shape (shape) | |
| {} | | {} | |
| | | | |
| void operator++ () | | void operator++ () | |
| { | | { | |
| this->m_ptr += m_stride [level]; | | this->m_ptr += m_stride [level]; | |
| } | | } | |
| | | | |
| void operator-- () | | void operator-- () | |
| | | | |
| skipping to change at line 1479 | | skipping to change at line 1512 | |
| { | | { | |
| next_type ret = *this; | | next_type ret = *this; | |
| ret += m_shape [level-1]; | | ret += m_shape [level-1]; | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| iterator iteratorForDimension(unsigned int d) const | | iterator iteratorForDimension(unsigned int d) const | |
| { | | { | |
| vigra_precondition(d <= level, | | vigra_precondition(d <= level, | |
| "StridedMultiIterator<N>::iteratorForDimension(d): d < N requir
ed"); | | "StridedMultiIterator<N>::iteratorForDimension(d): d < N requir
ed"); | |
|
| return iterator(this->m_ptr, &m_stride [d], 0); | | return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0); | |
| } | | } | |
| | | | |
| template <unsigned int K> | | template <unsigned int K> | |
| StridedMultiIterator<K+1, T, REFERENCE, POINTER> & | | StridedMultiIterator<K+1, T, REFERENCE, POINTER> & | |
| dim() | | dim() | |
| { | | { | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| StridedMultiIterator<1, T, REFERENCE, POINTER> & | | StridedMultiIterator<1, T, REFERENCE, POINTER> & | |
| | | | |
| skipping to change at line 1561 | | skipping to change at line 1594 | |
| */ | | */ | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| | | | |
| /** multi difference type | | /** multi difference type | |
| (used for offsetting along all axes simultaneously) | | (used for offsetting along all axes simultaneously) | |
| */ | | */ | |
| typedef typename MultiArrayShape<N>::type multi_difference_type; | | typedef typename MultiArrayShape<N>::type multi_difference_type; | |
| | | | |
| /** difference type (used for offsetting) | | /** difference type (used for offsetting) | |
| */ | | */ | |
|
| | | #ifndef DOXYGEN | |
| | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| | | #else | |
| typedef MultiArrayIndex difference_type; | | typedef MultiArrayIndex difference_type; | |
|
| | | #endif | |
| | | | |
| /** the StridedMultiIterator for the next lower dimension. | | /** the StridedMultiIterator for the next lower dimension. | |
| */ | | */ | |
| typedef base_type next_type; | | typedef base_type next_type; | |
| | | | |
| /** the 1-dimensional iterator for this iterator hierarchy | | /** the 1-dimensional iterator for this iterator hierarchy | |
| (result of iteratorForDimension()). | | (result of iteratorForDimension()). | |
| */ | | */ | |
| typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | | typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator; | |
| | | | |
| | | | |
| skipping to change at line 1587 | | skipping to change at line 1626 | |
| | | | |
| /** default constructor. | | /** default constructor. | |
| */ | | */ | |
| StridedMultiIterator () | | StridedMultiIterator () | |
| {} | | {} | |
| | | | |
| /** construct from pointer, strides (offset of a sample to the | | /** construct from pointer, strides (offset of a sample to the | |
| next) for every dimension, and the shape. | | next) for every dimension, and the shape. | |
| */ | | */ | |
| StridedMultiIterator (pointer ptr, | | StridedMultiIterator (pointer ptr, | |
|
| const difference_type *stride, | | const difference_array_type & stride, | |
| const difference_type *shape) | | const difference_array_type & shape) | |
| : base_type (ptr, stride, shape) | | : base_type (ptr, stride, shape) | |
| {} | | {} | |
| | | | |
|
| /** prefix-increment the iterator in it's current dimension | | /** prefix-increment the iterator in its current dimension | |
| */ | | */ | |
| void operator++ () | | void operator++ () | |
| { | | { | |
| this->m_ptr += this->m_stride [level]; | | this->m_ptr += this->m_stride [level]; | |
| } | | } | |
| | | | |
|
| /** prefix-decrement the iterator in it's current dimension | | /** prefix-decrement the iterator in its current dimension | |
| */ | | */ | |
| void operator-- () | | void operator-- () | |
| { | | { | |
| this->m_ptr -= this->m_stride [level]; | | this->m_ptr -= this->m_stride [level]; | |
| } | | } | |
| | | | |
|
| /** postfix-increment the iterator in it's current dimension | | /** postfix-increment the iterator in its current dimension | |
| */ | | */ | |
| StridedMultiIterator operator++ (int) | | StridedMultiIterator operator++ (int) | |
| { | | { | |
| StridedMultiIterator ret = *this; | | StridedMultiIterator ret = *this; | |
| ++(*this); | | ++(*this); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
|
| /** postfix-decrement the iterator in it's current dimension | | /** postfix-decrement the iterator in its current dimension | |
| */ | | */ | |
| StridedMultiIterator operator-- (int) | | StridedMultiIterator operator-- (int) | |
| { | | { | |
| StridedMultiIterator ret = *this; | | StridedMultiIterator ret = *this; | |
| --(*this); | | --(*this); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
|
| /** increment the iterator in it's current dimension | | /** increment the iterator in its current dimension | |
| by the given value. | | by the given value. | |
| */ | | */ | |
| StridedMultiIterator & operator+= (difference_type n) | | StridedMultiIterator & operator+= (difference_type n) | |
| { | | { | |
| this->m_ptr += n * this->m_stride [level]; | | this->m_ptr += n * this->m_stride [level]; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** increment the iterator in all dimensions | | /** increment the iterator in all dimensions | |
| by the given offset. | | by the given offset. | |
| */ | | */ | |
| StridedMultiIterator & operator+= (multi_difference_type const & d) | | StridedMultiIterator & operator+= (multi_difference_type const & d) | |
| { | | { | |
| this->m_ptr += total_stride(d.begin()); | | this->m_ptr += total_stride(d.begin()); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| /** decrement the iterator in it's current dimension | | /** decrement the iterator in its current dimension | |
| by the given value. | | by the given value. | |
| */ | | */ | |
| StridedMultiIterator & operator-= (difference_type n) | | StridedMultiIterator & operator-= (difference_type n) | |
| { | | { | |
| this->m_ptr -= n * this->m_stride [level]; | | this->m_ptr -= n * this->m_stride [level]; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** decrement the iterator in all dimensions | | /** decrement the iterator in all dimensions | |
| by the given offset. | | by the given offset. | |
| | | | |
| skipping to change at line 1815 | | skipping to change at line 1854 | |
| for(; i != end; ++i) | | for(; i != end; ++i) | |
| { | | { | |
| // go down the current column starting at the location of '
outer' | | // go down the current column starting at the location of '
outer' | |
| } | | } | |
| \endcode | | \endcode | |
| */ | | */ | |
| iterator iteratorForDimension(unsigned int d) const | | iterator iteratorForDimension(unsigned int d) const | |
| { | | { | |
| vigra_precondition(d <= level, | | vigra_precondition(d <= level, | |
| "StridedMultiIterator<N>::iteratorForDimension(d): d < N requir
ed"); | | "StridedMultiIterator<N>::iteratorForDimension(d): d < N requir
ed"); | |
|
| return iterator(this->m_ptr, &this->m_stride [d], 0); | | return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d
),0); | |
| } | | } | |
| /** Return the multi-iterator that operates on dimension K in order | | /** Return the multi-iterator that operates on dimension K in order | |
| to manipulate this dimension directly. Usage: | | to manipulate this dimension directly. Usage: | |
| | | | |
| \code | | \code | |
| | | | |
| StridedMultiIterator<3, int> i3 = ...; | | StridedMultiIterator<3, int> i3 = ...; | |
| | | | |
| i3.template dim<2>()++; // increment outer dimension | | i3.template dim<2>()++; // increment outer dimension | |
| i3.template dim<0>()++; // increment inner dimension | | i3.template dim<0>()++; // increment inner dimension | |
| | | | |
| skipping to change at line 1869 | | skipping to change at line 1908 | |
| difference_type | | difference_type | |
| total_stride(typename multi_difference_type::const_iterator d) const | | total_stride(typename multi_difference_type::const_iterator d) const | |
| { | | { | |
| return d[level]*this->m_stride[level] + base_type::total_stride(d); | | return d[level]*this->m_stride[level] + base_type::total_stride(d); | |
| } | | } | |
| | | | |
| }; | | }; | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
|
| | | template <int K> | |
| | | struct CoordinateToScanOrder | |
| | | { | |
| | | template <int N> | |
| | | static MultiArrayIndex | |
| | | exec(const TinyVector <MultiArrayIndex, N> &shape, | |
| | | const TinyVector <MultiArrayIndex, N> & coordinate) | |
| | | { | |
| | | return coordinate[N-K] + shape[N-K] * CoordinateToScanOrder<K-1>::e | |
| | | xec(shape, coordinate); | |
| | | } | |
| | | }; | |
| | | | |
| | | template <> | |
| | | struct CoordinateToScanOrder<1> | |
| | | { | |
| | | template <int N> | |
| | | static MultiArrayIndex | |
| | | exec(const TinyVector <MultiArrayIndex, N> & /*shape*/, | |
| | | const TinyVector <MultiArrayIndex, N> & coordinate) | |
| | | { | |
| | | return coordinate[N-1]; | |
| | | } | |
| | | }; | |
| | | | |
| template <unsigned int M> | | template <unsigned int M> | |
| struct MoveToScanOrderIndex | | struct MoveToScanOrderIndex | |
| { | | { | |
| template <class Shape, class Ptr> | | template <class Shape, class Ptr> | |
| static void | | static void | |
| exec(MultiArrayIndex newIndex, Shape const & shape, | | exec(MultiArrayIndex newIndex, Shape const & shape, | |
| Shape & point, Ptr & p, Shape const & strides) | | Shape & point, Ptr & p, Shape const & strides) | |
| { | | { | |
| enum { N = Shape::static_size }; | | enum { N = Shape::static_size }; | |
| MultiArrayIndex newPos = newIndex % shape[N-1-M]; | | MultiArrayIndex newPos = newIndex % shape[N-1-M]; | |
| | | | |
| skipping to change at line 1908 | | skipping to change at line 1971 | |
| | | | |
| template <> | | template <> | |
| struct MoveToScanOrderIndex<0> | | struct MoveToScanOrderIndex<0> | |
| { | | { | |
| template <class Shape, class Ptr> | | template <class Shape, class Ptr> | |
| static void | | static void | |
| exec(MultiArrayIndex newIndex, Shape const & shape, | | exec(MultiArrayIndex newIndex, Shape const & shape, | |
| Shape & point, Ptr & p, Shape const & strides) | | Shape & point, Ptr & p, Shape const & strides) | |
| { | | { | |
| enum { N = Shape::static_size }; | | enum { N = Shape::static_size }; | |
|
| MultiArrayIndex newPos = newIndex % shape[N-1]; | | MultiArrayIndex newPos = std::min(newIndex, shape[N-1]); | |
| p += (newPos - point[N-1]) * strides[N-1]; | | p += (newPos - point[N-1]) * strides[N-1]; | |
| point[N-1] = newPos; | | point[N-1] = newPos; | |
| } | | } | |
| | | | |
| template <class Shape, class Ptr1, class Ptr2> | | template <class Shape, class Ptr1, class Ptr2> | |
| static void | | static void | |
| exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point, | | exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point, | |
| Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & stride
s2) | | Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & stride
s2) | |
| { | | { | |
| enum { N = Shape::static_size }; | | enum { N = Shape::static_size }; | |
|
| MultiArrayIndex newPos = newIndex % shape[N-1]; | | MultiArrayIndex newPos = std::min(newIndex, shape[N-1]); | |
| p1 += (newPos - point[N-1]) * strides1[N-1]; | | p1 += (newPos - point[N-1]) * strides1[N-1]; | |
| p2 += (newPos - point[N-1]) * strides2[N-1]; | | p2 += (newPos - point[N-1]) * strides2[N-1]; | |
| point[N-1] = newPos; | | point[N-1] = newPos; | |
| } | | } | |
| }; | | }; | |
| | | | |
| #if 0 // alternative implementation, may be faster on some machines | | #if 0 // alternative implementation, may be faster on some machines | |
| template <unsigned int M> | | template <unsigned int M> | |
| struct MoveToScanOrderIndex | | struct MoveToScanOrderIndex | |
| { | | { | |
| | | | |
| skipping to change at line 2023 | | skipping to change at line 2086 | |
| typedef StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1> base_ty
pe; | | typedef StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1> base_ty
pe; | |
| enum { level = M-1 }; | | enum { level = M-1 }; | |
| | | | |
| public: | | public: | |
| | | | |
| typedef typename base_type::value_type value_type; | | typedef typename base_type::value_type value_type; | |
| typedef typename base_type::pointer pointer; | | typedef typename base_type::pointer pointer; | |
| typedef typename base_type::reference reference; | | typedef typename base_type::reference reference; | |
| typedef typename base_type::const_reference const_reference; | | typedef typename base_type::const_reference const_reference; | |
| typedef typename base_type::shape_type shape_type; | | typedef typename base_type::shape_type shape_type; | |
|
| typedef MultiArrayIndex difference_type; | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| typedef StridedScanOrderIterator iterator; | | typedef StridedScanOrderIterator iterator; | |
| typedef std::random_access_iterator_tag iterator_category; | | typedef std::random_access_iterator_tag iterator_category; | |
| | | | |
| StridedScanOrderIterator() | | StridedScanOrderIterator() | |
| {} | | {} | |
| | | | |
| StridedScanOrderIterator(pointer i, | | StridedScanOrderIterator(pointer i, | |
| shape_type const & shape, shape_type const & s
trides) | | shape_type const & shape, shape_type const & s
trides) | |
| : base_type(i, shape, strides) | | : base_type(i, shape, strides) | |
| {} | | {} | |
| | | | |
| skipping to change at line 2060 | | skipping to change at line 2125 | |
| ++*this; | | ++*this; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| StridedScanOrderIterator & operator+=(MultiArrayIndex i) | | StridedScanOrderIterator & operator+=(MultiArrayIndex i) | |
| { | | { | |
| this->moveToScanOrderIndex(this->index_+i); | | this->moveToScanOrderIndex(this->index_+i); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | //! overload to add a coord-tuple: | |
| | | // it should be cheaper because the modulo-divisions are avoided | |
| | | StridedScanOrderIterator & operator+=(const shape_type &coordOffset) | |
| | | { | |
| | | this->moveRelative(dot(coordOffset,this->strides_), | |
| | | detail::CoordinateToScanOrder<N>::exec(this->shape_, coordOf | |
| | | fset), | |
| | | coordOffset); | |
| | | return *this; | |
| | | } | |
| | | StridedScanOrderIterator & operator-=(const shape_type &coordOffset) | |
| | | { | |
| | | return operator+=(-coordOffset); | |
| | | } | |
| | | | |
| StridedScanOrderIterator & operator--() | | StridedScanOrderIterator & operator--() | |
| { | | { | |
| base_type::operator--(); | | base_type::operator--(); | |
| if(this->point_[level-1] == -1) | | if(this->point_[level-1] == -1) | |
| { | | { | |
| base_type::inverseReset(); | | base_type::inverseReset(); | |
| this->i_ -= this->strides_[level]; | | this->i_ -= this->strides_[level]; | |
| --this->point_[level]; | | --this->point_[level]; | |
| } | | } | |
| return *this; | | return *this; | |
| | | | |
| skipping to change at line 2118 | | skipping to change at line 2197 | |
| StridedScanOrderIterator operator+(MultiArrayIndex d) const | | StridedScanOrderIterator operator+(MultiArrayIndex d) const | |
| { | | { | |
| return StridedScanOrderIterator(*this) += d; | | return StridedScanOrderIterator(*this) += d; | |
| } | | } | |
| | | | |
| StridedScanOrderIterator operator-(MultiArrayIndex d) const | | StridedScanOrderIterator operator-(MultiArrayIndex d) const | |
| { | | { | |
| return StridedScanOrderIterator(*this) -= d; | | return StridedScanOrderIterator(*this) -= d; | |
| } | | } | |
| | | | |
|
| | | StridedScanOrderIterator operator+(const shape_type &coordOffset) const | |
| | | { | |
| | | return StridedScanOrderIterator(*this) += coordOffset; | |
| | | } | |
| | | | |
| | | StridedScanOrderIterator operator-(const shape_type &coordOffset) const | |
| | | { | |
| | | return StridedScanOrderIterator(*this) -= coordOffset; | |
| | | } | |
| | | | |
| MultiArrayIndex operator-(StridedScanOrderIterator const & r) const | | MultiArrayIndex operator-(StridedScanOrderIterator const & r) const | |
| { | | { | |
| return base_type::operator-(r); | | return base_type::operator-(r); | |
| } | | } | |
| | | | |
| bool operator==(StridedScanOrderIterator const & r) | | bool operator==(StridedScanOrderIterator const & r) | |
| { | | { | |
| return base_type::operator==(r); | | return base_type::operator==(r); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 2200 | | skipping to change at line 2289 | |
| { | | { | |
| base_type::decrement(p2, strides2); | | base_type::decrement(p2, strides2); | |
| if(this->point_[level-1] == -1) | | if(this->point_[level-1] == -1) | |
| { | | { | |
| base_type::inverseReset(); | | base_type::inverseReset(); | |
| this->i_ -= this->strides_[level]; | | this->i_ -= this->strides_[level]; | |
| p2 -= strides2[level] - this->shape_[level-1]*strides2[level-1]
; | | p2 -= strides2[level] - this->shape_[level-1]*strides2[level-1]
; | |
| --this->point_[level]; | | --this->point_[level]; | |
| } | | } | |
| } | | } | |
|
| | | StridedScanOrderIterator & moveRelative(const MultiArrayIndex &pointerO | |
| | | ffset, | |
| | | const MultiArrayIndex &indexOff | |
| | | set, | |
| | | const shape_type &coordOffset) | |
| | | { | |
| | | base_type::moveRelative(pointerOffset, indexOffset, coordOffset); | |
| | | this->point_[level] += coordOffset[level]; | |
| | | return *this; | |
| | | } | |
| }; | | }; | |
| | | | |
| template <unsigned int N, class T, class REFERENCE, class POINTER> | | template <unsigned int N, class T, class REFERENCE, class POINTER> | |
| class StridedScanOrderIterator<N, T, REFERENCE, POINTER, 1> | | class StridedScanOrderIterator<N, T, REFERENCE, POINTER, 1> | |
| { | | { | |
| enum { level = 0 }; | | enum { level = 0 }; | |
| | | | |
| public: | | public: | |
| | | | |
| typedef T value_type; | | typedef T value_type; | |
| typedef POINTER pointer; | | typedef POINTER pointer; | |
| typedef T const * const_pointer; | | typedef T const * const_pointer; | |
| typedef REFERENCE reference; | | typedef REFERENCE reference; | |
| typedef T const & const_reference; | | typedef T const & const_reference; | |
| typedef typename MultiArrayShape<N>::type shape_type; | | typedef typename MultiArrayShape<N>::type shape_type; | |
|
| typedef MultiArrayIndex difference_type; | | typedef MultiIteratorStrideTraits<POINTER> stride_traits; | |
| | | typedef typename stride_traits::stride_type difference_type; | |
| | | typedef typename stride_traits::stride_array_type difference_array_type | |
| | | ; | |
| typedef StridedScanOrderIterator iterator; | | typedef StridedScanOrderIterator iterator; | |
| typedef std::random_access_iterator_tag iterator_category; | | typedef std::random_access_iterator_tag iterator_category; | |
| | | | |
| StridedScanOrderIterator() | | StridedScanOrderIterator() | |
| : i_((pointer)0), | | : i_((pointer)0), | |
| index_(0) | | index_(0) | |
| {} | | {} | |
| | | | |
| StridedScanOrderIterator(pointer i, | | StridedScanOrderIterator(pointer i, | |
| shape_type const & shape, shape_type const & s
trides) | | shape_type const & shape, shape_type const & s
trides) | |
| | | | |
| skipping to change at line 2253 | | skipping to change at line 2352 | |
| ++*this; | | ++*this; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| StridedScanOrderIterator & operator+=(MultiArrayIndex i) | | StridedScanOrderIterator & operator+=(MultiArrayIndex i) | |
| { | | { | |
| this->moveToScanOrderIndex(index_+i); | | this->moveToScanOrderIndex(index_+i); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | //! overload to add a coord-tuple: | |
| | | StridedScanOrderIterator & operator+=(const shape_type &coordOffset) | |
| | | { | |
| | | this->moveRelative(dot(coordOffset,strides_), | |
| | | detail::CoordinateToScanOrder<N>::exec(shape_, coordOffset), | |
| | | coordOffset); | |
| | | return *this; | |
| | | } | |
| | | | |
| | | StridedScanOrderIterator & operator-=(const shape_type &coordOffset) | |
| | | { | |
| | | return operator+=(-coordOffset); | |
| | | } | |
| | | | |
| StridedScanOrderIterator & operator--() | | StridedScanOrderIterator & operator--() | |
| { | | { | |
| i_ -= strides_[level]; | | i_ -= strides_[level]; | |
| --point_[level]; | | --point_[level]; | |
| --index_; | | --index_; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| StridedScanOrderIterator operator--(int) | | StridedScanOrderIterator operator--(int) | |
| { | | { | |
| | | | |
| skipping to change at line 2329 | | skipping to change at line 2442 | |
| { | | { | |
| return StridedScanOrderIterator(*this) += d; | | return StridedScanOrderIterator(*this) += d; | |
| } | | } | |
| | | | |
| StridedScanOrderIterator | | StridedScanOrderIterator | |
| operator-(MultiArrayIndex d) const | | operator-(MultiArrayIndex d) const | |
| { | | { | |
| return StridedScanOrderIterator(*this) -= d; | | return StridedScanOrderIterator(*this) -= d; | |
| } | | } | |
| | | | |
|
| | | StridedScanOrderIterator operator+(const shape_type &coordOffset) const | |
| | | { | |
| | | return StridedScanOrderIterator(*this) += coordOffset; | |
| | | } | |
| | | | |
| | | StridedScanOrderIterator operator-(const shape_type &coordOffset) const | |
| | | { | |
| | | return StridedScanOrderIterator(*this) -= coordOffset; | |
| | | } | |
| | | | |
| MultiArrayIndex | | MultiArrayIndex | |
| operator-(StridedScanOrderIterator const & r) const | | operator-(StridedScanOrderIterator const & r) const | |
| { | | { | |
| return index() - r.index(); | | return index() - r.index(); | |
| } | | } | |
| | | | |
| bool | | bool | |
| operator==(StridedScanOrderIterator const & r) | | operator==(StridedScanOrderIterator const & r) | |
| { | | { | |
| return index() == r.index(); | | return index() == r.index(); | |
| | | | |
| skipping to change at line 2453 | | skipping to change at line 2576 | |
| p2 -= strides2[level]; | | p2 -= strides2[level]; | |
| } | | } | |
| | | | |
| template <class Ptr> | | template <class Ptr> | |
| void moveToScanOrderIndex(MultiArrayIndex newIndex, Ptr & p2, shape_typ
e const & strides2) | | void moveToScanOrderIndex(MultiArrayIndex newIndex, Ptr & p2, shape_typ
e const & strides2) | |
| { | | { | |
| index_ = newIndex; | | index_ = newIndex; | |
| detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i
_, strides_, p2, strides2); | | detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i
_, strides_, p2, strides2); | |
| } | | } | |
| | | | |
|
| | | StridedScanOrderIterator & moveRelative(const MultiArrayIndex &pointerO | |
| | | ffset, | |
| | | const MultiArrayIndex &indexOff | |
| | | set, | |
| | | const shape_type &coordOffset) | |
| | | { | |
| | | point_[level] += coordOffset[level]; | |
| | | | |
| | | index_+= indexOffset; | |
| | | i_ += pointerOffset; | |
| | | | |
| | | return *this; | |
| | | } | |
| | | | |
| pointer i_; | | pointer i_; | |
| shape_type point_, shape_, strides_; | | shape_type point_, shape_, strides_; | |
| MultiArrayIndex index_; | | MultiArrayIndex index_; | |
| }; | | }; | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_MULTI_ITERATOR_HXX | | #endif // VIGRA_MULTI_ITERATOR_HXX | |
| | | | |
End of changes. 45 change blocks. |
| 40 lines changed or deleted | | 190 lines changed or added | |
|
| splineimageview.hxx | | splineimageview.hxx | |
| | | | |
| skipping to change at line 109 | | skipping to change at line 109 | |
| class SplineImageView | | class SplineImageView | |
| { | | { | |
| typedef typename NumericTraits<VALUETYPE>::RealPromote InternalValue; | | typedef typename NumericTraits<VALUETYPE>::RealPromote InternalValue; | |
| | | | |
| public: | | public: | |
| | | | |
| /** The view's value type (return type of access and derivative fun
ctions). | | /** The view's value type (return type of access and derivative fun
ctions). | |
| */ | | */ | |
| typedef VALUETYPE value_type; | | typedef VALUETYPE value_type; | |
| | | | |
|
| | | /** The view's squared norm type (return type of g2() etc.). | |
| | | */ | |
| | | typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType | |
| | | ; | |
| | | | |
| /** The view's size type. | | /** The view's size type. | |
| */ | | */ | |
| typedef Size2D size_type; | | typedef Size2D size_type; | |
| | | | |
| /** The view's difference type. | | /** The view's difference type. | |
| */ | | */ | |
| typedef TinyVector<double, 2> difference_type; | | typedef TinyVector<double, 2> difference_type; | |
| | | | |
| /** The order of the spline used. | | /** The order of the spline used. | |
| */ | | */ | |
| | | | |
| skipping to change at line 310 | | skipping to change at line 314 | |
| { return dxxy(d[0], d[1]); } | | { return dxxy(d[0], d[1]); } | |
| | | | |
| /** Access mixed 3rd derivative dxyy at real-valued coordinate <tt>
d</tt>. | | /** Access mixed 3rd derivative dxyy at real-valued coordinate <tt>
d</tt>. | |
| Equivalent to <tt>splineView.dxyy(d[0], d[1])</tt>. | | Equivalent to <tt>splineView.dxyy(d[0], d[1])</tt>. | |
| */ | | */ | |
| value_type dxyy(difference_type const & d) const | | value_type dxyy(difference_type const & d) const | |
| { return dxyy(d[0], d[1]); } | | { return dxyy(d[0], d[1]); } | |
| | | | |
| /** Access gradient squared magnitude at real-valued coordinate <tt
>(x, y)</tt>. | | /** Access gradient squared magnitude at real-valued coordinate <tt
>(x, y)</tt>. | |
| */ | | */ | |
|
| value_type g2(double x, double y) const; | | SquaredNormType g2(double x, double y) const; | |
| | | | |
| /** Access 1st derivative in x-direction of gradient squared magnit
ude | | /** Access 1st derivative in x-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>(x, y)</tt>. | | at real-valued coordinate <tt>(x, y)</tt>. | |
| */ | | */ | |
|
| value_type g2x(double x, double y) const; | | SquaredNormType g2x(double x, double y) const; | |
| | | | |
| /** Access 1st derivative in y-direction of gradient squared magnit
ude | | /** Access 1st derivative in y-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>(x, y)</tt>. | | at real-valued coordinate <tt>(x, y)</tt>. | |
| */ | | */ | |
|
| value_type g2y(double x, double y) const; | | SquaredNormType g2y(double x, double y) const; | |
| | | | |
| /** Access 2nd derivative in x-direction of gradient squared magnit
ude | | /** Access 2nd derivative in x-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>(x, y)</tt>. | | at real-valued coordinate <tt>(x, y)</tt>. | |
| */ | | */ | |
|
| value_type g2xx(double x, double y) const; | | SquaredNormType g2xx(double x, double y) const; | |
| | | | |
| /** Access mixed 2nd derivative of gradient squared magnitude | | /** Access mixed 2nd derivative of gradient squared magnitude | |
| at real-valued coordinate <tt>(x, y)</tt>. | | at real-valued coordinate <tt>(x, y)</tt>. | |
| */ | | */ | |
|
| value_type g2xy(double x, double y) const; | | SquaredNormType g2xy(double x, double y) const; | |
| | | | |
| /** Access 2nd derivative in y-direction of gradient squared magnit
ude | | /** Access 2nd derivative in y-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>(x, y)</tt>. | | at real-valued coordinate <tt>(x, y)</tt>. | |
| */ | | */ | |
|
| value_type g2yy(double x, double y) const; | | SquaredNormType g2yy(double x, double y) const; | |
| | | | |
| /** Access gradient squared magnitude at real-valued coordinate <tt
>d</tt>. | | /** Access gradient squared magnitude at real-valued coordinate <tt
>d</tt>. | |
| */ | | */ | |
|
| value_type g2(difference_type const & d) const | | SquaredNormType g2(difference_type const & d) const | |
| { return g2(d[0], d[1]); } | | { return g2(d[0], d[1]); } | |
| | | | |
| /** Access 1st derivative in x-direction of gradient squared magnit
ude | | /** Access 1st derivative in x-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>d</tt>. | | at real-valued coordinate <tt>d</tt>. | |
| */ | | */ | |
|
| value_type g2x(difference_type const & d) const | | SquaredNormType g2x(difference_type const & d) const | |
| { return g2x(d[0], d[1]); } | | { return g2x(d[0], d[1]); } | |
| | | | |
| /** Access 1st derivative in y-direction of gradient squared magnit
ude | | /** Access 1st derivative in y-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>d</tt>. | | at real-valued coordinate <tt>d</tt>. | |
| */ | | */ | |
|
| value_type g2y(difference_type const & d) const | | SquaredNormType g2y(difference_type const & d) const | |
| { return g2y(d[0], d[1]); } | | { return g2y(d[0], d[1]); } | |
| | | | |
| /** Access 2nd derivative in x-direction of gradient squared magnit
ude | | /** Access 2nd derivative in x-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>d</tt>. | | at real-valued coordinate <tt>d</tt>. | |
| */ | | */ | |
|
| value_type g2xx(difference_type const & d) const | | SquaredNormType g2xx(difference_type const & d) const | |
| { return g2xx(d[0], d[1]); } | | { return g2xx(d[0], d[1]); } | |
| | | | |
| /** Access mixed 2nd derivative of gradient squared magnitude | | /** Access mixed 2nd derivative of gradient squared magnitude | |
| at real-valued coordinate <tt>d</tt>. | | at real-valued coordinate <tt>d</tt>. | |
| */ | | */ | |
|
| value_type g2xy(difference_type const & d) const | | SquaredNormType g2xy(difference_type const & d) const | |
| { return g2xy(d[0], d[1]); } | | { return g2xy(d[0], d[1]); } | |
| | | | |
| /** Access 2nd derivative in y-direction of gradient squared magnit
ude | | /** Access 2nd derivative in y-direction of gradient squared magnit
ude | |
| at real-valued coordinate <tt>d</tt>. | | at real-valued coordinate <tt>d</tt>. | |
| */ | | */ | |
|
| value_type g2yy(difference_type const & d) const | | SquaredNormType g2yy(difference_type const & d) const | |
| { return g2yy(d[0], d[1]); } | | { return g2yy(d[0], d[1]); } | |
| | | | |
| /** The width of the image. | | /** The width of the image. | |
| <tt>0 <= x <= width()-1</tt> is required for all access functio
ns. | | <tt>0 <= x <= width()-1</tt> is required for all access functio
ns. | |
| */ | | */ | |
| unsigned int width() const | | unsigned int width() const | |
| { return w_; } | | { return w_; } | |
| | | | |
| /** The height of the image. | | /** The height of the image. | |
| <tt>0 <= y <= height()-1</tt> is required for all access functi
ons. | | <tt>0 <= y <= height()-1</tt> is required for all access functi
ons. | |
| | | | |
| skipping to change at line 405 | | skipping to change at line 409 | |
| { return TinyVector<unsigned int, 2>(w_, h_); } | | { return TinyVector<unsigned int, 2>(w_, h_); } | |
| | | | |
| /** The internal image holding the spline coefficients. | | /** The internal image holding the spline coefficients. | |
| */ | | */ | |
| InternalImage const & image() const | | InternalImage const & image() const | |
| { | | { | |
| return image_; | | return image_; | |
| } | | } | |
| | | | |
| /** Get the array of polynomial coefficients for the facet containi
ng | | /** Get the array of polynomial coefficients for the facet containi
ng | |
|
| the point <tt>(x, y)</tt>. The array <tt>res</tt> will be resiz
ed to | | the point <tt>(x, y)</tt>. The array <tt>res</tt> must have | |
| dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients
, the | | dimension <tt>(ORDER+1)x(ORDER+1)</tt>. From these coefficients
, the | |
| value of the interpolated function can be calculated by the fol
lowing | | value of the interpolated function can be calculated by the fol
lowing | |
| algorithm | | algorithm | |
| | | | |
| \code | | \code | |
| SplineImageView<ORDER, float> view(...); | | SplineImageView<ORDER, float> view(...); | |
| double x = ..., y = ...; | | double x = ..., y = ...; | |
| double dx, dy; | | double dx, dy; | |
| | | | |
| // calculate the local facet coordinates of x and y | | // calculate the local facet coordinates of x and y | |
| | | | |
| skipping to change at line 664 | | skipping to change at line 668 | |
| ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::ex
ec(kx_, image_.rowBegin(iy_[j]), ix_)); | | ky_[j]*detail::SplineImageViewUnrollLoop2<ORDER, RealPromote>::ex
ec(kx_, image_.rowBegin(iy_[j]), ix_)); | |
| } | | } | |
| return detail::RequiresExplicitCast<VALUETYPE>::cast(sum); | | return detail::RequiresExplicitCast<VALUETYPE>::cast(sum); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
| template <class Array> | | template <class Array> | |
| void | | void | |
| SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Arr
ay & res) const | | SplineImageView<ORDER, VALUETYPE>::coefficientArray(double x, double y, Arr
ay & res) const | |
| { | | { | |
|
| | | typedef typename Array::value_type ResType; | |
| typename Spline::WeightMatrix & weights = Spline::weights(); | | typename Spline::WeightMatrix & weights = Spline::weights(); | |
|
| double tmp[ksize_][ksize_]; | | ResType tmp[ksize_][ksize_]; | |
| | | | |
| calculateIndices(x, y); | | calculateIndices(x, y); | |
| for(int j=0; j<ksize_; ++j) | | for(int j=0; j<ksize_; ++j) | |
| { | | { | |
| for(int i=0; i<ksize_; ++i) | | for(int i=0; i<ksize_; ++i) | |
| { | | { | |
|
| tmp[i][j] = 0.0; | | tmp[i][j] = ResType(); | |
| for(int k=0; k<ksize_; ++k) | | for(int k=0; k<ksize_; ++k) | |
| { | | { | |
| tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]); | | tmp[i][j] += weights[i][k]*image_(ix_[k], iy_[j]); | |
| } | | } | |
| } | | } | |
| } | | } | |
|
| res.resize(ksize_, ksize_); | | | |
| for(int j=0; j<ksize_; ++j) | | for(int j=0; j<ksize_; ++j) | |
| { | | { | |
| for(int i=0; i<ksize_; ++i) | | for(int i=0; i<ksize_; ++i) | |
| { | | { | |
|
| res(i,j) = 0.0; | | res(i,j) = ResType(); | |
| for(int k=0; k<ksize_; ++k) | | for(int k=0; k<ksize_; ++k) | |
| { | | { | |
| res(i,j) += weights[j][k]*tmp[i][k]; | | res(i,j) += weights[j][k]*tmp[i][k]; | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y)
const | | VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y)
const | |
| | | | |
| skipping to change at line 713 | | skipping to change at line 717 | |
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y, | | VALUETYPE SplineImageView<ORDER, VALUETYPE>::operator()(double x, double y, | |
| unsigned int dx, unsigned
int dy) const | | unsigned int dx, unsigned
int dy) const | |
| { | | { | |
| calculateIndices(x, y); | | calculateIndices(x, y); | |
| derivCoefficients(u_, dx, kx_); | | derivCoefficients(u_, dx, kx_); | |
| derivCoefficients(v_, dy, ky_); | | derivCoefficients(v_, dy, ky_); | |
| return convolve(); | | return convolve(); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
|
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const | | typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType | |
| | | SplineImageView<ORDER, VALUETYPE>::g2(double x, double y) const | |
| { | | { | |
|
| return sq(dx(x,y)) + sq(dy(x,y)); | | return squaredNorm(dx(x,y)) + squaredNorm(dy(x,y)); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
|
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const | | typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType | |
| | | SplineImageView<ORDER, VALUETYPE>::g2x(double x, double y) const | |
| { | | { | |
|
| return VALUETYPE(2.0)*(dx(x,y) * dxx(x,y) + dy(x,y) * dxy(x,y)); | | return SquaredNormType(2.0)*(dot(dx(x,y), dxx(x,y)) + dot(dy(x,y), dxy(
x,y))); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
|
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const | | typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType | |
| | | SplineImageView<ORDER, VALUETYPE>::g2y(double x, double y) const | |
| { | | { | |
|
| return VALUETYPE(2.0)*(dx(x,y) * dxy(x,y) + dy(x,y) * dyy(x,y)); | | return SquaredNormType(2.0)*(dot(dx(x,y), dxy(x,y)) + dot(dy(x,y), dyy(
x,y))); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
|
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const | | typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType | |
| | | SplineImageView<ORDER, VALUETYPE>::g2xx(double x, double y) const | |
| { | | { | |
|
| return VALUETYPE(2.0)*(sq(dxx(x,y)) + dx(x,y) * dx3(x,y) + sq(dxy(x,y)) | | return SquaredNormType(2.0)*(squaredNorm(dxx(x,y)) + dot(dx(x,y), dx3(x | |
| + dy(x,y) * dxxy(x,y)); | | ,y)) + | |
| | | squaredNorm(dxy(x,y)) + dot(dy(x,y), dxxy( | |
| | | x,y))); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
|
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const | | typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType | |
| | | SplineImageView<ORDER, VALUETYPE>::g2yy(double x, double y) const | |
| { | | { | |
|
| return VALUETYPE(2.0)*(sq(dxy(x,y)) + dx(x,y) * dxyy(x,y) + sq(dyy(x,y) | | return SquaredNormType(2.0)*(squaredNorm(dxy(x,y)) + dot(dx(x,y), dxyy( | |
| ) + dy(x,y) * dy3(x,y)); | | x,y)) + | |
| | | squaredNorm(dyy(x,y)) + dot(dy(x,y), dy3(x | |
| | | ,y))); | |
| } | | } | |
| | | | |
| template <int ORDER, class VALUETYPE> | | template <int ORDER, class VALUETYPE> | |
|
| VALUETYPE SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const | | typename SplineImageView<ORDER, VALUETYPE>::SquaredNormType | |
| | | SplineImageView<ORDER, VALUETYPE>::g2xy(double x, double y) const | |
| { | | { | |
|
| return VALUETYPE(2.0)*(dx(x,y) * dxxy(x,y) + dy(x,y) * dxyy(x,y) + dxy( | | return SquaredNormType(2.0)*(dot(dx(x,y), dxxy(x,y)) + dot(dy(x,y), dxy | |
| x,y) * (dxx(x,y) + dyy(x,y))); | | y(x,y)) + | |
| | | dot(dxy(x,y), dxx(x,y) + dyy(x,y))); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* SplineImageView0 */ | | /* SplineImageView0 */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| template <class VALUETYPE, class INTERNAL_INDEXER> | | template <class VALUETYPE, class INTERNAL_INDEXER> | |
| class SplineImageView0Base | | class SplineImageView0Base | |
| { | | { | |
| typedef typename INTERNAL_INDEXER::value_type InternalValue; | | typedef typename INTERNAL_INDEXER::value_type InternalValue; | |
| public: | | public: | |
| typedef VALUETYPE value_type; | | typedef VALUETYPE value_type; | |
|
| | | typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType
; | |
| typedef Size2D size_type; | | typedef Size2D size_type; | |
| typedef TinyVector<double, 2> difference_type; | | typedef TinyVector<double, 2> difference_type; | |
| enum StaticOrder { order = 0 }; | | enum StaticOrder { order = 0 }; | |
| | | | |
| public: | | public: | |
| | | | |
| SplineImageView0Base(unsigned int w, unsigned int h) | | SplineImageView0Base(unsigned int w, unsigned int h) | |
| : w_(w), h_(h) | | : w_(w), h_(h) | |
| {} | | {} | |
| | | | |
| | | | |
| skipping to change at line 909 | | skipping to change at line 923 | |
| | | | |
| value_type dy3(difference_type const & d) const | | value_type dy3(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<VALUETYPE>::zero(); } | |
| | | | |
| value_type dxxy(difference_type const & d) const | | value_type dxxy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<VALUETYPE>::zero(); } | |
| | | | |
| value_type dxyy(difference_type const & d) const | | value_type dxyy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<VALUETYPE>::zero(); } | |
| | | | |
|
| value_type g2(double x, double y) const | | SquaredNormType g2(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2x(double x, double y) const | | SquaredNormType g2x(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2y(double x, double y) const | | SquaredNormType g2y(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xx(double x, double y) const | | SquaredNormType g2xx(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xy(double x, double y) const | | SquaredNormType g2xy(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2yy(double x, double y) const | | SquaredNormType g2yy(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2(difference_type const & d) const | | SquaredNormType g2(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2x(difference_type const & d) const | | SquaredNormType g2x(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2y(difference_type const & d) const | | SquaredNormType g2y(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xx(difference_type const & d) const | | SquaredNormType g2xx(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xy(difference_type const & d) const | | SquaredNormType g2xy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2yy(difference_type const & d) const | | SquaredNormType g2yy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
| unsigned int width() const | | unsigned int width() const | |
| { return w_; } | | { return w_; } | |
| | | | |
| unsigned int height() const | | unsigned int height() const | |
| { return h_; } | | { return h_; } | |
| | | | |
| size_type size() const | | size_type size() const | |
| { return size_type(w_, h_); } | | { return size_type(w_, h_); } | |
| | | | |
| TinyVector<unsigned int, 2> shape() const | | TinyVector<unsigned int, 2> shape() const | |
| { return TinyVector<unsigned int, 2>(w_, h_); } | | { return TinyVector<unsigned int, 2>(w_, h_); } | |
| | | | |
| template <class Array> | | template <class Array> | |
| void coefficientArray(double x, double y, Array & res) const | | void coefficientArray(double x, double y, Array & res) const | |
| { | | { | |
|
| res.resize(1, 1); | | | |
| res(0, 0) = operator()(x,y); | | res(0, 0) = operator()(x,y); | |
| } | | } | |
| | | | |
| bool isInsideX(double x) const | | bool isInsideX(double x) const | |
| { | | { | |
| return x >= 0.0 && x <= width() - 1.0; | | return x >= 0.0 && x <= width() - 1.0; | |
| } | | } | |
| | | | |
| bool isInsideY(double y) const | | bool isInsideY(double y) const | |
| { | | { | |
| | | | |
| skipping to change at line 1014 | | skipping to change at line 1027 | |
| \ref vigra::MultiArray<2, ...>, and \ref vigra::MultiArrayView<
;2, ...>. | | \ref vigra::MultiArray<2, ...>, and \ref vigra::MultiArrayView<
;2, ...>. | |
| | | | |
| */ | | */ | |
| template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V
ALUETYPE>::const_traverser> | | template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V
ALUETYPE>::const_traverser> | |
| class SplineImageView0 | | class SplineImageView0 | |
| : public SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> | | : public SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> | |
| { | | { | |
| typedef SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> Base; | | typedef SplineImageView0Base<VALUETYPE, INTERNAL_TRAVERSER> Base; | |
| public: | | public: | |
| typedef typename Base::value_type value_type; | | typedef typename Base::value_type value_type; | |
|
| | | typedef typename Base::SquaredNormType SquaredNormType; | |
| typedef typename Base::size_type size_type; | | typedef typename Base::size_type size_type; | |
| typedef typename Base::difference_type difference_type; | | typedef typename Base::difference_type difference_type; | |
| enum StaticOrder { order = Base::order }; | | enum StaticOrder { order = Base::order }; | |
| typedef BasicImage<VALUETYPE> InternalImage; | | typedef BasicImage<VALUETYPE> InternalImage; | |
| | | | |
| protected: | | protected: | |
| typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I
nternalTraverser; | | typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I
nternalTraverser; | |
| typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int
ernalAccessor; | | typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int
ernalAccessor; | |
| typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int
ernalConstTraverser; | | typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int
ernalConstTraverser; | |
| typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso
r InternalConstAccessor; | | typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso
r InternalConstAccessor; | |
| | | | |
| skipping to change at line 1089 | | skipping to change at line 1103 | |
| InternalImage image_; | | InternalImage image_; | |
| }; | | }; | |
| | | | |
| template <class VALUETYPE, class StridedOrUnstrided> | | template <class VALUETYPE, class StridedOrUnstrided> | |
| class SplineImageView0<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns
trided> > | | class SplineImageView0<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns
trided> > | |
| : public SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid
edOrUnstrided> > | | : public SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid
edOrUnstrided> > | |
| { | | { | |
| typedef SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St
ridedOrUnstrided> > Base; | | typedef SplineImageView0Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St
ridedOrUnstrided> > Base; | |
| public: | | public: | |
| typedef typename Base::value_type value_type; | | typedef typename Base::value_type value_type; | |
|
| | | typedef typename Base::SquaredNormType SquaredNormType; | |
| typedef typename Base::size_type size_type; | | typedef typename Base::size_type size_type; | |
| typedef typename Base::difference_type difference_type; | | typedef typename Base::difference_type difference_type; | |
| enum StaticOrder { order = Base::order }; | | enum StaticOrder { order = Base::order }; | |
| typedef BasicImage<VALUETYPE> InternalImage; | | typedef BasicImage<VALUETYPE> InternalImage; | |
| | | | |
| protected: | | protected: | |
| typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe
r; | | typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe
r; | |
| | | | |
| public: | | public: | |
| | | | |
| | | | |
| skipping to change at line 1152 | | skipping to change at line 1167 | |
| InternalImage image_; | | InternalImage image_; | |
| }; | | }; | |
| | | | |
| template <class VALUETYPE> | | template <class VALUETYPE> | |
| class SplineImageView<0, VALUETYPE> | | class SplineImageView<0, VALUETYPE> | |
| : public SplineImageView0<VALUETYPE> | | : public SplineImageView0<VALUETYPE> | |
| { | | { | |
| typedef SplineImageView0<VALUETYPE> Base; | | typedef SplineImageView0<VALUETYPE> Base; | |
| public: | | public: | |
| typedef typename Base::value_type value_type; | | typedef typename Base::value_type value_type; | |
|
| | | typedef typename Base::SquaredNormType SquaredNormType; | |
| typedef typename Base::size_type size_type; | | typedef typename Base::size_type size_type; | |
| typedef typename Base::difference_type difference_type; | | typedef typename Base::difference_type difference_type; | |
| enum StaticOrder { order = Base::order }; | | enum StaticOrder { order = Base::order }; | |
| typedef typename Base::InternalImage InternalImage; | | typedef typename Base::InternalImage InternalImage; | |
| | | | |
| protected: | | protected: | |
| typedef typename Base::InternalTraverser InternalTraverser; | | typedef typename Base::InternalTraverser InternalTraverser; | |
| typedef typename Base::InternalAccessor InternalAccessor; | | typedef typename Base::InternalAccessor InternalAccessor; | |
| typedef typename Base::InternalConstTraverser InternalConstTraverser; | | typedef typename Base::InternalConstTraverser InternalConstTraverser; | |
| typedef typename Base::InternalConstAccessor InternalConstAccessor; | | typedef typename Base::InternalConstAccessor InternalConstAccessor; | |
| | | | |
| skipping to change at line 1211 | | skipping to change at line 1227 | |
| /* SplineImageView1 */ | | /* SplineImageView1 */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| template <class VALUETYPE, class INTERNAL_INDEXER> | | template <class VALUETYPE, class INTERNAL_INDEXER> | |
| class SplineImageView1Base | | class SplineImageView1Base | |
| { | | { | |
| typedef typename INTERNAL_INDEXER::value_type InternalValue; | | typedef typename INTERNAL_INDEXER::value_type InternalValue; | |
| public: | | public: | |
| typedef VALUETYPE value_type; | | typedef VALUETYPE value_type; | |
| typedef Size2D size_type; | | typedef Size2D size_type; | |
|
| | | typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType
; | |
| typedef TinyVector<double, 2> difference_type; | | typedef TinyVector<double, 2> difference_type; | |
| enum StaticOrder { order = 1 }; | | enum StaticOrder { order = 1 }; | |
| | | | |
| public: | | public: | |
| | | | |
| SplineImageView1Base(unsigned int w, unsigned int h) | | SplineImageView1Base(unsigned int w, unsigned int h) | |
| : w_(w), h_(h) | | : w_(w), h_(h) | |
| {} | | {} | |
| | | | |
| SplineImageView1Base(int w, int h, INTERNAL_INDEXER i) | | SplineImageView1Base(int w, int h, INTERNAL_INDEXER i) | |
| | | | |
| skipping to change at line 1478 | | skipping to change at line 1495 | |
| | | | |
| value_type dy3(difference_type const & d) const | | value_type dy3(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<VALUETYPE>::zero(); } | |
| | | | |
| value_type dxxy(difference_type const & d) const | | value_type dxxy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<VALUETYPE>::zero(); } | |
| | | | |
| value_type dxyy(difference_type const & d) const | | value_type dxyy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<VALUETYPE>::zero(); } | |
| | | | |
|
| value_type g2(double x, double y) const | | SquaredNormType g2(double x, double y) const | |
| { return sq(dx(x,y)) + sq(dy(x,y)); } | | { return squaredNorm(dx(x,y)) + squaredNorm(dy(x,y)); } | |
| | | | |
|
| value_type g2x(double x, double y) const | | SquaredNormType g2x(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2y(double x, double y) const | | SquaredNormType g2y(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xx(double x, double y) const | | SquaredNormType g2xx(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xy(double x, double y) const | | SquaredNormType g2xy(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2yy(double x, double y) const | | SquaredNormType g2yy(double x, double y) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2(difference_type const & d) const | | SquaredNormType g2(difference_type const & d) const | |
| { return g2(d[0], d[1]); } | | { return g2(d[0], d[1]); } | |
| | | | |
|
| value_type g2x(difference_type const & d) const | | SquaredNormType g2x(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2y(difference_type const & d) const | | SquaredNormType g2y(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xx(difference_type const & d) const | | SquaredNormType g2xx(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2xy(difference_type const & d) const | | SquaredNormType g2xy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
|
| value_type g2yy(difference_type const & d) const | | SquaredNormType g2yy(difference_type const & d) const | |
| { return NumericTraits<VALUETYPE>::zero(); } | | { return NumericTraits<SquaredNormType>::zero(); } | |
| | | | |
| unsigned int width() const | | unsigned int width() const | |
| { return w_; } | | { return w_; } | |
| | | | |
| unsigned int height() const | | unsigned int height() const | |
| { return h_; } | | { return h_; } | |
| | | | |
| size_type size() const | | size_type size() const | |
| { return size_type(w_, h_); } | | { return size_type(w_, h_); } | |
| | | | |
| | | | |
| skipping to change at line 1571 | | skipping to change at line 1588 | |
| unsigned int w_, h_; | | unsigned int w_, h_; | |
| INTERNAL_INDEXER internalIndexer_; | | INTERNAL_INDEXER internalIndexer_; | |
| }; | | }; | |
| | | | |
| template <class VALUETYPE, class INTERNAL_INDEXER> | | template <class VALUETYPE, class INTERNAL_INDEXER> | |
| template <class Array> | | template <class Array> | |
| void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::coefficientArray(do
uble x, double y, Array & res) const | | void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::coefficientArray(do
uble x, double y, Array & res) const | |
| { | | { | |
| int ix, iy, ix1, iy1; | | int ix, iy, ix1, iy1; | |
| calculateIndices(x, y, ix, iy, ix1, iy1); | | calculateIndices(x, y, ix, iy, ix1, iy1); | |
|
| res.resize(2, 2); | | | |
| res(0,0) = internalIndexer_(ix,iy); | | res(0,0) = internalIndexer_(ix,iy); | |
| res(1,0) = internalIndexer_(ix1,iy) - internalIndexer_(ix,iy); | | res(1,0) = internalIndexer_(ix1,iy) - internalIndexer_(ix,iy); | |
| res(0,1) = internalIndexer_(ix,iy1) - internalIndexer_(ix,iy); | | res(0,1) = internalIndexer_(ix,iy1) - internalIndexer_(ix,iy); | |
| res(1,1) = internalIndexer_(ix,iy) - internalIndexer_(ix1,iy) - | | res(1,1) = internalIndexer_(ix,iy) - internalIndexer_(ix1,iy) - | |
| internalIndexer_(ix,iy1) + internalIndexer_(ix1,iy1); | | internalIndexer_(ix,iy1) + internalIndexer_(ix1,iy1); | |
| } | | } | |
| | | | |
| template <class VALUETYPE, class INTERNAL_INDEXER> | | template <class VALUETYPE, class INTERNAL_INDEXER> | |
| void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::calculateIndices(do
uble x, double y, int & ix, int & iy, int & ix1, int & iy1) const | | void SplineImageView1Base<VALUETYPE, INTERNAL_INDEXER>::calculateIndices(do
uble x, double y, int & ix, int & iy, int & ix1, int & iy1) const | |
| { | | { | |
| | | | |
| skipping to change at line 1648 | | skipping to change at line 1664 | |
| In addition, <tt>x</tt> and <tt>y</tt> can have type \ref vigra::FixedP
oint instead of | | In addition, <tt>x</tt> and <tt>y</tt> can have type \ref vigra::FixedP
oint instead of | |
| <tt>double</tt>. | | <tt>double</tt>. | |
| */ | | */ | |
| template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V
ALUETYPE>::const_traverser> | | template <class VALUETYPE, class INTERNAL_TRAVERSER = typename BasicImage<V
ALUETYPE>::const_traverser> | |
| class SplineImageView1 | | class SplineImageView1 | |
| : public SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> | | : public SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> | |
| { | | { | |
| typedef SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> Base; | | typedef SplineImageView1Base<VALUETYPE, INTERNAL_TRAVERSER> Base; | |
| public: | | public: | |
| typedef typename Base::value_type value_type; | | typedef typename Base::value_type value_type; | |
|
| | | typedef typename Base::SquaredNormType SquaredNormType; | |
| typedef typename Base::size_type size_type; | | typedef typename Base::size_type size_type; | |
| typedef typename Base::difference_type difference_type; | | typedef typename Base::difference_type difference_type; | |
| enum StaticOrder { order = Base::order }; | | enum StaticOrder { order = Base::order }; | |
| typedef BasicImage<VALUETYPE> InternalImage; | | typedef BasicImage<VALUETYPE> InternalImage; | |
| | | | |
| protected: | | protected: | |
| typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I
nternalTraverser; | | typedef typename IteratorTraits<INTERNAL_TRAVERSER>::mutable_iterator I
nternalTraverser; | |
| typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int
ernalAccessor; | | typedef typename IteratorTraits<InternalTraverser>::DefaultAccessor Int
ernalAccessor; | |
| typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int
ernalConstTraverser; | | typedef typename IteratorTraits<INTERNAL_TRAVERSER>::const_iterator Int
ernalConstTraverser; | |
| typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso
r InternalConstAccessor; | | typedef typename IteratorTraits<InternalConstTraverser>::DefaultAccesso
r InternalConstAccessor; | |
| | | | |
| skipping to change at line 1723 | | skipping to change at line 1740 | |
| InternalImage image_; | | InternalImage image_; | |
| }; | | }; | |
| | | | |
| template <class VALUETYPE, class StridedOrUnstrided> | | template <class VALUETYPE, class StridedOrUnstrided> | |
| class SplineImageView1<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns
trided> > | | class SplineImageView1<VALUETYPE, MultiArrayView<2, VALUETYPE, StridedOrUns
trided> > | |
| : public SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid
edOrUnstrided> > | | : public SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, Strid
edOrUnstrided> > | |
| { | | { | |
| typedef SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St
ridedOrUnstrided> > Base; | | typedef SplineImageView1Base<VALUETYPE, MultiArrayView<2, VALUETYPE, St
ridedOrUnstrided> > Base; | |
| public: | | public: | |
| typedef typename Base::value_type value_type; | | typedef typename Base::value_type value_type; | |
|
| | | typedef typename Base::SquaredNormType SquaredNormType; | |
| typedef typename Base::size_type size_type; | | typedef typename Base::size_type size_type; | |
| typedef typename Base::difference_type difference_type; | | typedef typename Base::difference_type difference_type; | |
| enum StaticOrder { order = Base::order }; | | enum StaticOrder { order = Base::order }; | |
| typedef BasicImage<VALUETYPE> InternalImage; | | typedef BasicImage<VALUETYPE> InternalImage; | |
| | | | |
| protected: | | protected: | |
| typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe
r; | | typedef MultiArrayView<2, VALUETYPE, StridedOrUnstrided> InternalIndexe
r; | |
| | | | |
| public: | | public: | |
| | | | |
| | | | |
| skipping to change at line 1786 | | skipping to change at line 1804 | |
| InternalImage image_; | | InternalImage image_; | |
| }; | | }; | |
| | | | |
| template <class VALUETYPE> | | template <class VALUETYPE> | |
| class SplineImageView<1, VALUETYPE> | | class SplineImageView<1, VALUETYPE> | |
| : public SplineImageView1<VALUETYPE> | | : public SplineImageView1<VALUETYPE> | |
| { | | { | |
| typedef SplineImageView1<VALUETYPE> Base; | | typedef SplineImageView1<VALUETYPE> Base; | |
| public: | | public: | |
| typedef typename Base::value_type value_type; | | typedef typename Base::value_type value_type; | |
|
| | | typedef typename Base::SquaredNormType SquaredNormType; | |
| typedef typename Base::size_type size_type; | | typedef typename Base::size_type size_type; | |
| typedef typename Base::difference_type difference_type; | | typedef typename Base::difference_type difference_type; | |
| enum StaticOrder { order = Base::order }; | | enum StaticOrder { order = Base::order }; | |
| typedef typename Base::InternalImage InternalImage; | | typedef typename Base::InternalImage InternalImage; | |
| | | | |
| protected: | | protected: | |
| typedef typename Base::InternalTraverser InternalTraverser; | | typedef typename Base::InternalTraverser InternalTraverser; | |
| typedef typename Base::InternalAccessor InternalAccessor; | | typedef typename Base::InternalAccessor InternalAccessor; | |
| typedef typename Base::InternalConstTraverser InternalConstTraverser; | | typedef typename Base::InternalConstTraverser InternalConstTraverser; | |
| typedef typename Base::InternalConstAccessor InternalConstAccessor; | | typedef typename Base::InternalConstAccessor InternalConstAccessor; | |
| | | | |
End of changes. 65 change blocks. |
| 81 lines changed or deleted | | 103 lines changed or added | |
|
| tinyvector.hxx | | tinyvector.hxx | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_TINYVECTOR_HXX | | #ifndef VIGRA_TINYVECTOR_HXX | |
| #define VIGRA_TINYVECTOR_HXX | | #define VIGRA_TINYVECTOR_HXX | |
| | | | |
| #include <cmath> // abs(double) | | #include <cmath> // abs(double) | |
| #include <cstdlib> // abs(int) | | #include <cstdlib> // abs(int) | |
| #include <iosfwd> // ostream | | #include <iosfwd> // ostream | |
|
| | | #include <algorithm> | |
| #include "config.hxx" | | #include "config.hxx" | |
| #include "error.hxx" | | #include "error.hxx" | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "memory.hxx" | | #include "memory.hxx" | |
| #include "mathutil.hxx" | | #include "mathutil.hxx" | |
| #include "diff2d.hxx" | | #include "diff2d.hxx" | |
| | | | |
| #ifdef VIGRA_CHECK_BOUNDS | | #ifdef VIGRA_CHECK_BOUNDS | |
| #define VIGRA_ASSERT_INSIDE(diff) \ | | #define VIGRA_ASSERT_INSIDE(diff) \ | |
| vigra_precondition(diff >= 0, "Index out of bounds");\ | | vigra_precondition(diff >= 0, "Index out of bounds");\ | |
| vigra_precondition(diff < SIZE, "Index out of bounds"); | | vigra_precondition(diff < SIZE, "Index out of bounds"); | |
| #else | | #else | |
| #define VIGRA_ASSERT_INSIDE(diff) | | #define VIGRA_ASSERT_INSIDE(diff) | |
| #endif | | #endif | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
|
| | | // mask cl.exe shortcomings [begin] | |
| | | #if defined(_MSC_VER) | |
| | | #pragma warning( push ) | |
| | | #pragma warning( disable : 4503 ) | |
| | | #endif | |
| | | | |
| using VIGRA_CSTD::abs; | | using VIGRA_CSTD::abs; | |
| using VIGRA_CSTD::ceil; | | using VIGRA_CSTD::ceil; | |
| using VIGRA_CSTD::floor; | | using VIGRA_CSTD::floor; | |
|
| | | using VIGRA_CSTD::sqrt; | |
| | | | |
| template <class V1, int SIZE, class D1, class D2> | | template <class V1, int SIZE, class D1, class D2> | |
| class TinyVectorBase; | | class TinyVectorBase; | |
| | | | |
| template <class V1, int SIZE, class D1, class D2> | | template <class V1, int SIZE, class D1, class D2> | |
| inline | | inline | |
| typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType | | typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType | |
| squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t); | | squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t); | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| #define VIGRA_EXEC_LOOP(NAME, OPER) \ | | #define VIGRA_EXEC_LOOP(NAME, OPER) \ | |
| template <class T1, class T2> \ | | template <class T1, class T2> \ | |
| static void NAME(T1 * left, T2 const * right) \ | | static void NAME(T1 * left, T2 const * right) \ | |
| { \ | | { \ | |
| for(int i=0; i<LEVEL; ++i) \ | | for(int i=0; i<LEVEL; ++i) \ | |
| (left[i]) OPER (right[i]); \ | | (left[i]) OPER (right[i]); \ | |
| } | | } | |
| | | | |
|
| | | #define VIGRA_EXEC_LOOP_MINMAX(NAME, OPER) \ | |
| | | template <class T1, class T2> \ | |
| | | static void NAME(T1 * left, T2 const * right) \ | |
| | | { \ | |
| | | for(int i=0; i<LEVEL; ++i) \ | |
| | | if(left[i] OPER right[i]) \ | |
| | | left[i] = right[i]; \ | |
| | | } | |
| | | | |
| #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ | | #define VIGRA_EXEC_LOOP_SCALAR(NAME, OPER) \ | |
| template <class T1, class T2> \ | | template <class T1, class T2> \ | |
| static void NAME(T1 * left, T2 right) \ | | static void NAME(T1 * left, T2 right) \ | |
| { \ | | { \ | |
| for(int i=0; i<LEVEL; ++i) \ | | for(int i=0; i<LEVEL; ++i) \ | |
| (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OP
ER (right)); \ | | (left[i]) = detail::RequiresExplicitCast<T1>::cast((left[i]) OP
ER (right)); \ | |
| } | | } | |
| | | | |
| template <int LEVEL> | | template <int LEVEL> | |
| struct ExecLoop | | struct ExecLoop | |
| | | | |
| skipping to change at line 114 | | skipping to change at line 131 | |
| left[i] = right[-i]; | | left[i] = right[-i]; | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assignScalar(T1 * left, T2 right) | | static void assignScalar(T1 * left, T2 right) | |
| { | | { | |
| for(int i=0; i<LEVEL; ++i) | | for(int i=0; i<LEVEL; ++i) | |
| left[i] = detail::RequiresExplicitCast<T1>::cast(right); | | left[i] = detail::RequiresExplicitCast<T1>::cast(right); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class T2> | |
| | | static void power(T1 * left, T2 right) | |
| | | { | |
| | | for(int i=0; i<LEVEL; ++i) | |
| | | left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, righ | |
| | | t)); | |
| | | } | |
| | | | |
| VIGRA_EXEC_LOOP(assign, =) | | VIGRA_EXEC_LOOP(assign, =) | |
| VIGRA_EXEC_LOOP(add, +=) | | VIGRA_EXEC_LOOP(add, +=) | |
| VIGRA_EXEC_LOOP(sub, -=) | | VIGRA_EXEC_LOOP(sub, -=) | |
| VIGRA_EXEC_LOOP(mul, *=) | | VIGRA_EXEC_LOOP(mul, *=) | |
| VIGRA_EXEC_LOOP(div, /=) | | VIGRA_EXEC_LOOP(div, /=) | |
| VIGRA_EXEC_LOOP(neg, = -) | | VIGRA_EXEC_LOOP(neg, = -) | |
| VIGRA_EXEC_LOOP(abs, = vigra::abs) | | VIGRA_EXEC_LOOP(abs, = vigra::abs) | |
| VIGRA_EXEC_LOOP(floor, = vigra::floor) | | VIGRA_EXEC_LOOP(floor, = vigra::floor) | |
| VIGRA_EXEC_LOOP(ceil, = vigra::ceil) | | VIGRA_EXEC_LOOP(ceil, = vigra::ceil) | |
|
| | | VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt) | |
| VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | | VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | |
| VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) | | VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) | |
| VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) | | VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) | |
| VIGRA_EXEC_LOOP_SCALAR(divScalar, /) | | VIGRA_EXEC_LOOP_SCALAR(divScalar, /) | |
| | | | |
|
| | | VIGRA_EXEC_LOOP_MINMAX(min, >) | |
| | | VIGRA_EXEC_LOOP_MINMAX(max, <) | |
| | | | |
| | | template <class T> | |
| | | static T const & minimum(T const * p) | |
| | | { | |
| | | return *std::min_element(p, p+LEVEL); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static T const & maximum(T const * p) | |
| | | { | |
| | | return *std::max_element(p, p+LEVEL); | |
| | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static bool notEqual(T1 const * left, T2 const * right) | | static bool notEqual(T1 const * left, T2 const * right) | |
| { | | { | |
| for(int i=0; i<LEVEL; ++i) | | for(int i=0; i<LEVEL; ++i) | |
| if(left[i] != right[i]) | | if(left[i] != right[i]) | |
| return true; | | return true; | |
| return false; | | return false; | |
| } | | } | |
| | | | |
|
| | | template <class T1, class T2> | |
| | | static bool less(T1 const * left, T2 const * right) | |
| | | { | |
| | | for(int i=0; i<LEVEL; ++i) | |
| | | { | |
| | | if(left[i] < right[i]) | |
| | | return true; | |
| | | if(right[i] < left[i]) | |
| | | return false; | |
| | | } | |
| | | return false; | |
| | | } | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
| typename NumericTraits<T>::Promote res(*d * *d); | | typename NumericTraits<T>::Promote res(*d * *d); | |
| for(int i=1; i<LEVEL; ++i) | | for(int i=1; i<LEVEL; ++i) | |
| res += d[i] * d[i]; | | res += d[i] * d[i]; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 169 | | skipping to change at line 221 | |
| squaredNorm(T const * d) | | squaredNorm(T const * d) | |
| { | | { | |
| typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*
d); | | typename NormTraits<T>::SquaredNormType res = vigra::squaredNorm(*
d); | |
| for(int i=1; i<LEVEL; ++i) | | for(int i=1; i<LEVEL; ++i) | |
| res += vigra::squaredNorm(d[i]); | | res += vigra::squaredNorm(d[i]); | |
| return res; | | return res; | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <int LEVEL> | | template <int LEVEL> | |
|
| struct UnrollDot | | struct UnrollScalarResult | |
| { | | { | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
|
| return *d * *d + UnrollDot<LEVEL-1>::dot(d+1); | | return *d * *d + UnrollScalarResult<LEVEL-1>::dot(d+1); | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static typename PromoteTraits<T1, T2>::Promote | | static typename PromoteTraits<T1, T2>::Promote | |
| dot(T1 const * left, T2 const * right) | | dot(T1 const * left, T2 const * right) | |
| { | | { | |
|
| return *left * *right + UnrollDot<LEVEL-1>::dot(left+1, right+1); | | return *left * *right + UnrollScalarResult<LEVEL-1>::dot(left+1, ri | |
| | | ght+1); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static typename NormTraits<T>::SquaredNormType | |
| | | squaredNorm(T const * d) | |
| | | { | |
| | | return vigra::squaredNorm(*d) + UnrollScalarResult<LEVEL-1>::square | |
| | | dNorm(d+1); | |
| | | } | |
| | | | |
| | | static std::ptrdiff_t | |
| | | squaredNorm(std::ptrdiff_t const * d) | |
| | | { | |
| | | return (*d)*(*d) + UnrollScalarResult<LEVEL-1>::squaredNorm(d+1); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static T const & minimum(T const * p) | |
| | | { | |
| | | T const & m = UnrollScalarResult<LEVEL - 1>::minimum(p+1); | |
| | | return *p < m | |
| | | ? *p | |
| | | : m; | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static T const & maximum(T const * p) | |
| | | { | |
| | | T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1); | |
| | | return *p > m | |
| | | ? *p | |
| | | : m; | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <> | | template <> | |
|
| struct UnrollDot<1> | | struct UnrollScalarResult<1> | |
| { | | { | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
| return *d * *d ; | | return *d * *d ; | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static typename PromoteTraits<T1, T2>::Promote | | static typename PromoteTraits<T1, T2>::Promote | |
| dot(T1 const * left, T2 const * right) | | dot(T1 const * left, T2 const * right) | |
| { | | { | |
| return *left * *right; | | return *left * *right; | |
| } | | } | |
|
| }; | | | |
| | | | |
|
| template <int LEVEL> | | | |
| struct UnrollSquaredNorm | | | |
| { | | | |
| template <class T> | | template <class T> | |
| static typename NormTraits<T>::SquaredNormType | | static typename NormTraits<T>::SquaredNormType | |
| squaredNorm(T const * d) | | squaredNorm(T const * d) | |
| { | | { | |
|
| return vigra::squaredNorm(*d) + UnrollSquaredNorm<LEVEL-1>::squared
Norm(d+1); | | return vigra::squaredNorm(*d); | |
| } | | } | |
| | | | |
| static std::ptrdiff_t | | static std::ptrdiff_t | |
| squaredNorm(std::ptrdiff_t const * d) | | squaredNorm(std::ptrdiff_t const * d) | |
| { | | { | |
|
| return (*d)*(*d) + UnrollSquaredNorm<LEVEL-1>::squaredNorm(d+1); | | return (*d)*(*d); | |
| } | | } | |
|
| }; | | | |
| | | | |
|
| template <> | | | |
| struct UnrollSquaredNorm<1> | | | |
| { | | | |
| template <class T> | | template <class T> | |
|
| static typename NormTraits<T>::SquaredNormType | | static T const & minimum(T const * p) | |
| squaredNorm(T const * d) | | | |
| { | | { | |
|
| return vigra::squaredNorm(*d); | | return *p; | |
| } | | } | |
| | | | |
|
| static std::ptrdiff_t | | template <class T> | |
| squaredNorm(std::ptrdiff_t const * d) | | static T const & maximum(T const * p) | |
| { | | { | |
|
| return (*d)*(*d); | | return *p; | |
| } | | } | |
| }; | | }; | |
| | | | |
| #undef VIGRA_EXEC_LOOP | | #undef VIGRA_EXEC_LOOP | |
|
| | | #undef VIGRA_EXEC_LOOP_MINMAX | |
| #undef VIGRA_EXEC_LOOP_SCALAR | | #undef VIGRA_EXEC_LOOP_SCALAR | |
| | | | |
| #define VIGRA_UNROLL_LOOP(NAME, OPER) \ | | #define VIGRA_UNROLL_LOOP(NAME, OPER) \ | |
| template <class T1, class T2> \ | | template <class T1, class T2> \ | |
| static void NAME(T1 * left, T2 const * right) \ | | static void NAME(T1 * left, T2 const * right) \ | |
| { \ | | { \ | |
| (*left) OPER (*right); \ | | (*left) OPER (*right); \ | |
| UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ | | UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ | |
| } | | } | |
| | | | |
|
| | | #define VIGRA_UNROLL_LOOP_MINMAX(NAME, OPER) \ | |
| | | template <class T1, class T2> \ | |
| | | static void NAME(T1 * left, T2 const * right) \ | |
| | | { \ | |
| | | if(*left OPER *right) \ | |
| | | *left = *right; \ | |
| | | UnrollLoop<LEVEL-1>::NAME(left+1, right+1); \ | |
| | | } | |
| | | | |
| #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ | | #define VIGRA_UNROLL_LOOP_SCALAR(NAME, OPER) \ | |
| template <class T1, class T2> \ | | template <class T1, class T2> \ | |
| static void NAME(T1 * left, T2 right) \ | | static void NAME(T1 * left, T2 right) \ | |
| { \ | | { \ | |
| (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (righ
t)); \ | | (*left) = detail::RequiresExplicitCast<T1>::cast((*left) OPER (righ
t)); \ | |
| UnrollLoop<LEVEL-1>::NAME(left+1, right); \ | | UnrollLoop<LEVEL-1>::NAME(left+1, right); \ | |
| } | | } | |
| | | | |
| template <int LEVEL> | | template <int LEVEL> | |
| struct UnrollLoop | | struct UnrollLoop | |
| | | | |
| skipping to change at line 281 | | skipping to change at line 365 | |
| UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); | | UnrollLoop<LEVEL-1>::assignCast(left+1, right+1); | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assignScalar(T1 * left, T2 right) | | static void assignScalar(T1 * left, T2 right) | |
| { | | { | |
| *left = detail::RequiresExplicitCast<T1>::cast(right); | | *left = detail::RequiresExplicitCast<T1>::cast(right); | |
| UnrollLoop<LEVEL-1>::assignScalar(left+1, right); | | UnrollLoop<LEVEL-1>::assignScalar(left+1, right); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class T2> | |
| | | static void power(T1 * left, T2 right) | |
| | | { | |
| | | *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right)); | |
| | | UnrollLoop<LEVEL-1>::power(left+1, right); | |
| | | } | |
| | | | |
| VIGRA_UNROLL_LOOP(assign, =) | | VIGRA_UNROLL_LOOP(assign, =) | |
| VIGRA_UNROLL_LOOP(add, +=) | | VIGRA_UNROLL_LOOP(add, +=) | |
| VIGRA_UNROLL_LOOP(sub, -=) | | VIGRA_UNROLL_LOOP(sub, -=) | |
| VIGRA_UNROLL_LOOP(mul, *=) | | VIGRA_UNROLL_LOOP(mul, *=) | |
| VIGRA_UNROLL_LOOP(div, /=) | | VIGRA_UNROLL_LOOP(div, /=) | |
| VIGRA_UNROLL_LOOP(neg, = -) | | VIGRA_UNROLL_LOOP(neg, = -) | |
| VIGRA_UNROLL_LOOP(abs, = vigra::abs) | | VIGRA_UNROLL_LOOP(abs, = vigra::abs) | |
| VIGRA_UNROLL_LOOP(floor, = vigra::floor) | | VIGRA_UNROLL_LOOP(floor, = vigra::floor) | |
| VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) | | VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) | |
|
| | | VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt) | |
| VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | | VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | |
| VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote
) | | VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote
) | |
| VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) | | VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) | |
| VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) | | VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) | |
| | | | |
|
| | | VIGRA_UNROLL_LOOP_MINMAX(min, >) | |
| | | VIGRA_UNROLL_LOOP_MINMAX(max, <) | |
| | | | |
| | | template <class T> | |
| | | static T const & minimum(T const * p) | |
| | | { | |
| | | return UnrollScalarResult<LEVEL>::minimum(p); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static T const & maximum(T const * p) | |
| | | { | |
| | | return UnrollScalarResult<LEVEL>::maximum(p); | |
| | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static bool notEqual(T1 const * left, T2 const * right) | | static bool notEqual(T1 const * left, T2 const * right) | |
| { | | { | |
| return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1,
right+1); | | return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1,
right+1); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class T2> | |
| | | static bool less(T1 const * left, T2 const * right) | |
| | | { | |
| | | if(*left < *right) | |
| | | return true; | |
| | | if(*right < *left) | |
| | | return false; | |
| | | return UnrollLoop<LEVEL - 1>::less(left+1, right+1); | |
| | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
|
| return UnrollDot<LEVEL>::dot(d); | | return UnrollScalarResult<LEVEL>::dot(d); | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static typename PromoteTraits<T1, T2>::Promote | | static typename PromoteTraits<T1, T2>::Promote | |
| dot(T1 const * left, T2 const * right) | | dot(T1 const * left, T2 const * right) | |
| { | | { | |
|
| return UnrollDot<LEVEL>::dot(left, right); | | return UnrollScalarResult<LEVEL>::dot(left, right); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static typename NormTraits<T>::SquaredNormType | | static typename NormTraits<T>::SquaredNormType | |
| squaredNorm(T const * d) | | squaredNorm(T const * d) | |
| { | | { | |
|
| return UnrollSquaredNorm<LEVEL>::squaredNorm(d); | | return UnrollScalarResult<LEVEL>::squaredNorm(d); | |
| } | | } | |
| }; | | }; | |
| | | | |
| #undef VIGRA_UNROLL_LOOP | | #undef VIGRA_UNROLL_LOOP | |
|
| | | #undef VIGRA_UNROLL_LOOP_MINMAX | |
| #undef VIGRA_UNROLL_LOOP_SCALAR | | #undef VIGRA_UNROLL_LOOP_SCALAR | |
| | | | |
| template <> | | template <> | |
| struct UnrollLoop<0> | | struct UnrollLoop<0> | |
| { | | { | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void reverseAssign(T1, T2) {} | | static void reverseAssign(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assignCast(T1, T2) {} | | static void assignCast(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assign(T1, T2) {} | | static void assign(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assignScalar(T1, T2) {} | | static void assignScalar(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| | | static void power(T1, T2) {} | |
| | | template <class T1, class T2> | |
| static void add(T1, T2) {} | | static void add(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void sub(T1, T2) {} | | static void sub(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void mul(T1, T2) {} | | static void mul(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void mulScalar(T1, T2) {} | | static void mulScalar(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void div(T1, T2) {} | | static void div(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| | | | |
| skipping to change at line 362 | | skipping to change at line 482 | |
| static void fromRealPromote(T1, T2) {} | | static void fromRealPromote(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void neg(T1, T2) {} | | static void neg(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void abs(T1, T2) {} | | static void abs(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void floor(T1, T2) {} | | static void floor(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void ceil(T1, T2) {} | | static void ceil(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| | | static void sqrt(T1, T2) {} | |
| | | template <class T1, class T2> | |
| static bool notEqual(T1, T2) { return false; } | | static bool notEqual(T1, T2) { return false; } | |
|
| | | template <class T1, class T2> | |
| | | static bool less(T1, T2) { return false; } | |
| | | template <class T1, class T2> | |
| | | static void min(T1, T2) {} | |
| | | template <class T1, class T2> | |
| | | static void max(T1, T2) {} | |
| | | template <class T> | |
| | | static T minimum(T const * p) | |
| | | { | |
| | | return NumericTraits<T>::max(); | |
| | | } | |
| | | template <class T> | |
| | | static T maximum(T const * p) | |
| | | { | |
| | | return NumericTraits<T>::min(); | |
| | | } | |
| }; | | }; | |
| | | | |
| template <int SIZE> | | template <int SIZE> | |
| struct LoopType | | struct LoopType | |
| { | | { | |
|
| typedef typename IfBool<(SIZE < 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >:
:type type; | | typedef typename IfBool<(SIZE <= 5), UnrollLoop<SIZE>, ExecLoop<SIZE> >
::type type; | |
| | | | |
| }; | | }; | |
| | | | |
| struct DontInit {}; | | struct DontInit {}; | |
| | | | |
| inline DontInit dontInit() {return DontInit(); } | | inline DontInit dontInit() {return DontInit(); } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| template <class T, int SIZE> | | template <class T, int SIZE> | |
| | | | |
| skipping to change at line 448 | | skipping to change at line 586 | |
| /** STL-compatible definition of const iterator | | /** STL-compatible definition of const iterator | |
| */ | | */ | |
| typedef value_type const * const_iterator; | | typedef value_type const * const_iterator; | |
| | | | |
| /** STL-compatible definition of size_type | | /** STL-compatible definition of size_type | |
| */ | | */ | |
| typedef unsigned int size_type; | | typedef unsigned int size_type; | |
| | | | |
| /** STL-compatible definition of difference_type | | /** STL-compatible definition of difference_type | |
| */ | | */ | |
|
| typedef int difference_type; | | typedef std::ptrdiff_t difference_type; | |
| | | | |
| /** the scalar type for the outer product | | /** the scalar type for the outer product | |
| */ | | */ | |
| typedef double scalar_multiplier; | | typedef double scalar_multiplier; | |
| | | | |
| /** the vector's squared norm type | | /** the vector's squared norm type | |
| */ | | */ | |
| typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType
; | | typedef typename NormTraits<VALUETYPE>::SquaredNormType SquaredNormType
; | |
| | | | |
| /** the vector's norm type | | /** the vector's norm type | |
| | | | |
| skipping to change at line 550 | | skipping to change at line 688 | |
| SquareRootTraits<SquaredNormType>::SquareRootArgument>(square
dMagnitude())); | | SquareRootTraits<SquaredNormType>::SquareRootArgument>(square
dMagnitude())); | |
| } | | } | |
| | | | |
| /** Calculate squared magnitude. | | /** Calculate squared magnitude. | |
| */ | | */ | |
| SquaredNormType squaredMagnitude() const | | SquaredNormType squaredMagnitude() const | |
| { | | { | |
| return Loop::squaredNorm(data_); | | return Loop::squaredNorm(data_); | |
| } | | } | |
| | | | |
|
| | | /** Return the minimal element. | |
| | | */ | |
| | | VALUETYPE const & minimum() const | |
| | | { | |
| | | return Loop::minimum(data_); | |
| | | } | |
| | | | |
| | | /** Return the maximal element. | |
| | | */ | |
| | | VALUETYPE const & maximum() const | |
| | | { | |
| | | return Loop::maximum(data_); | |
| | | } | |
| | | | |
| /** Access component by index. | | /** Access component by index. | |
| */ | | */ | |
| reference operator[](difference_type i) | | reference operator[](difference_type i) | |
| { | | { | |
| VIGRA_ASSERT_INSIDE(i); | | VIGRA_ASSERT_INSIDE(i); | |
| return data_[i]; | | return data_[i]; | |
| } | | } | |
| | | | |
| /** Get component by index. | | /** Get component by index. | |
| */ | | */ | |
| | | | |
| skipping to change at line 646 | | skipping to change at line 798 | |
| typedef typename BaseType::iterator iterator; | | typedef typename BaseType::iterator iterator; | |
| typedef typename BaseType::const_iterator const_iterator; | | typedef typename BaseType::const_iterator const_iterator; | |
| typedef typename BaseType::size_type size_type; | | typedef typename BaseType::size_type size_type; | |
| typedef typename BaseType::difference_type difference_type; | | typedef typename BaseType::difference_type difference_type; | |
| typedef typename BaseType::scalar_multiplier scalar_multiplier; | | typedef typename BaseType::scalar_multiplier scalar_multiplier; | |
| typedef typename BaseType::SquaredNormType SquaredNormType; | | typedef typename BaseType::SquaredNormType SquaredNormType; | |
| typedef typename BaseType::NormType NormType; | | typedef typename BaseType::NormType NormType; | |
| | | | |
| enum ReverseCopyTag { ReverseCopy }; | | enum ReverseCopyTag { ReverseCopy }; | |
| | | | |
|
| /** Construction with constant value | | /** Construction with constant value. | |
| | | | |
| | | Initializes all vector elements with the given value. | |
| */ | | */ | |
| explicit TinyVector(value_type const & initial) | | explicit TinyVector(value_type const & initial) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::assignScalar(BaseType::begin(), initial); | | Loop::assignScalar(BaseType::begin(), initial); | |
| } | | } | |
| | | | |
|
| /** Construction with Diff2D (only implemented for 2D TinyVector) | | /** Construction with Diff2D. | |
| | | | |
| | | Use only when <tt>SIZE == 2</tt>. | |
| */ | | */ | |
| explicit TinyVector(Diff2D const & initial) | | explicit TinyVector(Diff2D const & initial) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.
x); | | BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.
x); | |
| BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.
y); | | BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.
y); | |
| } | | } | |
| | | | |
| /** Construction with explicit values. | | /** Construction with explicit values. | |
| Call only if SIZE == 2 | | Call only if SIZE == 2 | |
| | | | |
| skipping to change at line 711 | | skipping to change at line 867 | |
| value_type const & i3, value_type const & i4, | | value_type const & i3, value_type const & i4, | |
| value_type const & i5) | | value_type const & i5) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| BaseType::data_[0] = i1; | | BaseType::data_[0] = i1; | |
| BaseType::data_[1] = i2; | | BaseType::data_[1] = i2; | |
| BaseType::data_[2] = i3; | | BaseType::data_[2] = i3; | |
| BaseType::data_[3] = i4; | | BaseType::data_[3] = i4; | |
| BaseType::data_[4] = i5; | | BaseType::data_[4] = i5; | |
| } | | } | |
|
| /** Default constructor (initializes all components with zero) | | | |
| | | /** Default constructor (initializes all elements with zero). | |
| */ | | */ | |
| TinyVector() | | TinyVector() | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero
()); | | Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero
()); | |
| } | | } | |
| | | | |
|
| | | /** Construct without initializing the vector elements. | |
| | | */ | |
| | | explicit TinyVector(SkipInitializationTag) | |
| | | : BaseType() | |
| | | {} | |
| | | | |
| | | explicit TinyVector(detail::DontInit) | |
| | | : BaseType() | |
| | | {} | |
| | | | |
| /** Copy constructor. | | /** Copy constructor. | |
| */ | | */ | |
| TinyVector(TinyVector const & r) | | TinyVector(TinyVector const & r) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::assign(BaseType::data_, r.data_); | | Loop::assign(BaseType::data_, r.data_); | |
| } | | } | |
| | | | |
| /** Constructor from C array. | | /** Constructor from C array. | |
| */ | | */ | |
| | | | |
| skipping to change at line 749 | | skipping to change at line 916 | |
| TinyVector<int, 3> v(1,2,3); | | TinyVector<int, 3> v(1,2,3); | |
| TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::Rever
seCopy); | | TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::Rever
seCopy); | |
| \endcode | | \endcode | |
| */ | | */ | |
| explicit TinyVector(const_pointer data, ReverseCopyTag) | | explicit TinyVector(const_pointer data, ReverseCopyTag) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::reverseAssign(BaseType::data_, data+SIZE-1); | | Loop::reverseAssign(BaseType::data_, data+SIZE-1); | |
| } | | } | |
| | | | |
|
| | | /** Copy with type conversion. | |
| | | */ | |
| | | template <class U, class DATA, class DERIVED> | |
| | | TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) | |
| | | : BaseType() | |
| | | { | |
| | | Loop::assignCast(BaseType::data_, r.begin()); | |
| | | } | |
| | | | |
| /** Copy assignment. | | /** Copy assignment. | |
| */ | | */ | |
| TinyVector & operator=(TinyVector const & r) | | TinyVector & operator=(TinyVector const & r) | |
| { | | { | |
| Loop::assign(BaseType::data_, r.data_); | | Loop::assign(BaseType::data_, r.data_); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | /** Copy assignment with type conversion. | |
| | | */ | |
| | | template <class U, class DATA, class DERIVED> | |
| | | TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r | |
| | | ) | |
| | | { | |
| | | Loop::assignCast(BaseType::data_, r.begin()); | |
| | | return *this; | |
| | | } | |
| | | | |
| /** Assignment from Diff2D. | | /** Assignment from Diff2D. | |
|
| | | | |
| | | Use only when <tt>SIZE == 2</tt>. | |
| */ | | */ | |
| TinyVector & operator=(Diff2D const & r) | | TinyVector & operator=(Diff2D const & r) | |
| { | | { | |
| BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x); | | BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(r.x); | |
| BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y); | | BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(r.y); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| /** Copy with type conversion. | | /** Assignment from scalar. Will set all entries to the given value
. | |
| */ | | */ | |
|
| template <class U> | | TinyVector & operator=(value_type const & v) | |
| TinyVector(TinyVector<U, SIZE> const & r) | | | |
| : BaseType() | | | |
| { | | { | |
|
| Loop::assignCast(BaseType::data_, r.begin()); | | Loop::assignScalar(BaseType::begin(), v); | |
| | | return *this; | |
| } | | } | |
| | | | |
|
| /** Copy with type conversion. | | /** Copy from a TinyVector with a different number of elements. | |
| */ | | | |
| template <class U, class DATA, class DERIVED> | | | |
| TinyVector(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r) | | | |
| : BaseType() | | | |
| { | | | |
| Loop::assignCast(BaseType::data_, r.begin()); | | | |
| } | | | |
| | | | |
|
| /** Copy assignment with type conversion. | | Only the first <tt>min(SIZE, USIZE)</tt> elements are copied. | |
| */ | | */ | |
|
| template <class U, class DATA, class DERIVED> | | template <class U, int USIZE, class DATA, class DERIVED> | |
| TinyVector & operator=(TinyVectorBase<U, SIZE, DATA, DERIVED> const & r | | TinyVector & copy(TinyVectorBase<U, USIZE, DATA, DERIVED> const & r) | |
| ) | | | |
| { | | { | |
|
| Loop::assignCast(BaseType::data_, r.begin()); | | static const int minSize = USIZE < SIZE | |
| | | ? USIZE | |
| | | : SIZE; | |
| | | | |
| | | typedef typename detail::LoopType<minSize>::type MinLoop; | |
| | | MinLoop::assignCast(BaseType::data_, r.begin()); | |
| return *this; | | return *this; | |
| } | | } | |
|
| | | | |
| explicit TinyVector(SkipInitializationTag) | | | |
| : BaseType() | | | |
| {} | | | |
| | | | |
| explicit TinyVector(detail::DontInit) | | | |
| : BaseType() | | | |
| {} | | | |
| }; | | }; | |
| | | | |
| /** \brief Wrapper for fixed size vectors. | | /** \brief Wrapper for fixed size vectors. | |
| | | | |
| This class wraps an array of size SIZE of the specified VALUETYPE. | | This class wraps an array of size SIZE of the specified VALUETYPE. | |
| Thus, the array can be accessed with an interface similar to | | Thus, the array can be accessed with an interface similar to | |
| that of std::vector (except that there are no functions | | that of std::vector (except that there are no functions | |
| that change the size of a TinyVectorView). The TinyVectorView | | that change the size of a TinyVectorView). The TinyVectorView | |
| does <em>not</em> assume ownership of the given memory. | | does <em>not</em> assume ownership of the given memory. | |
| | | | |
| | | | |
| skipping to change at line 941 | | skipping to change at line 1117 | |
| /// component-wise not equal | | /// component-wise not equal | |
| template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | |
| inline bool | | inline bool | |
| operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, | | operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| TinyVectorBase<V2, SIZE, D3, D4> const & r) | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| { | | { | |
| typedef typename detail::LoopType<SIZE>::type ltype; | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| return ltype::notEqual(l.begin(), r.begin()); | | return ltype::notEqual(l.begin(), r.begin()); | |
| } | | } | |
| | | | |
|
| | | /// component-wise lexicographical comparison | |
| | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class | |
| | | D4> | |
| | | inline bool | |
| | | operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | return ltype::less(l.begin(), r.begin()); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* TinyVector Output */ | | /* TinyVector Output */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /// stream output | | /// stream output | |
| template <class V1, int SIZE, class DATA, class DERIVED> | | template <class V1, int SIZE, class DATA, class DERIVED> | |
| std::ostream & | | std::ostream & | |
| operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> cons
t & l) | | operator<<(std::ostream & out, TinyVectorBase<V1, SIZE, DATA, DERIVED> cons
t & l) | |
| | | | |
| skipping to change at line 1027 | | skipping to change at line 1213 | |
| { | | { | |
| typedef TinyVector<T, SIZE> Type; | | typedef TinyVector<T, SIZE> Type; | |
| typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; | | typedef TinyVector<typename NumericTraits<T>::Promote, SIZE> Promote; | |
| typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPr
omote; | | typedef TinyVector<typename NumericTraits<T>::RealPromote, SIZE> RealPr
omote; | |
| typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> Com
plexPromote; | | typedef TinyVector<typename NumericTraits<T>::ComplexPromote, SIZE> Com
plexPromote; | |
| typedef T ValueType; | | typedef T ValueType; | |
| | | | |
| typedef typename NumericTraits<T>::isIntegral isIntegral; | | typedef typename NumericTraits<T>::isIntegral isIntegral; | |
| typedef VigraFalseType isScalar; | | typedef VigraFalseType isScalar; | |
| typedef typename NumericTraits<T>::isSigned isSigned; | | typedef typename NumericTraits<T>::isSigned isSigned; | |
|
| typedef VigraFalseType isOrdered; | | typedef VigraTrueType isOrdered; | |
| typedef VigraFalseType isComplex; | | typedef VigraFalseType isComplex; | |
| | | | |
|
| static TinyVector<T, SIZE> zero() { | | static TinyVector<T, SIZE> zero() | |
| | | { | |
| return TinyVector<T, SIZE>(NumericTraits<T>::zero()); | | return TinyVector<T, SIZE>(NumericTraits<T>::zero()); | |
| } | | } | |
|
| static TinyVector<T, SIZE> one() { | | static TinyVector<T, SIZE> one() | |
| | | { | |
| return TinyVector<T, SIZE>(NumericTraits<T>::one()); | | return TinyVector<T, SIZE>(NumericTraits<T>::one()); | |
| } | | } | |
|
| static TinyVector<T, SIZE> nonZero() { | | static TinyVector<T, SIZE> nonZero() | |
| | | { | |
| return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); | | return TinyVector<T, SIZE>(NumericTraits<T>::nonZero()); | |
| } | | } | |
| | | | |
|
| | | static TinyVector<T, SIZE> min() | |
| | | { | |
| | | return TinyVector<T, SIZE>(NumericTraits<T>::min()); | |
| | | } | |
| | | static TinyVector<T, SIZE> max() | |
| | | { | |
| | | return TinyVector<T, SIZE>(NumericTraits<T>::max()); | |
| | | } | |
| | | | |
| template <class D1, class D2> | | template <class D1, class D2> | |
| static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) | | static Promote toPromote(TinyVectorBase<T, SIZE, D1, D2> const & v) | |
| { | | { | |
| return Promote(v); | | return Promote(v); | |
| } | | } | |
| | | | |
| template <class D1, class D2> | | template <class D1, class D2> | |
| static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const
& v) | | static RealPromote toRealPromote(TinyVectorBase<T, SIZE, D1, D2> const
& v) | |
| { | | { | |
| return RealPromote(v); | | return RealPromote(v); | |
| | | | |
| skipping to change at line 1419 | | skipping to change at line 1617 | |
| inline | | inline | |
| TinyVector<V, SIZE> | | TinyVector<V, SIZE> | |
| floor(TinyVectorBase<V, SIZE, D1, D2> const & v) | | floor(TinyVectorBase<V, SIZE, D1, D2> const & v) | |
| { | | { | |
| TinyVector<V, SIZE> res(detail::dontInit()); | | TinyVector<V, SIZE> res(detail::dontInit()); | |
| typedef typename detail::LoopType<SIZE>::type ltype; | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| ltype::floor(res.begin(), v.begin()); | | ltype::floor(res.begin(), v.begin()); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| | | /** Apply sqrt() function to each vector component. | |
| | | */ | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | TinyVector<V, SIZE> | |
| | | sqrt(TinyVectorBase<V, SIZE, D1, D2> const & v) | |
| | | { | |
| | | TinyVector<V, SIZE> res(detail::dontInit()); | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | ltype::sqrt(res.begin(), v.begin()); | |
| | | return res; | |
| | | } | |
| | | | |
| | | using std::pow; | |
| | | | |
| | | /** Apply pow() function to each vector component. | |
| | | */ | |
| | | template <class V, int SIZE, class D1, class D2, class E> | |
| | | inline | |
| | | TinyVector<V, SIZE> | |
| | | pow(TinyVectorBase<V, SIZE, D1, D2> const & v, E exponent) | |
| | | { | |
| | | TinyVector<V, SIZE> res(v); | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | ltype::power(res.begin(), exponent); | |
| | | return res; | |
| | | } | |
| | | | |
| /// cross product | | /// cross product | |
| template <class V1, class D1, class D2, class V2, class D3, class D4> | | template <class V1, class D1, class D2, class V2, class D3, class D4> | |
| inline | | inline | |
| TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> | | TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> | |
| cross(TinyVectorBase<V1, 3, D1, D2> const & r1, | | cross(TinyVectorBase<V1, 3, D1, D2> const & r1, | |
| TinyVectorBase<V2, 3, D3, D4> const & r2) | | TinyVectorBase<V2, 3, D3, D4> const & r2) | |
| { | | { | |
| typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> | | typedef TinyVector<typename PromoteTraits<V1, V2>::Promote, 3> | |
| Res; | | Res; | |
| return Res(r1[1]*r2[2] - r1[2]*r2[1], | | return Res(r1[1]*r2[2] - r1[2]*r2[1], | |
| | | | |
| skipping to change at line 1480 | | skipping to change at line 1706 | |
| inline | | inline | |
| typename NumericTraits<V>::Promote | | typename NumericTraits<V>::Promote | |
| prod(TinyVectorBase<V, SIZE, D1, D2> const & l) | | prod(TinyVectorBase<V, SIZE, D1, D2> const & l) | |
| { | | { | |
| typename NumericTraits<V>::Promote res = l[0]; | | typename NumericTraits<V>::Promote res = l[0]; | |
| for(int k=1; k<SIZE; ++k) | | for(int k=1; k<SIZE; ++k) | |
| res *= l[k]; | | res *= l[k]; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| /// cumulative sum of the vector's elements | | /// cumulative product of the vector's elements | |
| template <class V, int SIZE, class D1, class D2> | | template <class V, int SIZE, class D1, class D2> | |
| inline | | inline | |
| TinyVector<typename NumericTraits<V>::Promote, SIZE> | | TinyVector<typename NumericTraits<V>::Promote, SIZE> | |
| cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l) | | cumprod(TinyVectorBase<V, SIZE, D1, D2> const & l) | |
| { | | { | |
| TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); | | TinyVector<typename NumericTraits<V>::Promote, SIZE> res(l); | |
| for(int k=1; k<SIZE; ++k) | | for(int k=1; k<SIZE; ++k) | |
| res[k] *= res[k-1]; | | res[k] *= res[k-1]; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| | | using std::min; | |
| | | | |
| /// element-wise minimum | | /// element-wise minimum | |
| template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | |
| inline | | inline | |
| TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> | | TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> | |
| min(TinyVectorBase<V1, SIZE, D1, D2> const & l, | | min(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| TinyVectorBase<V2, SIZE, D3, D4> const & r) | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| { | | { | |
|
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); | | TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); | |
|
| for(int k=0; k<SIZE; ++k) | | ltype::min(res.begin(), r.begin()); | |
| if(r[k] < res[k]) | | return res; | |
| res[k] = r[k]; | | } | |
| | | | |
| | | // we also have to overload min for like-typed argument to prevent match of | |
| | | std::min() | |
| | | template <class V1, int SIZE, class D1, class D2> | |
| | | inline | |
| | | TinyVector<V1, SIZE> | |
| | | min(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V1, SIZE, D1, D2> const & r) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | TinyVector<V1, SIZE> res(l); | |
| | | ltype::min(res.begin(), r.begin()); | |
| | | return res; | |
| | | } | |
| | | | |
| | | template <class V1, int SIZE> | |
| | | inline | |
| | | TinyVector<V1, SIZE> | |
| | | min(TinyVector<V1, SIZE> const & l, | |
| | | TinyVector<V1, SIZE> const & r) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | TinyVector<V1, SIZE> res(l); | |
| | | ltype::min(res.begin(), r.begin()); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| | | /// minimum element | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | V const & | |
| | | min(TinyVectorBase<V, SIZE, D1, D2> const & l) | |
| | | { | |
| | | return l.minimum(); | |
| | | } | |
| | | | |
| | | using std::max; | |
| | | | |
| /// element-wise maximum | | /// element-wise maximum | |
| template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | |
| inline | | inline | |
| TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> | | TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> | |
| max(TinyVectorBase<V1, SIZE, D1, D2> const & l, | | max(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| TinyVectorBase<V2, SIZE, D3, D4> const & r) | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| { | | { | |
|
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); | | TinyVector<typename PromoteTraits<V1, V2>::Promote, SIZE> res(l); | |
|
| for(int k=0; k<SIZE; ++k) | | ltype::max(res.begin(), r.begin()); | |
| if(res[k] < r[k]) | | return res; | |
| res[k] = r[k]; | | } | |
| | | | |
| | | // we also have to overload max for like-typed argument to prevent match of | |
| | | std::max() | |
| | | template <class V1, int SIZE, class D1, class D2> | |
| | | inline | |
| | | TinyVector<V1, SIZE> | |
| | | max(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V1, SIZE, D1, D2> const & r) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | TinyVector<V1, SIZE> res(l); | |
| | | ltype::max(res.begin(), r.begin()); | |
| | | return res; | |
| | | } | |
| | | | |
| | | template <class V1, int SIZE> | |
| | | inline | |
| | | TinyVector<V1, SIZE> | |
| | | max(TinyVector<V1, SIZE> const & l, | |
| | | TinyVector<V1, SIZE> const & r) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | TinyVector<V1, SIZE> res(l); | |
| | | ltype::max(res.begin(), r.begin()); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| | | /// maximum element | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | V const & | |
| | | max(TinyVectorBase<V, SIZE, D1, D2> const & l) | |
| | | { | |
| | | return l.maximum(); | |
| | | } | |
| | | | |
| /// squared norm | | /// squared norm | |
| template <class V1, int SIZE, class D1, class D2> | | template <class V1, int SIZE, class D1, class D2> | |
| inline | | inline | |
| typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType | | typename TinyVectorBase<V1, SIZE, D1, D2>::SquaredNormType | |
| squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t) | | squaredNorm(TinyVectorBase<V1, SIZE, D1, D2> const & t) | |
| { | | { | |
| return t.squaredMagnitude(); | | return t.squaredMagnitude(); | |
| } | | } | |
| | | | |
| /// squared norm | | /// squared norm | |
| template <class V, int SIZE> | | template <class V, int SIZE> | |
| inline | | inline | |
| typename TinyVector<V, SIZE>::SquaredNormType | | typename TinyVector<V, SIZE>::SquaredNormType | |
| squaredNorm(TinyVector<V, SIZE> const & t) | | squaredNorm(TinyVector<V, SIZE> const & t) | |
| { | | { | |
| return t.squaredMagnitude(); | | return t.squaredMagnitude(); | |
| } | | } | |
| //@} | | //@} | |
| | | | |
|
| | | // mask cl.exe shortcomings [end] | |
| | | #if defined(_MSC_VER) | |
| | | #pragma warning( pop ) | |
| | | #endif | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| #undef VIGRA_ASSERT_INSIDE | | #undef VIGRA_ASSERT_INSIDE | |
| #endif // VIGRA_TINYVECTOR_HXX | | #endif // VIGRA_TINYVECTOR_HXX | |
| | | | |
End of changes. 69 change blocks. |
| 65 lines changed or deleted | | 372 lines changed or added | |
|