1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
5 // Copyright (C) 2018-2019 Intel Corporation
8 #ifndef OPENCV_GAPI_OWN_MAT_HPP
9 #define OPENCV_GAPI_OWN_MAT_HPP
11 #include "opencv2/gapi/opencv_includes.hpp"
12 #include "opencv2/gapi/own/types.hpp"
13 #include "opencv2/gapi/own/scalar.hpp"
14 #include "opencv2/gapi/own/saturate.hpp"
15 #include "opencv2/gapi/own/assert.hpp"
17 #include <memory> //std::shared_ptr
18 #include <cstring> //std::memcpy
19 #include "opencv2/gapi/util/throw.hpp"
21 namespace cv { namespace gapi { namespace own {
23 template <typename T, unsigned char channels>
24 void assign_row(void* ptr, int cols, Scalar const& s)
26 auto p = static_cast<T*>(ptr);
27 for (int c = 0; c < cols; c++)
29 for (int ch = 0; ch < channels; ch++)
31 p[c * channels + ch] = saturate<T>(s[ch], roundd);
36 inline size_t default_step(int type, int cols)
38 return CV_ELEM_SIZE(type) * cols;
40 //Matrix header, i.e. fields that are unique to each Mat object.
41 //Devoted class is needed to implement custom behavior on move (erasing state of moved from object)
43 enum { AUTO_STEP = 0};
44 enum { TYPE_MASK = 0x00000FFF };
46 MatHeader() = default;
48 MatHeader(int _rows, int _cols, int type, void* _data, size_t _step)
49 : flags((type & TYPE_MASK)), rows(_rows), cols(_cols), data((uchar*)_data), step(_step == AUTO_STEP ? detail::default_step(type, _cols) : _step)
52 MatHeader(const MatHeader& ) = default;
53 MatHeader(MatHeader&& src) : MatHeader(src) // reuse copy constructor here
55 MatHeader empty; //give it a name to call copy(not move) assignment below
58 MatHeader& operator=(const MatHeader& ) = default;
59 MatHeader& operator=(MatHeader&& src)
61 *this = src; //calling a copy assignment here, not move one
62 MatHeader empty; //give it a name to call copy(not move) assignment below
66 /*! includes several bit-fields:
72 //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
73 int rows = 0, cols = 0;
74 //! pointer to the data
75 uchar* data = nullptr;
79 //concise version of cv::Mat suitable for GAPI needs (used when no dependence on OpenCV is required)
80 class Mat : public detail::MatHeader{
86 @param _rows Number of rows in a 2D array.
87 @param _cols Number of columns in a 2D array.
88 @param _type Array type. Use CV_8UC1, ..., CV_64FC4 to create 1-4 channel matrices, or
89 CV_8UC(n), ..., CV_64FC(n) to create multi-channel (up to CV_CN_MAX channels) matrices.
90 @param _data Pointer to the user data. Matrix constructors that take data and step parameters do not
91 allocate matrix data. Instead, they just initialize the matrix header that points to the specified
92 data, which means that no data is copied. This operation is very efficient and can be used to
93 process external data using OpenCV functions. The external data is not automatically deallocated, so
94 you should take care of it.
95 @param _step Number of bytes each matrix row occupies. The value should include the padding bytes at
96 the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed
97 and the actual step is calculated as cols*elemSize(). See Mat::elemSize.
99 Mat(int _rows, int _cols, int _type, void* _data, size_t _step = AUTO_STEP)
100 : MatHeader (_rows, _cols, _type, _data, _step)
103 Mat(Mat const& src, const Rect& roi )
108 data = ptr(roi.y, roi.x);
111 Mat(Mat const& src) = default;
112 Mat(Mat&& src) = default;
114 Mat& operator=(Mat const& src) = default;
115 Mat& operator=(Mat&& src) = default;
117 /** @brief Sets all or some of the array elements to the specified value.
118 @param s Assigned scalar converted to the actual array type.
120 Mat& operator = (const Scalar& s)
122 constexpr unsigned max_channels = 4; //Scalar can't fit more than 4
123 const auto channels = static_cast<unsigned int>(this->channels());
124 GAPI_Assert(channels <= max_channels);
126 using func_p_t = void (*)(void*, int, Scalar const&);
127 using detail::assign_row;
128 #define TABLE_ENTRY(type) {assign_row<type, 1>, assign_row<type, 2>, assign_row<type, 3>, assign_row<type, 4>}
129 static constexpr func_p_t func_tbl[][max_channels] = {
140 static_assert(CV_8U == 0 && CV_8S == 1 && CV_16U == 2 && CV_16S == 3
141 && CV_32S == 4 && CV_32F == 5 && CV_64F == 6,
142 "OCV type ids used as indexes to array, thus exact numbers are important!"
145 const auto depth = static_cast<unsigned int>(this->depth());
146 GAPI_Assert(depth < sizeof(func_tbl)/sizeof(func_tbl[0]));
148 for (int r = 0; r < rows; ++r)
150 auto* f = func_tbl[depth][channels -1];
151 (*f)(static_cast<void *>(ptr(r)), cols, s );
156 /** @brief Returns the matrix element size in bytes.
158 The method returns the matrix element size in bytes. For example, if the matrix type is CV_16SC3 ,
159 the method returns 3\*sizeof(short) or 6.
161 size_t elemSize() const
163 return CV_ELEM_SIZE(type());
165 /** @brief Returns the type of a matrix element.
167 The method returns a matrix element type. This is an identifier compatible with the CvMat type
168 system, like CV_16SC3 or 16-bit signed 3-channel array, and so on.
170 int type() const {return CV_MAT_TYPE(flags);}
172 /** @brief Returns the depth of a matrix element.
174 The method returns the identifier of the matrix element depth (the type of each individual channel).
175 For example, for a 16-bit signed element array, the method returns CV_16S . A complete list of
176 matrix types contains the following values:
177 - CV_8U - 8-bit unsigned integers ( 0..255 )
178 - CV_8S - 8-bit signed integers ( -128..127 )
179 - CV_16U - 16-bit unsigned integers ( 0..65535 )
180 - CV_16S - 16-bit signed integers ( -32768..32767 )
181 - CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
182 - CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
183 - CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
185 int depth() const {return CV_MAT_DEPTH(flags);}
187 /** @brief Returns the number of matrix channels.
189 The method returns the number of matrix channels.
191 int channels() const {return CV_MAT_CN(flags);}
194 @param _rows New number of rows.
195 @param _cols New number of columns.
196 @param _type New matrix type.
198 void create(int _rows, int _cols, int _type)
200 create({_cols, _rows}, _type);
203 @param _size Alternative new matrix size specification: Size(cols, rows)
204 @param _type New matrix type.
206 void create(Size _size, int _type)
208 if (_size != Size{cols, rows} )
210 Mat tmp{_size.height, _size.width, _type, nullptr};
211 tmp.memory.reset(new uchar[ tmp.step * tmp.rows], [](uchar * p){delete[] p;});
212 tmp.data = tmp.memory.get();
214 *this = std::move(tmp);
218 /** @brief Copies the matrix to another one.
220 The method copies the matrix data to another matrix. Before copying the data, the method invokes :
222 m.create(this->size(), this->type());
224 so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the
225 function does not handle the case of a partial overlap between the source and the destination
228 void copyTo(Mat& dst) const
230 dst.create(rows, cols, type());
231 for (int r = 0; r < rows; ++r)
233 std::copy_n(ptr(r), detail::default_step(type(),cols), dst.ptr(r));
237 /** @brief Returns true if the array has no elements.
239 The method returns true if Mat::total() is 0 or if Mat::data is NULL. Because of pop_back() and
240 resize() methods `M.total() == 0` does not imply that `M.data == NULL`.
244 /** @brief Returns the total number of array elements.
246 The method returns the number of array elements (a number of pixels if the array represents an
251 return static_cast<size_t>(rows * cols);
256 @param roi Extracted submatrix specified as a rectangle.
258 Mat operator()( const Rect& roi ) const
260 return Mat{*this, roi};
264 /** @brief Returns a pointer to the specified matrix row.
266 The methods return `uchar*` or typed pointer to the specified matrix row. See the sample in
267 Mat::isContinuous to know how to use these methods.
268 @param row Index along the dimension 0
269 @param col Index along the dimension 1
271 uchar* ptr(int row, int col = 0)
273 return const_cast<uchar*>(const_cast<const Mat*>(this)->ptr(row,col));
276 const uchar* ptr(int row, int col = 0) const
278 return data + step * row + CV_ELEM_SIZE(type()) * col;
283 //actual memory allocated for storage, or nullptr if object is non owning view to over memory
284 std::shared_ptr<uchar> memory;
291 #endif /* OPENCV_GAPI_OWN_MAT_HPP */