我的问题非常简单:
如何获得一个Android
android.hardware.Camera2
,它具有1:1的比例且没有像Instagram那样的变形?
我已经尝试使用GoogeSamples项目android-Camera2Basic进行测试。但是当我将预览更改为1:1比例时,图像会变形。有人对此有想法吗?
我的问题非常简单:
如何获得一个Android
android.hardware.Camera2
,它具有1:1的比例且没有像Instagram那样的变形?
我已经尝试使用GoogeSamples项目android-Camera2Basic进行测试。但是当我将预览更改为1:1比例时,图像会变形。有人对此有想法吗?
感谢@CommonsWare。
我按照您的建议使用负边距(上下)并且它有效。
为了做到这一点,我只需更新AutoFitTextureView在GoogeSamples项目android-Camera2Basic中,就像这样:
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);
}
}
}
}
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
这一行是故意这样写的吗?还是第二个参数应该是高度?即使我将其更改,你的解决方案仍然无效。请提供一个更新后的答案。谢谢。 - A S M Sayem <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>
previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height, videoSize);
videoSize
是什么? - Dipayan Ray
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;
}
}
在活动/片段中为您的纹理视图调用setAspectRatio。
if (mVideoSize.width > mVideoSize.height) {
mTextureView.setAspectRatio(mVideoSize.height, mVideoSize.width, true);
} else {
mTextureView.setAspectRatio(mVideoSize.width, mVideoSize.height, true);
}
mCamera.setPreviewTexture(mTextureView.getSurfaceTexture());
mCamera.startPreview();
SurfaceView
或TextureView
与相机拍摄的图像具有相同的纵横比,然后使用负边距或等效的渲染技巧,仅显示从相机中获取的正方形子集。 - CommonsWare