// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html #include "opencv2/core/mat.hpp" #include "precomp.hpp" namespace cv { NAryMatIterator::NAryMatIterator() : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) { } NAryMatIterator::NAryMatIterator(const Mat** _arrays, Mat* _planes, int _narrays) : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) { init(_arrays, _planes, 0, _narrays); } NAryMatIterator::NAryMatIterator(const Mat** _arrays, uchar** _ptrs, int _narrays) : arrays(0), planes(0), ptrs(0), narrays(0), nplanes(0), size(0), iterdepth(0), idx(0) { init(_arrays, 0, _ptrs, _narrays); } void NAryMatIterator::init(const Mat** _arrays, Mat* _planes, uchar** _ptrs, int _narrays) { CV_Assert( _arrays && (_ptrs || _planes) ); int i, j, d1=0, i0 = -1, d = -1; arrays = _arrays; ptrs = _ptrs; planes = _planes; narrays = _narrays; nplanes = 0; size = 0; if( narrays < 0 ) { for( i = 0; _arrays[i] != 0; i++ ) ; narrays = i; CV_Assert(narrays <= 1000); } iterdepth = 0; for( i = 0; i < narrays; i++ ) { CV_Assert(arrays[i] != 0); const Mat& A = *arrays[i]; if( ptrs ) ptrs[i] = A.data; if( !A.data ) continue; if( i0 < 0 ) { i0 = i; d = A.dims; // find the first dimensionality which is different from 1; // in any of the arrays the first "d1" step do not affect the continuity for( d1 = 0; d1 < d; d1++ ) if( A.size[d1] > 1 ) break; } else CV_Assert( A.size == arrays[i0]->size ); if( !A.isContinuous() ) { CV_Assert( A.step[d-1] == A.elemSize() ); for( j = d-1; j > d1; j-- ) if( A.step[j]*A.size[j] < A.step[j-1] ) break; iterdepth = std::max(iterdepth, j); } } if( i0 >= 0 ) { size = arrays[i0]->size[d-1]; for( j = d-1; j > iterdepth; j-- ) { int64 total1 = (int64)size*arrays[i0]->size[j-1]; if( total1 != (int)total1 ) break; size = (int)total1; } iterdepth = j; if( iterdepth == d1 ) iterdepth = 0; nplanes = 1; for( j = iterdepth-1; j >= 0; j-- ) nplanes *= arrays[i0]->size[j]; } else iterdepth = 0; idx = 0; if( !planes ) return; for( i = 0; i < narrays; i++ ) { CV_Assert(arrays[i] != 0); const Mat& A = *arrays[i]; if( !A.data ) { planes[i] = Mat(); continue; } planes[i] = Mat(1, (int)size, A.type(), A.data); } } NAryMatIterator& NAryMatIterator::operator ++() { if( idx >= nplanes-1 ) return *this; ++idx; if( iterdepth == 1 ) { if( ptrs ) { for( int i = 0; i < narrays; i++ ) { if( !ptrs[i] ) continue; ptrs[i] = arrays[i]->data + arrays[i]->step[0]*idx; } } if( planes ) { for( int i = 0; i < narrays; i++ ) { if( !planes[i].data ) continue; planes[i].data = arrays[i]->data + arrays[i]->step[0]*idx; } } } else { for( int i = 0; i < narrays; i++ ) { const Mat& A = *arrays[i]; if( !A.data ) continue; int _idx = (int)idx; uchar* data = A.data; for( int j = iterdepth-1; j >= 0 && _idx > 0; j-- ) { int szi = A.size[j], t = _idx/szi; data += (_idx - t * szi)*A.step[j]; _idx = t; } if( ptrs ) ptrs[i] = data; if( planes ) planes[i].data = data; } } return *this; } NAryMatIterator NAryMatIterator::operator ++(int) { NAryMatIterator it = *this; ++*this; return it; } //================================================================================================== Point MatConstIterator::pos() const { if( !m ) return Point(); CV_DbgAssert(m->dims <= 2); ptrdiff_t ofs = ptr - m->ptr(); int y = (int)(ofs/m->step[0]); return Point((int)((ofs - y*m->step[0])/elemSize), y); } void MatConstIterator::pos(int* _idx) const { CV_Assert(m != 0 && _idx); ptrdiff_t ofs = ptr - m->ptr(); for( int i = 0; i < m->dims; i++ ) { size_t s = m->step[i], v = ofs/s; ofs -= v*s; _idx[i] = (int)v; } } ptrdiff_t MatConstIterator::lpos() const { if(!m) return 0; if( m->isContinuous() ) return (ptr - sliceStart)/elemSize; ptrdiff_t ofs = ptr - m->ptr(); int i, d = m->dims; if( d == 2 ) { ptrdiff_t y = ofs/m->step[0]; return y*m->cols + (ofs - y*m->step[0])/elemSize; } ptrdiff_t result = 0; for( i = 0; i < d; i++ ) { size_t s = m->step[i], v = ofs/s; ofs -= v*s; result = result*m->size[i] + v; } return result; } void MatConstIterator::seek(ptrdiff_t ofs, bool relative) { if( m->isContinuous() ) { ptr = (relative ? ptr : sliceStart) + ofs*elemSize; if( ptr < sliceStart ) ptr = sliceStart; else if( ptr > sliceEnd ) ptr = sliceEnd; return; } int d = m->dims; if( d == 2 ) { ptrdiff_t ofs0, y; if( relative ) { ofs0 = ptr - m->ptr(); y = ofs0/m->step[0]; ofs += y*m->cols + (ofs0 - y*m->step[0])/elemSize; } y = ofs/m->cols; int y1 = std::min(std::max((int)y, 0), m->rows-1); sliceStart = m->ptr(y1); sliceEnd = sliceStart + m->cols*elemSize; ptr = y < 0 ? sliceStart : y >= m->rows ? sliceEnd : sliceStart + (ofs - y*m->cols)*elemSize; return; } if( relative ) ofs += lpos(); if( ofs < 0 ) ofs = 0; int szi = m->size[d-1]; ptrdiff_t t = ofs/szi; int v = (int)(ofs - t*szi); ofs = t; ptr = m->ptr() + v*elemSize; sliceStart = m->ptr(); for( int i = d-2; i >= 0; i-- ) { szi = m->size[i]; t = ofs/szi; v = (int)(ofs - t*szi); ofs = t; sliceStart += v*m->step[i]; } sliceEnd = sliceStart + m->size[d-1]*elemSize; if( ofs > 0 ) ptr = sliceEnd; else ptr = sliceStart + (ptr - m->ptr()); } void MatConstIterator::seek(const int* _idx, bool relative) { int d = m->dims; ptrdiff_t ofs = 0; if( !_idx ) ; else if( d == 2 ) ofs = _idx[0]*m->size[1] + _idx[1]; else { for( int i = 0; i < d; i++ ) ofs = ofs*m->size[i] + _idx[i]; } seek(ofs, relative); } //================================================================================================== SparseMatConstIterator::SparseMatConstIterator(const SparseMat* _m) : m((SparseMat*)_m), hashidx(0), ptr(0) { if(!_m || !_m->hdr) return; SparseMat::Hdr& hdr = *m->hdr; const std::vector<size_t>& htab = hdr.hashtab; size_t i, hsize = htab.size(); for( i = 0; i < hsize; i++ ) { size_t nidx = htab[i]; if( nidx ) { hashidx = i; ptr = &hdr.pool[nidx] + hdr.valueOffset; return; } } } SparseMatConstIterator& SparseMatConstIterator::operator ++() { if( !ptr || !m || !m->hdr ) return *this; SparseMat::Hdr& hdr = *m->hdr; size_t next = ((const SparseMat::Node*)(ptr - hdr.valueOffset))->next; if( next ) { ptr = &hdr.pool[next] + hdr.valueOffset; return *this; } size_t i = hashidx + 1, sz = hdr.hashtab.size(); for( ; i < sz; i++ ) { size_t nidx = hdr.hashtab[i]; if( nidx ) { hashidx = i; ptr = &hdr.pool[nidx] + hdr.valueOffset; return *this; } } hashidx = sz; ptr = 0; return *this; } } // cv::