mirror of
https://github.com/opencv/opencv.git
synced 2026-11-09 18:04:29 -06:00
Merge pull request #29851 from utibenkei:fix-java-mat-get-put
java: fix Mat get/put JNI for 0D/1D/ND Mats in OpenCV 5 - #29851#29851
## Summary
Fix incorrect behavior of Java `Mat.get()` / `Mat.put()` JNI bindings for
0D (scalar), 1D, and ND `cv::Mat` objects.
The Java JNI layer in `modules/java/generator/src/cpp/Mat.cpp` still assumed
essentially 2D row/col indexing in several get/put code paths. This caused
wrong results or failed access for scalar and 1D Mats, and incorrect bounds
handling for ND Mats accessed via index arrays.
This PR updates the native get/put helpers in `Mat.cpp` and adds regression
tests in `modules/core/misc/java/test/MatTest.java`.
## Problem (before this patch)
### 1. 0D (scalar) Mats
- `Mat::ptr(const int*)` requires `dims >= 1`, so idx-based paths that called
`m->ptr(idx.data())` directly (e.g. `nGetIdx`, `mat_copy_data`, `PUT_ITEM_IDX`)
could not access a true 0D Mat correctly.
- `idx2Offset()` always read `indices[0]` without checking `dims <= 0`.
- Row/col helpers always built a 2-element index `{row, col}` instead of an
empty index vector for 0D Mats.
Although OpenCV 5 supports 0D Mats at the C++ level, the Java wrapper did not
correctly implement idx-based access with an empty index array (`new int[]{}`).
This PR adds explicit JNI support for that case via `mat_elem_ptr()` and
related helpers.
**Example:** For `Mat m = new Mat(new int[]{}, CvType.CV_64F)` (`dims()==0`),
`m.put(new int[]{}, 42.0)` and `m.get(new int[]{}, buf)` could fail or access
the wrong memory.
### 2. 1D Mats (`dims() == 1`)
- Row/col get/put always converted `(row, col)` to `{row, col}` (length 2),
while a 1D Mat requires a single-element index vector.
- For a 1D Mat, OpenCV 5 represents the shape as `dims == rows == 1` and
`cols == total() == N`. The Java row/col access path must therefore interpret
`(row, col)` as the 1D element index represented by `col` (with `row == 0`),
converting internally to `{col}` via `row_col_to_idx()`.
**Example:** For `Mat m = new Mat(new int[]{10}, CvType.CV_32F)`, calling
`m.put(0, 3, values)` could behave incorrectly because native code treated
the access as `{0, 3}` instead of `{3}`.
### 3. ND Mats (`dims() > 2`) via row/col API
- Row/col get/put only checked `rows` and `cols`, without rejecting Mats with
`dims > 2`.
- ND Mats must be accessed via idx-based APIs; using row/col on them could
produce silently wrong results instead of failing early.
### 4. Idx-based API bounds checking
- Old code checked `size[i] <= idx[i]` but did not validate:
- `idx.length == dims`
- negative index values
- `nPutDIdx` computed the number of remaining elements with a per-dimension
product loop (`channels * (size[i] - idx[i]) * ...`). For ND Mats, this did
not correctly account for the current linear index position when determining
how many elements remain from the selected subarray onward. The fix uses
`(total() - idx2Offset(m, idx)) * channels()`, which matches the linear
layout used by `mat_copy_data()`.
## Changes
- Add `mat_elem_ptr()` to support 0D scalar Mats (`Mat::ptr(const int*)`
requires `dims >= 1`).
- Add `check_row_col_access()`, `check_idx_access()`, and `row_col_to_idx()`
to validate access and convert row/col indices according to OpenCV semantics.
- Update `idx2Offset()`, `offset2Idx()`, and `mat_copy_data()` for 0D/1D Mats.
- Route row/col get/put through `row_col_to_idx()` (1D: element index in `col`,
`row == 0`).
- Restrict row/col APIs to Mats with `dims <= 2`; ND Mats must use idx-based
APIs (`nGet*Idx`, `nPut*Idx`, `nGetIdx`, `nPutDIdx`).
- Fix remaining-element calculation in `nPutDIdx` to use `idx2Offset()`.
## Behavior notes
| API | 0D Mat (`dims==0`) | 1D Mat (`dims==1`) | 2D Mat | ND Mat (`dims>2`) |
|-----|-------------------|-------------------|--------|-------------------|
| `get/put(int[] idx, ...)` | supported (`idx.length == 0`; added by this PR) | supported (`idx.length == 1`) | supported | supported |
| `get/put(row, col, ...)` | supported (`row=0`, `col=0`) | supported (index in `col`, `row=0`) | supported | rejected at JNI layer return 0; |
| `get(row, col)` | supported | supported | supported | rejected at JNI layer return 0; |
| `get(int[] idx)` | supported | supported | supported | supported |
## Test plan
Added regression tests in `MatTest.java`:
- `testGetPut0DMat` — idx and row/col get/put on a scalar Mat (`new int[]{}`)
- `testGetPut1DMat` — idx and row/col get/put on `new Mat(new int[]{5}, ...)`
- `testGetPut1DMatDoubleArray` — bulk double put/get via idx on a 1D Mat
- `testGetPut3DMat` — row/col API rejected for 3D Mat; idx API works
### Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -994,6 +994,88 @@ public class MatTest extends OpenCVTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetPut0DMat() {
|
||||
Mat m = new Mat(new int[]{}, CvType.CV_64F);
|
||||
assertEquals(0, m.dims());
|
||||
assertEquals(1, m.total());
|
||||
|
||||
double[] buf = new double[1];
|
||||
assertEquals(1, m.put(new int[]{}, 42.0));
|
||||
assertEquals(8, m.get(new int[]{}, buf));
|
||||
assertEquals(42.0, buf[0], EPS);
|
||||
assertArrayEquals(new double[]{42.0}, m.get(new int[]{}), EPS);
|
||||
|
||||
assertEquals(1, m.put(0, 0, 99.0));
|
||||
assertArrayEquals(new double[]{99.0}, m.get(0, 0), EPS);
|
||||
|
||||
try {
|
||||
m.get(new int[]{0}, buf);
|
||||
fail("Expected IllegalArgumentException (Incorrect number of indices)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetPut1DMat() {
|
||||
Mat m = new Mat(new int[]{5}, CvType.CV_32F);
|
||||
assertEquals(1, m.dims());
|
||||
assertEquals(5, m.total());
|
||||
assertEquals(1, m.rows());
|
||||
assertEquals(5, m.cols());
|
||||
|
||||
float[] data = new float[]{10, 20, 30, 40, 50};
|
||||
assertEquals(20, m.put(new int[]{0}, data));
|
||||
float[] read = new float[5];
|
||||
assertEquals(20, m.get(new int[]{0}, read));
|
||||
assertTrue(Arrays.equals(data, read));
|
||||
|
||||
assertEquals(1, m.put(new int[]{2}, 99.0f));
|
||||
assertArrayEquals(new double[]{99.0}, m.get(new int[]{2}), EPS);
|
||||
|
||||
assertEquals(1, m.put(0, 1, 77.0f));
|
||||
assertArrayEquals(new double[]{77.0}, m.get(0, 1), EPS);
|
||||
|
||||
float[] single = new float[1];
|
||||
assertEquals(4, m.get(0, 3, single));
|
||||
assertEquals(40.0f, single[0], EPS);
|
||||
|
||||
assertEquals(20, m.put(0, 0, data));
|
||||
assertEquals(20, m.get(0, 0, read));
|
||||
assertTrue(Arrays.equals(data, read));
|
||||
|
||||
try {
|
||||
m.get(new int[]{0, 0}, new float[1]);
|
||||
fail("Expected IllegalArgumentException (Incorrect number of indices)");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetPut1DMatDoubleArray() {
|
||||
Mat m = new Mat(new int[]{4}, CvType.CV_64F);
|
||||
assertEquals(1, m.dims());
|
||||
|
||||
assertEquals(3, m.put(new int[]{1}, 1.0, 2.0, 3.0));
|
||||
double[] buf = new double[3];
|
||||
assertEquals(24, m.get(new int[]{1}, buf));
|
||||
assertArrayEquals(new double[]{1.0, 2.0, 3.0}, buf, EPS);
|
||||
}
|
||||
|
||||
public void testGetPut3DMat() {
|
||||
Mat m = new Mat(new int[]{2, 2, 2}, CvType.CV_32F, new Scalar(0));
|
||||
assertEquals(3, m.dims());
|
||||
|
||||
float[] buf = new float[1];
|
||||
assertEquals(0, m.put(0, 0, 1.0f));
|
||||
assertEquals(0, m.get(0, 0, buf));
|
||||
assertNull(m.get(0, 0));
|
||||
|
||||
assertEquals(4, m.put(new int[]{1, 0, 1}, new float[]{3.14f}));
|
||||
assertEquals(4, m.get(new int[]{1, 0, 1}, buf));
|
||||
assertEquals(3.14f, buf[0], EPS);
|
||||
assertArrayEquals(new double[]{3.14}, m.get(new int[]{1, 0, 1}), EPS);
|
||||
}
|
||||
|
||||
public void testRelease() {
|
||||
assertFalse(gray0.empty());
|
||||
assertTrue(gray0.rows() > 0);
|
||||
|
||||
@@ -2139,7 +2139,15 @@ namespace {
|
||||
#undef JOCvT
|
||||
}
|
||||
|
||||
// Element pointer that also supports 0D scalar Mats (OpenCV Mat::ptr(const int*) requires dims >= 1).
|
||||
static uchar* mat_elem_ptr(cv::Mat* m, const int* idx) {
|
||||
if (!m || !m->data) return nullptr;
|
||||
if (m->dims <= 0) return m->data;
|
||||
return m->ptr(idx);
|
||||
}
|
||||
|
||||
static size_t idx2Offset(cv::Mat* mat, std::vector<int>& indices) {
|
||||
if (mat->dims <= 0) return 0;
|
||||
size_t offset = indices[0];
|
||||
for (int dim=1; dim < mat->dims; dim++) {
|
||||
offset = offset*mat->size[dim] + indices[dim];
|
||||
@@ -2148,9 +2156,15 @@ static size_t idx2Offset(cv::Mat* mat, std::vector<int>& indices) {
|
||||
}
|
||||
|
||||
static void offset2Idx(cv::Mat* mat, size_t offset, std::vector<int>& indices) {
|
||||
if (mat->dims <= 0) {
|
||||
indices.clear();
|
||||
return;
|
||||
}
|
||||
if ((int)indices.size() != mat->dims)
|
||||
indices.resize(mat->dims);
|
||||
for (int dim=mat->dims-1; dim>=0; dim--) {
|
||||
indices[dim] = offset % mat->size[dim];
|
||||
offset = (offset - indices[dim]) / mat->size[dim];
|
||||
indices[dim] = (int)(offset % mat->size[dim]);
|
||||
offset = (offset - (size_t)indices[dim]) / mat->size[dim];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2163,31 +2177,66 @@ static bool updateIdx(cv::Mat* mat, std::vector<int>& indices, size_t inc) {
|
||||
return reachedEnd;
|
||||
}
|
||||
|
||||
// row/col APIs only address Mats with dims <= 2 (0D/1D/2D). ND Mats must use idx APIs.
|
||||
// Matches OpenCV Mat::ptr(row,col) semantics: for dims<=1, row must be 0 and col is the index.
|
||||
static bool check_row_col_access(const cv::Mat* me, int row, int col) {
|
||||
if (!me) return false;
|
||||
if (me->dims > 2) return false;
|
||||
if (row < 0 || col < 0) return false;
|
||||
if (me->rows <= row || me->cols <= col) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_idx_access(const cv::Mat* me, const std::vector<int>& idx) {
|
||||
if (!me) return false;
|
||||
if ((int)idx.size() != me->dims) return false;
|
||||
for (int i = 0; i < me->dims; i++) {
|
||||
if (idx[i] < 0 || me->size[i] <= idx[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert (row, col) to a dims-length index vector (OpenCV ptr(row,col) convention).
|
||||
static std::vector<int> row_col_to_idx(const cv::Mat* m, int row, int col) {
|
||||
if (m->dims <= 0)
|
||||
return std::vector<int>();
|
||||
if (m->dims == 1)
|
||||
return std::vector<int>(1, col);
|
||||
int indicesArray[] = { row, col };
|
||||
return std::vector<int>(indicesArray, indicesArray+2);
|
||||
}
|
||||
|
||||
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;
|
||||
if(! m->data) return 0;
|
||||
if ((int)idx.size() != m->dims) return 0;
|
||||
|
||||
size_t countBytes = count * sizeof(T);
|
||||
size_t countBytes = (size_t)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 (countBytes == 0) return 0;
|
||||
|
||||
if( m->isContinuous() )
|
||||
if( m->isContinuous() || m->dims <= 1 )
|
||||
{
|
||||
uchar* data = mat_elem_ptr(m, idx.data());
|
||||
if (!data) return 0;
|
||||
if (isPut) {
|
||||
memcpy(m->ptr(idx.data()), buff, countBytes);
|
||||
memcpy(data, buff, countBytes);
|
||||
} else {
|
||||
memcpy(buff, m->ptr(idx.data()), countBytes);
|
||||
memcpy(buff, data, countBytes);
|
||||
}
|
||||
} else {
|
||||
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];;
|
||||
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());
|
||||
uchar* data = mat_elem_ptr(m, idx.data());
|
||||
if (!data) return 0;
|
||||
while(countBytes>0){
|
||||
if (isPut) {
|
||||
memcpy(data, buff, copyCount);
|
||||
@@ -2198,7 +2247,8 @@ template<typename T> static int mat_copy_data(cv::Mat* m, std::vector<int>& idx,
|
||||
countBytes -= copyCount;
|
||||
buff += copyCount;
|
||||
copyCount = countBytes<blockSize?countBytes:blockSize;
|
||||
data = m->ptr(idx.data());
|
||||
data = mat_elem_ptr(m, idx.data());
|
||||
if (!data) break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -2211,8 +2261,7 @@ template<typename T> static int mat_put_idx(cv::Mat* m, std::vector<int>& idx, i
|
||||
|
||||
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);
|
||||
std::vector<int> indices = row_col_to_idx(m, row, col);
|
||||
return mat_put_idx<T>(m, indices, count, offset, buff);
|
||||
}
|
||||
|
||||
@@ -2224,7 +2273,7 @@ template<class ARRAY> static jint java_mat_put(JNIEnv* env, jlong self, jint row
|
||||
cv::Mat* me = (cv::Mat*) self;
|
||||
if(! self) return 0; // no native object behind
|
||||
if(me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_1 && me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_2) return 0; // incompatible type
|
||||
if(me->rows<=row || me->cols<=col) return 0; // indexes out of range
|
||||
if(!check_row_col_access(me, row, col)) return 0; // indexes out of range / dims > 2
|
||||
|
||||
char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
|
||||
int res = mat_put<typename JavaOpenCVTrait<ARRAY>::value_type>(me, row, col, count, offset, values);
|
||||
@@ -2248,9 +2297,7 @@ template<class ARRAY> static jint java_mat_put_idx(JNIEnv* env, jlong self, jint
|
||||
if(! self) return 0; // no native object behind
|
||||
if(me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_1 && me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_2) return 0; // incompatible type
|
||||
std::vector<int> idx = convertJintArrayToVector(env, idxArray);
|
||||
for (int i = 0; i < me->dims ; i++ ) {
|
||||
if (me->size[i]<=idx[i]) return 0;
|
||||
}
|
||||
if (!check_idx_access(me, idx)) return 0;
|
||||
char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
|
||||
int res = mat_put_idx<typename JavaOpenCVTrait<ARRAY>::value_type>(me, idx, count, offset, values);
|
||||
env->ReleasePrimitiveArrayCritical(vals, values, JNI_ABORT);
|
||||
@@ -2370,7 +2417,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutD
|
||||
LOGD("%s", method_name);
|
||||
cv::Mat* me = (cv::Mat*) self;
|
||||
if(!me || !me->data) return 0; // no native object behind
|
||||
if(me->rows<=row || me->cols<=col) return 0; // indexes out of range
|
||||
if(!check_row_col_access(me, row, col)) return 0; // indexes out of range / dims > 2
|
||||
|
||||
int rest = ((me->rows - row) * me->cols - col) * me->channels();
|
||||
if(count>rest) count = rest;
|
||||
@@ -2417,7 +2464,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutD
|
||||
}
|
||||
|
||||
// unlike other nPut()-s this one (with double[]) should convert input values to correct type
|
||||
#define PUT_ITEM_IDX(T, I) { T*dst = (T*)me->ptr(I); for(int ch=0; ch<me->channels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast<T>(*src); }
|
||||
#define PUT_ITEM_IDX(T, I) { T*dst = (T*)mat_elem_ptr(me, I); for(int ch=0; ch<me->channels() && count>0; count--,ch++,src++,dst++) *dst = cv::saturate_cast<T>(*src); }
|
||||
|
||||
JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
|
||||
(JNIEnv* env, jclass, jlong self, jintArray idxArray, jint count, jdoubleArray vals);
|
||||
@@ -2431,14 +2478,10 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
|
||||
cv::Mat* me = (cv::Mat*) self;
|
||||
if(!me || !me->data) return 0; // no native object behind
|
||||
std::vector<int> idx = convertJintArrayToVector(env, idxArray);
|
||||
for (int i=0; i<me->dims; i++) {
|
||||
if (me->size[i]<=idx[i]) return 0; // indexes out of range
|
||||
}
|
||||
int rest = me->channels();
|
||||
for (int i=0; i<me->dims; i++) {
|
||||
rest *= (me->size[i] - idx[i]);
|
||||
}
|
||||
if(count>rest) count = rest;
|
||||
if (!check_idx_access(me, idx)) return 0; // indexes out of range
|
||||
if (count <= 0) return 0;
|
||||
size_t rest = (me->total() - idx2Offset(me, idx)) * (size_t)me->channels();
|
||||
if ((size_t)count > rest) count = (jint)rest;
|
||||
int res = count;
|
||||
double* values = (double*)env->GetPrimitiveArrayCritical(vals, 0);
|
||||
double* src = values;
|
||||
@@ -2475,8 +2518,7 @@ template<typename T> static int mat_get_idx(cv::Mat* m, std::vector<int>& idx, i
|
||||
|
||||
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
|
||||
{
|
||||
int indicesArray[] = { row, col };
|
||||
std::vector<int> indices(indicesArray, indicesArray+2);
|
||||
std::vector<int> indices = row_col_to_idx(m, row, col);
|
||||
return mat_get_idx<T>(m, indices, count, buff);
|
||||
}
|
||||
|
||||
@@ -2487,7 +2529,7 @@ template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row
|
||||
cv::Mat* me = (cv::Mat*) self;
|
||||
if(! self) return 0; // no native object behind
|
||||
if(me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_1 && me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_2) return 0; // incompatible type
|
||||
if(me->rows<=row || me->cols<=col) return 0; // indexes out of range
|
||||
if(!check_row_col_access(me, row, col)) return 0; // indexes out of range / dims > 2
|
||||
|
||||
char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
|
||||
int res = mat_get<typename JavaOpenCVTrait<ARRAY>::value_type>(me, row, col, count, values);
|
||||
@@ -2510,9 +2552,7 @@ template<class ARRAY> static jint java_mat_get_idx(JNIEnv* env, jlong self, jint
|
||||
if(! self) return 0; // no native object behind
|
||||
if(me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_1 && me->depth() != JavaOpenCVTrait<ARRAY>::cvtype_2) return 0; // incompatible type
|
||||
std::vector<int> idx = convertJintArrayToVector(env, idxArray);
|
||||
for (int i = 0; i < me->dims ; i++ ) {
|
||||
if (me->size[i]<=idx[i]) return 0;
|
||||
}
|
||||
if (!check_idx_access(me, idx)) return 0;
|
||||
|
||||
char* values = (char*)env->GetPrimitiveArrayCritical(vals, 0);
|
||||
int res = mat_get_idx<typename JavaOpenCVTrait<ARRAY>::value_type>(me, idx, count, values);
|
||||
@@ -2629,21 +2669,22 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGet
|
||||
try {
|
||||
LOGD("%s", method_name);
|
||||
cv::Mat* me = (cv::Mat*) self;
|
||||
if(! self) return 0; // no native object behind
|
||||
if(me->rows<=row || me->cols<=col) return 0; // indexes out of range
|
||||
if(! self || !me->data) return 0; // no native object behind
|
||||
if(!check_row_col_access(me, row, col)) return 0; // indexes out of range / dims > 2
|
||||
|
||||
jdoubleArray res = env->NewDoubleArray(me->channels());
|
||||
if(res){
|
||||
jdouble buff[CV_CN_MAX];//me->channels()
|
||||
uchar* elem = me->ptr(row, col);
|
||||
int i;
|
||||
switch(me->depth()){
|
||||
case CV_8U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned char*) me->ptr(row, col) + i); break;
|
||||
case CV_8S: for(i=0; i<me->channels(); i++) buff[i] = *((signed char*) me->ptr(row, col) + i); break;
|
||||
case CV_16U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned short*)me->ptr(row, col) + i); break;
|
||||
case CV_16S: for(i=0; i<me->channels(); i++) buff[i] = *((signed short*) me->ptr(row, col) + i); break;
|
||||
case CV_32S: for(i=0; i<me->channels(); i++) buff[i] = *((int*) me->ptr(row, col) + i); break;
|
||||
case CV_32F: for(i=0; i<me->channels(); i++) buff[i] = *((float*) me->ptr(row, col) + i); break;
|
||||
case CV_64F: for(i=0; i<me->channels(); i++) buff[i] = *((double*) me->ptr(row, col) + i); break;
|
||||
case CV_8U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned char*) elem + i); break;
|
||||
case CV_8S: for(i=0; i<me->channels(); i++) buff[i] = *((signed char*) elem + i); break;
|
||||
case CV_16U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned short*)elem + i); break;
|
||||
case CV_16S: for(i=0; i<me->channels(); i++) buff[i] = *((signed short*) elem + i); break;
|
||||
case CV_32S: for(i=0; i<me->channels(); i++) buff[i] = *((int*) elem + i); break;
|
||||
case CV_32F: for(i=0; i<me->channels(); i++) buff[i] = *((float*) elem + i); break;
|
||||
case CV_64F: for(i=0; i<me->channels(); i++) buff[i] = *((double*) elem + i); break;
|
||||
}
|
||||
env->SetDoubleArrayRegion(res, 0, me->channels(), buff);
|
||||
}
|
||||
@@ -2667,24 +2708,24 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Mat_nGetIdx
|
||||
try {
|
||||
LOGD("%s", method_name);
|
||||
cv::Mat* me = (cv::Mat*) self;
|
||||
if(! self) return 0; // no native object behind
|
||||
if(! self || !me->data) return 0; // no native object behind
|
||||
std::vector<int> idx = convertJintArrayToVector(env, idxArray);
|
||||
for (int i=0; i<me->dims; i++) {
|
||||
if (me->size[i]<=idx[i]) return 0; // indexes out of range
|
||||
}
|
||||
if (!check_idx_access(me, idx)) return 0; // indexes out of range
|
||||
|
||||
jdoubleArray res = env->NewDoubleArray(me->channels());
|
||||
if(res){
|
||||
jdouble buff[CV_CN_MAX];//me->channels()
|
||||
uchar* elem = mat_elem_ptr(me, idx.data());
|
||||
if (!elem) return 0;
|
||||
int i;
|
||||
switch(me->depth()){
|
||||
case CV_8U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned char*) me->ptr(idx.data()) + i); break;
|
||||
case CV_8S: for(i=0; i<me->channels(); i++) buff[i] = *((signed char*) me->ptr(idx.data()) + i); break;
|
||||
case CV_16U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned short*)me->ptr(idx.data()) + i); break;
|
||||
case CV_16S: for(i=0; i<me->channels(); i++) buff[i] = *((signed short*) me->ptr(idx.data()) + i); break;
|
||||
case CV_32S: for(i=0; i<me->channels(); i++) buff[i] = *((int*) me->ptr(idx.data()) + i); break;
|
||||
case CV_32F: for(i=0; i<me->channels(); i++) buff[i] = *((float*) me->ptr(idx.data()) + i); break;
|
||||
case CV_64F: for(i=0; i<me->channels(); i++) buff[i] = *((double*) me->ptr(idx.data()) + i); break;
|
||||
case CV_8U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned char*) elem + i); break;
|
||||
case CV_8S: for(i=0; i<me->channels(); i++) buff[i] = *((signed char*) elem + i); break;
|
||||
case CV_16U: for(i=0; i<me->channels(); i++) buff[i] = *((unsigned short*)elem + i); break;
|
||||
case CV_16S: for(i=0; i<me->channels(); i++) buff[i] = *((signed short*) elem + i); break;
|
||||
case CV_32S: for(i=0; i<me->channels(); i++) buff[i] = *((int*) elem + i); break;
|
||||
case CV_32F: for(i=0; i<me->channels(); i++) buff[i] = *((float*) elem + i); break;
|
||||
case CV_64F: for(i=0; i<me->channels(); i++) buff[i] = *((double*) elem + i); break;
|
||||
}
|
||||
env->SetDoubleArrayRegion(res, 0, me->channels(), buff);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user