Full-screen Android texture preview with correct aspect ratio

I worked with camera2 api demo from google and, unfortunately, the sample application was built to display the texture preview at about 70% of the screen height, after inspecting I was able to determine that this is due to the fact that AutoFitTextureView overrides the onMeasure() method, as shown below:

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

I tried to fix this by setting the correct heights and widths in setMeasuredDimension(width, height); , this fixed a problem with the height and provided me with a full-screen preview from a texture image, however, the aspect ratio is completely broken and distorted on each device, what is the standard way to fix it? I see that many applications in the game store have found a way to solve this problem, but havent been able to track the fix, any help will go a long way, thanks.

+12
source share
4 answers

I managed to fix the problem by switching setMeasuredDimension ();

  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(height * mRatioWidth / mRatioHeight, height); } else { setMeasuredDimension(width, width * mRatioHeight / mRatioWidth); } } 
+17
source

I will let you under the code that we used to measure the preview, which supports preview sizes of 4: 3, 16: 9 and 1: 1. The height is scaled because the application is a block in the portrait; it does not rotate toward the landscape.

Hope this helps you or someone else with the same problem!

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); Log.d(TAG, "[onMeasure] Before transforming: " + width + "x" + height); int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation(); boolean isInHorizontal = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation; int newWidth; int newHeight; Log.d(TAG, "[onMeasure] Get measured dimensions: " + getMeasuredWidth() + "x" + getMeasuredHeight()); if (isInHorizontal) { newHeight = getMeasuredHeight(); if (mAspectRatioOneOne) newWidth = getMeasuredHeight(); else newWidth = (int) (newHeight * mAspectRatio); } else { newWidth = getMeasuredWidth(); if (mAspectRatioOneOne) newHeight = getMeasuredWidth(); else newHeight = (int) (newWidth * mAspectRatio); } setMeasuredDimension(newWidth, newHeight); Log.d(TAG, "[onMeasure] After transforming: " + getMeasuredWidth() + "x" + getMeasuredHeight()); } 
+2
source

I had a similar problem when using Camera2. I used the implementation of TextureView in AutoFitTextureView as a preview from the camera and want to adjust the aspect ratio. My problem came from different method implementations and extended to onSurfaceTextureSizeChanged. [1] com.google.android.cameraview.CameraView # onMeasure (..) โ†’ [2] com.google.android.cameraview.AutoFitTextureView # onMeasure (..) โ†’ [3] onSurfaceTextureSizeChanged (..)

The problem is that it is different if [1] than in [2]. I replaced in [1]:

 if (height < width * ratio.getY() / ratio.getX()) { 
from

before

 if (!(height < width * ratio.getY() / ratio.getX())) { 

because [2] has, if based on width, not height

  if (width < height * mRatioWidth / mRatioHeight) { 

Check if the onMeasure (..) methods are implemented correctly.

Or you could do like Edmund Rojas - above

+1
source

If you need a full-screen, undistorted preview, then you need to choose a preview resolution for the camera that matches the aspect ratio of the screen.

However, if the screen size is not standard (mainly 16: 9 or 4: 3), especially after subtracting the soft buttons and the notification panel (provided that you are not completely full screen), then the only option to preview the screen is to cut some of them.

You should be able to modify the TextureView transformation matrix to remove distortion by looking at the width and height of the view, as well as at the selected width and height of the preview, but this will definitely disable some of them.

0
source

All Articles