Question

I have the following snippet of code. The marked line is causing a BufferUnderflowException. I read the documentation on the exception but still do not understand what exactly it menas. I use the .rewind() method which I was under the impression mitigates the issue.

Can anyone please enlighten me on the topic or cause of my error?

            Bitmap cameraBaseSized = BitmapFactory.decodeFile(cameraPath, opts);
            Bitmap canvasBlendSized = BitmapFactory.decodeFile(canvasPath, options);
            Bitmap result = cameraBaseSized.copy(Config.ARGB_8888, true);
            IntBuffer buffBase = IntBuffer.allocate(cameraBaseSized.getWidth()
                    * cameraBaseSized.getHeight());
            cameraBaseSized.copyPixelsToBuffer(buffBase);
            buffBase.rewind();
            IntBuffer buffBlend = IntBuffer.allocate(canvasBlendSized.getWidth()
                    * canvasBlendSized.getHeight());
            canvasBlendSized.copyPixelsToBuffer(buffBlend);
            buffBlend.rewind();
            IntBuffer buffOut = IntBuffer.allocate(cameraBaseSized.getWidth()
                    * cameraBaseSized.getHeight());
            buffOut.rewind();
            while (buffOut.position() < buffOut.limit()) {
                int filterInt = buffBlend.get(); //BUFFERUNDERFLOW EXCEPTION
                int srcInt = buffBase.get();
                int redValueFilter = Color.red(filterInt);
                int greenValueFilter = Color.green(filterInt);
                int blueValueFilter = Color.blue(filterInt);
                int redValueSrc = Color.red(srcInt);
                int greenValueSrc = Color.green(srcInt);
                int blueValueSrc = Color.blue(srcInt);
                int redValueFinal = multiply(redValueFilter, redValueSrc);
                int greenValueFinal = multiply(greenValueFilter, greenValueSrc);
                int blueValueFinal = multiply(blueValueFilter, blueValueSrc);
                int pixel = Color.argb(255, redValueFinal, greenValueFinal, blueValueFinal);
                buffOut.put(pixel);
            }
            buffOut.rewind();
            result.copyPixelsFromBuffer(buffOut);

And the exception snippet

11-29 14:41:57.347: E/AndroidRuntime(2166): Caused by: java.nio.BufferUnderflowException
11-29 14:41:57.347: E/AndroidRuntime(2166):     at java.nio.IntArrayBuffer.get(IntArrayBuffer.java:55)

I also would like to add this is happening only on specific devices, particularly samsung flavors.

Was it helpful?

Solution 2

Since it is happening on certain devices, it could be possible that you are not getting the pixel format you are expecting.

Also if buffBlend is for any reason shorter than buffOut (which could potentially be caused by the bitmaps being different formats), you will get this exception when you try and get() past the end of it.

EDIT:

You could change int filterInt = buffBlend.get(); to

int filterInt = 0;
if (buffBlend.position() < buffBlend.limit())
    filterInt = buffBlend.get();

If you do that for both of your buffers, that should protect you against the exception, and blend with black when one image is bigger than the other.

OTHER TIPS

Maybe this test will help:

    ByteBuffer b = ByteBuffer.allocate(1);
    b.get();
    b.get();

After allocation there is 1 byte in the buffer, the first get() reads this byte and buffer reaches its limit, second get() is illegal, there is nothing to read, so you get BufferUnderflowException.

This code does not fail:

    ByteBuffer b = ByteBuffer.allocate(1);
    b.get();
               b.rewind();
    b.get();

Your read the byte, but it is still in the buffer, so you can rewind it and read the byte again

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top