繁体   English   中英

Camera2 API中的预览图像变形

[英]Distorted preview Image in Camera2 API

我知道对此已经提出了很多问题。 我已经尝试了其中一些。 但是没有任何东西对我有用。 这是我创建预览的方式

TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {

        fetchCameraData();
        prepareSurface();
        prepareCameraDevice(cameraId);

    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) 
    {
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

    }
    };

    private void prepareCamera() {
    previewView = (AutoFitTextureView) findViewById(R.id.textureview);
    previewView.setSurfaceTextureListener(listener);
    }

    private void fetchCameraData() {

    cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
    try {

        for (String cameraID : cameraManager.getCameraIdList()) {
            cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraID);
            if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
                continue;
            }
            cameraId = cameraID;

            StreamConfigurationMap streamConfigs = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            previewSize =  Collections.max(
                    Arrays.asList(streamConfigs.getOutputSizes(ImageFormat.JPEG)),
                    new CompareSizesByArea());

            break;
        }


    } catch (CameraAccessException e) {
        e.printStackTrace();
        Toast.makeText(this, "Unable to fetch camera data", Toast.LENGTH_SHORT).show();

     }
   }

     private void prepareSurface() {

    SurfaceTexture texture = previewView.getSurfaceTexture();
    textureSurface = new Surface(texture);

    jpegReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(), ImageFormat.JPEG, 1);
    jpegSurface = jpegReader.getSurface();
    jpegReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader imageReader) {
            Image image = imageReader.acquireLatestImage();
            ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
            byte jpegBytes[] = new byte[byteBuffer.remaining()];
            byteBuffer.get(jpegBytes);
            Bitmap imageBitmap = BitmapFactory.decodeByteArray(jpegBytes, 0, jpegBytes.length);
            capturedImage = imageBitmap;
            decodeBase64Image(getBase64Image(imageBitmap));
            image.close();
        }
      }, null);
     }

     private void prepareCameraDevice(String cameraId) {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
        try {
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice cameraDevice) {
                    mCameraDevice = cameraDevice;
                    prepareCaptureSession();

                }

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

                @Override
                public void onError(@NonNull CameraDevice cameraDevice, int i) {

                }


            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
            Toast.makeText(this, "Unable to user Camera", Toast.LENGTH_SHORT).show();
        }
    } else {
        requestPermission();
    }

}

    private void prepareCaptureSession() {
    List<Surface> surfaceList = Arrays.asList(textureSurface, jpegSurface);
    try {
        mCameraDevice.createCaptureSession(surfaceList, new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                session = cameraCaptureSession;
                startCamera();

            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

            }
        }, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
        Toast.makeText(this, "Unable to create session", Toast.LENGTH_SHORT).show();


    }
}

         private void startCamera() {
    try {
        requestPreview = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        requestPreview.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        requestPreview.addTarget(textureSurface);
        session.setRepeatingRequest(requestPreview.build(), null, null);
    } catch (CameraAccessException e) {
        Toast.makeText(this, "Unable to create preview", Toast.LENGTH_SHORT).show();

    }
}

我的AutoFitTextureView类如下

public class AutoFitTextureView extends TextureView {

private int mRatioWidth = 0;
private int mRatioHeight = 0;

public AutoFitTextureView(Context context) {
    this(context, null);
}

public AutoFitTextureView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) 
{
    super(context, attrs, defStyle);
}


/**
 * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
 * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
 * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
 *
 * @param width  Relative horizontal size
 * @param height Relative vertical size
 */
public void setAspectRatio(int width, int height) {
    if (width < 0 || height < 0) {
        throw new IllegalArgumentException("Size cannot be negative.");
    }
    if (mRatioWidth == width && mRatioHeight == height) {
        return;
    }
    mRatioWidth = width;
    mRatioHeight = height;
    requestLayout();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);
    if (0 == mRatioWidth || 0 == mRatioHeight) {
        setMeasuredDimension(width, height);
    } else {
        if (width < height * mRatioWidth / mRatioHeight) {
            setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
        } else {
            setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
        }
    }
}

}

这是我的xml

 <?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="in.thoughtsmith.miinterface.MainActivity">

<Button
    android:id="@+id/scanButton"
    android:layout_width="70dp"
    android:layout_height="wrap_content"
    android:layout_alignParentEnd="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginEnd="10dp"
    android:layout_marginTop="10dp"
    android:layout_weight="1"
    android:alpha="0.50"
    android:background="@drawable/button_shape"
    android:text="Scan"
    android:textColor="@color/white" />


<in.thoughtsmith.miinterface.AutoFitTextureView
    android:id="@+id/textureview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

<ImageView
    android:id="@+id/captureImage"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    android:visibility="gone" />


<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:orientation="horizontal"
    android:weightSum="2">

    <Button
        android:id="@+id/buyButton"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="10dp"
        android:layout_marginEnd="10dp"
        android:layout_marginStart="5dp"
        android:layout_weight="1"
        android:alpha="0.5"
        android:background="@drawable/button_shape"
        android:text="Buy"
        android:textColor="@color/white" />

    <Button
        android:id="@+id/accessoriesButton"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_marginBottom="10dp"
        android:layout_marginEnd="5dp"
        android:layout_marginStart="10dp"
        android:layout_weight="1"
        android:alpha="0.5"
        android:background="@drawable/button_shape"
        android:text="Accessories"
        android:textColor="@color/white" />


</LinearLayout>


</RelativeLayout>

上面的代码使我在某些设备中的预览图像失真。 它使我在OnePlus 3T设备上的预览显示失真。

对于AutoFitTextureView,将layout_width和layout_height更改为“ wrap_content”,而不是“ match_parent”。

“ match_parent”不允许视图覆盖此处需要的大小。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM