颤动相机显得拉长

时间:2018-04-20 16:37:20

标签: camera dart android-camera flutter

到目前为止,我一直在四处奔波,我很喜欢它,但我在让相机工作时遇到了问题。

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

13 个答案:

答案 0 :(得分:13)

lase解决方案的基础上,即使设备的纵横比与摄像头的纵横比不同,此方法也可以工作:

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),
    ),
  ),
);

答案 1 :(得分:7)

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

免责声明:这是在锁定了纵向的应用中进行的测试,但不能保证该功能可以横向使用。另外,这似乎确实会将某些相机预览像素放置在屏幕之外,但目前我还没有补救措施。

无论选择哪种摄像机分辨率,摄像机控制器的宽高比均保持不变,但是屏幕的宽高比有所不同,因此较早的文章中提到的计算适用于一个(较短)的屏幕,但不适用于另一个(taller)的屏幕

经过长时间的计算,很明显,要填充整个屏幕,比例因子必须大于1。因此,最后,要使该比例在两个屏幕上都可以使用,必须检查是否一个比率大于另一个比率并切换操作数,以得到大于1的比例因子。

TL; DR

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

计算

  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),
        ),
      ),
    );
  }

结果

请注意,缩放比例必须大于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
  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
  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

答案 2 :(得分:5)

我遇到了类似的问题,虽然理查德的答案很有帮助,但我也遇到了预览太小的问题。可能有更好的方法,但我能够通过像这样的宽高比反转来缩放它来解决它:

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)),
      )),
);

从内到外,这应该:

  1. 以正确的宽高比构建CameraPreview
  2. 在视图中居中此预览
  3. 应用缩放变换,允许预览根据宽高比
  4. 适当填充屏幕

答案 3 :(得分:1)

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

$f

答案 4 :(得分:1)

我只想基于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),
        ),
      ),
    ),
  ),
);

最幸运的家伙!我花了一个小时左右的时间来解决这个问题。因此,希望没有人遇到相同的问题。

答案 5 :(得分:0)

这是我想出的(仅在纵向模式下):

    Map<String, double> ratios = {
      '1:1': 1 / 1,
      '9:16': 9 / 16,
      '3:4': 3 / 4,
      '9:21': 9 / 21,
      'full': MediaQuery.of(context).size.aspectRatio,
    };
          final size = MediaQuery.of(context).size;
          print('screen ratio: ${size.aspectRatio}, default: $_defaultRatio');

          return Transform.scale(
            scale: 1.0,
            child: AspectRatio(
              aspectRatio: _defaultRatio,
              child: OverflowBox(
                alignment: Alignment.center,
                child: FittedBox(
                  fit: size.aspectRatio >= _defaultRatio
                      ? BoxFit.fitHeight
                      : BoxFit.fitWidth,
                  child: Container(
                    width: size.aspectRatio >= _defaultRatio
                        ? size.height
                        : size.width,
                    height: size.aspectRatio >= _defaultRatio
                        ? size.height / controller.value.aspectRatio
                        : size.width / controller.value.aspectRatio,
                    child: Stack(
                      children: <Widget>[
                        CameraPreview(controller),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          );

答案 6 :(得分:0)

在我的情况下,我应用了RotatedBox()。 下面的代码运行完美:

ggplot(data = data2)  + scale_y_reverse(limits = c(1000, 0)) +
  scale_x_continuous(limits = c(0, 200)) +
  geom_point(aes(y = Depth, x = C_flux_umol, fill = SampleType, shape = TrapType),
             colour = "black", stroke = 1, size = 5) +
  #geom_point(aes(x = tot_flux2)) +
scale_shape_manual(values = c(25, 22))+
  scale_size_manual(values = c(3, 4)) +
  ylab("Depth (m)") + xlab("Flux micro-mol/m^2/day") +
  guides(fill = guide_legend(override.aes = list(shape = 25))) +
  theme_cowplot() +
  theme(legend.position = c(0.5, 0.4),
        legend.box.background = element_rect(color = "black", size = .5))

我使用了“ package:camera / camera.dart ”; 您唯一需要考虑的就是“ 3:0”参数。 3-表示您的盒子转动了几圈(顺时针)。三-表示系统按钮在右侧。第二个0-这就是如何在窗口上缩放预览(现在是拉伸)。您可能需要增加灵活性,并从设备读取实际位置并更改这些数字。 我使用了其他汽车覆盖物,以查看如何将汽车放置在相机的前部以将照片发布到广告中。板。 [Android screen photo landscape]

答案 7 :(得分:0)

编辑:下面的方法效果很好,但是将FittedBox和SizedBox一起使用会更好。参见this video from the flutter devs

FittedBox(child: SizedBox(child: texture, width: imageWidthInPixels, height: imageHeightInPixels));

执行此操作的最佳方法是遵循Widget of the week video on AspectRatio中的说明。使用AspectRatio确保视频保持其宽高比(如图)。然后将其包裹在Align中,然后展开。如果您使用RotatedBox调整方向,请在Align中将宽高比包装在其中。

Expanded(
    child:Align(
        child:AspectRatio(
            child:texture, aspectRatio:cameraAspectRatio)

答案 8 :(得分:0)

我在横向时也遇到了相同的问题,我通过上下文内部的以下源代码解决了这个问题-

if (!_cameraController.value.isInitialized) {
  return Container();
}

final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;
double xScale = _cameraController.value.aspectRatio / deviceRatio;
final yScale = 1.0;

if (MediaQuery.of(context).orientation == Orientation.landscape) {
  xScale = 1.0;
}

,这样,小部件视图就这样对齐了,我在OnePlus 6 (29 Q)Asus Z010D (23 Marshmallow) Android OS版本上进行了测试,并且运行良好。

RotatedBox(
  quarterTurns: MediaQuery.of(context).orientation == Orientation.landscape ? 3 : 0,
  child: Container(
    child: AspectRatio(
      aspectRatio: deviceRatio,
      child: Transform(
        alignment: Alignment.center,
        transform: Matrix4.diagonal3Values(xScale, yScale, 1),
        child: CameraPreview(_cameraController),
      ),
    ),
  ),
),

希望这会对某人有所帮助。

答案 9 :(得分:0)

缩放已经过重新设计,因此您不必使用其他插件来制作任何技巧: camera awesome

答案 10 :(得分:0)

在花了很长时间试图找到一种方法来解决这个问题后,我转向了这个包 https://pub.dev/packages/camerawesome 并节省了很多时间。

答案 11 :(得分:-1)

我只想补充一点,如果将相机预览放置在中心位置并且不是全屏,那么将相机的分辨率更改为veryHigh肯定会使其全屏。

CameraController( cameras[0], ResolutionPreset.veryHigh )

答案 12 :(得分:-1)

我尝试了所有解决方案,但在某些情况下所有解决方案都存在问题,请尝试一下,它的工作原理就像是一种魅力:

第一:

final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;

然后:

return Transform.scale(
   scale: 1,
   child: Center(
     child: AspectRatio(
       aspectRatio: deviceRatio,
       child: CameraPreview(_cameraController),
     ),
   ),
);

希望对您有帮助...