Skip to content

Commit 4950f54

Browse files
committed
Fix for SGBM compute() buffer allocation failure on big images
1 parent 73b5ef4 commit 4950f54

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

modules/calib3d/src/stereosgbm.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ static void computeDisparitySGBM( const Mat& img1, const Mat& img2,
353353

354354
if( buffer.empty() || !buffer.isContinuous() ||
355355
buffer.cols*buffer.rows*buffer.elemSize() < totalBufSize )
356-
buffer.create(1, (int)totalBufSize, CV_8U);
356+
buffer.reserveBuffer(totalBufSize);
357357

358358
// summary cost over different (nDirs) directions
359359
CostType* Cbuf = (CostType*)alignPtr(buffer.ptr(), ALIGN);
@@ -939,7 +939,7 @@ void getBufferPointers(Mat& buffer, int width, int width1, int D, int num_ch, in
939939
16; //to compensate for the alignPtr shifts
940940

941941
if( buffer.empty() || !buffer.isContinuous() || buffer.cols*buffer.rows*buffer.elemSize() < totalBufSize )
942-
buffer.create(1, (int)totalBufSize, CV_8U);
942+
buffer.reserveBuffer(totalBufSize);
943943

944944
// set up all the pointers:
945945
curCostVolumeLine = (CostType*)alignPtr(buffer.ptr(), 16);
@@ -1615,7 +1615,7 @@ void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDif
16151615
int width = img.cols, height = img.rows, npixels = width*height;
16161616
size_t bufSize = npixels*(int)(sizeof(Point2s) + sizeof(int) + sizeof(uchar));
16171617
if( !_buf.isContinuous() || _buf.empty() || _buf.cols*_buf.rows*_buf.elemSize() < bufSize )
1618-
_buf.create(1, (int)bufSize, CV_8U);
1618+
_buf.reserveBuffer(bufSize);
16191619

16201620
uchar* buf = _buf.ptr();
16211621
int i, j, dstep = (int)(img.step/sizeof(T));

modules/core/include/opencv2/core/mat.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,14 @@ class CV_EXPORTS Mat
14161416
*/
14171417
void reserve(size_t sz);
14181418

1419+
/** @brief Reserves space for the certain number of bytes.
1420+
1421+
The method reserves space for sz bytes. If the matrix already has enough space to store sz bytes,
1422+
nothing happens. If matrix has to be reallocated its previous content could be lost.
1423+
@param sz Number of bytes.
1424+
*/
1425+
void reserveBuffer(size_t sz);
1426+
14191427
/** @brief Changes the number of matrix rows.
14201428
14211429
The methods change the number of matrix rows. If the matrix is reallocated, the first

modules/core/src/matrix.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,32 @@ void Mat::reserve(size_t nelems)
830830
dataend = data + step.p[0]*r;
831831
}
832832

833+
void Mat::reserveBuffer(size_t nbytes)
834+
{
835+
size_t esz = 1;
836+
int mtype = CV_8UC1;
837+
if (!empty())
838+
{
839+
if (!isSubmatrix() && data + nbytes <= dataend)//Should it be datalimit?
840+
return;
841+
esz = elemSize();
842+
mtype = type();
843+
}
844+
845+
size_t nelems = (nbytes - 1) / esz + 1;
846+
847+
#if SIZE_MAX > UINT_MAX
848+
CV_Assert(nelems <= size_t(INT_MAX)*size_t(INT_MAX));
849+
int newrows = nelems > size_t(INT_MAX) ? nelems > 0x400*size_t(INT_MAX) ? nelems > 0x100000 * size_t(INT_MAX) ? nelems > 0x40000000 * size_t(INT_MAX) ?
850+
size_t(INT_MAX) : 0x40000000 : 0x100000 : 0x400 : 1;
851+
#else
852+
int newrows = nelems > size_t(INT_MAX) ? 2 : 1;
853+
#endif
854+
int newcols = (int)((nelems - 1) / newrows + 1);
855+
856+
create(newrows, newcols, mtype);
857+
}
858+
833859

834860
void Mat::resize(size_t nelems)
835861
{

0 commit comments

Comments
 (0)