Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter camera appears stretched

I've been playing around with flutter an i'm loving it so far, but I'm having an issue getting the camera working.

I follow the directions on this page https://pub.dartlang.org/packages/camera and it works. However, the camera is stretched so that it fits the phone screen, but the image is warped and taller than it should be. Other apps which use the camera seem to keep it in proportion, is there a way to ensure that it doesn't get stretched but still fills the screen?

like image 294
Angus Allman Avatar asked Apr 20 '18 16:04

Angus Allman


People also ask

How do I change the camera preview size in flutter?

The way I solve it is very simple. return Stack( children: [ Container( width: double. infinity, height: double. infinity, child: CameraPreview(_cameraController)) ], );

What is aspect ratio flutter?

Since the height is fixed at 100.0 in this example and the aspect ratio is set to 16 / 9, the width should then be 100.0 / 9 * 16. To create a local project with this code sample, run: flutter create --sample=widgets.AspectRatio.1 mysample.

What is camera preview in flutter?

A Flutter plugin for controlling the camera. Supports previewing the camera feed, capturing images and video, and streaming image buffers to Dart.


2 Answers

Building upon the solution by lase, this works even when the aspect ratio of the device is different then the camera ratio:

final size = MediaQuery.of(context).size; final deviceRatio = size.width / size.height; return Transform.scale(   scale: controller.value.aspectRatio / deviceRatio,   child: Center(     child: AspectRatio(       aspectRatio: controller.value.aspectRatio,       child: CameraPreview(controller),     ),   ), ); 
like image 60
Marek Lisý Avatar answered Sep 16 '22 12:09

Marek Lisý


UPDATE: version v0.7.0 of the camera package introduced a breaking change for calculating camera aspectRatio and it seems they add the AspectRatio widget by default

Well, inspired by previous posts, I got it to work on 2 screens with different screen aspect ratios. What I did was print the values and look for differences (not quite what you'd call an educated approach). What came out of that was that one screen was taller than the other, although the same width so the screen aspect ratio is different.

Disclaimer: This was tested in an app locked to portrait orientation, no guaranty that this will work in landscape orientation. Also, it seems that this does put some of the camera preview pixels outside the screen, but at the moment I have no remedy for that.

No matter which camera resolution was selected, the camera controller aspect ratio stayed the same, but the screen aspect ratio differed so the calculations mentioned in older posts than this one worked for one (shorter) screen but not the other (taller).

After some long calculations it became apparent that, to fill the screen, the scale factor has to be greater than 1. So, in the end, to get the scale to work on both screens, there needs to be a check if one ratio is greater than the other and switch operands, to get a scale factor greater than 1, accordingly.

TL;DR

Here is what was changed and end result:

Calculation

1. Camera package version v0.7.0 and above

  Widget cameraWidget(context) {     var camera = _cameraController.value;     // fetch screen size     final size = MediaQuery.of(context).size;              // calculate scale depending on screen and camera ratios     // this is actually size.aspectRatio / (1 / camera.aspectRatio)     // because camera preview size is received as landscape     // but we're calculating for portrait orientation     var scale = size.aspectRatio * camera.aspectRatio;      // to prevent scaling down, invert the value     if (scale < 1) scale = 1 / scale;      return Transform.scale(       scale: scale,       child: Center(         child: CameraPreview(_cameraController),       ),   ); } 

2. Older versions - v0.6.6 and below

  Widget cameraWidget(context) {     // get screen size     final size = MediaQuery.of(context).size;      // calculate scale for aspect ratio widget     var scale = _cameraController.value.aspectRatio / size.aspectRatio;      // check if adjustments are needed...     if (_cameraController.value.aspectRatio < size.aspectRatio) {       scale = 1 / scale;     }      return Transform.scale(       scale: scale,       child: Center(         child: AspectRatio(           aspectRatio: _cameraController.value.aspectRatio,           child: CameraPreview(_cameraController),         ),       ),     );   } 

Results

NOTE: results below are valid only for versions below 0.7.0 but the concept is the same

Notice that the scale has to be greater than 1 to fill the whole screen.

  1. taller screen with above calculation
Screen size (w/h): Size(411.4, 797.7) Screen size aspect ratio: 0.515759312320917 Controller preview size: Size(1280.0, 720.0) Controller aspect ratio: 0.5625 Scale: 1.0906249999999997 
  1. shorter screen with above calculation
Screen size (w/h): Size(411.4, 683.4) Screen size aspect ratio: 0.6020066889632107 Controller preview size: Size(1280.0, 720.0) Controller aspect ratio: 0.5625 Scale: 1.0702341137123745 
  1. shorter screen without above calculation
Screen size (w/h): Size(411.4, 683.4) Screen size aspect ratio: 0.6020066889632107 Controller preview size: Size(1280.0, 720.0) Controller aspect ratio: 0.5625 Scale: 0.934375 
like image 43
rexxar Avatar answered Sep 18 '22 12:09

rexxar