camera2以纵向方式处理Renderscript

时间:2018-05-20 18:51:18

标签: android android-camera2 renderscript

我正在尝试一个简单的应用程序,它可以在以纵向模式锁定的camera2 repeatingrequest提供的预览帧上执行一些RenderScript处理。我试过从提供的例子开始工作,但似乎没有解决处理原始图像然后以肖像显示的问题。

图像显示旋转90度并在显示时拉伸。我曾试图应用矩阵变换来纠正这个问题,但却无法找到正确的变换来防止图像拉伸。这导致我使用TextureView,但我以前尝试过SurfaceView无济于事。

这是一个精简的应用程序,用我当前的解决方案显示我所处的位置(用硬编码值替换大量设置等)。

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;

import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    private CameraDevice mCameraDevice;
    private RenderScript mRenderScript;
    private ScriptIntrinsicYuvToRGB mScript;
    //private Size mDimensions = new Size(1024,576);
    private Size mDimensions = new Size(1280,720);
    private Allocation mScriptInputAllocation;
    private Allocation mScriptOutputAllocation;
    private CameraCaptureSession mCaptureSession;
    private TextureView mTextureView;
    private SurfaceTexture mDisplaySurface;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextureView = findViewById(R.id.textureView);
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);

        mRenderScript = RenderScript.create(this);

        Type.Builder yuvTypeBuilder = new Type.Builder(mRenderScript, Element.YUV(mRenderScript));
        yuvTypeBuilder.setX(mDimensions.getWidth());
        yuvTypeBuilder.setY(mDimensions.getHeight());
        yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
        mScriptInputAllocation = Allocation.createTyped(mRenderScript, yuvTypeBuilder.create(),
                Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);

        Type.Builder rgbTypeBuilder = new Type.Builder(mRenderScript, Element.RGBA_8888(mRenderScript));
        rgbTypeBuilder.setX(mDimensions.getWidth());
        rgbTypeBuilder.setY(mDimensions.getHeight());
        mScriptOutputAllocation = Allocation.createTyped(mRenderScript, rgbTypeBuilder.create(),
                Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);

        mScript = ScriptIntrinsicYuvToRGB.create(mRenderScript, Element.U8_4(mRenderScript));
        mScript.setInput(mScriptInputAllocation);

        mScriptInputAllocation.setOnBufferAvailableListener(mOnBufferAvailableListener);

        if((ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)){
         setUpCamera();
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
        }
    }

    @SuppressLint("MissingPermission")
    private void setUpCamera() {
        try {
            CameraManager mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
            String cameraId = null;
            String[] cameraIds = new String[0];

            cameraIds = mCameraManager.getCameraIdList();

            for (String id : cameraIds) {
                cameraId = id;
                CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id);
                Integer facing = info.get(CameraCharacteristics.LENS_FACING);
                if(facing == CameraCharacteristics.LENS_FACING_BACK)
                {
                    break;
                }
            }

            mCameraManager.openCamera(cameraId, mCameraDeviceStateCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        setUpCamera();
    }

    private void startCameraSessionIfReady(){
        if(mTextureView != null && mCameraDevice != null){
            startCameraSession();
        }
    }

    private void startCameraSession() {
        try {
            mCameraDevice.createCaptureSession(Arrays.asList(mScriptInputAllocation.getSurface()), mCameraSessionStateCallback, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void sendCaptureRequest() {
        try {
            CaptureRequest.Builder previewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            previewBuilder.addTarget(mScriptInputAllocation.getSurface());
            CaptureRequest previewRequest = previewBuilder.build();
            mCaptureSession.setRepeatingRequest(previewRequest, null, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private Allocation.OnBufferAvailableListener mOnBufferAvailableListener = new Allocation.OnBufferAvailableListener(){

        @Override
        public void onBufferAvailable(Allocation a) {
            mScriptInputAllocation.ioReceive();
            mScript.forEach(mScriptOutputAllocation);
            mScriptOutputAllocation.ioSend();
        }
    };

    private CameraCaptureSession.StateCallback mCameraSessionStateCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            Surface surface = new Surface(mDisplaySurface);
            mScriptOutputAllocation.setSurface(surface);
            mCaptureSession = session;
            sendCaptureRequest();
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {}
    };

    private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback(){
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCameraDevice = camera;
            startCameraSessionIfReady();
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {}

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {}
    };

    private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            mDisplaySurface = surface;

            //Matrix matrix = new Matrix();
            //matrix.postRotate(90, width/2f, height/2f);
            //matrix.postScale((float)width/mDimensions.getHeight(), (float)height/mDimensions.getWidth(), width/2, height/2);
            //mTextureView.setTransform(matrix);

            startCameraSessionIfReady();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {return false;}
        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
    };
}

如果有人能指出我正确的方向,我们将非常感激。

0 个答案:

没有答案