Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/227.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何获得像Instagram一样的1:1比例的Android Camera2?_Android_Android Camera2 - Fatal编程技术网

如何获得像Instagram一样的1:1比例的Android Camera2?

如何获得像Instagram一样的1:1比例的Android Camera2?,android,android-camera2,Android,Android Camera2,我的问题很简单: 如何获得AndroidAndroid.hardware.Camera2的比例为1:1且不会像Instagram那样变形 我用GoogeSamples项目进行了测试。但当我以1:1的比例更改预览时,图像会变形。有人对此有想法吗 谢谢@commonware 我遵循了你的建议,使用了负边距(顶部和底部),效果很好 为此,我只需通过以下方式更新GoogeSamples项目: public class AutoFitTextureView extends TextureView {

我的问题很简单:

如何获得Android
Android.hardware.Camera2
的比例为1:1且不会像Instagram那样变形


我用GoogeSamples项目进行了测试。但当我以1:1的比例更改预览时,图像会变形。有人对此有想法吗

谢谢@commonware

我遵循了你的建议,使用了负边距(顶部和底部),效果很好

为此,我只需通过以下方式更新GoogeSamples项目:

public class AutoFitTextureView extends TextureView {

    //...
    private boolean mWithMargin = false;

    //...

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int margin = (height - width) / 2;

        if(!mWithMargin) {
            mWithMargin = true;
            ViewGroup.MarginLayoutParams margins = ViewGroup.MarginLayoutParams.class.cast(getLayoutParams());
            margins.topMargin = -margin;
            margins.bottomMargin = -margin;
            margins.leftMargin = 0;
            margins.rightMargin = 0;
            setLayoutParams(margins);
        }

        if (0 == mRatioWidth || 0 == mRatioHeight) {
            setMeasuredDimension(width, height);
        } else {
            if (width < height) {
                setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
            } else {
                setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
            }
        }
    }
}
公共类AutoFitTextureView扩展了TextureView{
//...
私有布尔值mWithMargin=false;
//...
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
超级测量(widthMeasureSpec,widthMeasureSpec);
int width=MeasureSpec.getSize(widthmasurespec);
int height=MeasureSpec.getSize(heightMeasureSpec);
整型边距=(高度-宽度)/2;
如果(!mWithMargin){
mWithMargin=真;
ViewGroup.MarginLayoutParams margins=ViewGroup.MarginLayoutParams.class.cast(getLayoutParams());
margins.topMargin=-margin;
margins.bottomMargin=-保证金;
margins.leftMargin=0;
margins.rightMargin=0;
setLayoutParams(边距);
}
如果(0==mRatioWidth | | 0==mRatioHeight){
设置测量尺寸(宽度、高度);
}否则{
if(宽度<高度){
设置测量尺寸(宽度、宽度*mRatioHeight/mRatioWidth);
}否则{
设置测量尺寸(高度*mRatioWidth/mRatioHeight,高度);
}
}
}
}

创建如下自定义纹理视图:

public class AutoFitTextureView extends TextureView {

    private int mCameraWidth = 0;
    private int mCameraHeight = 0;
    private boolean mSquarePreview = false;

    public AutoFitTextureView(Context context) {
        this(context, null);
    }

    public AutoFitTextureView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setAspectRatio(int width, int height, boolean squarePreview) {
        if (width < 0 || height < 0) {
            throw new IllegalArgumentException("Size cannot be negative.");
        }
        mCameraWidth = width;
        mCameraHeight = height;
        mSquarePreview = squarePreview;
        requestLayout();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (0 == mCameraWidth || 0 == mCameraHeight) {
            setMeasuredDimension(width, height);
        } else {
            /**
             * Vertical orientation
             */
            if (width < height) {
                if (mSquarePreview) {
                    setTransform(squareTransform(width, height));
                    setMeasuredDimension(width, width);
                } else {
                    setMeasuredDimension(width, width * mCameraHeight / mCameraWidth);
                }
            }
            /**
             * Horizontal orientation
             */
            else {
                if (mSquarePreview) {
                    setTransform(squareTransform(width, height));
                    setMeasuredDimension(height, height);
                } else {
                    setMeasuredDimension(height * mCameraWidth / mCameraHeight, height);
                }
            }
        }
    }

    private Matrix setupTransform(int sw, int sh, int dw, int dh) {
        Matrix matrix = new Matrix();
        RectF src = new RectF(0, 0, sw, sh);
        RectF dst = new RectF(0, 0, dw, dh);
        RectF screen = new RectF(0, 0, dw, dh);

        matrix.postRotate(-90, screen.centerX(), screen.centerY());
        matrix.mapRect(dst);

        matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
        matrix.mapRect(src);

        matrix.setRectToRect(screen, src, Matrix.ScaleToFit.FILL);
        matrix.postRotate(-90, screen.centerX(), screen.centerY());

        return matrix;
    }

    private Matrix squareTransform(int viewWidth, int viewHeight) {
        Matrix matrix = new Matrix();

        if (viewWidth < viewHeight) {
            MyLogger.log(AutoFitTextureView.class, "Horizontal");
            matrix.setScale(1, (float) mCameraHeight / (float) mCameraWidth, viewWidth / 2, viewHeight / 2);
        } else {
            MyLogger.log(AutoFitTextureView.class, "Vertical");
            matrix.setScale((float) mCameraHeight / (float) mCameraWidth, 1, viewWidth / 2, viewHeight / 2);
        }

        return matrix;
    }
}

我是通过布局来实现的,这样一来,谷歌代码就可以保持原样,并根据用户界面自动设置1:1的预览

    <android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@id/footer"
    android:layout_below="@id/header">

    <com.example.android.camera2video.AutoFitTextureView
        android:id="@+id/texture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</android.support.constraint.ConstraintLayout>

只需将AutoFitTextureView放入ConstraintLayout中,然后

previewSize=chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class)),
宽度、高度、尺寸);

所有的魔法对任何想找这个的人来说,我试过了。添加边距以隐藏textureview的一部分,使其在预览中看起来方形。但在保存图像时,还应删除输出图像中的隐藏区域

一个更简单的解决方案是显示完整的textureview,并在其上覆盖一些其他布局,使其看起来方形。您可以轻松地从输出中裁剪图像


您可以找到示例代码

“但是当我以1:1的比率更改预览时,图像会变形”--除非您提供代码,否则我们无法帮助您调试您的代码,因为这是示例代码的一部分。一般来说,答案是让
SurfaceView
TextureView
与相机外的图像具有相同的纵横比,但随后使用负边距或等效的渲染技巧,仅显示来自相机的图像的平方子集。谢谢@commonware。使用负边距更正我的问题。我在回复中发布了我的代码。@lopez.mikhael您是如何更改纵横比的?看看@lopez.mikhael:我想以类似的方式实现它,你是如何将方面比例设置为1:1的?嗨!我也有同样的问题。我添加了AutoFitTextureView的实现,但它仍然不起作用。你能不能提供一些你的应用程序代码,使相机预览和图片在广场上?谢谢当我这样做时,我会在预览的底部看到一个黑条。。有什么想法吗?嗨,米克尔!我尝试实施您的解决方案,但不起作用。你能给我发一个完整的实现吗?太棒了!这里的
videoSize
是什么?
    <android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@id/footer"
    android:layout_below="@id/header">

    <com.example.android.camera2video.AutoFitTextureView
        android:id="@+id/texture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintDimensionRatio="w,1:1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</android.support.constraint.ConstraintLayout>