自定义相机所踩的坑,现在分享出来希望能够帮助的有需要的小伙伴
由于项目的需要,需要在fragment们中嵌入一个自定义相机。其中在此过程中遇到了几个比较需要注意的问题下面给大家分享一下。
对于如何自定义相机我就不多说了,已经有很多人写过相关的博客。
1、如何实现自动对焦
首先设置的属性
Camera.Parameters myParam =camera.getParameters();
myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.autoFocus(this);
camera.cancelAutoFocus(); //这句话一定要加上否则将不会自动对焦
2、相机预览变形
相机预览变形的原因是由于底层返回的预览大小和你设置预览界面的大小不一致导致的,也就是surfaceview的大小(更准确的说是宽高比),而我们无法去控制底层返回预览的大小
我们能做的只有2件事情,一、改变surfaceview的大小,二、从底层返回的大小中选出一个宽高比最接近的大小设置。具体代码为:
camera.stopPreview();
Camera.Parameters parameters = camera.getParameters();
Camera.Size sizes = getBestPreviewSize(width, height);
if (sizes != null) {
parameters.setPreviewSize(sizes.width, sizes.height);
camera.setParameters(parameters);
}
此方法有点小瑕疵就是有可能会找不到小于0.1差值,返回就是null 所以需要在使用是先判断是否为空,或者在方法里边改进一下,具体如何改相信大家都可以
改进,容我偷个小懒就不改了。
private Camera.Size getBestPreviewSize(int width, int height) {
Camera.Size result = null;
final Camera.Parameters p = camera.getParameters();
//特别注意此处需要规定rate的比是大的比小的,不然有可能出现rate = height/width。
float rate = (float) Math.max(width, height) / (float) Math.min(width, height);
float tmp_diff;
float min_diff = 0.1f;
for (Camera.Size size : p.getSupportedPreviewSizes()) {
float current_rate = (float) Math.max(size.width, size.height) / (float) Math.min(size.width, size.height);
tmp_diff = Math.abs(current_rate - rate);
if (tmp_diff < min_diff) {
min_diff = tmp_diff;
result = size;
}
}
return result;
}
经过上面的方法筛选后还有可能会有一点点变形,如果客户需要继续改进则需要改变surfaceview的大小去调节,让它能找到完全贴合的比例就可以了
3、内存溢出
这个问题可能对于许多安卓开发者都会比较头疼,因为如果应用内存溢出了那往往不是一个地方导致的,而是可能多处地方导致的。有可能是有内存泄漏了没办法及时回收,
也有可能是某些资源占用内存太大直接导出溢出。
对于内存泄漏给大家极力推荐使用leakcanary检测(谁用谁知道),检测出来了就是修改啦。
对于占用资源太大的一般来说这都是bitmap的锅,所以对于使用完bitmap之后一定要recycle()
还有一个是帧动画使用完之后记得马上clear.
除此之外我们还可以通过设置options.inSampleSize来控制bitmap返回的大小下面给出我的处理方法
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = false; //此属性设置为true是将不会返回真正的bitmap,但会返回bitmap的宽和高可以通过返回的宽高去inSampleSize的值从
//而改变bimap的大小这或许是更为合理的办法,但我认为只有bitmap大小高过一定阀值才需要做此操作,但有可能第一次读取时就内存溢出了try-catch,在内存溢出时直接让他变形再次读取,不知道此方法合不合理欢迎大神指点。
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);// data是字节数据,将其解析成位图
if (mBitmap.getByteCount() > 60 * 1024 * 1024) { //读出bitmap先判断是否过大 如何过大则进行bitmap压缩重新读取 保存到本地时内存溢出
options.inSampleSize = 2;
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
此外还有一个地方可能会造成内存溢出,那就是在图片保存到本地的时候下面给出我的处理的办法
try {
fout = new FileOutputStream(jpegName);
BufferedOutputStream bos = new BufferedOutputStream(fout);
if (getBitmapSize(bmp) < 20*1024 * 1024) {
bmp.compress(Bitmap.CompressFormat.JPEG, 95, bos);
} else if (getBitmapSize(bmp) <40* 1024 * 1024) {
bmp.compress(Bitmap.CompressFormat.JPEG, 75, bos);
} else {
bmp.compress(Bitmap.CompressFormat.JPEG, 55, bos);
}
bmp.recycle();
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
还是通过根据bitmap的大小来进行不同程度的压缩
4、另外有某些手机拍照保存之后照片会旋转90度,这个可以根据你自己的相机的是横向还是竖向然后去判断通过bitmap的宽高去设置旋转
if (bitmap.getWidth() > bitmap.getHeight()) { //我的为竖屏拍照所以当宽大于高时候我把它旋转九十度
bitmap = ImageTools.rotateToDegrees(bitmap, 90);
}
/**
* 图片旋转
* @param tmpBitmap
* @param degrees
* @return
*/
public static Bitmap rotateToDegrees(Bitmap tmpBitmap, float degrees) {
Matrix matrix = new Matrix();
matrix.reset();
matrix.setRotate(degrees);
return tmpBitmap = Bitmap.createBitmap(tmpBitmap, 0, 0, tmpBitmap.getWidth(), tmpBitmap.getHeight(), matrix,
false);
}
- 点赞
- 收藏
- 关注作者
评论(0)