-1

I need get the bitmap from IFrameCallback which was functioned to deal with the frame from a UVCCamera preview, but there's comes the exception:

java.lang.UnsupportedOperationException at java.nio.ByteBuffer.arrayOffset

private final IFrameCallback callback = new IFrameCallback() {
    @override
    public void onFrame(final ByteBuffer frame) {
        new Thread(new Runnable() {
            byte[] bytes = new byte[frame.remaining()];
            frame.get(bytes);

            if(bytes.length > 0) {
                int offset = frame.arrayOffset();
                Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, offset, bytes.length - offset);
                ......
            }
        }).start();
    }
}

or if I use createBitmap instead of decodeByteArray, I got this exception:

java.lang.RuntimeException: Buffer not large enough for pixels at android.graphics.Bitmap.copyPixelsFromBuffer

private final IFrameCallback callback = new IFrameCallback() {
    @override
    public void onFrame(final ByteBuffer frame) {
        new Thread(new Runnable() {
            Bitmap bitmap = Bitmap.createBitmap(UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, Bitmap.Config.ARGB_8888);
            bitmap.copyPixelsFromBuffer(frame);
            ......
        }).start();
    }
}

Because the preview size is 1280 x 720, so the problem of RuntimeException can be ignored.

Is there any ideas about the first exception to get the arrayOffset from ByteBuffer?

PS: I know

UnsupportedOperationException - If this buffer is not backed by an accessible array

My point is: is there any other ways to get the arrayOffset, or if can't do that and how to solve the RuntimeException?

frank jorsn
  • 489
  • 1
  • 9
  • 27
  • 1
    read teh javadoc: *UnsupportedOperationException - If this buffer is not backed by an accessible Array*. – Jens Jan 07 '19 at 08:41
  • Read the javadoc [here](https://docs.oracle.com/javase/10/docs/api/java/nio/ByteBuffer.html#arrayOffset--). This is for Java 10. `Throws: ReadOnlyBufferException - If this buffer is backed by an array but is read-only UnsupportedOperationException - If this buffer is not backed by an accessible array` – Adam Jan 07 '19 at 08:48
  • @Jens Hey, Jens, I know that, and that is why I got the byteBuffer.ayyar() by byteBuffer.get(). The problem is how can I get the arrayOffset and can avoid the exception! – frank jorsn Jan 07 '19 at 08:49
  • @frankjorsn frame.get(bytes); Returns a ByteBuffer. You have to assign it to a variable and work on it: https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#get(byte[]) – Jens Jan 07 '19 at 08:51

1 Answers1

0

Well, since there's no a good solution, I had changed the way to get the bitmap from IFrameCallback.

Because I had applied the UVCCamera.PIXEL_FORMAT_NV21 format to the UVCCamera:

uvcCamera.setFrameCallback(frameCallback, UVCCamera.PIXEL_FORMAT_NV21);

So, I can get the bitmap just transform YuvImage:

private ChannelBufferOutputStream stream = new ChannelBufferOutputStream(MessageBuffers.dynamicBuffer());
......
private final IFrameCallback callback = new IFrameCallback() {
    @override
    public void onFrame(final ByteBuffer frame) {
        new Thread(new Runnable() {
            @override
            public void run() {
                byte[] bytes = new byte[frame.remaining()];
                frame.get(bytes);

                if(bytes.length > 0) {
                    YuvImage yuvImage = new YuvImage(bytes, ImageFormat.NV21, UVCCamera.DEFAULT_PREVIEW_WIDTH, UVCCamera.DEFAULT_PREVIEW_HEIGHT, null);
                    bytes = null;

                    if(yuvImage.getYuvData().length > 0) {
                        yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 80, stream);
                        Bitmap bitmap = BitmapFactory.decodeByteArray(stream.buffer().array(), 0, stream.buffer().array().length);
                        ......
                    }
                }
            }
        }).start();
    }
}
frank jorsn
  • 489
  • 1
  • 9
  • 27