I've been following the Camera2 example (android/camera-samples/Camera2Video) to create an abstraction over the Camera2 library. The idea of my abstraction is to give the user the ability to use a Camera view from React Native, so it's just a <Camera>
view which can be whatever size/aspect ratio.
While this works out of the box on iOS, I can't seem to get the preview on Android to display "what the camera sees" in the correct aspect ratio.
The official example from Android works like this:
- They create a custom
SurfaceView
extension that should automatically fit to the correct aspect ratio (see: AutoFitSurfaceView
)
- They use that
AutoFitSurfaceView
in their layout
- They add a listener to the
AutoFitSurfaceView
's Surface
to find out when it has been created (source)
- Once the
Surface
has been created, they call getPreviewOutputSize(...)
to get the best matching camera preview size (e.g. so you don't stream 4k for a 1080p screen, that's wasted pixels)
- Then they pass the best matching camera preview size to the
AutoFitSurfaceView::setAspectRatio(...)
function
- By knowing the desired aspect ratio, the
AutoFitSurfaceView
should then automatically perform a center-crop transform in it's onMeasure
override
If you read the source code of their getPreviewOutputSize(...)
function, you might notice that this uses a Display
to find the best matching preview size. If I understood the code correctly, this would only work if the camera preview (AutoFitSurfaceView
) is exactly the same size as the device's screen. This is poorly designed, as there are lots of cases where that simply isn't true. In my case, the Camera has a bit of a bottom spacing/margin, so it doesn't fill the screen and therefore has weird resolutions (1080x1585 on a 1080x1920 screen)
With that long introduction, here comes my question: How do I actually perform a correct center crop transform (aka scaleType = CENTER_CROP
) on my SurfaceView? I've tried the following:
- Set the size of my SurfaceView using
SurfaceHolder::setFixedSize(...)
, but that didn't change anything at all
- Remove their
getPreviewOutputSize(...)
stuff and simply use the highest resolution available
- Use the Android View properties
scaleX
and scaleY
to scale the view by the aspect-ratio difference of the view <-> camera input scaler size (this somewhat worked, but is giving me errors if I try to use high-speed capture: Surface size 1080x1585 is not part of the high speed supported size list [1280x720, 1920x1080]
)
Any help appreciated!
question from:
https://stackoverflow.com/questions/65682233/camera2-make-surfaceview-aspect-fit-to-fill-scaletype-center-crop 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…