首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React Native android camera2纵横比问题

React Native android camera2纵横比问题
EN

Stack Overflow用户
提问于 2017-11-29 19:38:13
回答 2查看 1.6K关注 0票数 3

我已经为安卓创建了一个库(查看this了解更多信息),安卓的Camera2功能都运行良好,但在全屏相机的纵横比问题上。

请检查下面的图片在预览和真实图片中的样子(只有预览有问题,捕获后没有真实图片)

捕获的图像水平:

水平预览图像:

垂直捕获的图像:

垂直预览图像:

谷歌的Camera2应用程序接口样本也有类似的问题,并解决了here问题。

但是同样的代码在我的react本机库代码中不起作用。可能是我对图像和视频都使用了一个代码,并为视频捕获添加了额外的代码。

EN

回答 2

Stack Overflow用户

发布于 2017-12-06 23:10:02

通常情况下,相机传感器的纵横比与屏幕的纵横比不匹配。结果就是你目前正在经历的事情。

由于宽高比的这种不匹配。你不能强制预览是全屏的。你必须选择“有效”尺寸。那么如何做到这一点呢?

我们对传感器的尺寸无能为力。我们必须回答的问题是,我的预览的高度应该是多少?(假设为纵向模式)

下面是一个例子:

传感器(假设为纵向):

  • width: 50
  • height: 100
  • 宽高比:(宽/高)= 0.5

屏幕(假设为纵向):

  • width: 400
  • height: 1000
  • 宽高比:(宽/高)= 0.4

有了上面的值,你的预览图像将被“拉伸”。

下面是如何修复它:

我们知道我们想要的纵横比:0.5

宽度/高度= 0.5

我们知道屏幕的宽度(纵向):400

400 /高度= 0.5

高度= 400 / 0.5 = 800

为了在x或y方向上没有拉伸,高度(假设为纵向)需要为:预览宽度/所需的纵横比

票数 1
EN

Stack Overflow用户

发布于 2020-08-06 19:17:15

我为那些想要更多理论的人详细回答了一个similar question here

简而言之,在cameraReady上,你必须抓取屏幕尺寸,支持的摄像头宽高比,然后找到与屏幕最匹配的比例,而不是太高。

示例应用程序如下所示:

代码语言:javascript
复制
import React, { useEffect, useState } from 'react';
import {StyleSheet, View, Text, Dimensions, Platform } from 'react-native';
import { Camera } from 'expo-camera';
import * as Permissions from 'expo-permissions';

export default function App() {
  //  camera permissions
  const [hasCameraPermission, setHasCameraPermission] = useState(null);
  const [camera, setCamera] = useState(null);

  // Screen Ratio and image padding
  const [imagePadding, setImagePadding] = useState(0);
  const [ratio, setRatio] = useState('4:3');  // default is 4:3
  const { height, width } = Dimensions.get('window');
  const screenRatio = height / width;
  const [isRatioSet, setIsRatioSet] =  useState(false);

  // on screen  load, ask for permission to use the camera
  useEffect(() => {
    async function getCameraStatus() {
      const { status } = await Permissions.askAsync(Permissions.CAMERA);
      setHasCameraPermission(status == 'granted');
    }
    getCameraStatus();
  }, []);

  // set the camera ratio and padding.
  // this code assumes a portrait mode screen
  const prepareRatio = async () => {
    let desiredRatio = '4:3';  // Start with the system default
    // This issue only affects Android
    if (Platform.OS === 'android') {
      const ratios = await camera.getSupportedRatiosAsync();

      // Calculate the width/height of each of the supported camera ratios
      // These width/height are measured in landscape mode
      // find the ratio that is closest to the screen ratio without going over
      let distances = {};
      let realRatios = {};
      let minDistance = null;
      for (const ratio of ratios) {
        const parts = ratio.split(':');
        const realRatio = parseInt(parts[0]) / parseInt(parts[1]);
        realRatios[ratio] = realRatio;
        // ratio can't be taller than screen, so we don't want an abs()
        const distance = screenRatio - realRatio; 
        distances[ratio] = realRatio;
        if (minDistance == null) {
          minDistance = ratio;
        } else {
          if (distance >= 0 && distance < distances[minDistance]) {
            minDistance = ratio;
          }
        }
      }
      // set the best match
      desiredRatio = minDistance;
      //  calculate the difference between the camera width and the screen height
      const remainder = Math.floor(
        (height - realRatios[desiredRatio] * width) / 2
      );
      // set the preview padding and preview ratio
      setImagePadding(remainder / 2);
      setRatio(desiredRatio);
      // Set a flag so we don't do this 
      // calculation each time the screen refreshes
      setIsRatioSet(true);
    }
  };

  // the camera must be loaded in order to access the supported ratios
  const setCameraReady = async() => {
    if (!isRatioSet) {
      await prepareRatio();
    }
  };

  if (hasCameraPermission === null) {
    return (
      <View style={styles.information}>
        <Text>Waiting for camera permissions</Text>
      </View>
    );
  } else if (hasCameraPermission === false) {
    return (
      <View style={styles.information}>
        <Text>No access to camera</Text>
      </View>
    );
  } else {
    return (
      <View style={styles.container}>
        {/* 
        We created a Camera height by adding margins to the top and bottom, 
        but we could set the width/height instead 
        since we know the screen dimensions
        */}
        <Camera
          style={[styles.cameraPreview, {marginTop: imagePadding, marginBottom: imagePadding}]}
          onCameraReady={setCameraReady}
          ratio={ratio}
          ref={(ref) => {
            setCamera(ref);
          }}>
        </Camera>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  information: { 
    flex: 1,
    justifyContent: 'center',
    alignContent: 'center',
    alignItems: 'center',
  },
  container: {
    flex: 1,
    backgroundColor: '#000',
    justifyContent: 'center',
  },
  cameraPreview: {
    flex: 1,
  }
});

您也可以使用try this code out online or in your Android on Expo Snack

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47551921

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档