bytesNum = sm.get(1, 1, buff11);
assertEquals(4, bytesNum);
assertTrue(Arrays.equals(new short[] {340, 341, 0, 0}, buff11));
+
+ Mat m2 = new Mat(new int[]{ 5, 6, 8 }, CvType.CV_16S);
+ short[] data = new short[(int)m2.total()];
+ for (int i = 0; i < data.length; i++ ) {
+ data[i] = (short)i;
+ }
+ m2.put(new int[] {0, 0, 0}, data);
+ Mat matNonContinuous = m2.submat(new Range[]{new Range(1,4), new Range(2,5), new Range(3,6)});
+ Mat matContinuous = matNonContinuous.clone();
+ short[] outNonContinuous = new short[(int)matNonContinuous.total()];
+ matNonContinuous.get(new int[] { 0, 0, 0 }, outNonContinuous);
+ short[] outContinuous = new short[(int)matNonContinuous.total()];
+ matContinuous.get(new int[] { 0, 0, 0 }, outContinuous);
+ assertArrayEquals(outNonContinuous, outContinuous);
+ Mat subMat2 = m2.submat(new Range[]{new Range(1,4), new Range(1,5), new Range(0,8)});
+ Mat subMatClone2 = subMat2.clone();
+ short[] outNonContinuous2 = new short[(int)subMat2.total()];
+ subMat2.get(new int[] { 0, 1, 1 }, outNonContinuous2);
+ short[] outContinuous2 = new short[(int)subMat2.total()];
+ subMatClone2.get(new int[] { 0, 1, 1 }, outContinuous2);
+ assertArrayEquals(outNonContinuous2, outContinuous2);
}
public void testGetNativeObjAddr() {
#undef JOCvT
}
-template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
-{
- if(! m) return 0;
- if(! buff) return 0;
-
- count *= sizeof(T);
- int rest = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
- if(count>rest) count = rest;
- int res = count;
+static size_t idx2Offset(cv::Mat* mat, std::vector<int>& indices) {
+ size_t offset = indices[0];
+ for (int dim=1; dim < mat->dims; dim++) {
+ offset = offset*mat->size[dim] + indices[dim];
+ }
+ return offset;
+}
- if( m->isContinuous() )
- {
- memcpy(m->ptr(row, col), buff + offset, count);
- } else {
- // row by row
- int num = (m->cols - col) * (int)m->elemSize(); // 1st partial row
- if(count<num) num = count;
- uchar* data = m->ptr(row++, col);
- while(count>0){
- memcpy(data, buff + offset, num);
- count -= num;
- buff += num;
- num = m->cols * (int)m->elemSize();
- if(count<num) num = count;
- data = m->ptr(row++, 0);
- }
+static void offset2Idx(cv::Mat* mat, size_t offset, std::vector<int>& indices) {
+ for (int dim=mat->dims-1; dim>=0; dim--) {
+ indices[dim] = offset % mat->size[dim];
+ offset = (offset - indices[dim]) / mat->size[dim];
}
- return res;
}
// returns true if final index was reached
-static bool updateIdx(cv::Mat* m, std::vector<int>& idx, int inc) {
- for (int i=m->dims-1; i>=0; i--) {
- if (inc == 0) return false;
- idx[i] = (idx[i] + 1) % m->size[i];
- inc--;
- }
- return true;
+static bool updateIdx(cv::Mat* mat, std::vector<int>& indices, size_t inc) {
+ size_t currentOffset = idx2Offset(mat, indices);
+ size_t newOffset = currentOffset + inc;
+ bool reachedEnd = newOffset>=(size_t)mat->total();
+ offset2Idx(mat, reachedEnd?0:newOffset, indices);
+ return reachedEnd;
}
-template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
-{
+template<typename T> static int mat_copy_data(cv::Mat* m, std::vector<int>& idx, int count, char* buff, bool isPut) {
if(! m) return 0;
if(! buff) return 0;
- count *= sizeof(T);
- int rest = (int)m->elemSize();
- for (int i = 0; i < m->dims; i++) {
- rest *= (m->size[i] - idx[i]);
- }
- if(count>rest) count = rest;
- int res = count;
+ size_t countBytes = count * sizeof(T);
+ size_t remainingBytes = (size_t)(m->total() - idx2Offset(m, idx))*m->elemSize();
+ countBytes = (countBytes>remainingBytes)?remainingBytes:countBytes;
+ int res = (int)countBytes;
if( m->isContinuous() )
{
- memcpy(m->ptr(idx.data()), buff + offset, count);
+ if (isPut) {
+ memcpy(m->ptr(idx.data()), buff, countBytes);
+ } else {
+ memcpy(buff, m->ptr(idx.data()), countBytes);
+ }
} else {
- // dim by dim
- int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
- if(count<num) num = count;
+ size_t blockSize = m->size[m->dims-1] * m->elemSize();
+ size_t firstPartialBlockSize = (m->size[m->dims-1] - idx[m->dims-1]) * m->step[m->dims-1];;
+ for (int dim=m->dims-2; dim>=0 && blockSize == m->step[dim]; dim--) {
+ blockSize *= m->size[dim];
+ firstPartialBlockSize += (m->size[dim] - (idx[dim]+1)) * m->step[dim];
+ }
+ size_t copyCount = (countBytes<firstPartialBlockSize)?countBytes:firstPartialBlockSize;
uchar* data = m->ptr(idx.data());
- while(count>0){
- memcpy(data, buff + offset, num);
- updateIdx(m, idx, num / (int)m->elemSize());
- count -= num;
- buff += num;
- num = m->size[m->dims-1] * (int)m->elemSize();
- if(count<num) num = count;
+ while(countBytes>0){
+ if (isPut) {
+ memcpy(data, buff, copyCount);
+ } else {
+ memcpy(buff, data, copyCount);
+ }
+ updateIdx(m, idx, copyCount / m->elemSize());
+ countBytes -= copyCount;
+ buff += copyCount;
+ copyCount = countBytes<blockSize?countBytes:blockSize;
data = m->ptr(idx.data());
}
}
return res;
}
+template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, int count, int offset, char* buff)
+{
+ return mat_copy_data<T>(m, idx, count, buff + offset, true);
+}
+
+template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
+{
+ int indicesArray[] = { row, col };
+ std::vector<int> indices(indicesArray, indicesArray+2);
+ return mat_put_idx<T>(m, indices, count, offset, buff);
+}
+
template<class ARRAY> static jint java_mat_put(JNIEnv* env, jlong self, jint row, jint col, jint count, jint offset, ARRAY vals)
{
static const char *method_name = JavaOpenCVTrait<ARRAY>::put;
} // extern "C"
-template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
+template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
{
- if(! m) return 0;
- if(! buff) return 0;
-
- int bytesToCopy = count * sizeof(T);
- int bytesRestInMat = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
- if(bytesToCopy > bytesRestInMat) bytesToCopy = bytesRestInMat;
- int res = bytesToCopy;
-
- if( m->isContinuous() )
- {
- memcpy(buff, m->ptr(row, col), bytesToCopy);
- } else {
- // row by row
- int bytesInRow = (m->cols - col) * (int)m->elemSize(); // 1st partial row
- while(bytesToCopy > 0)
- {
- int len = std::min(bytesToCopy, bytesInRow);
- memcpy(buff, m->ptr(row, col), len);
- bytesToCopy -= len;
- buff += len;
- row++;
- col = 0;
- bytesInRow = m->cols * (int)m->elemSize();
- }
- }
- return res;
+ return mat_copy_data<T>(m, idx, count, buff, false);
}
-template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
+template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
{
- if(! m) return 0;
- if(! buff) return 0;
-
- count *= sizeof(T);
- int rest = (int)m->elemSize();
- for (int i = 0; i < m->dims; i++) {
- rest *= (m->size[i] - idx[i]);
- }
- if(count>rest) count = rest;
- int res = count;
-
- if( m->isContinuous() )
- {
- memcpy(buff, m->ptr(idx.data()), count);
- } else {
- // dim by dim
- int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
- if(count<num) num = count;
- uchar* data = m->ptr(idx.data());
- while(count>0){
- memcpy(buff, data, num);
- updateIdx(m, idx, num / (int)m->elemSize());
- count -= num;
- buff += num;
- num = m->size[m->dims-1] * (int)m->elemSize();
- if(count<num) num = count;
- data = m->ptr(idx.data());
- }
- }
- return res;
+ int indicesArray[] = { row, col };
+ std::vector<int> indices(indicesArray, indicesArray+2);
+ return mat_get_idx<T>(m, indices, count, buff);
}
template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) {