-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: switch width and height of target resolution if portrait for Android #833
Conversation
What happens when the user rotates his phone after the Camera has been initialized? |
In my case, the camera still works in the specified resolution. |
In the docs, it says that the resolution Size should be expressed in the coordinate frame after rotating the supported sizes by the target rotation: https://developer.android.com/reference/kotlin/androidx/camera/core/ImageAnalysis.Builder#setTargetResolution(android.util.Size) |
FWIW I've been using a hack which shares similarities with what @xulihang proposes. https://gist.github.com/ldstein/bf8b88fabc27617dca891aa3be58f9d7 Seemed to get me out of trouble for the limited devices I have on hand. I noticed in this PR, An alternative would be to reference context.resources.configuration.orientation as this will inform us explicitly if the device is currently in Landscape or Portrait.
As @xulihang mentions, it appears to work. Maybe under the hood it's already flipping it around when I do wonder however if |
In the docs: https://developer.android.com/training/camera2/camera-preview-large-screens#camera-orientation, it says that the camera sensor’s natural orientation is landscape. |
In the above link it states:
If you have an Android tablet which is naturally landscape orientated, this logic I think will incorrectly set the wrong resolution: // Asume:
// Device Rotation: 0
// Device Screen Size: 1024x768
// Camera Sensor Orientation: Landscape (same as screen)
// format.videoSize.width:1024
// format.videoSize.height: 768
if (getDisplay().rotation == Surface.ROTATION_0) {
val newWidth = format.videoSize.height // 768
val newHeight = format.videoSize.width // 1024
targetPreviewResolution = Size(newWidth, newHeight) // resolution is incorrectly set to portrait I think that's why my original hack fixed the resolution for phones, but did not work on @viljark's TB-X505L tablet.
// Asume:
// Device Rotation: 0
// Device Screen Size: 1024x768
// Camera Sensor Orientation: Landscape (same as screen)
// format.videoSize.width:1024
// format.videoSize.height: 768
val videoSize = when (context.resources.configuration.orientation) {
Configuration.ORIENTATION_PORTRAIT -> Size(format.videoSize.height, format.videoSize.width) // resolution is set to portrait
else -> format.videoSize // resolution is set to landscape
} Having said all this, I'm no expert, so happy to be proven wrong :) |
Using orientation seems a better solution. I also find a page on detecting the natural orientation: http://www.java2s.com/example/android/user-interface/get-device-natural-orientation.html |
I've updated the code to use orientation. |
@@ -410,9 +411,15 @@ class CameraView(context: Context, private val frameProcessorThread: ExecutorSer | |||
// User has selected a custom format={}. Use that | |||
val format = DeviceFormat(format!!) | |||
Log.i(TAG, "Using custom format - photo: ${format.photoSize}, video: ${format.videoSize} @ $fps FPS") | |||
previewBuilder.setTargetResolution(format.videoSize) | |||
val videoSize:Size | |||
if (context.resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, thanks again for the PR.
Unfortunately I am still not quite sure if I understand this correctly, doesn't this only check the "locked" Orientation in AndroidManifest? What if the user is holding his phone in portrait, then going to landscape? And then going back to portrait? Is it still the correct resolution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I read the docs correctly, context.resources.configuration.orientation
returns the device's current orientation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but can we use outputOrientation
instead of context.resources.configuration.orientation
here? I already detect orientation in this class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
outputRotation
is referencing context.displayRotation
. That tells us how many degrees the device is rotated from it's natural position but I believe we cannot assume zero rotation is portrait.
context.resources.configuration.orientation
differs as it tells us explicitly whether the device is currently being viewed in portrait or landscape.
Similarly, there maybe an issue here in the outputRotation getter. Portrait would only equal Surface.ROTATION_0 for naturally-portrait devices:
private val outputRotation: Int
get() {
if (orientation != null) {
// user is overriding output orientation
return when (orientation!!) {
"portrait" -> Surface.ROTATION_0
"landscapeRight" -> Surface.ROTATION_90
"portraitUpsideDown" -> Surface.ROTATION_180
"landscapeLeft" -> Surface.ROTATION_270
Also not 100% sure on this, but maybe imageAnalysis.targetRotation
should be the same as preview.targetRotation
? Keeps the analysis results 1:1 with the preview (when drawing overlays, for example).
I can see the use of the 'orientation' prop to affect photo / video output, but maybe should be independent to modifying the frame processor rotation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot find outputOrientation
. There is orientation
which is a string
and outputRotation
which is an integer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, typo on my end. I fixed up my earlier post. I meant outputRotation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay guys thanks for the insights. I will test this some time this week and then merge the PR if everything works in every use-case :)
Would be helpful if anyone could help me with testing, with various devices and various orientations (e.g. start with landscape or portrait, then rotate)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use `ImageProxy.imageInfo.rotationDegrees` to apply the appropriate rotation to the image in order to align the orientation of the image with the target orientation. Potential alternative to mrousavy#833
Use `ImageProxy.imageInfo.rotationDegrees` to apply the appropriate rotation to the image in order to align the orientation of the image with the target orientation. Potential alternative to mrousavy#833
Use `ImageProxy.imageInfo.rotationDegrees` to apply the appropriate rotation to the image in order to align the orientation of the image with the target orientation. Potential alternative to mrousavy#833
Use `ImageProxy.imageInfo.rotationDegrees` to apply the appropriate rotation to the image in order to align the orientation of the image with the target orientation. Potential alternative to mrousavy#833
Camera formats and everything related to it are are completely wrong.
how all of this is even possible :| |
Hey, thanks for your PR and sorry for the long radio silence here! width and height are swapped because Camera sensors are in 90deg orientation. Orientation is now tracked in this issue: #1891 |
What
This PR fixes the incorrect resolution setting for Android.
Changes
switch height and width of target resolution if portrait for Android
Tested on
Sharp S2, Android 8
Related issues
#770
#325
#281