java.lang.UnsupportedOperationException в java.nio.ByteBuffer.arrayOffset? - PullRequest
0 голосов
/ 07 января 2019

Мне нужно получить растровое изображение из IFrameCallback , которое было использовано для обработки фрейма из UVCCamera предварительного просмотра, но есть исключение:

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();
    }
}

или если я использую createBitmap вместо decodeByteArray , я получу это исключение:

java.lang.RuntimeException: буфер недостаточно велик для пикселей в 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();
    }
}

Поскольку размер предварительного просмотра составляет 1280 x 720 , проблема RuntimeException может быть проигнорирована.

Есть ли идеи о первом исключении для получения arrayOffset из ByteBuffer ?

PS: я знаю

UnsupportedOperationException - Если этот буфер не поддержан доступный массив

Моя точка зрения такова: есть ли другие способы получить arrayOffset , или если не можете этого сделать и как решить RuntimeException?

1 Ответ

0 голосов
/ 07 января 2019

Ну, поскольку хорошего решения нет, я изменил способ получения растрового изображения из IFrameCallback .

Поскольку я применил формат UVCCamera.PIXEL_FORMAT_NV21 к UVCCamera :

uvcCamera.setFrameCallback (frameCallback, UVCCamera.PIXEL_FORMAT_NV21);

Итак, я могу получить растровое изображение просто преобразовать 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();
    }
}
...