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);
|
||||
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() {
|
||||
|
||||
@ -2129,80 +2129,83 @@ namespace {
|
||||
#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;
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
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 {
|
||||
// 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;
|
||||
memcpy(buff, m->ptr(idx.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];;
|
||||
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;
|
||||
@ -2455,68 +2458,16 @@ JNIEXPORT jint JNICALL Java_org_opencv_core_Mat_nPutDIdx
|
||||
|
||||
} // 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)
|
||||
{
|
||||
if(! m) return 0;
|
||||
if(! buff) return 0;
|
||||
return mat_copy_data<T>(m, idx, count, buff, false);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
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) {
|
||||
|
||||
@ -279,20 +279,24 @@ public class OpenCVTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static <E extends Number> 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(double[] ar1, double[] ar2, double epsilon) {
|
||||
if (ar1.length != ar2.length) {
|
||||
fail("Arrays have different sizes.");
|
||||
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) {
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i], ar2[i], epsilon);
|
||||
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
|
||||
|
||||
@ -305,20 +305,23 @@ public class OpenCVTestCase extends TestCase {
|
||||
}
|
||||
|
||||
public static <E extends Number> 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(double[] ar1, double[] ar2, double epsilon) {
|
||||
if (ar1.length != ar2.length) {
|
||||
fail("Arrays have different sizes.");
|
||||
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) {
|
||||
assertEquals(ar1.length, ar2.length);
|
||||
|
||||
for (int i = 0; i < ar1.length; i++)
|
||||
assertEquals(ar1[i], ar2[i], epsilon);
|
||||
//assertTrue(Math.abs(ar1[i].doubleValue() - ar2[i].doubleValue()) <= epsilon);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user