mirror of
https://github.com/opencv/opencv.git
synced 2026-07-26 13:53:03 +04:00
358 lines
8.3 KiB
C++
358 lines
8.3 KiB
C++
// 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 "precomp.hpp"
|
|
#include "opencv2/core/mat.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::
|