星力9源码:三星S9(18:9)相机预览拉伸(android samsung 9)

关于星力9源码的问题,在android samsung 9中经常遇到, 我正在使用 Android Camera API,它在纵向和横向模式下都能正常工作 16:9 比例的设备。但是在 Samsung S9 18:9 比例的设备中,在横向模式下,预览看起来被拉伸了。在 Samsung S9 上,我得到了以下支持的预览尺寸1920X1080,1440X1080,1088X1088,1280X720,1056X704,1024X768,960X720,800X450,720X720,720X480,640X480,352X288,320X240,256X144,176X144因此,最佳预览尺寸为1920X1080,但设备的实际

我正在使用 Android Camera API,它在纵向和横向模式下都能正常工作 16:9 比例的设备。但是在 Samsung S9 18:9 比例的设备中,在横向模式下,预览看起来被拉伸了。在 Samsung S9 上,我得到了以下支持的预览尺寸1920X1080,1440X1080, 1088X1088,1280X720,1056X704, 1024X768, 960X720,800X450,720X720,720X480,640X480,352X288,320X240,256X144,176X144因此,最佳预览尺寸为1920X1080,但设备的实际分辨率为2

@SuppressLint("ClickableViewAccessibility")
    @SuppressWarnings("deprecation")
    public CameraPreview(Context context, Camera.PreviewCallback previewCallback) {
        super(context);
        this.previewCallback = previewCallback;
        mContext = context;
        // Install a SuceHolder.Callback so we get notified when the
        // underlying suce is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SuceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    public void setCameraDisplayOrientation(Context activity,
                                            int cameraId, Camera camera) {
        Camera.CameraInfo info =
                new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, info);
        int rotation = ((AppCompatActivity) activity).getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Suce.ROTATION_0:
                degrees = 0;
                break;
            case Suce.ROTATION_90:
                degrees = 90;
                break;
            case Suce.ROTATION_180:
                degrees = 180;
                break;
            case Suce.ROTATION_270:
                degrees = 270;
                break;
        }
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        mDisplayOrientation = result;
        Log.d(TAG, "setCameraDisplayOrientation: "+mDisplayOrientation);
        camera.setDisplayOrientation(result);
    }
    public void takePhoto(final PictureCallback pCalback) {
        mCamera.takePicture(null, null, pCalback);
    }
    public void suceCreated(SuceHolder holder) {
        // The Suce has been created, acquire the camera and tell it where
        // to draw.
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        }
        try {
            mCamera = Camera.open();
            //setCameraDisplayOrientation(mContext, 0, mCamera);
            /*mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
            int screenWidth = displayMetrics.widthPixels;
            int screenHeight = displayMetrics.heightPixels;
            optimalPreviewSize = getBestAspectPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight);//Bug Fix for Samsung A8
            mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPreviewFpsRange(30000, 30000);
            mCamera.setParameters(mParameters);*/
            /*mCamera.setPreviewDisplay(holder);
            mCamera.setPreviewCallback(previewCallback);*/
            mCamera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        } catch (Exception exception) {
            mCamera = null;
            //previewCount = 0;
        }
        if (mCameraPreviewListener != null) {
            mCameraPreviewListener.onCameraSuceCreated();
        }
    }
    public void suceDestroyed(SuceHolder holder) {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        }
        if (mCameraPreviewListener != null) {
            mCameraPreviewListener.onCameraSuceDestroyed();
        }
    }
    public void stopCamera() {
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
            //previewCount = 0;
        }
    }
    @SuppressWarnings("null")
    public void suceChanged(SuceHolder holder, int format, int w, int h) {
        try {
            // Now that the size is known, set up the camera parameters and begin
            // the preview.
            mParameters = mCamera.getParameters();
            Log.d("CameraFix", "parameters -> " + mParameters.flatten());
            setCameraDisplayOrientation(mContext, 0, mCamera);
            mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            //Size optimalPreviewSize = getOptimalPreviewSize(mParameters.getSupportedPreviewSizes(), getWidth(), getHeight());
            DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
            int screenWidth = displayMetrics.widthPixels;
            int screenHeight = displayMetrics.heightPixels;
            //Size optimalPreviewSize = getOptimalPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight, getHeight());
            mSupportedPreviewSizes = mParameters.getSupportedPreviewSizes();
            optimalPreviewSize = getBestAspectPreviewSize(mParameters.getSupportedPreviewSizes(), screenWidth, screenHeight);//Bug Fix for Samsung A8
            Log.d("CameraFix", "optimalPreviewSize.width -> " + optimalPreviewSize.width);
            Log.d("CameraFix", "optimalPreviewSize.height -> " + optimalPreviewSize.height);
            mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPictureSize(optimalPreviewSize.width, optimalPreviewSize.height);
            mParameters.setPreviewFpsRange(30000, 30000);
            /*if (mDisplayOrientation == 0 || mDisplayOrientation == 180) {
                setLayoutParams(new FrameLayout.LayoutParams(optimalPreviewSize.width, optimalPreviewSize.height,Gravity.CENTER));
            }*/
            Log.d("CameraFix", "setPreviewFpsRange");
            mCamera.setParameters(mParameters);
            mCamera.setPreviewDisplay(holder);
            //SuceTexture st = new SuceTexture(10);
            //mCamera.setPreviewTexture(st);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            Log.d("CameraFix", "start preview");
            if (mCameraPreviewListener != null) {
                mCameraPreviewListener.onCameraSuceChanged();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("CameraFix", e.toString());
        }
    }
public void toggleFlash(boolean flashModeOn) {
        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) {
            Parameters parameters = mCamera.getParameters();
            if (flashModeOn) {
                //parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
                parameters.setFlashMode(Parameters.FLASH_MODE_ON);
                mCamera.setParameters(parameters);
                mCamera.startPreview();
                //Toast.makeText(mContext, R.string.flash_mode_on, Toast.LENGTH_SHORT).show();
            } else {
                parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
                mCamera.setParameters(parameters);
                //Toast.makeText(mContext, R.string.flash_mode_off, Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(mContext, R.string.flash_not_available, Toast.LENGTH_SHORT).show();
        }
    }
/**
     * Source for this solution - https://stackoverflow.com/questions/21354313/camera-preview-quality-in-android-is-poor/21354442#21354442
     *
     * @param supportedPreviewSizes
     * @param screenWidth
     * @param screenHeight
     * @return
     */
    private Size getBestAspectPreviewSize(List<Size> supportedPreviewSizes, int screenWidth, int screenHeight) {
        double targetRatio = (double) screenWidth / screenHeight;
        Camera.Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;
        for (int i = 0; i < supportedPreviewSizes.size(); i++) {
            Size size = supportedPreviewSizes.get(i);
            Log.d(TAG, "getBestAspectPreviewSize: supportedPreviewSizes -> "+size.width +"X"+size.height);
        }
        Log.d(TAG, "getBestAspectPreviewSize: supportedPreviewSizes -> "+supportedPreviewSizes.toString());
        Log.d(TAG, "getBestAspectPreviewSize: mDisplayOrientation -> "+mDisplayOrientation);
        if (mDisplayOrientation == 90 || mDisplayOrientation == 270) {
            Log.d(TAG, "getBestAspectPreviewSize: inside 90 - 270 ");
            targetRatio = (double) screenHeight / screenWidth;
        }
        Log.d(TAG, "getBestAspectPreviewSize: targetRatio -> "+targetRatio);
        Collections.sort(supportedPreviewSizes,
                Collections.reverseOrder(new SizeComparator()));
        for (Size size : supportedPreviewSizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(ratio - targetRatio);
            }
            if (minDiff < 0.0d) {
                break;
            }
        }
        return (optimalSize);
        /*if (mDisplayOrientation == 0 || mDisplayOrientation == 180) {
            if (optimalSize != null) {
                return mCamera.new Size(optimalSize.height, optimalSize.width);
            } else {
                return null;
            }
        }
        else{
            return (optimalSize);
        }*/
        //return mCamera.new Size(2220,1080);
    }
    public int getDisplayOrientation() {
        return mDisplayOrientation;
    }
    public void setDisplayOrientation(int displayOrientation) {
        this.mDisplayOrientation = displayOrientation;
    }
    public Parameters getCameraParameters() {
        return mCamera.getParameters();
    }
public void setCameraPreviewListener(CameraPreviewListener cameraPreviewListener) {
        mCameraPreviewListener = cameraPreviewListener;
    }
    public intece CameraPreviewListener {
        void onCameraSuceCreated();
        void onCameraSuceChanged();
        void onCameraSuceDestroyed();
        void onCameraPreviewStarted();
    }
    private static class SizeComparator implements
            Comparator<Size> {
        @Override
        public int compare(Size lhs, Size rhs) {
            int left = lhs.width * lhs.height;
            int right = rhs.width * rhs.height;
            if (left < right) {
                return (-1);
            } else if (left > right) {
                return (1);
            }
            return (0);
        }
    }

S9 Camera stretched in landscape mode

2

您应该再次检查默认相机的可显示区域,我认为它在那个分辨率下没有拉伸就不能完全显示,它可能有一个黑域,工具栏,状态栏...

在这种情况下,您应该使表面视图 (1920 x 1080) 居中,然后在顶部和底部添加黑色填充区域。

0

请看看我的答案,希望它会有所帮助,我通过以下代码解决了拉伸问题,方法名称可能会改变。我分享我的实现,因为我知道在 Android 中实现相机有多难,所以请不要犹豫,看看的部分。

在 ButtonAction 中调用 loadCamera 方法。

private void loadCamera() {
        if (CommonUtils.deviceHasCamera(getActivityContext)) {
            startBackgroundThread();
            mCameraTimeOut=(isPermissionGranted?2500:5000);
            if (mTextureView.isAvailable()) {
                openCamera(mTextureView.getWidth(), mTextureView.getHeight());
            } else {
                mTextureView.setSuceTextureListener(mSuceTextureListener);
            }
        }else{
            ShowToastUtils.INSTANCE.showCustomToast(getActivityContext, getString(R.string.msg_no_camera));
        }
    }

最初为相机调用的 SuceListener

private TextureView.SuceTextureListener mSuceTextureListener
            = new TextureView.SuceTextureListener() {
        @Override
        public void onSuceTextureAvailable(SuceTexture suceTexture,
                                              int width, int height) {
            mCameraTimeOut=(isPermissionGranted?2500:5000);
            Log.e(TAG1, "chooseOptimalSize"+"-SuceTextureListener ---=>Width---=>"+width);
            Log.e(TAG1, "chooseOptimalSize"+"-SuceTextureListener ---=>Height---=>"+height);
            openCamera(width, height);
        }
        @Override
        public void onSuceTextureSizeChanged(SuceTexture suceTexture,
                                                int width, int height) {
            configureTransform(width, height);
        }
        @Override
        public boolean onSuceTextureDestroyed(SuceTexture suceTexture) {
            return true;
        }
        @Override
        public void onSuceTextureUpdated(SuceTexture suceTexture) {}
    };

为纹理选择最佳预览尺寸

//Samsung-S6-choices[0]
//Samsung-S7-edge-choices[6]
//OnePlus-5T-choices[15]
/*Following is used for Camera Preview in TextureView,  based on device camera resolution*/
    /*
     * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
     * width and height are at least as large as the respective requested values, and whose aspect
     * ratio matches with the specified value.
     *
     * @param choices     The list of sizes that the camera supports for the intended output class
     * @param width       The minimum desired width
     * @param height      The minimum desired height
     * @param aspectRatio The aspect ratio
     * @return The optimal {@code Size}, or an arbitrary one if none were big enough
     */
     private  Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
        // Collect the supported resolutions that are at least as big as the preview Suce
        int loopCounter=0;
        Log.e(TAG1, "Screen-->Width x Height="+screenWidth+" x "+screenHeight);
        for (Size size : choices) {
            Log.e(TAG1, "chooseOptimalSize:"+size);
        }
        for (Size size : choices) {
            int orientation = getActivityContext.getResources().getConfiguration().orientation;
            if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                if((size.getWidth()/16) == (size.getHeight()/9) && size.getWidth() <=7680 ) {//8K UHDTV Super Hi-Vision
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"--LoopPosition---==>"+loopCounter);
                    return size;
                }
            } else {
                Log.e(TAG1, "chooseOptimalSize:--given--"+size);
                if((size.getWidth()/16) == (size.getHeight()/9) && ((size.getWidth() <=1280)||(size.getHeight()<=1920))) {
                    mCameraRatio=RATIO_16_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-16:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((size.getWidth()/18) == (size.getHeight()/9) && ((size.getWidth() <=2160)||(size.getHeight()<=3840))) {
                    mCameraRatio=RATIO_18_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-18:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((size.getWidth()/18.5) == (size.getHeight()/9) && ((size.getWidth() <=2160)||(size.getHeight()<=3840))) {
                    mCameraRatio=RATIO_18_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-18.5:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((width/19) == (height/9) && ((width <=2208)||(height<=3216))) {
                    mCameraRatio=RATIO_19_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-19:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else if((size.getWidth()/19.5) == (size.getHeight()/9) && ((size.getWidth() <=3840)||(size.getHeight()<=2160))) {
                    mCameraRatio=RATIO_19_9;
                    Log.e(TAG1, "chooseOptimalSize:"+size.getWidth()+"x"+size.getHeight()+"-19.5:9"+"--LoopPosition---==>"+loopCounter);
                    return size;
                }else{
                    Log.e(TAG1, "chooseOptimalSize"+" not proper aspect resolution");
                }
            }
                  loopCounter++;
        }
}

打开相机

    private void openCamera(int width, int height) {
                CameraManager manager = (CameraManager) getActivityContext.getSystemService(Context.CAMERA_SERVICE);
                try {
                    Log.e(TAG, "tryAcquire");
                    if (!mCameraOpenCloseLock.tryAcquire(mCameraTimeOut, TimeUnit.MILLISECONDS)) {
                        throw new RuntimeException("Time out waiting to lock camera opening.");
                    }
                    String mCameraId = manager.getCameraIdList()[cameraId];
                    // Choose the sizes for camera preview and video recording
                    characteristics = manager.getCameraCharacteristics(mCameraId);
                    StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                    try {
                        mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
                        maximumZoomLevel = characteristics.get(CameraCharacteristics.SCALER_AILABLE_MAX_DIGITAL_ZOOM);
                        if (map == null) {
                            throw new RuntimeException("Cannot get available preview/video sizes");
                        }
                        mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
    /*This Line will configure the Texture size*/
                        mPreviewSize = chooseOptimalSize(map.getOutputSizes(SuceTexture.class), width, height, mVideoSize);
int orientation = getResources().getConfiguration().orientation;
                    if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                        Log.e(TAG1, "Width" + mPreviewSize.getWidth() + "X Height" + mPreviewSize.getHeight());
                        mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
                    } else {
                        Log.e(TAG1, "Width" + mPreviewSize.getHeight() + "X Height" + mPreviewSize.getWidth());
                        mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
    //S10 preview Size
                        /* mTextureView.setAspectRatio(1080, 2280);*/
                        //mTextureView.setAspectRatio(2208, 2944);
                    }
                    if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                        configureTransform(width, height);
                    }
                    if (isPermissionGranted) {
                        manager.openCamera(mCameraId, mStateCallback, null);
                    }
                }catch (Exception ex){ex.printStackTrace();}finally {
                    map=null;
                    Runtime.getRuntime().gc();
                }
            } catch (CameraAccessException e) {
                Toast.makeText(getActivityContext, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
                //getActivityContext.finish();
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
                throw new RuntimeException("Interrupted while trying to lock camera opening.");
            }
        }

用于方向处理的 ConfigureTransform 方法

/*
     * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
     * This method should not to be called until the camera preview size is determined in
     * openCamera, or until the size of `mTextureView` is fixed.
     *
     * @param viewWidth  The width of `mTextureView`
     * @param viewHeight The height of `mTextureView`
     */
private void configureTransform(int viewWidth, int viewHeight) {
    if (null == mTextureView || null == mPreviewSize) {
        return;
    }
    int rotation = getActivityContext.getWindowManager().getDefaultDisplay().getRotation();
    Matrix matrix = new Matrix();
    RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
    RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
    float centerX = viewRect.centerX();
    float centerY = viewRect.centerY();
    if (Suce.ROTATION_90 == rotation || Suce.ROTATION_270 == rotation) {
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale = Math.max((float) viewHeight / mPreviewSize.getHeight(),(float) viewWidth / mPreviewSize.getWidth());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(90 * (rotation - 2), centerX, centerY);
    }else if (Suce.ROTATION_0 == rotation) {
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale=Math.max((float) viewWidth / mPreviewSize.getWidth(), (float) viewHeight / mPreviewSize.getHeight());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(0, centerX, centerY);
    }else if(Suce.ROTATION_180== rotation){
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale=Math.max((float) viewWidth / mPreviewSize.getWidth(), (float) viewHeight / mPreviewSize.getHeight());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(0, centerX, centerY);
    }
    try {
        mTextureView.setTransform(matrix);
    }catch (Exception ex){ex.printStackTrace();}finally {
        bufferRect=null;
        viewRect=null;
        matrix=null;
    }
}

最后开始预览

private void startPreview() {
        if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
            return;
        }
        try {
            closePreviewSession();
            SuceTexture texture = mTextureView.getSuceTexture();
            assert texture != null;
            texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            //texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            Suce previewSuce = new Suce(texture);
            mPreviewBuilder.addTarget(previewSuce);
            mCameraDevice.createCaptureSession(Collections.singletonList(previewSuce),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession session) {
                            mPreviewSession = session;
                            updatePreview();
                        }
                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                            Toast.makeText(getActivityContext, "Failed", Toast.LENGTH_SHORT).show();
                        }
                    }, mBackgroundHandler);
            //previewSuce=null;
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(800)
Mpg播放器:无法在Android中播放mpg文件
上一篇
Charles怎么设置过滤:在Android上设置Charles代理时 Internet连接丢失
下一篇

相关推荐

发表评论

登录 后才能评论

评论列表(22条)