颤动相机显得拉长

Ang*_*man 6 camera android-camera dart flutter

到目前为止,我一直在四处奔波,我很喜欢它,但是我有一个问题让相机正常工作.

我按照此页面上的说明https://pub.dartlang.org/packages/camera进行操作.但是,相机被拉伸以适应手机屏幕,但图像翘曲并且比应有的高.其他使用相机的应用程序似乎保持比例,有没有办法确保它不会拉伸但仍然填满屏幕?

rex*_*xar 28

更新:相机包的v0.7.0版本引入了计算相机纵横比的重大变化,似乎他们默认添加了纵横比小部件

好吧,受之前帖子的启发,我让它在具有不同屏幕纵横比的 2 个屏幕上工作。我所做的是打印值并寻找差异(不完全是您所说的受过教育的方法)。结果是一个屏幕比另一个高,尽管宽度相同,因此屏幕纵横比不同。

免责声明:这是在锁定为纵向的应用程序中测试的,不保证这将在横向下工作。此外,这似乎确实将一些相机预览像素置于屏幕之外,但目前我对此没有补救措施。

无论选择哪种相机分辨率,相机控制器的纵横比都保持不变,但屏幕纵横比不同,因此较旧的帖子中提到的计算适用于一个(较短的)屏幕,但不适用于另一个(较高)的屏幕。

经过一些长时间的计算,很明显,要填充屏幕,比例因子必须大于 1。大于另一个并切换操作数,从而获得大于 1 的比例因子。

TL; 博士

这是更改的内容和最终结果:

计算

1.相机包版本v0.7.0及以上

  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),
      ),
  );
}
Run Code Online (Sandbox Code Playgroud)

2. 旧版本 - v0.6.6 及以下

  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),
        ),
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

结果

注意:下面的结果仅对 0.7.0 以下的版本有效,但概念是相同的

请注意,比例必须大于 1 才能填满整个屏幕。

  1. 更高的屏幕上述计算
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
Run Code Online (Sandbox Code Playgroud)
  1. 更短的画面上述计算
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
Run Code Online (Sandbox Code Playgroud)
  1. 没有以上计算的较短屏幕
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
Run Code Online (Sandbox Code Playgroud)


Mar*_*isý 24

激光解决方案的基础上,即使设备的纵横比与摄像机比率不同,这也可以工作:

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),
    ),
  ),
);
Run Code Online (Sandbox Code Playgroud)


las*_*ase 8

我有一个类似的问题,尽管理查德的回答很有帮助,但我也有预览太小的问题。也许有更好的方法,但是我可以通过像这样反转纵横比来缩放来解决它:

return new Scaffold(
  appBar: new AppBar(title: new Text('Capture')),
  body: new Transform.scale(
      scale: 1 / controller.value.aspectRatio,
      child: new Center(
        child: new AspectRatio(
            aspectRatio: controller.value.aspectRatio,
            child: new CameraPreview(controller)),
      )),
);
Run Code Online (Sandbox Code Playgroud)

从内到外,这应该:

  1. CameraPreview以正确的宽高比构建
  2. 将此预览置于视图中心
  3. 应用缩放变换,该变换允许预览基于宽高比适当地填充屏幕

  • 不幸的是,这在诸如 Galaxy S9+(超奇怪的 37:18 比例)之类的拉伸设备上无法正常工作。预览不适合整个屏幕,上下有白色条纹。我将尝试深入研究并在此处发布解决方案。 (2认同)

kiw*_*des 7

我只想基于Marek Lisy的回答,因为它确实破坏了容器。就我而言,我使用的是TabBarView,但该答案会导致不正确地捕捉到选项卡。我使用ClipRect修复了此问题,如下所示:

final size = MediaQuery.of(context).size;

if (!controller.value.isInitialized) {
  return Container();
}
return ClipRect(
  child: Container(
    child: Transform.scale(
      scale: controller.value.aspectRatio / size.aspectRatio,
      child: Center(
        child: AspectRatio(
          aspectRatio: controller.value.aspectRatio,
          child: CameraPreview(controller),
        ),
      ),
    ),
  ),
);
Run Code Online (Sandbox Code Playgroud)

祝您好运!我花了一个小时左右的时间来解决这个问题。因此,希望没有人会遇到同样的问题。


Ric*_*eap 5

您需要将预览包装在提供正确长宽比的小部件中-通过自己将宽度和高度设置为正确的长宽比,或使用AspectRatio。例如,相机插件示例使用:

new Expanded(
  child: new Padding(
    padding: const EdgeInsets.all(5.0),
    child: new Center(
      child: new AspectRatio(
        aspectRatio: controller.value.aspectRatio,
        child: new CameraPreview(controller),
      ),
    ),
  ),
),
Run Code Online (Sandbox Code Playgroud)