如何在横向上将YUV转换为位图? [英] How to convert YUV to bitmap in landscape orientation?

查看:114
本文介绍了如何在横向上将YUV转换为位图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我设置 javasetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); java setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

Camera2运行正常,并从imageavailablelistener保存图像.

Camera2 is running fine and save image from imageavailablelistener.

当我设置java setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); java setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);

它将退出应用程序,并且无法保存图像

It will exit from the app and cannot save image

YUV图像到位图方法归功于

YUV Image to Bitmap method is credit to link

    private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            final Image image = reader.acquireLatestImage();
            if (image == null)
                return;
            BitmapFunctions bitmapFunctions = new BitmapFunctions();
//            QrDecoder qrDecoder = new QrDecoder();

            //Convert YUV to RGB and return bitmap
            Bitmap bitmap = bitmapFunctions.mediaImageToBitmap(image, activity);

实际转换功能

public class BitmapFunctions {
    private Allocation allocationYuv;
    private Allocation allocationRgb;
    private RenderScript rs;




    public Bitmap mediaImageToBitmap(Image image, Context context) {
        final ByteBuffer yuvBytes = imageToByteBuffer(image);

        // Convert YUV to RGB
        rs = RenderScript.create(context);

        Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
        allocationRgb = Allocation.createFromBitmap(rs, bitmap);

        allocationYuv = Allocation.createSized(rs, Element.U8(rs), yuvBytes.array().length);
        allocationYuv.copyFrom(yuvBytes.array());

        ScriptIntrinsicYuvToRGB scriptYuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
        scriptYuvToRgb.setInput(allocationYuv);
        scriptYuvToRgb.forEach(allocationRgb);

        allocationRgb.copyTo(bitmap);
        return bitmap;
    }

    public void release() {
        allocationYuv.destroy();
        allocationRgb.destroy();
        rs.destroy();
    }

    
    private ByteBuffer imageToByteBuffer(final Image image) {
        final Rect crop = image.getCropRect();
        final int width = crop.width();
        final int height = crop.height();

        final Image.Plane[] planes = image.getPlanes();
        final byte[] rowData = new byte[planes[0].getRowStride()];
        final int bufferSize = width * height * ImageFormat.getBitsPerPixel(ImageFormat.YUV_420_888) / 8;
        final ByteBuffer output = ByteBuffer.allocateDirect(bufferSize);

        int channelOffset = 0;
        int outputStride = 0;

        for (int planeIndex = 0; planeIndex < 3; planeIndex++) {
            if (planeIndex == 0) {
                channelOffset = 0;
                outputStride = 1;
            } else if (planeIndex == 1) {
                channelOffset = width * height + 1;
                outputStride = 2;
            } else if (planeIndex == 2) {
                channelOffset = width * height;
                outputStride = 2;
            }

            final ByteBuffer buffer = planes[planeIndex].getBuffer();
            final int rowStride = planes[planeIndex].getRowStride();
            final int pixelStride = planes[planeIndex].getPixelStride();

            final int shift = (planeIndex == 0) ? 0 : 1;
            final int widthShifted = width >> shift;
            final int heightShifted = height >> shift;

            buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));

            for (int row = 0; row < heightShifted; row++) {
                final int length;

                if (pixelStride == 1 && outputStride == 1) {
                    length = widthShifted;
                    buffer.get(output.array(), channelOffset, length);
                    channelOffset += length;
                } else {
                    length = (widthShifted - 1) * pixelStride + 1;
                    buffer.get(rowData, 0, length);

                    for (int col = 0; col < widthShifted; col++) {
                        output.array()[channelOffset] = rowData[col * pixelStride];
                        channelOffset += outputStride;
                    }
                }

                if (row < heightShifted - 1) {
                    buffer.position(buffer.position() + rowStride - length);
                }
            }
        }

        return output;
    }

错误

2019-06-19 17:04:47.551 23356-23423/com.dsonic.datasonicscanner E/AndroidRuntime: FATAL EXCEPTION: CameraBackground
    Process: com.dsonic.datasonicscanner, PID: 23356
    java.lang.IllegalStateException: buffer is inaccessible
        at java.nio.DirectByteBuffer.get(DirectByteBuffer.java:219)
        at com.dsonic.dsoniccamera2lib.Camera2.BitmapFunctions.imageToByteBuffer(BitmapFunctions.java:105)
        at com.dsonic.dsoniccamera2lib.Camera2.BitmapFunctions.mediaImageToBitmap(BitmapFunctions.java:36)
        at com.dsonic.dsoniccamera2lib.Camera2.Camera2Manager$4.onImageAvailable(Camera2Manager.java:302)
        at android.media.ImageReader$ListenerHandler.handleMessage(ImageReader.java:812)
        at android.os.Handler.dispatchMessage(Handler.java:108)
        at android.os.Looper.loop(Looper.java:166)
        at android.os.HandlerThread.run(HandlerThread.java:65)

ctrl+f查找错误行

BitmapFunctions.java:105是channelOffset + = outputStride;

BitmapFunctions.java:105 is channelOffset += outputStride;

BitmapFunctions.java:36是位图bitmap = Bitmap.createBitmap(image.getWidth(),image.getHeight(),Bitmap.Config.ARGB_8888);

BitmapFunctions.java:36 is Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);

Camera2Manager.java:302是位图位图= bitmapFunctions.mediaImageToBitmap(image,activity);

Camera2Manager.java:302 is Bitmap bitmap = bitmapFunctions.mediaImageToBitmap(image, activity);

现在一切正常,相同的代码不变.使用相同的电缆,但电话今天早晨重新启动并添加了Log.e("Image Size", "Width = " + image.getWidth() + " Height = " + image.getHeight());.

Everything run fine now, same code nothing change. Using same cable but phone is restarted this morning and added Log.e("Image Size", "Width = " + image.getWidth() + " Height = " + image.getHeight());.

我将其注释掉后,它又自动退出了我的视线.现在,我删除了该评论,它不再起作用. WTF?

After I comment it out it auto exit on me again. Now I remove the comment, it can't work again. WTF?

有人可以向我解释吗?

推荐答案

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR)而不是进行设置.

将其更改为强制在清单中定向.不知道为什么这样工作

Change it to force orientation in Manifest. Don't know why this work

希望有人可以向我解释.

Hope someone can explain to me.

这篇关于如何在横向上将YUV转换为位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆