bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.41k stars 1.57k forks source link

Buffer underflow exception when trying to access Mat.data() (v. 1.5.7) #2108

Closed b005t3r closed 9 months ago

b005t3r commented 9 months ago

For some reason I can't copy the data of a Mat instance using the data() method (I get a BufferUnderflowException even when I try to copy a single element). BUT when I create an Indexer, accessing data works just fine.

Here's the example code:

            try(PointerScope scope = new PointerScope()) {
                Mat srcMat = toMat(src, null);
                Mat dstMat = toMat(dst, null);

                if(srcType == ImageType.COMPATIBLE && dstType == ImageType.BGR) {
                    opencv_imgproc.cvtColor(srcMat, dstMat, opencv_imgproc.COLOR_RGBA2BGR);

                    DataBufferByte dstBuffer = (DataBufferByte) dst.getRaster().getDataBuffer();
                    //dstMat.data().asBuffer().get(dstBuffer.getData(), 0, dstMat.rows() * dstMat.cols() * 3);
                    dstMat.createIndexer().pointer().asByteBuffer().get(dstBuffer.getData(), 0, dstMat.rows() * dstMat.cols() * 3);
                }
                else if(srcType == ImageType.BGR && dstType == ImageType.COMPATIBLE) {
                    opencv_imgproc.cvtColor(srcMat, dstMat, opencv_imgproc.COLOR_BGR2RGBA);

                    DataBufferInt dstBuffer = (DataBufferInt) dst.getRaster().getDataBuffer();
                    //dstMat.data().asBuffer().asIntBuffer().get(dstBuffer.getData(), 0, dstMat.rows() * dstMat.cols());
                    dstMat.createIndexer().pointer().asByteBuffer().asIntBuffer().get(dstBuffer.getData(), 0, dstMat.rows() * dstMat.cols());
                }
                else {
                    throw new IllegalStateException("unhandled type combination, srcType: " + srcType + ", dstType: " + dstType);
                }
            }

Commented-out lines throw the exception, the lines below them (which create indexers) work with no issues.

Am I missing something?

saudet commented 9 months ago

Why not just call Mat.createBuffer()?

b005t3r commented 9 months ago

I already have a buffer created and need to copy the contents of the Mat to that buffer.

Can you explain why the commented out parts don't work, please? Am I doing something wrong?

saudet commented 9 months ago

You can look at what Mat.createBuffer() is doing, that's what it does.

b005t3r commented 9 months ago

OK, I see, so I can't use data() directly, need to call createBuffer() to obtain the pointed to the Mat's underlying data?

saudet commented 9 months ago

No, we can use data(), that's what Mat.createBuffer() does, so you can refer to the code in that method: https://github.com/bytedeco/javacpp-presets/blob/master/opencv/src/main/java/org/bytedeco/opencv/opencv_core/AbstractArray.java#L32

b005t3r commented 9 months ago

But not directly, right? I need to call the rest of the stuff first, like position() and capacity(), is that correct?