Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Camera2 Preview is rotated 90deg while in Landscape

I was following a youtube tutorial, trying to learn Camera2 API. Of course, I was learning this at the same time that I was developing my own app. One inconsistency between the tutorial and my app is that the tutorial made the camera in portrait mode only while my app must be in landscape.

I'm currently able to view the preview of the camera, though while my app is in landscape or horizontal, the camera preview looks rotated 90 degrees. It almost feels like I can rotate the TextureView, but that just seems incorrect, like when I take a picture, it will be rotated incorrectly.

Below is the code that has to do with image sizes (the whole code is very long)

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

I've been playing with the getPreferredPreviewSize method, but I don't understand it as well as I should. I'm not sure about the compare at the end of that using lhs and rhs.

Am I missing something simple to have this rotated?

like image 703
ntgCleaner Avatar asked Dec 30 '15 20:12

ntgCleaner


People also ask

How do I change camera preview orientation on Android?

The image must be rotated 270 degrees counterclockwise so that the preview's orientation matches the device orientation: A back-facing camera would produce an image buffer with the same orientation as the buffer above, but SENSOR_ORIENTATION is 90 degrees. As a result, the buffer is rotated 90 degrees clockwise.

What is camera preview in android?

PreviewView is a subclass of FrameLayout . To display the camera feed, it uses either a SurfaceView or TextureView , provides a preview surface to the camera when it's ready, tries to keep it valid as long as the camera is using it, and when released prematurely, provides a new surface if the camera is still in use.

What is Camera2 API Android?

Camera2 is the latest low-level Android camera package and replaces the deprecated Camera class. Camera2 provides in-depth controls for complex use cases, but requires you to manage device-specific configurations. You can read about specific Camera2 classes and functions in the reference documentation.


1 Answers

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

    }
like image 88
Alma González Avatar answered Nov 07 '22 01:11

Alma González