I'm using Camera that comes from expo package and I'm having trouble with camera view distortion. My phone has 2:1 ratio, which is non-standard.
When I use getSupportedRatiosAsync method of the camera, I get all kinds of ratios like 1:1, 2:1, 4:3, 16:9, however only 2:1 looks good.
How can I select a ratio that fits device's natural resolution? Is there a way, to access device's preferred ratio? Or is there any hack around it, like always selecting 16:9 and having the camera component add black margins, where the actual device's ratio is not fitting the 16:9?
EDIT:
My phone resolution is 2196x1080, therefore correct ratio should be 2:1. But I'm unable to come up with a function that would compute 2196x1080=>2:1, since (2 * 1080) !== 2196
Is there any way how to infer best possible ratio even for such stupid resolutions?
On Samsung S9, the screen aspect ratio of 18.5:9 is very close to 2:1. And if you don't hide the navigation bar, the area devoted to your camera preview is probably even closer to the suported 2:1.
But if you want this to work on all devices with their different screen aspect ratios and different supported camera aspect ratios, you must crop the preview to your window, see e.g. https://github.com/waitopiggu/rn-camera-android-cropping-test.
As for choosing the best camera aspect ratio, you are right that exact match may not be acvailable; let's find the one that is closest to what we want:
const wantedRatio = height/width
var bestRatio = 0;
var bestRatioError = 100000;
for (i in ratios) {
const r = ratios[i].split(":")
if (abs(wantedRatio - r[0]/r[1]) < bestRatioError) {
bestRatioError = abs(wantedRatio - r[0]/r[1])
bestRatio = ratios[i]
}
}
this.setState({
bestRatio
})
Related
This question must have been asked here before, but I can't find a proper explaining answer.
So I'm a new unity3d programmer who knows about C#. Now, I selected my canvas size to 854x480 and tested the scene on moto g, samsung tabs etc. They all look same and I wonder why. Because if I design for 854x480, shouldn't I get blue bars on high-res phones?
Another question is, how do I design it so that it looks all the same on different devices. In my case, 854x480 does look zoomed a little on a kindle fire.
Please provide a conceptual answer.
The concept behind this is the aspect ratio and scale factor.
Aspect ratio = width / height
If you run your game in any device with the same aspect ratio then your game will look exactly same because the scale factor for height and width is same.
In your case,Aspect ratio = 480/854 = 0.562
If you run your game on Moto G(1st Gen) which has a resolution of 1280 x 720(In portrait),
Aspect ratio = 720/1280 = 0.562 which is same as your canvas's aspect ratio so the scale factor for width and height will be same.
Now if you run your game on kindle fire, which has a resolution of 1280 x 800,
Aspect ratio = 800/1280 = 0.625 which is not same as your canvas's aspect ratio. So the scale factor(which unity will automatically calculate) will be different for width and height(In your case, scale factor of height will be more) and hence your assets will look a little zoomed in height.
Hope it explains the concept.
The thing is that the camera rendering frame changes based on resolution, so instead of "blue bars" you get extra rendered image that is displayed instead of it, as for the UI goes, since it can't render extra UI (there is no extra UI, everything has to be shown) it changes position and scale of elements by using anchors. You can change these setting when selecting Canvas and changing values in the inspector.
I am trying to make my 1st game in unity. I need to support different resolutions of android and iOS. The problem is when i place the background image for any one res ex. 1536x2048,It doesn't displays properly for 640x960. The screen size is varying, but sprites and bg sprite is not scaling as per res.
I am not clear how to acheive it. But, it must be a basic thing as there are so many games on android and all phones have different res. and dpi.
There should be some formula or we just need to set orthographic.size for this. I am using this :
// to calc size
Camera.main.orthographicSize = Screen.currentResolution.height / (2*70); //
Camera.main.orthographicSize = Screen.currentResolution.height / 2;
Debug.Log("Camera size :" + Camera.main.orthographicSize);
Debug.Log("Width : " + Screen.currentResolution.width + " height : " + Screen.currentResolution.height);
// this doesnt give me width and height as per resolution of screen for ex. for 1536x2048 -> i get, Width : 1366 height : 768
i found this as similar question
http://forum.unity3d.com/threads/orthographic-screen-size.113641/ but it didnt help, whereas problem is nearly same.
If somebody can share how to get correct screen resolution by code and how to set width of bg sprite and other sprite, it can solve the problem OR
if there is some setting which takes the default scene and scales automatically for various resolution. it will help.
Unity does not scale like that. Instead, we design assets to suit our needs. You are using a formula but i don't know what you expect from it.
here's some info: Orthographic size is height of view port. Taking your example, for height of 2048, camera size is : 2048/2/100=10.24. This will be maintained irrespective of device screen size. Only difference being it will be less detailed on smaller devices, kind of like a zoom out effect. Now for width,i'm not sure for portrait, but let's say 9:16 is the widest. So if you design the bg for this aspect ratio, the bg will be cropped on smaller devices, shown full on 9:16 devices. To design for this aspect ratio, your bg needs to be 9/16*10.24*100=576 px. (Again i'm not sure which aspect ratio is widest in portrait mode). Hope that helps
I have a SurfaceView to display a live camera preview image in my Android app. The SurfaceView covers the whole width of the portrait screen, and a portion of the screen height.
I tried setting various preview sizes, so the preview had a distorted aspect ratio, short and fat or tall and skinny.
I printed debugs showing the actual preview display size, and the available preview camera sizes, so I could work out the aspect ratio error.
Screen size available for preview: w*h:1200*1646; Aspect ratio: 0.73
Rotation: 0; finalCameraRotation: 90; sideways: true
Supported Preview size: w*h:1080*1920: AspectRatio: 0.56: Error: -22.84%
Supported Preview size: w*h:768*1280: AspectRatio: 0.60: Error: -17.70%
...
Usually, I would pick the preview size with the lowest error in aspect ratio, but I was experimenting.
List<Camera.Size> ss = parameters.getSupportedPreviewSizes();
...
Camera.Size s = ss.get(pickOne);
parameters.setPreviewSize(s.width, s.height);
...
camera.setParameters(parameters);
...
camera.startPreview();
I measured the aspect ratio error of the preview display by pointing the camera at a white square and screenshotting it using Eclipse, then measuring the image of the white square in the screenshot using the photoshop ruler tool:.
I measured the x and y size of the square in screen pixels and computed 1-(y/x), and that should be the same as the aspect ratio error predicted in the debug log above.
I tried this on
Alcatel 995, Android 4.0.4
Samsung Note 2, Android 4.4.2
Google Nexus 7, Android 4.4.4
Google Nexus 5, Android 5.0
with various aspect ratios, as much as 25% in error from square, and in all of these, I measured aspect ratios in the preview within about 1% of that predicted. (There are errors, the camera might be not straight-on, it might be a bit out of focus...)
Except for the Google Nexus 7.
No matter what preview size I set for the Nexus 7, the measured aspect ratio was about 2% too tall, which just happens to be the best possible aspect ratio available:
Supported Preview size: w*h:768*1024: AspectRatio: 0.75: Error: 2.87%
It's as though some other program was coming and fixing the optimal preview size after I set it. I actually put in code to wait 10 seconds and read back the preview size from the camera, and it was the one I set, yet the display didn't reflect that. The display is always optimal no matter what preview size I set.
Is there something weird about preview sizes on Nexus 7?
I know that my setPreviewSize is doing something, because I can set the preview to 144*176px and then I see odd upsampling pixellation artefacts in the display. But it still has the nearly-corrrect aspect ratio!
I've just stumbled upon this problem myself. Reportedly, this happens to some devices, when camera's picture size and preview size parameters have different aspect ratios. In my case, my Nexus 7 appeared to always use a 4:3 preview, no matter what I'd set. Also, getPreviewSize() reported the size I'd set, not the one really used.
The solution is to find a picture size with an aspect ratio matching preview's one. So, get a list of supported picture sizes with getSupportedPictureSizes(), choose one with a proper width/height ratio and then setPictureSize(int width, int height). It worked for me like a charm :)
No matter what preview size I set for the Nexus 7, the measured aspect ratio was about 2% too tall, which just happens to be the best possible aspect ratio available:
Supported Preview size: w*h:768*1024: AspectRatio: 0.75: Error: 2.87%
[…] Is there something weird about preview sizes on Nexus 7?
Answer: yes, there's something weird …
The bug of the Nexus 7 is that all its preview sizes contain 4:3 image data, stretched to the size of the preview frames. In other words: The content of Nexus 7 viewfinder frames is always what you'd get by scaling a 1920×1440 px image1 (4:3) non-proportionally to the selected live camera preview size. Which means scaling by stretching as necessary, without cropping anything off.
Now here's why you observed the behaviour described in the question: by chance, your 1646×1200 of available screen space is nearly 4:3. So scaling the 4:3 image data provided by the Nexus 7 to that size will always result in the low aspect ratio error observed (2.87%). The intermediate step of scaling to preview size does not change anything, as it is undone by the following scaling to the available screen size.
It's a bug
You were lucky that your available screen size is 4:3, leading to proper previews from the Nexus 7. Everyone else however will fight with the fact that previews from Nexus 7 displayed in their indicated, natural size will appear distorted.
For example: the Nexus 7 reports many available preview sizes with aspect ratio that is not 4:3; let's take 1920×1080 (aspect ratio 1.78). Displaying the 4:3 frame content in a 1920×1080 rectangle then leads to stretched images.
So definitely there is a bug in the preview behaviour of the Nexus 7. The error seems to be that the 4:3 previews are meant for still images and 19:10 previews for video images, but the frames then erroneously always contain 4:3 image data. Or the other way around: the camera reports both types of preview sizes while its current mode only allows either 4:3 or 19:10 previews.
Workaround
There must be a proper way to work around this, as the Nexus 7 native camera app in video mode provides a 19:10 preview without distortions (means, it does not contain 4:3 image data).
As reported by #fljau in the other answer, setting the camera's still image capture resolution to match the aspect ratio of your selected preview will fix the issue. You can then display the camera live preview in its natural, reported size and will see no distortions of circular objects on the screen.
I just did this in Qt QML as follows:
Camera {
imageCapture {
resolution: "1920x1080"
}
viewfinder.resolution: "1920x1080"
}
It is not necessary to set Camera { captureMode: CaptureStillImage } for this to work. The still image resolution will affect the preview image data for any captureMode as a side effect (making it more clear that this is indeed a bug).
For a generic, model-independent solution in QML, you could go through the available viewfinder resolutions and then through the available still image resolutions and then set imageCapture.resolution as above to a value that matches the largest (resp. your desired) viewfinder resolution in aspect ratio.
Alternative workarounds
When you know the actual aspect ratio of the data inside the preview frames, you could show your camera live preview non-proportionally scaled to match this aspect ratio. Basically what the question author did accidentally (within a 2.87% error margin).
I also tried setting capture mode to "video" in the hopes that it will lead to 19:10 "video style" preview frame content does not work though. (For reference, I tried it in Qt QML with Camera { captureMode: Camera.CaptureVideo }.) That did not work.
1 A 1920×1440 px image is simply a 4:3 image large enough to cover the maximum supported preview size of 1920×1080 px. I made that size up for the sake of the argument so that scaling will not lose pixels you'd see in the preview.
I am currently using the Orthographic Camera. Before I get too much into the game, I want to fix the screen size first. Currently, I have the screen size set for 800 x 480. Will this work well on other devices and screen sizes? Right now all I have is a splash screen and game screen. What lines of code would I have to add to achieve this.
Having a static width on your camera is perfectly ok as it gives your game a single fixed dimension that you can work with reliably. This works because the camera is used to define world coordinates which are not always one to one with screen coordinates.
Your issues come from the fixed camera height. Having a fixed height will cause your screen to stretch taller or shorter depending on the aspect ratio of the device screen. If you want to account for the different aspect ratios, you'll need to multiply your camera height (currently 480) by the display ratio. You can get the screen ratio by dividing the height by the width by the height. This would look something like:
float width = Gdx.graphics.getWidth();
float height = Gdx.graphics.getHeight();
OrthographicCamera camera = new OrthographicCamera(800, 480 * (height / width));
As pointed out by BennX in the comments, LibGDX introduced viewports which allow you do very much the same thing as above, just in a different way. To achieve the same effect as I outlined above, only using a viewport, you'd use an ExtendViewport. What this does is maintain the world size in one direction while stretching it in the other direction. So the world will first scale up to fill the screen, then the shorter dimension is expanded while maintaining aspect ratio. To create this type of viewport, it'd look something like this:
OrthographicCamera camera = new OrthographicCamera(800, 480);
ExtendViewport viewport = new ExtendViewport(800, 480, camera);
The viewport above will have a minimum width of 800 and a minimum height of 480. One of these values will be the same after the viewport is applied and the other will change based on the aspect ratio of the screen. More narrow screens will have more vertical space while wider screens will have more horizontal space. For more on viewports, visit the LibGDX wiki page here.
I am using below approach and it's works for almost all screen sizes with ignoble minor scaling issue.
I always uses graphics images for screen size 1920.0x1080.0
ScreenViewport screenViewport=new ScreenViewport(camera);
screenViewport.setUnitsPerPixel(Math.min(1920.0f/Gdx.graphics.getWidth(),1080.0f/Gdx.graphics.getHeight()));
Here you can set your approach from Math.min() or Math.max().
It will result your camera view-port size near to 1920.0*1080.0
Device screen-size Math.max() Math.max()
800.0x480.0 1800.0x1080.0 1920.0x1152.0
1920.0x1080.0 1920.0x1080.0 1920.0x1080.0
2048.0x1440.0 1536.0x1080.0 1920.0x1350.0
Note: Always use camera.viewportWidth and camera.viewportHeight for set positions of Games UI screens.
Google Nexus 7 is a 800x1280 px tablet (not counting the system 75/64 px bars height).
But when i take a picture with a camera app, the resulting pic dimensions are 960x1280.
There is no magnification set in the camera preferences.
Wondering what gives. If i have to render this picture on the screen and i scale it and maintain the aspect ratio, won't it clip some information from the original height?
Thanks.
I'm not sure why you expect the resolution of the picture you take to be the same as the screen. When you take a picture with a regular digital camera you don't expect it to match up with it's screen right? The screens on most digital cameras are pretty low resolution.
So yes, if your picture and screen are different aspect ratios, then if you scale it up either you will clip areas or have empty bars on the side.