Android Camera2 预览在风景中旋转 90 度

标签 android android-camera2

我正在关注 youtube tutorial , 尝试学习 Camera2 API。当然,我是在开发自己的应用程序的同时学习这一点的。教程和我的应用程序之间的一个不一致之处是,教程仅将相机设置为纵向模式,而我的应用程序必须处于横向模式。

我目前可以查看相机的预览,但当我的应用处于横向或水平状态时,相机预览看起来旋转了 90 度。几乎感觉我可以旋转 TextureView,但这似乎不正确,就像当我拍照时,它会被错误地旋转。

下面是与图片大小有关的代码(整个代码很长)

private void setupCamera(int width, int height) {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(camera_id);
        StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
        mCameraId = camera_id;
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}


//TODO Look for a way to make this horizontal
private Size getPreferredPreviewSize(Size[] mapSizes, int width, int height) {
    List<Size> collectorSizes = new ArrayList<>();
    for (Size option : mapSizes) {
        if (width > height) { //If the screen is in landscape
            Toast.makeText(getApplicationContext(), "Screen is Landscape", Toast.LENGTH_SHORT).show();
            if (option.getWidth() > width && option.getHeight() > height) {
                collectorSizes.add(option);
            }
        } else { //if the screen is in portrait
            Toast.makeText(getApplicationContext(), "Screen is Portrait", Toast.LENGTH_SHORT).show();
            if (option.getWidth() > height && option.getHeight() > width) {
                collectorSizes.add(option);
            }
        }
    }
    if (collectorSizes.size() > 0) {
        return Collections.min(collectorSizes, new Comparator<Size>() {
            @Override
            public int compare(Size lhs, Size rhs) {
                return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() + rhs.getHeight());
            }
        });
    }

    return mapSizes[0];
}
private void openCamera() {
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, null);
    } catch (CameraAccessException e){
        e.printStackTrace();
    }
}

private void createCameraPreviewSession() {
    try {
        SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        Surface previewSurface = new Surface(surfaceTexture);
        mPreviewCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        mPreviewCaptureRequestBuilder.addTarget(previewSurface);
        mCameraDevice.createCaptureSession(Arrays.asList(previewSurface),
                new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(CameraCaptureSession session) {
                        if(mCameraDevice == null){
                            return;
                        }
                        try {
                            mPreviewCaptureRequest = mPreviewCaptureRequestBuilder.build();
                            mCameraCaptureSession = session;
                            mCameraCaptureSession.setRepeatingRequest(mPreviewCaptureRequest, mSessionCaptureCallback, null);
                        } catch (CameraAccessException e){
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onConfigureFailed(CameraCaptureSession session) {
                        Toast.makeText(getApplicationContext(), "Preview Session Failed", Toast.LENGTH_SHORT).show();
                    }
                }, null);
    } catch (CameraAccessException e){
        e.printStackTrace();
    }
}

我一直在使用 getPreferredPreviewSize 方法,但我对它的理解并不尽如人意。我不确定最后使用 lhsrhscompare

我是否遗漏了一些简单的旋转方法?

最佳答案

private void transformImage (int width, int height)
{
    if(mPreviewSize == null || mTextureView == null)
    {
        return;
    }
    Matrix matrix = new Matrix();
    int rotation = getWindowManager().getDefaultDisplay().getRotation();
    RectF textureRectF = new RectF(0,0,width,height);
    RectF previewRectF = new RectF(0,0,mPreviewSize.getHeight(),mPreviewSize.getWidth());
    float centerX = textureRectF.centerX();
    float centery = textureRectF.centerY();

    if(rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270)
    {}
    else if(rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270)
    {
        previewRectF.offset(centerX - previewRectF.centerX(),centery-previewRectF.centerY());
        matrix.setRectToRect(textureRectF,previewRectF,Matrix.ScaleToFit.FILL);
        float scale = Math.max((float)width / mPreviewSize.getWidth(),(float)height/ mPreviewSize.getHeight());

        matrix.postScale(scale,scale,centerX,centery);
        matrix.postRotate(90*(rotation-2),centerX,centery);
        mTextureView.setTransform(matrix );

    }

关于Android Camera2 预览在风景中旋转 90 度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34536798/

相关文章:

android - ScrollView 和 layout_weight ="1"?

java - 使用随机类获取随机颜色?

安卓相机2 : the most optimal and fast way to change the output surface set on-the-fly

用于预览和 MediaCodec 输入 Surface 的 Android Camera2 管道

java - 为什么打开闪光灯会改变相机的对焦模式?

java - RecyclerView 行 onClick 和子按钮 onClick

android - 如何通过 FaSTLane 创建 aab (bundle)?

java - Android LiveData 未更新

java - Android Camera2 没有获取物理相机

Android Camera2 Renderscript 过热问题