Fix/optimize Android put/get functions
This commit is contained in:
parent
fba70f7991
commit
5cf08b0722
@ -455,6 +455,27 @@ public class MatTest extends OpenCVTestCase {
|
|||||||
bytesNum = sm.get(1, 1, buff11);
|
bytesNum = sm.get(1, 1, buff11);
|
||||||
assertEquals(4, bytesNum);
|
assertEquals(4, bytesNum);
|
||||||
assertTrue(Arrays.equals(new short[] {340, 341, 0, 0}, buff11));
|
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() {
|
public void testGetNativeObjAddr() {
|
||||||
|
|||||||
@ -2129,80 +2129,83 @@ namespace {
|
|||||||
#undef JOCvT
|
#undef JOCvT
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> static int mat_put(cv::Mat* m, int row, int col, int count, int offset, char* buff)
|
static size_t idx2Offset(cv::Mat* mat, std::vector<int>& indices) {
|
||||||
{
|
size_t offset = indices[0];
|
||||||
if(! m) return 0;
|
for (int dim=1; dim < mat->dims; dim++) {
|
||||||
if(! buff) return 0;
|
offset = offset*mat->size[dim] + indices[dim];
|
||||||
|
}
|
||||||
count *= sizeof(T);
|
return offset;
|
||||||
int rest = ((m->rows - row) * m->cols - col) * (int)m->elemSize();
|
}
|
||||||
if(count>rest) count = rest;
|
|
||||||
int res = count;
|
static void offset2Idx(cv::Mat* mat, size_t offset, std::vector<int>& indices) {
|
||||||
|
for (int dim=mat->dims-1; dim>=0; dim--) {
|
||||||
if( m->isContinuous() )
|
indices[dim] = offset % mat->size[dim];
|
||||||
{
|
offset = (offset - indices[dim]) / mat->size[dim];
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if final index was reached
|
// returns true if final index was reached
|
||||||
static bool updateIdx(cv::Mat* m, std::vector<int>& idx, int inc) {
|
static bool updateIdx(cv::Mat* mat, std::vector<int>& indices, size_t inc) {
|
||||||
for (int i=m->dims-1; i>=0; i--) {
|
size_t currentOffset = idx2Offset(mat, indices);
|
||||||
if (inc == 0) return false;
|
size_t newOffset = currentOffset + inc;
|
||||||
idx[i] = (idx[i] + 1) % m->size[i];
|
bool reachedEnd = newOffset>=(size_t)mat->total();
|
||||||
inc--;
|
offset2Idx(mat, reachedEnd?0:newOffset, indices);
|
||||||
}
|
return reachedEnd;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(! m) return 0;
|
||||||
if(! buff) return 0;
|
if(! buff) return 0;
|
||||||
|
|
||||||
count *= sizeof(T);
|
size_t countBytes = count * sizeof(T);
|
||||||
int rest = (int)m->elemSize();
|
size_t remainingBytes = (size_t)(m->total() - idx2Offset(m, idx))*m->elemSize();
|
||||||
for (int i = 0; i < m->dims; i++) {
|
countBytes = (countBytes>remainingBytes)?remainingBytes:countBytes;
|
||||||
rest *= (m->size[i] - idx[i]);
|
int res = (int)countBytes;
|
||||||
}
|
|
||||||
if(count>rest) count = rest;
|
|
||||||
int res = count;
|
|
||||||
|
|
||||||
if( m->isContinuous() )
|
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 {
|
} else {
|
||||||
// dim by dim
|
size_t blockSize = m->size[m->dims-1] * m->elemSize();
|
||||||
int num = (m->size[m->dims-1] - idx[m->dims-1]) * (int)m->elemSize(); // 1st partial row
|
size_t firstPartialBlockSize = (m->size[m->dims-1] - idx[m->dims-1]) * m->step[m->dims-1];;
|
||||||
if(count<num) num = count;
|
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 = m->ptr(idx.data());
|
||||||
while(count>0){
|
while(countBytes>0){
|
||||||
memcpy(data, buff + offset, num);
|
if (isPut) {
|
||||||
updateIdx(m, idx, num / (int)m->elemSize());
|
memcpy(data, buff, copyCount);
|
||||||
count -= num;
|
} else {
|
||||||
buff += num;
|
memcpy(buff, data, copyCount);
|
||||||
num = m->size[m->dims-1] * (int)m->elemSize();
|
}
|
||||||
if(count<num) num = count;
|
updateIdx(m, idx, copyCount / m->elemSize());
|
||||||
|
countBytes -= copyCount;
|
||||||
|
buff += copyCount;
|
||||||
|
copyCount = countBytes<blockSize?countBytes:blockSize;
|
||||||
data = m->ptr(idx.data());
|
data = m->ptr(idx.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
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)
|
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;
|
static const char *method_name = JavaOpenCVTrait<ARRAY>::put;
|
||||||
@ -2455,68 +2458,16 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
|
|||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_idx(cv::Mat* m, std::vector<int>& idx, int count, char* buff)
|
||||||
{
|
{
|
||||||
if(! m) return 0;
|
return mat_copy_data<T>(m, idx, count, buff, false);
|
||||||
if(! buff) return 0;
|
}
|
||||||
|
|
||||||
count *= sizeof(T);
|
template<typename T> static int mat_get(cv::Mat* m, int row, int col, int count, char* buff)
|
||||||
int rest = (int)m->elemSize();
|
{
|
||||||
for (int i = 0; i < m->dims; i++) {
|
int indicesArray[] = { row, col };
|
||||||
rest *= (m->size[i] - idx[i]);
|
std::vector<int> indices(indicesArray, indicesArray+2);
|
||||||
}
|
return mat_get_idx<T>(m, indices, count, buff);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) {
|
template<class ARRAY> static jint java_mat_get(JNIEnv* env, jlong self, jint row, jint col, jint count, ARRAY vals) {
|
||||||
|
|||||||
@ -279,19 +279,23 @@ public class OpenCVTestCase extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
|
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
|
||||||
if (ar1.length != ar2.length) {
|
assertEquals(ar1.length, ar2.length);
|
||||||
fail("Arrays have different sizes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ar1.length; i++)
|
for (int i = 0; i < ar1.length; i++)
|
||||||
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
|
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
|
||||||
//assertTrue(Math.abs(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) {
|
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
|
||||||
if (ar1.length != ar2.length) {
|
assertEquals(ar1.length, ar2.length);
|
||||||
fail("Arrays have different sizes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ar1.length; i++)
|
for (int i = 0; i < ar1.length; i++)
|
||||||
assertEquals(ar1[i], ar2[i], epsilon);
|
assertEquals(ar1[i], ar2[i], epsilon);
|
||||||
|
|||||||
@ -305,19 +305,22 @@ public class OpenCVTestCase extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
|
public static <E extends Number> void assertArrayEquals(E[] ar1, E[] ar2, double epsilon) {
|
||||||
if (ar1.length != ar2.length) {
|
assertEquals(ar1.length, ar2.length);
|
||||||
fail("Arrays have different sizes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ar1.length; i++)
|
for (int i = 0; i < ar1.length; i++)
|
||||||
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
|
assertEquals(ar1[i].doubleValue(), ar2[i].doubleValue(), epsilon);
|
||||||
//assertTrue(Math.abs(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) {
|
public static void assertArrayEquals(double[] ar1, double[] ar2, double epsilon) {
|
||||||
if (ar1.length != ar2.length) {
|
assertEquals(ar1.length, ar2.length);
|
||||||
fail("Arrays have different sizes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < ar1.length; i++)
|
for (int i = 0; i < ar1.length; i++)
|
||||||
assertEquals(ar1[i], ar2[i], epsilon);
|
assertEquals(ar1[i], ar2[i], epsilon);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user