当前位置: 首页 > 知识库问答 >
问题:

相机预览在一些Android设备中被拉伸

仲孙疏珂
2023-03-14

我在玩谷歌的API2摄像头,我的代码有一些问题。我有两个不同的摄像头,一个用于视频,另一个用于图像。为了提高效率,我将代码更改为使用唯一会话,并使应用程序更高效。

在我这样做之后,我的相机预览不能充分工作。当我使用4:3宽高比时,我的预览会在高处拉伸。换句话说,当我使用16:9的比例时,它看起来很好。在这两种情况下,我的照片看起来都很好,我的意思是,预览不能正确工作,但是我拍的照片有正确的宽高比。

我已经用同样的问题检查了不同的帖子:相机预览在一些Android设备上拉伸

全屏相机显示/预览无法保持纵横比-图像倾斜、拉伸以适应屏幕

但是不同的答案对我没有帮助。我知道问题出在我的on测量()setTransformMatrix()OnLayoutChangeListener()方法中,但是我不知道我做错了什么。

忽略关于旋转的代码,现在它是动态的。它总是在其他条件下进入。

这是我的密码:

private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right,
                               int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {

        Log.d(TAG, "[onLayoutChange] " + mCameraUI.getTextureView().getMeasuredWidth() + "x" + mCameraUI.getTextureView().getMeasuredHeight());

        int width = right - left;
        int height = bottom - top;
        if (mPreviewWidth != width || mPreviewHeight != height
                || (mOrientationResize != mPrevOrientationResize)
                || mAspectRatioResize || mOrientationChanged) {

            Log.i(TAG, "[onLayoutChange] Layout changed");
            mPreviewWidth = width;
            mPreviewHeight = height;
            Log.i(TAG, "[onLayoutChange] Preview size: "+ mPreviewWidth + "x" + mPreviewHeight);
            setTransformMatrix(width, height);
            mController.onScreenSizeChanged((int) mSurfaceTextureUncroppedWidth,
                    (int) mSurfaceTextureUncroppedHeight);
            mAspectRatioResize = false;
            mOrientationChanged = true;
        }
    }
};

集合变换

 private void setTransformMatrix(int width, int height) {


    Log.i(TAG, "Screen: " + mPreviewWidth + "x" + mPreviewHeight);

    mMatrix = new Matrix();
    //mCameraUI.getTextureView().getTransform(mMatrix);
    float scaleX = 1f, scaleY = 1f;
    float scaledTextureWidth, scaledTextureHeight;

     mAspectRatio= (float)height/(float)width;
    if (mAspectRatio==(4f / 3f)){

            scaledTextureWidth = Math.max(width,
                    (int) (height / mAspectRatio));
            scaledTextureHeight = Math.max(height,
                    (int) (width * mAspectRatio));
        Log.i(TAG, "[PhotoUIManager]: Aspect Ratio 4:3=" + scaledTextureWidth + "x" + scaledTextureHeight );
    }
    else{
        scaledTextureWidth = Math.max(width,
                (int) (height / mAspectRatio));
        scaledTextureHeight = Math.max(height,
                (int) (width * mAspectRatio));
        Log.i(TAG, "[PhotoUIManager]: Aspect Ratio 16:9=" + scaledTextureWidth + "x" + scaledTextureHeight );
    }       


    if (mSurfaceTextureUncroppedWidth != scaledTextureWidth || mSurfaceTextureUncroppedHeight != scaledTextureHeight) {
        Log.e(TAG,"mi SurfaceWidth = " + mSurfaceTextureUncroppedWidth + "and mi scaledWidth=" + scaledTextureWidth);
        Log.e(TAG,"mi SurfaceHeigh = " + mSurfaceTextureUncroppedHeight + "and mi scaledHeight=" + scaledTextureHeight);
        mSurfaceTextureUncroppedWidth = scaledTextureWidth;
        mSurfaceTextureUncroppedHeight = scaledTextureHeight;
        Log.e(TAG,"Surfaces: " + mSurfaceTextureUncroppedWidth + "x" + mSurfaceTextureUncroppedHeight);
        if (mSurfaceTextureSizeListener != null) {
            mSurfaceTextureSizeListener.onSurfaceTextureSizeChanged(
                    (int) mSurfaceTextureUncroppedWidth, (int) mSurfaceTextureUncroppedHeight);
        }
    }
    scaleX = scaledTextureWidth / width;
    scaleY = scaledTextureHeight / height;
    mMatrix.setScale(scaleX, scaleY, scaledTextureWidth/2, scaledTextureHeight/2);
    Log.e(TAG, "scale: X= " + scaleX + " Y=" + scaleY + "Width= " + scaledTextureWidth + "Height= " + scaledTextureHeight);

    // init the position (this seems to be necessary too when the ratio is 16/9
    mCameraUI.getTextureView().setX(0);
    mCameraUI.getTextureView().setY(0);

    // Translate the preview with the rotation is aspect ration is 4/3
    if (mAspectRatio == 4f / 3f) {
        Log.e(TAG, "aspect ratio standard");
        float verticalTranslateOffset = (mCameraUI.getTextureView().getMeasuredHeight() - scaledTextureHeight) / 2;
        float horizontalTranslateOffset = (mCameraUI.getTextureView().getMeasuredWidth() - scaledTextureWidth) / 2;
        int rotation = CameraUtil.getDisplayRotation(mActivity);
        switch (rotation) {
            case 0:
                // phone portrait; translate the preview up
                mCameraUI.getTextureView().setY(-verticalTranslateOffset);
                mFaceView.setStandardPreviewTranslationOffset(-verticalTranslateOffset);
                mFocusView.setStandardPreviewTranslationOffset(-verticalTranslateOffset);
                break;
            case 90:
                // phone landscape: translate the preview left
                mCameraUI.getTextureView().setX(-horizontalTranslateOffset);
                mFaceView.setStandardPreviewTranslationOffset(-horizontalTranslateOffset);
                mFocusView.setStandardPreviewTranslationOffset(-horizontalTranslateOffset);
                break;
            case 180:
                // phone upside down: translate the preview bottom
                mCameraUI.getTextureView().setY(verticalTranslateOffset);
                mFaceView.setStandardPreviewTranslationOffset(verticalTranslateOffset);
                mFocusView.setStandardPreviewTranslationOffset(verticalTranslateOffset);
                break;
            case 270:
                // reverse landscape: translate the preview right
                mCameraUI.getTextureView().setX(horizontalTranslateOffset);
                mFaceView.setStandardPreviewTranslationOffset(horizontalTranslateOffset);
                mFocusView.setStandardPreviewTranslationOffset(horizontalTranslateOffset);
                break;
        }

    } else {
        Log.e(TAG, "aspect ratio full");
        mFaceView.setStandardPreviewTranslationOffset(0);
        mFocusView.setStandardPreviewTranslationOffset(0);
    }

    mRenderOverlay.updateLayout();
    mCameraUI.getTextureView().setTransform(mMatrix);

    RectF previewRect = new RectF(0, 0, width, height);

    mController.onPreviewRectChanged(CameraUtil.rectFToRect(previewRect));

}

测量

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    Log.d(TAG, "onMeasure PREVIOUS. Width x Height [" + widthMeasureSpec + " = " + width + "x" + heightMeasureSpec + " = " + height + "]");

    int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation();
    boolean isInHorizontal = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation;

    int newWidth;
    int newHeight;

    if (isInHorizontal) {

        newHeight = getMeasuredHeight();
        newWidth = (int) (newHeight * mAspectRatio);
    } else {

        newWidth = getMeasuredWidth();
        newHeight = (int) (newWidth * mAspectRatio);
    }

    setMeasuredDimension(newWidth, newHeight);
    Log.d(TAG, "onMeasure. Width x Height [" + newWidth + "x" + newHeight + "]");

}

共有1个答案

卢和昶
2023-03-14

解决了的!

我的纹理的BufferSize有一个默认值,当我初始化一个新会话或更改after ratio后会重新启动。但是纹理的宽度和高度值没有随比率更新,因此它会一次又一次地拉伸。

我解决了它改变我的默认缓冲区大小与预览大小,我总是更新,我改变比率。

   public void createCameraPreviewSession(Size previewsize, Surface recordingSurface) {
    try {
        if (mCaptureSession != null) {
            mCaptureSession.stopRepeating();
            mCaptureSession.close();
            mCaptureSession = null;
        }

        SurfaceTexture texture = mTextureView.getSurfaceTexture();
        assert texture != null;

        List<Surface> surfaces = new ArrayList<Surface>();

        // We configure the size of default buffer to be the size of camera preview we want.
        texture.setDefaultBufferSize(previewsize.getWidth(),previewsize.getHeight());
        ;
        // This is the output Surface we need to start preview.
        Surface surface = new Surface(texture);
.......
 类似资料:
  • 我一直在努力在Android上制作我的自定义相机活动,但当旋转相机时,表面视图的纵横比会变得混乱。 在我的oncreate for the activity中,我设置了framelayout,它保存了显示相机参数的曲面视图。 然后,在曲面视图中,我设置要显示的相机参数 您可以看到,当手机旋转时,乐高男会变得更高、更瘦: 如何确保相机视图的纵横比正确?

  • 注意:“设备预览”功能已从 Photoshop CC 2007 年 10 月版中移除。此外,自 2017 年 10 月起,Preview CC iOS 应用程序将不再可供下载,也不再进行有效维护。如果您的 iOS 设备上之前已下载了 Preview CC 版本,则可以继续照常将其与 Photoshop 的早期版本配合使用。 此页面的信息与 Photoshop 的早期版本相关。 通过 Photosh

  • 我使用相机仅显示预览(不拍照或录制视频)。 该应用程序始终处于竖屏状态(横向模式被禁用)。相机预览始终旋转90度ccw,我无法更改它(无论是还是和。 预览总是这样旋转还是依赖于设备?如果在纵向模式下总是这样,我可以在之后旋转图像。 或者有没有办法正确设置摄像头?我读了很多关于这个的帖子,但没有一个答案对我有用(Galaxy s2,Android v2.3)

  • 请帮助正确配置Android摄像头(在HTC Desire 2.3.3上测试),以便在旋转(人像)模式下从摄像头预览。预览必须占用屏幕的一半以下,它的宽度必须等于设备的宽度,缩放必须根据相机的纵横比动态设置。我的当前代码: 活动布局: AndroidManifest配置为肖像: 你可以看到图像的比例不对。如何使以适当的比例显示旋转和缩放相机预览? 部分代码取自Mixare开源项目,http://w

  • 我正在创建一个相机应用程序,实现它自己的相机预览拍照。该应用目前强制进入人像模式。 我的问题是来自相机的预览略有拉伸(纵横比有点偏)。有趣的是,我正在设置我的SurfaceView大小总是匹配预览大小。这确保纵横比应始终保持...但它不是... 下面是我用来展示相机预览的布局:

  • 我正在用相机显示预览。应用程序始终处于纵向模式(禁用横向模式)。相机预览总是逆时针旋转90度,我无法更改它(无论是使用setDisplayOrientation还是使用p.set(“方向”,“肖像”)和p.set(“旋转”,90))。 预览总是这样旋转还是依赖于设备?如果在纵向模式下总是这样,我可以在之后旋转图像。 我将手机保持在“纵向模式”,但cameraPreview处于横向模式(即,我看到某