How to rotate the camera preview to capture landscape photos in portrait mode?

I see a lot of advice from people who want to take portrait photos that tell them to rotate the camera 90 degrees. However, no matter what I'm trying to do, the only thing that actually โ€œrotatesโ€ is the image that the camera takes, however it retains the proportions of the width and the height, so the image does not get distorted if the SurfaceView is narrow and tall.

What I'm trying to achieve is to take a 4x3 photo that is NOT deformed in a 3x4 layout. I know this will be pretty narrow, but the goal is to rotate the Preview -90degrees view and still maintain the normal aspect ratio of the camera. Be that as it may, all that I tried led to the image being scratchy if I wanted to orient the photograph in my portrait.

I'm starting to suspect that I need to apply the matrix to Preview, which will rotate it -90 degrees, but I'm not sure how to do this, or if this is really the right approach. I would like to consult.

Edit: just to be clear here, the corresponding javadocs excerpt is: setPreviewSize () "If the display orientation is set to 0 or 180, the preview size should be set to 480x320. If the display orientation is set to 90 or 270 , the preview size must be set to 320x480. "

This does not completely solve the problem when you want to keep the device in portrait mode, but the camera preview appears in a small landscape window (which I am trying to achieve).

TIA

+4
source share
2 answers

If you use SurfaceView to display the output of the cameraโ€™s preview, and you want your preview to not be distorted, both in the preview mode and in the landscape, you need to make sure that the aspect ratio of your SurfaceView matches the aspect ratio of the cameraโ€™s preview size. SurfaceView simply scales the preview to fit inside itself, so if it is 500x500 and the preview size is 640x480, the preview will look stretched vertically.

Conceptually, the easiest approach is to simply manually set the width and height of the SurfaceView by updating the SurfaceView layout to a fixed size using LayoutParams and setLayoutParams . The problem with this approach is that it can be fragile with different screen sizes, since you need to figure out what pixel sizes you really want, and for a simple layout on different Android devices, you really want to think in dp instead of pixels. But for testing, you can simply force SurfaceView to have the screen width of the test device and the height set to

surface height = preview height / preview width * surface width 

The best approach would be to create a new class inherited from SurfaceView that performs the necessary aspect ratio adjustments in the onMeasure method. Explaining this in detail, you can read in detail the documentation for custom components on the Android developer site. But, roughly speaking, you need to set the width / height values, which always lead to the same aspect ratio as the size of the camera preview that you configured.

Once you get the right image in the right size, you usually also need to rotate the camera preview output using setDisplayOrientation ; Generating orientation maths can be confusing, so use the sample code provided in the documentation link above to figure it out.

Basically, there is one coordinate system in the world, the camera sensor has another (fixed on the device), and the user interface system has a third (fixed in relation to your current orientation), and all three can change relative to each other. Although the correct orientation of the preview does not depend on the position of the device relative to the world, the orientation of the pictures taken by the camera (which is setRotation ).

+3
source

My suggestion:

Donโ€™t try to use Layout on Android anymore, itโ€™s very difficult, and if you want to succeed, you have to read the open source Android code and have to change that.

So, I suggest you use Canvas (Import Graphics package) and use these classes.

-6
source

All Articles