我们OpenCv采用的是JavaCameraView 类,本质还是调用的相机,找的相机的设置代码。
发现在JavaCameraView 中有个initializeCamera 方法,在此方法中修改
...
protected boolean initializeCamera(int width, int height) {
Log.d(TAG, "Initialize java camera");
boolean result = true;
synchronized (this) {
mCamera = null;
if (mCameraIndex == CAMERA_ID_ANY) {
Log.d(TAG, "Trying to open camera with old open()");
try {
mCamera = Camera.open();
} catch (Exception e) {
Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage());
}
if (mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
boolean connected = false;
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")");
try {
mCamera = Camera.open(camIdx);
connected = true;
} catch (RuntimeException e) {
Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage());
}
if (connected)
break;
}
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
int localCameraIndex = mCameraIndex;
if (mCameraIndex == CAMERA_ID_BACK) {
Log.i(TAG, "Trying to open back camera");
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
localCameraIndex = camIdx;
break;
}
}
} else if (mCameraIndex == CAMERA_ID_FRONT) {
Log.i(TAG, "Trying to open front camera");
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
localCameraIndex = camIdx;
break;
}
}
}
if (localCameraIndex == CAMERA_ID_BACK) {
Log.e(TAG, "Back camera not found!");
} else if (localCameraIndex == CAMERA_ID_FRONT) {
Log.e(TAG, "Front camera not found!");
} else {
Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(localCameraIndex) + ")");
try {
mCamera = Camera.open(localCameraIndex);
} catch (RuntimeException e) {
Log.e(TAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage());
}
}
}
}
if (mCamera == null)
return false;
/* Now set camera parameters */
try {
Camera.Parameters params = mCamera.getParameters();
Log.d(TAG, "getSupportedPreviewSizes()");
List<android.hardware.Camera.Size> sizes = params.getSupportedPreviewSizes();
if (sizes != null) {
/* Select the size that fits surface considering maximum size allowed */
Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
/* Image format NV21 causes issues in the Android emulators */
if (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT))
params.setPreviewFormat(ImageFormat.YV12); // "generic" or "android" = android emulator
else
params.setPreviewFormat(ImageFormat.NV21);
mPreviewFormat = params.getPreviewFormat();
Log.d(TAG, "Set preview size to " + Integer.valueOf((int) frameSize.width) + "x" + Integer.valueOf((int) frameSize.height));
params.setPreviewSize((int) frameSize.width, (int) frameSize.height);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !android.os.Build.MODEL.equals("GT-I9100"))
params.setRecordingHint(true);
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
//此处设置相机的参数
mCamera.setParameters(params);
//自己写了个相机预览适配的方法
setCameraParameters();
params = mCamera.getParameters();
mFrameWidth = params.getPreviewSize().width;
mFrameHeight = params.getPreviewSize().height;
if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))
mScale = Math.min(((float) height) / mFrameHeight, ((float) width) / mFrameWidth);
else
mScale = 0;
if (mFpsMeter != null) {
mFpsMeter.setResolution(mFrameWidth, mFrameHeight);
}
int size = mFrameWidth * mFrameHeight;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
mCamera.addCallbackBuffer(mBuffer);
mCamera.setPreviewCallbackWithBuffer(this);
mFrameChain = new Mat[2];
mFrameChain[0] = new Mat(mFrameHeight + (mFrameHeight / 2), mFrameWidth, CvType.CV_8UC1);
mFrameChain[1] = new Mat(mFrameHeight + (mFrameHeight / 2), mFrameWidth, CvType.CV_8UC1);
AllocateCache();
mCameraFrame = new JavaCameraFrame[2];
mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], mFrameWidth, mFrameHeight);
mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], mFrameWidth, mFrameHeight);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
mCamera.setPreviewTexture(mSurfaceTexture);
} else
mCamera.setPreviewDisplay(null);
/* Finally we are ready to start the preview */
Log.d(TAG, "startPreview");
mCamera.startPreview();
} else
result = false;
} catch (Exception e) {
result = false;
e.printStackTrace();
}
}
return result;
}
...
只有在设置的地方修改即可,完美解决大部分手机预览图片压缩问题,扁了或者长了
/**
* 获取屏幕的宽度
*
* @param context context
* @return
*/
public int getScreenWidth(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return displayMetrics.widthPixels;
}
/**
* 获取屏幕的高度
*
* @param context context
* @return
*/
public int getScreenHeight(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return displayMetrics.heightPixels;
}
/**
* 设置照相机参数
*/
private void setCameraParameters() {
if (mCamera == null)
return;
Camera.Parameters parameters = mCamera.getParameters();
// 选择合适的预览尺寸
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
Collections.sort(sizeList, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
return rhs.height - lhs.height;
}
});
Camera.Size tempSize = null;
for (Camera.Size size : sizeList) {
if (size.width *getScreenWidth(mContext) ==getScreenHeight(mContext) * size.height) {
tempSize = size;// parameters.setPreviewSize(size.width, size.height);
break;
}
}
if (tempSize == null) {
for (Camera.Size size : sizeList) {
//小于100W像素
if (size.width * 16 == 9 * size.height) {
tempSize = size;// parameters.setPictureSize(size.width, size.height);
break;
}
}
}
if (tempSize == null) {
for (Camera.Size size : sizeList) {
//小于100W像素
if (size.width * 9 == 16 * size.height) {
tempSize = size;// parameters.setPictureSize(size.width, size.height);
break;
}
}
}
if (tempSize == null) {
tempSize = sizeList.get(0);
}
parameters.setPreviewSize(tempSize.width, tempSize.height);
tempSize = null;
//设置生成的图片大小
sizeList = parameters.getSupportedPictureSizes();
Collections.sort(sizeList, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
return rhs.height - lhs.height;
}
});
if (sizeList.size() > 0) {
for (Camera.Size size : sizeList) {
//小于100W像素
if (size.width * getScreenWidth(mContext) == getScreenHeight(mContext) * size.height) {
tempSize = size;// parameters.setPictureSize(size.width, size.height);
break;
}
}
}
if (tempSize == null) {
for (Camera.Size size : sizeList) {
//小于100W像素
if (size.width * 16 == 9 * size.height) {
tempSize = size;// parameters.setPictureSize(size.width, size.height);
break;
}
}
}
if (tempSize == null) {
for (Camera.Size size : sizeList) {
//小于100W像素
if (size.width * 9 == 16 * size.height) {
tempSize = size;// parameters.setPictureSize(size.width, size.height);
break;
}
}
}
if (tempSize == null) {
tempSize = sizeList.get(0);
}
parameters.setPictureSize(tempSize.width, tempSize.height);
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
/* Image format NV21 causes issues in the Android emulators */
if (Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT))
parameters.setPreviewFormat(ImageFormat.YV12); // "generic" or "android" = android emulator
else
parameters.setPreviewFormat(ImageFormat.NV21);
// //设置图片格式
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setRotation(270);
parameters.setJpegQuality(100);
parameters.setJpegThumbnailQuality(100);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !android.os.Build.MODEL.equals("GT-I9100"))
parameters.setRecordingHint(true);
List<String> FocusModes = parameters.getSupportedFocusModes();
if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
//自动聚焦模式
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
try {
mCamera.setParameters(parameters);
} catch (Exception e) {
e.printStackTrace();
//非常罕见的情况
//个别机型在SupportPreviewSizes里汇报了支持某种预览尺寸,但实际是不支持的,设置进去就会抛出RuntimeException.
e.printStackTrace();
try {
//遇到上面所说的情况,只能设置一个最小的预览尺寸
parameters.setPreviewSize(1080, 1920);
mCamera.setParameters(parameters);
} catch (Exception e1) {
//到这里还有问题,就是拍照尺寸的锅了,同样只能设置一个最小的拍照尺寸
e1.printStackTrace();
try {
parameters.setPictureSize(1080, 1920);
mCamera.setParameters(parameters);
} catch (Exception ignored) {
}
}
}
//开启屏幕朝向监听
}