Reputation: 3667
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.
Upvotes: 1
Views: 10830
Reputation: 1
If someone is still interested:
Short solution: call buffBlend.position(0);
before executing the while loop. Do the same for all your IntBuffer objects.
Background:
When you put an element into a IntBuffer the index/position of the IntBuffer is incremented. And when you call .get()
method the incrimination continues. That's the problem. Let's say you put 3 int values into an IntBuffer. After that you call the .get()
and you get the BufferUnderflowException
. This happens because when you call the get() method the position/index increments to the 4, but your IntBuffer has the capacity of 3.
Solution: before calling the first get()
, execute intBufferObject.position(0);
that is how you get your index position back to the 0.
See more here get() and put() methods documentation. https://docs.oracle.com/javase/7/docs/api/java/nio/IntBuffer.html#get()
Upvotes: 0
Reputation: 2258
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.
Upvotes: 1
Reputation: 136122
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
Upvotes: 4