The preview image showed in surfaceview, it has bad scale。
"android:screenOrientation="landscape" has bean set.
and my device screen is 960x540. what scale proportion should I set?
Related
Intro
I'm using CaptureRequest.Builder and provide two surfaces as a target: a SurfaceTexture for drawing GL and an ImageReader (getSurface()) for processing frame.
I set desired resolution 640x480 by setting surfaceTexture.setDefaultBufferSize and by creating ImageReader.newInstance.
The problem
It appears that SurfaceTexture OpenGL texture is getting image that is of different aspect ration than 640x480 (4:3), more like 2560x1440 (16:9)(SurfaceTexture occupying full screen, see IMG 3). It has to be noted that both phones have same resolution aspect ratio 16:9. (Texture offset from the sides is left intentionally).
Below you can see IMG 1 displayed on a monitor screen, and IMG 2 and IMG 3 are phone screen captures where current activity view is showing camera preview.
The question
How to correctly force SurfaceTexture or GLSurfaceView.Renderer to get specific (4:3 in this case) aspect ratio texture image from camera for arbitrary size View?
Relevant
It has to be noted that there is an app that addresses issue, but for that they change the view size to correspond to desired aspect ratio.
See also:
GitHub repo.
Relevant source code.
Related post
Related post
IMG 1 - Displayed source image:
IMG 2 - Good aspect ratio (Google Nexus 5 - Android 6.0.1):
IMG 3 - Bad texture aspect ratio (LG-D855 - Android 5.0)
"Fixed" the issue by updating LG phone to Android 6.0.
The problem appears on my Nexus 6P device. After going through all the motions to detect optimal previews, aspect ratios, video sizes etc, I end up with the following:
SurfaceView dimens 2392x1440 (full screen)
Once re-measured with the aspect ratio of the camera preview resolution, this changes to 2560x1440 or 2392x1351 depending on the calculation method.
Camera preview size: 1920x1080
This is set on the camera params using setPreviewSize():
params.setPreviewSize(mOptimalPreviewSizes.width, mOptimalPreviewSizes.height);
Media recorder video size: 1920x1080 (forced by the settings)
This is set on the media recorder:
mMediaRecorder.setVideoSize(mOptimalVideoSize.width, mOptimalVideoSize.height);
When I click the record button, the camera preview 'zooms in', i.e. resizes to video size. If I change the video size setting to for example 3840x2160, the preview works fine with no resizing.
I was under impression that it is possible to set video size separatly to the preview size, so I'm a bit confused to why I'm seeing this and how can I work around this.
EDIT:
As an example, OpenCamera seems to be able to separate preview surface resolution from video resolution. https://sourceforge.net/p/opencamera/code/ci/master/tree/src/net/sourceforge/opencamera/
To make sure, I've added a line just before video_recorder.prepare(); to set a custom video size (video_recorder.setVideoSize(640,480);). The preview surface was still measuring near full screen at 2392x1351, and camera preview was still set to 1920x1080. I've also double checked the resulting video and it was 640x480 as expected. Unfortunately I cannot see anything in their code that would indicate how this is achieved.
EDIT 2:
I've also noticed that this 'zooming' action always happens to a specific resolution/value. Regardless of whether I'm recording at 1920x1080 or 320x200, the preview gets zoomed and looses about a cm of the picture that was available before the recording started. The end video has the expected cropping in relation to the resolution.
The problem seems to be related to the video stabilisation. I suppose this actually makes sense as stabilising against shakes usually requires cropping and when the preview resolution is already significantly lower than the surface size, it causes the picture to 'jump' or 'zoom' in. Removing video stabilisation fixes the issue.
For some reasons when I use camera setPictureSize the camera preview is become distort. Have anybody face that problem?
According to my experience there is a dependency between setPictureSize and camera preview size.
Most of tutorials like official (http://developer.android.com/reference/android/hardware/Camera.html) calculates preview size depending on actual screen size. But this won't work with actual picture size. So I now calculate optimal preview size according to selected picture size.
I would recommend to look at Android camera source code of Android 2.3 that is not so complicated: https://android.googlesource.com/platform/packages/apps/Camera.git/+/android-cts-2.3_r12
I'm writing a small android app where a user can place an image inside the live preview of the camera and take a picture of this. The app will then combine the two images appropriately -- All of this is working fine.
I understand you can get/set the PreviewSize using Camera.getParameters(), I assume this is related to the size of the realtime "camera feed".
However, the size of my SurfaceView where the camera preview is shown is different from the reported (and used) PreviewSizes. For example, in the emulator my available SurfaceView happens to be 360x215, while the PreviewSize is 320x240. Still, the entire SurfaceView is filled with the preview.
But the picture that's generated in the end is (also?) 320x240. How does android compensate for these differences in size and aspect ratio? Is the image truncated?
Or am I simply misunderstanding what the PreviewSize is about - is this related to the size of the generated pictures, or is it related to the "realtime preview" that's projected on the SurfaceView? Are there any non-trivial Camera examples that deal with this?
I need to know how what transformation takes place to, eventually, copy/scale the image correctly into the photo, hence these questions.
I am trying to figure this out myself. Here is what I found out so far..
The surface view has an internal surface called mSurface which is actually used as camera feed and the encoder feed. So this buffer has to be the actual size at which you want do the recording.
You can set the size of this mSurface to be independent of the SurfaceView by using the setFixedSize method
Now you might want to perform a HD recording so the mSurface needs to 1280x760 resolution but you SurfaceView can't be that big (Assuming you are running it on a phone with a WVGA screen). So you try to set to a smaller resolution than 1280x760 which also maintains the same aspect ratio.
Android now performs a resizing on the HD buffer to get the preview resolution, cropping is not done, it is just resized to the SurfaceView reoslutions
So at this point both the mSurface and the previewSize that you set to the camera is the same resolution and hence the resultant video recording will also be of the same resolution.
That being said I am still struggling to get my VGA recorder to work on Nexus S, it is working on a LG Maha device. :)
I'm trying to build an app that shows a preview from the camera, but only shows it in about 1/4 of the screen. I limited my SurfaceView to just that quarter, but my tests show that I'm not getting the full camera preview.
Is there a way to scale this and crop it to my specifications?