最近项目使用JCameraView录制小视频,发现预览时图像被拉伸了,无奈的我只能下源码查找了下原因了。
最终整合了下,感觉还可以用,特此记录下,希望能帮助更多人。
项目地址:
https://github.com/CJT2325/CameraView
解决方案如下:
JCameraView下
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
float widthSize = mVideoView.getMeasuredWidth();
float heightSize = mVideoView.getMeasuredHeight();
if (screenProp == 0) {
screenProp = heightSize / widthSize;
}
}
这个方法获取了videoView的大小,我发现是10802340
当进入CameraInterface匹配分辨率时,找到的最合适的分辨率是7201440
前者是2340/1080=2.166的比率,而后者是1440/720=2.0的比率,
最终使用2.0的比率来填充2.1的比率的手机时,就会出现拉伸现象,我的是竖屏可以,横过来就拉伸了。
结合网上的说法,参考这篇文章:
https://blog.csdn.net/u012674854/article/details/80239371
我给整合过来。
在JCameraView下新添加方法:
private void setSuitableParams() {
if (screenProp > 1.8) { //屏幕的宽高比大于1.8的时候处理
float previewProp = CameraInterface.getInstance().getPrevewProp();
if (previewProp == 0 || mVideoView == null) { //获取的size宽高比
return;
}
int measuredHeight = mVideoView.getMeasuredHeight();
int measuredWidth = mVideoView.getMeasuredWidth();
float clacWidth = measuredHeight / previewProp; //计算出要显示的预览界面的宽度。
ViewGroup.LayoutParams layoutParams = mVideoView.getLayoutParams();
if (layoutParams == null) {
layoutParams = new ViewGroup.LayoutParams((int) clacWidth, measuredHeight);
}
// if (clacWidth > 800 && Math.abs(clacWidth - measuredWidth) > clacWidth * 0.1F) { //计算的宽度大于 800 并且和显示正常的布局的误差超过10%
layoutParams.width = (int) clacWidth;
// }
final ViewGroup.LayoutParams finalLayoutParams = layoutParams;
mVideoView.post(new Runnable() {
@Override
public void run() {
if (mVideoView != null && finalLayoutParams != null) {
mVideoView.setLayoutParams(finalLayoutParams);
}
}
});
}
}
这里的10%的误差我给屏蔽了,因为我发现,我的就是误差45像素,在10%之内。
在CameraInterface的doStartPreview方法中添加:
prevewProp = previewSize.width / previewSize.height;
获取当前比率。
最后在
@Override
public void cameraHasOpened() {
CameraInterface.getInstance().doStartPreview(mVideoView.getHolder(), screenProp);
setSuitableParams();
}
启动摄像头后重新绘制下videoView的布局。
private float prevewProp;
public float getPrevewProp() {
return prevewProp;
}
public void doStartPreview(SurfaceHolder holder, float screenProp) {
if (isPreviewing) {
LogUtil.i("doStartPreview isPreviewing");
}
if (this.screenProp < 0) {
this.screenProp = screenProp;
}
if (holder == null) {
return;
}
this.mHolder = holder;
if (mCamera != null) {
try {
mParams = mCamera.getParameters();
Camera.Size previewSize = CameraParamUtil.getInstance().getPreviewSize(mParams
.getSupportedPreviewSizes(), 1000, screenProp);
Camera.Size pictureSize = CameraParamUtil.getInstance().getPictureSize(mParams
.getSupportedPictureSizes(), 1200, screenProp);
prevewProp = (float) previewSize.width / (float) previewSize.height;
mParams.setPreviewSize(previewSize.width, previewSize.height);
preview_width = previewSize.width;
preview_height = previewSize.height;
mParams.setPictureSize(pictureSize.width, pictureSize.height);
if (CameraParamUtil.getInstance().isSupportedFocusMode(
mParams.getSupportedFocusModes(),
Camera.Parameters.FOCUS_MODE_AUTO)) {
mParams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
if (CameraParamUtil.getInstance().isSupportedPictureFormats(mParams.getSupportedPictureFormats(),
ImageFormat.JPEG)) {
mParams.setPictureFormat(ImageFormat.JPEG);
mParams.setJpegQuality(100);
}
mCamera.setParameters(mParams);
mParams = mCamera.getParameters();
mCamera.setPreviewDisplay(holder); //SurfaceView
mCamera.setDisplayOrientation(cameraAngle);//浏览角度
mCamera.setPreviewCallback(this); //每一帧回调
mCamera.startPreview();//启动浏览
isPreviewing = true;
Log.i(TAG, "=== Start Preview ===");
} catch (IOException e) {
e.printStackTrace();
}
}
}
好了,就这些,希望能帮助有用的人。