如何使用新的android.hardware.camera2 API显示摄像机预览?

问题描述 投票:0回答:1

我想用android.hardware.camera2 API取代不推荐使用的相机API。 github上的示例项目显示了相机图片,但是如果设备的分辨率与完美的相机缩放选项不匹配,则会在屏幕边缘创建黑色条纹。我已经在模拟器(Android 26-29,Nexus 2)上尝试过。与三星设备SM-T395和SM-T585上的结果相同。在FullHD上非常奇怪。

增加MAX_PREVIEW_HEIGHTMAX_PREVIEW_WIDTH无效。我想我需要

这里是仿真器的一些示例图片:

Custom resolution with quite a good  fit FullHD sample

如何在自定义尺寸的预览中显示摄像机的预览?

android scaling android-camera2
1个回答
0
投票

问题完全取决于设备。每个供应商都会为其相机设置并列出支持的分辨率。此外,它对于预览和实际图像捕获可能有所不同(很少但仍然)。如果您不希望扭曲和扭曲图像并进行预览,则不能超出此列表。

虽然并非所有事情都如此令人沮丧。通常,在此列表中,有几种受支持的分辨率,这些分辨率的纵横比与手机的屏幕相同(或至少有一种分辨率会在图像的顶部或底部添加黑色空间,但不在侧面添加黑屏)

因此,我建议您找到屏幕的长宽比(TextureView / SurfaceView)。计算相机支持的所有预览宽高比。比较这些比率,然后选择与屏幕相同的比率(TextureView / SurfaceView),但分辨率最高。对于可能在顶部或底部显示黑色空间而不在侧面显示黑色空间的分辨率,您可能会实现类似的效果。

这里是一个示例代码,它执行相似的操作,但方式有所不同。

//Create TextureView & TextureView surfaceTextureListener
private TextureView mTextureView;
    private TextureView.SurfaceTextureListener mSurfaceTextureListener =
            new TextureView.SurfaceTextureListener() {
                @Override
                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                    setupCamera(width, height);
                }
                @Override
                public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                }
                @Override
                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                    return false;
                }
                @Override
                public void onSurfaceTextureUpdated(SurfaceTexture surface) {
                }
            };
//Implement Activity onResume
@Override
   public void onResume() {
       super.onResume();
       if(mTextureView.isAvailable()) {
       } else {
           mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
       }
   }
//Get surface preview sizes & camera Id
private void setupCamera(int width, int height) {
       CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
       try {
           for(String cameraId : cameraManager.getCameraIdList()) {
               CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
               if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) ==
                       CameraCharacteristics.LENS_FACING_FRONT){
                   continue;
               }
               StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
               mPreviewSize = getPreferredPreviewSize(map.getOutputSizes(SurfaceTexture.class), width, height);
               mCameraId = cameraId;
               return;
           }
       } catch (CameraAccessException e) {
           e.printStackTrace();
       }
   }
   private Size getPreferredPreviewSize(Size[] mapSizes, int width, int height) {
       List<Size> collectorSizes = new ArrayList<>();
       for(Size option : mapSizes) {
           if(width > height) {
               if(option.getWidth() > width &&
                       option.getHeight() > height) {
                   collectorSizes.add(option);
               }
           } else {
               if(option.getWidth() > height &&
                       option.getHeight() > width) {
                   collectorSizes.add(option);
               }
           }
       }
       if(collectorSizes.size() > 0) {
           return Collections.min(collectorSizes, new Comparator<Size>() {
               @Override
               public int compare(Size lhs, Size rhs) {
                   return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());
               }
           });
       }
       return mapSizes[0];
   }

取自here

希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.