Как изменить размер CameraSource, например, setPreviewSize и PictureSize

Это относится к API GoogleVision. CameraPreview хорошо работает для полного экрана. Но изображение искажается при предварительном просмотре камеры в коробке.

Это код, который я использовал. Моя проблема в том, что предварительный просмотр заполняет поле, но предварительный просмотр растягивается, и я не могу отрегулировать размер cameraPreview. Переменная CameraPreview имеет тип SurfaceView. Я использую CameraSource для запуска предварительного просмотра. Есть ли способ изменить размер CameraPreview(SurfaceView) и сделать обрезку предварительного просмотра уместным в поле?

  cameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
            protected List<Camera.Size> mPreviewSizeList;
            protected List<Camera.Size> mPictureSizeList;
            protected Camera.Size mPreviewSize;
            protected Camera.Size mPictureSize;
            protected boolean mSurfaceChanged = false;
            private int mSurfaceChangedCallDepth = 0;
            private int mCenterPosX = -1;
            private int mCenterPosY = 0;
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(ClientIdScannerActivity.this,
                            new String[]{Manifest.permission.CAMERA}, RequestCameraPermissionId);
                    Toast.makeText(ClientIdScannerActivity.this, "The App requires this permission", Toast.LENGTH_SHORT).show();
                    return;
                }
                try {
                    cameraSource.start(cameraPreview.getHolder());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
                mSurfaceChangedCallDepth++;

             /*   cameraSource.stop();

                Camera.Parameters cameraParams = mCamera.getParameters();

                if (!mSurfaceChanged) {
                    Camera.Size previewSize = determinePreviewSize(cameraWidth, cameraHight);
                    Camera.Size pictureSize = determinePictureSize(previewSize);
                    mPreviewSize = previewSize;
                    mPictureSize = pictureSize;
                    mSurfaceChanged = adjustSurfaceLayoutSize(previewSize,i1, i2);

                    if (mSurfaceChanged && (mSurfaceChangedCallDepth <= 1)) {
                        return;
                    }
                }

                cameraParams.setRotation(270);
                if (UtilFunctions.isTablet()) {
                } else {
                    mCamera.setDisplayOrientation(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? 270 : 90);
                }*/

//            cameraParams.setRotation(270);
//            mCamera.setDisplayOrientation(UtilFunctions.isTablet() ? 90 : 270);

              /*  cameraParams.set("orientation", "portrait");
                //  cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                cameraParams.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
                cameraParams.setPictureSize(mPictureSize.width, mPictureSize.height);
                if (cameraParams.getSupportedFocusModes().contains(
                        Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                    cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                }*/

                mSurfaceChanged = false;

                try {
                    if (ActivityCompat.checkSelfPermission(ClientIdScannerActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                        // TODO: Consider calling
                        //    ActivityCompat#requestPermissions
                        // here to request the missing permissions, and then overriding
                        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                        //                                          int[] grantResults)
                        // to handle the case where the user grants the permission. See the documentation
                        // for ActivityCompat#requestPermissions for more details.
                        Toast.makeText(ClientIdScannerActivity.this, "App requires Camera permission to scan ID", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    cameraSource.start(cameraPreview.getHolder());
                } catch (Exception e) {
                    // Remove failed size

                    // Reconfigure
                    if (mPreviewSizeList.size() > 0) { // prevent infinite loop
                        surfaceChanged(null, 0, i1, i2);
                    } else {
//                Utils.showToast(CameraNewActivity.this, "Can't start preview", Toast.LENGTH_LONG);
                    }
                }

                mSurfaceChangedCallDepth--;
            }

            protected Camera.Size determinePreviewSize(int reqWidth, int reqHeight) {

                int reqPreviewWidth = 640;//reqHeight; // requested width in terms of camera hardware
                int reqPreviewHeight = 480;// reqWidth; // requested height in terms of camera hardware
                Camera.Size retSize = null;
                for (Camera.Size size : mPreviewSizeList) {
                    if (size.width == reqPreviewWidth && size.height == reqPreviewHeight) {
                        retSize = size;
                    }
                }
                //  retSize = mPreviewSizeList.get(mPreviewSizeList.size()-1);
                return retSize;
            }

            protected Camera.Size determinePictureSize(Camera.Size previewSize) {
                Camera.Size retSize = null;
                for (Camera.Size size : mPictureSizeList) {
                    if (size.equals(previewSize)) {
                        return size;
                    }
                }

                // if the preview size is not supported as a picture size
                float reqRatio = ((float) previewSize.width) / previewSize.height;
                float curRatio, deltaRatio;
                float deltaRatioMin = Float.MAX_VALUE;
                for (Camera.Size size : mPictureSizeList) {
                    curRatio = ((float) size.width) / size.height;
                    deltaRatio = Math.abs(reqRatio - curRatio);
                    if (deltaRatio < deltaRatioMin) {
                        deltaRatioMin = deltaRatio;
                        retSize = size;
                    }
                }

                return retSize;
            }

            protected boolean adjustSurfaceLayoutSize(Camera.Size previewSize,
                                                      int availableWidth, int availableHeight) {

                float tmpLayoutHeight = previewSize.width;
                float tmpLayoutWidth = previewSize.height;

                float factH, factW, fact;
                factH = availableHeight / tmpLayoutHeight;
                factW = availableWidth / tmpLayoutWidth;

//        if (factH < factW) {
//            fact = factH;
//        } else {
                fact = factW;
                //  }

                FrameLayout.LayoutParams layoutParams =(FrameLayout.LayoutParams) cameraPreview.getLayoutParams();
                int layoutHeight = (int) (tmpLayoutHeight * fact);
                int layoutWidth = (int) (tmpLayoutWidth * fact);

                boolean layoutChanged;
                if ((layoutWidth != cameraPreview.getWidth()) || (layoutHeight != cameraPreview.getHeight())) {
                    layoutParams.height = layoutHeight;
                    layoutParams.width = layoutWidth;
                    if (mCenterPosX >= 0) {
                        layoutParams.topMargin = mCenterPosY - (layoutHeight / 2);
                        layoutParams.leftMargin = mCenterPosX - (layoutWidth / 2);
                    }
                    cameraPreview.setLayoutParams(layoutParams); // this will trigger another surfaceChanged invocation.
                    layoutChanged = true;
                } else {
                    layoutChanged = false;
                }

                return layoutChanged;
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
                cameraSource.stop();
            }
        });

1 ответ

Обратите внимание, что та же проблема существует для "полноэкранного" предварительного просмотра камеры. Не гарантируется, что соотношение сторон выбранного вами размера предварительного просмотра будет достаточно близко к соотношению сторон экрана. Пожалуйста, смотрите более подробную информацию здесь: Предварительный просмотр камеры на нескольких устройствах Android.

Естественно, вы должны выбрать оптимальную ширину и высоту, чтобы соответствовать виду, но этого недостаточно. Вы должны скрыть "висящие" части поверхности предварительного просмотра за некоторыми непрозрачными видами. Посмотрите, например, как вы можете сделать круговой предварительный просмотр.

Еще одна важная вещь здесь - это всегда синхронизировать размеры предварительного просмотра и изображения. Это не значит, что они должны быть одинаковыми, но пропорции должны. Некоторые устройства имеют странные эффекты, когда соотношение сторон изменяется, чтобы сделать снимок.

Другие вопросы по тегам