如何获得像Instagram一样的1:1比例的Android Camera2?
我的问题很简单: 如何获得Android如何获得像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.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>