diff --git a/modules/core/misc/java/test/MatTest.java b/modules/core/misc/java/test/MatTest.java index 039aa39929ee9824ded4f40e5fb2fcd78fc8e7bf..00e7b7cb32038a7667f714cf6dbec264b7df5521 100644 --- a/modules/core/misc/java/test/MatTest.java +++ b/modules/core/misc/java/test/MatTest.java @@ -455,6 +455,27 @@ public class MatTest extends OpenCVTestCase { 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() { diff --git a/modules/java/generator/src/cpp/Mat.cpp b/modules/java/generator/src/cpp/Mat.cpp index 5203413ae4231b9bc53953cc0efc4c8ed0f2938e..d59fe4a5065ac7db8c8572ad2ed23dfc62f3257a 100644 --- a/modules/java/generator/src/cpp/Mat.cpp +++ b/modules/java/generator/src/cpp/Mat.cpp @@ -2129,80 +2129,83 @@ namespace { #undef JOCvT } -template 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& 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(countptr(row++, col); - while(count>0){ - memcpy(data, buff + offset, num); - count -= num; - buff += num; - num = m->cols * (int)m->elemSize(); - if(countptr(row++, 0); - } +static void offset2Idx(cv::Mat* mat, size_t offset, std::vector& 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& 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& 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 static int mat_put_idx(cv::Mat* m, std::vector& idx, int count, int offset, char* buff) -{ +template static int mat_copy_data(cv::Mat* m, std::vector& 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(countsize[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 = (countBytesptr(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(count0){ + if (isPut) { + memcpy(data, buff, copyCount); + } else { + memcpy(buff, data, copyCount); + } + updateIdx(m, idx, copyCount / m->elemSize()); + countBytes -= copyCount; + buff += copyCount; + copyCount = countBytesptr(idx.data()); } } return res; } +template static int mat_put_idx(cv::Mat* m, std::vector& idx, int count, int offset, char* buff) +{ + return mat_copy_data(m, idx, count, buff + offset, true); +} + +template static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff) +{ + int indicesArray[] = { row, col }; + std::vector indices(indicesArray, indicesArray+2); + return mat_put_idx(m, indices, count, offset, buff); +} + template 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::put; @@ -2455,68 +2458,16 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx } // extern "C" -template static int mat_get(cv::Mat* m, int row, int col, int count, char* buff) +template static int mat_get_idx(cv::Mat* m, std::vector& 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(m, idx, count, buff, false); } -template static int mat_get_idx(cv::Mat* m, std::vector& idx, int count, char* buff) +template 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(countptr(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(countptr(idx.data()); - } - } - return res; + int indicesArray[] = { row, col }; + std::vector indices(indicesArray, indicesArray+2); + return mat_get_idx(m, indices, count, buff); } template static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) { diff --git a/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java index 5c6432c9f2a1f92fe096309c8d2d95a8000dd030..802bb2daa4ce6acf373a5d2d7a7a0f1801c80968 100644 --- a/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java @@ -279,19 +279,23 @@ public class OpenCVTestCase extends TestCase { } public static void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) { - if (ar1.length != ar2.length) { - fail("Arrays have different sizes."); - } + assertEquals(ar1.length, ar2.length); for (int i = 0; i < ar1.length; i++) assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon); //assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon); } + public static void assertArrayEquals(short[] ar1, short[] ar2) { + assertEquals(ar1.length, ar2.length); + + for (int i = 0; i < ar1.length; i++) + assertEquals(ar1[i], ar2[i]); + //assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon); + } + public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) { - if (ar1.length != ar2.length) { - fail("Arrays have different sizes."); - } + assertEquals(ar1.length, ar2.length); for (int i = 0; i < ar1.length; i++) assertEquals(ar1[i], ar2[i], epsilon); diff --git a/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java index 5b303f38369490b0b587e52cbf68e686e8f3034f..3fd918dbfe93f6dbc99266c9e58c79d8a8277121 100644 --- a/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java @@ -305,19 +305,22 @@ public class OpenCVTestCase extends TestCase { } public static void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) { - if (ar1.length != ar2.length) { - fail("Arrays have different sizes."); - } + assertEquals(ar1.length, ar2.length); for (int i = 0; i < ar1.length; i++) assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon); //assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon); } + public static void assertArrayEquals(short[] ar1, short[] ar2) { + assertEquals(ar1.length, ar2.length); + + for (int i = 0; i < ar1.length; i++) + assertEquals(ar1[i], ar2[i]); + } + public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) { - if (ar1.length != ar2.length) { - fail("Arrays have different sizes."); - } + assertEquals(ar1.length, ar2.length); for (int i = 0; i < ar1.length; i++) assertEquals(ar1[i], ar2[i], epsilon);