diff --git a/modules/core/misc/java/src/java/core+Mat.java b/modules/core/misc/java/src/java/core+Mat.java index 98cdba9736..c975f0c44b 100644 --- a/modules/core/misc/java/src/java/core+Mat.java +++ b/modules/core/misc/java/src/java/core+Mat.java @@ -1015,6 +1015,21 @@ public class Mat { throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); } + // javadoc:Mat::put(row,col,data,offset,length) + public int put(int row, int col, byte[] data, int offset, int length) { + int t = type(); + if (data == null || length % CvType.channels(t) != 0) + throw new java.lang.UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutBwOffset(nativeObj, row, col, length, offset, data); + } + throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t); + } + // javadoc:Mat::get(row,col,data) public int get(int row, int col, byte[] data) { int t = type(); @@ -1318,6 +1333,8 @@ public class Mat { private static native int nPutB(long self, int row, int col, int count, byte[] data); + private static native int nPutBwOffset(long self, int row, int col, int count, int offset, byte[] data); + private static native int nGetB(long self, int row, int col, int count, byte[] vals); private static native int nGetS(long self, int row, int col, int count, short[] vals); diff --git a/modules/core/misc/java/src/java/core+MatOfByte.java b/modules/core/misc/java/src/java/core+MatOfByte.java index 7756eb94f9..eb928fb0a9 100644 --- a/modules/core/misc/java/src/java/core+MatOfByte.java +++ b/modules/core/misc/java/src/java/core+MatOfByte.java @@ -35,6 +35,11 @@ public class MatOfByte extends Mat { fromArray(a); } + public MatOfByte(int offset, int length, byte...a) { + super(); + fromArray(offset, length, a); + } + public void alloc(int elemNumber) { if(elemNumber>0) super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); @@ -48,6 +53,20 @@ public class MatOfByte extends Mat { put(0, 0, a); //TODO: check ret val! } + public void fromArray(int offset, int length, byte...a) { + if (offset < 0) + throw new IllegalArgumentException("offset < 0"); + if (a == null) + throw new NullPointerException(); + if (length < 0 || length + offset > a.length) + throw new IllegalArgumentException("invalid 'length' parameter: " + Integer.toString(length)); + if (a.length == 0) + return; + int num = length / _channels; + alloc(num); + put(0, 0, a, offset, length); //TODO: check ret val! + } + public byte[] toArray() { int num = checkVector(_channels, _depth); if(num < 0) diff --git a/modules/core/misc/java/test/MatOfByteTest.java b/modules/core/misc/java/test/MatOfByteTest.java new file mode 100644 index 0000000000..18f56e2010 --- /dev/null +++ b/modules/core/misc/java/test/MatOfByteTest.java @@ -0,0 +1,70 @@ +package org.opencv.test.core; + +import java.util.Arrays; + +import org.opencv.core.Core; +import org.opencv.core.CvException; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.MatOfDouble; +import org.opencv.test.OpenCVTestCase; +import org.opencv.imgcodecs.Imgcodecs; + +public class MatOfByteTest extends OpenCVTestCase { + + public void testMatOfSubByteArray() { + byte[] inputBytes = { 1,2,3,4,5 }; + + MatOfByte m0 = new MatOfByte(inputBytes); + MatOfByte m1 = new MatOfByte(0, inputBytes.length, inputBytes); + MatOfByte m2 = new MatOfByte(1, inputBytes.length - 2, inputBytes); + + assertEquals(5.0, m0.size().height); + assertEquals(1.0, m0.size().width); + + assertEquals(m0.get(0, 0)[0], m1.get(0, 0)[0]); + assertEquals(m0.get((int) m0.size().height - 1, 0)[0], m1.get((int) m1.size().height - 1, 0)[0]); + + assertEquals(3.0, m2.size().height); + assertEquals(1.0, m2.size().width); + + assertEquals(2.0, m2.get(0, 0)[0]); + assertEquals(3.0, m2.get(1, 0)[0]); + assertEquals(4.0, m2.get(2, 0)[0]); + } + + + public void testMatOfSubByteArray_BadArg() { + byte[] inputBytes = { 1,2,3,4,5 }; + + try { + MatOfByte m1 = new MatOfByte(-1, inputBytes.length, inputBytes); + fail("Missing check: offset < 0"); + } catch (IllegalArgumentException e) { + // pass + } + + try { + MatOfByte m1 = new MatOfByte(0, inputBytes.length, null); + fail("Missing check: NullPointerException"); + } catch (NullPointerException e) { + // pass + } + + try { + MatOfByte m1 = new MatOfByte(0, -1, inputBytes); + fail("Missing check: length < 0"); + } catch (IllegalArgumentException e) { + // pass + } + + try { + MatOfByte m1 = new MatOfByte(1, inputBytes.length, inputBytes); + fail("Missing check: buffer bounds"); + } catch (IllegalArgumentException e) { + // pass + } + } + +} diff --git a/modules/java/generator/src/cpp/Mat.cpp b/modules/java/generator/src/cpp/Mat.cpp index 6122a7e1e3..14f5497a1d 100644 --- a/modules/java/generator/src/cpp/Mat.cpp +++ b/modules/java/generator/src/cpp/Mat.cpp @@ -1863,7 +1863,7 @@ namespace { #undef JOCvT } -template static int mat_put(cv::Mat* m, int row, int col, int count, char* buff) +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; @@ -1875,14 +1875,14 @@ template static int mat_put(cv::Mat* m, int row, int col, int count, if( m->isContinuous() ) { - memcpy(m->ptr(row, col), buff, count); + 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, num); + memcpy(data, buff + offset, num); count -= num; buff += num; num = m->cols * (int)m->elemSize(); @@ -1893,7 +1893,7 @@ template static int mat_put(cv::Mat* m, int row, int col, int count, return res; } -template static jint java_mat_put(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) +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; try { @@ -1904,7 +1904,7 @@ template static jint java_mat_put(JNIEnv* env, jlong self, jint row if(me->rows<=row || me->cols<=col) return 0; // indexes out of range char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0); - int res = mat_put::value_type>(me, row, col, count, values); + int res = mat_put::value_type>(me, row, col, count, offset, values); env->ReleasePrimitiveArrayCritical(vals, values, JNI_ABORT); return res; } catch(const std::exception &e) { @@ -1924,7 +1924,16 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutB JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutB (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jbyteArray vals) { - return java_mat_put(env, self, row, col, count, vals); + return java_mat_put(env, self, row, col, count, 0, vals); +} + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwOffset + (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jint offset, jbyteArray vals); + +JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutBwOffset + (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jint offset, jbyteArray vals) +{ + return java_mat_put(env, self, row, col, count, offset, vals); } JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutS @@ -1933,7 +1942,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutS JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutS (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jshortArray vals) { - return java_mat_put(env, self, row, col, count, vals); + return java_mat_put(env, self, row, col, count, 0, vals); } JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutI @@ -1942,7 +1951,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutI JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutI (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jintArray vals) { - return java_mat_put(env, self, row, col, count, vals); + return java_mat_put(env, self, row, col, count, 0, vals); } JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF @@ -1951,7 +1960,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutF (JNIEnv* env, jclass, jlong self, jint row, jint col, jint count, jfloatArray vals) { - return java_mat_put(env, self, row, col, count, vals); + return java_mat_put(env, self, row, col, count, 0, vals); } } // extern "C"