浅析Android Camera开发中的三个尺寸和三种变形 (贡献一个自适配Picturesize和Previewsize的工具类)
2015-08-02 10:11
661 查看
经常听人问Camera开发中,各种变形问题,今天有空就在此梳理总结下。
三个尺寸:
1、Surfaceview的尺寸
Surfaceview是用来预览Camera的,当它全屏时就是Screen的大小。
2、Picturesize的尺寸
这是拍照后的PictureSize尺寸。
3、Previewsize的尺寸
这是预览时帧数据的尺寸。
三种变形:
1、预览画面的物体长宽失真。原因是Surfaceview和Previewsize的长宽比率不一致,就会导致预览画面上失真。因为camera在显示时会将预览帧数据缩放成Surfaceview大小,当比率不一致必然会物体变形。至于这个缩放算法可能不同手机会有区别。
2、拍照后照片上物体变形。
3、点击拍照瞬间,预览画面上会突然变形然后恢复到正常预览。
2、3两种变形都是因为Previewsize和Picturesize的长宽比率不一致所致。总之一句话,为了保证图片不是真,要保证预览Surfaceview、Previewsize、Picturesize的长宽比率要一直。如果Surfaceview是全屏的话,要获取屏幕长和宽得到比率。
为此我写了一个工具类,获得合适的Picturesize和Previewsize,名字为:MyCamPara.java。
previewsize低的话 清晰度是会受影响,这个没有办法。预览尺寸设的小了,底层压力就小,预览更流畅。
[java] view
plaincopyprint?
package org.yanzi.util;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
public class MyCamPara {
private static final String tag = "yan";
private CameraSizeComparator sizeComparator = new CameraSizeComparator();
private static MyCamPara myCamPara = null;
private MyCamPara(){
}
public static MyCamPara getInstance(){
if(myCamPara == null){
myCamPara = new MyCamPara();
return myCamPara;
}
else{
return myCamPara;
}
}
public Size getPreviewSize(List<Camera.Size> list, int th){
Collections.sort(list, sizeComparator);
int i = 0;
for(Size s:list){
if((s.width > th) && equalRate(s, 1.33f)){
Log.i(tag, "最终设置预览尺寸:w = " + s.width + "h = " + s.height);
break;
}
i++;
}
return list.get(i);
}
public Size getPictureSize(List<Camera.Size> list, int th){
Collections.sort(list, sizeComparator);
int i = 0;
for(Size s:list){
if((s.width > th) && equalRate(s, 1.33f)){
Log.i(tag, "最终设置图片尺寸:w = " + s.width + "h = " + s.height);
break;
}
i++;
}
return list.get(i);
}
public boolean equalRate(Size s, float rate){
float r = (float)(s.width)/(float)(s.height);
if(Math.abs(r - rate) <= 0.2)
{
return true;
}
else{
return false;
}
}
public class CameraSizeComparator implements Comparator<Camera.Size>{
//按升序排列
public int compare(Size lhs, Size rhs) {
// TODO Auto-generated method stub
if(lhs.width == rhs.width){
return 0;
}
else if(lhs.width > rhs.width){
return 1;
}
else{
return -1;
}
}
}
}
对上面这个工具类注释如下:
1,是个单例模式类。调用示例:
[java] view
plaincopyprint?
Size pictureS = MyCamPara.getInstance().getPictureSize(pictureSizes, 800);
myParam.setPictureSize(pictureS.width, pictureS.height);
2,程序首先对预览尺寸的list进行升序排序,因为实际中发现,有的手机提供的是升序有的是降序。
3,通过equalRate(Size s, float rate)保证Size的长宽比率。一般而言这个比率为1.333/1.7777即通常说的4:3和16:9比率。
4、在getPreviewSize()函数里增加判断if((s.width > th) && equalRate(s, 1.33f)),除保证比率外,还保证用户需要设置的尺寸宽度最小值。这个大家根据需要随便改。
三个尺寸:
1、Surfaceview的尺寸
Surfaceview是用来预览Camera的,当它全屏时就是Screen的大小。
2、Picturesize的尺寸
这是拍照后的PictureSize尺寸。
3、Previewsize的尺寸
这是预览时帧数据的尺寸。
三种变形:
1、预览画面的物体长宽失真。原因是Surfaceview和Previewsize的长宽比率不一致,就会导致预览画面上失真。因为camera在显示时会将预览帧数据缩放成Surfaceview大小,当比率不一致必然会物体变形。至于这个缩放算法可能不同手机会有区别。
2、拍照后照片上物体变形。
3、点击拍照瞬间,预览画面上会突然变形然后恢复到正常预览。
2、3两种变形都是因为Previewsize和Picturesize的长宽比率不一致所致。总之一句话,为了保证图片不是真,要保证预览Surfaceview、Previewsize、Picturesize的长宽比率要一直。如果Surfaceview是全屏的话,要获取屏幕长和宽得到比率。
为此我写了一个工具类,获得合适的Picturesize和Previewsize,名字为:MyCamPara.java。
previewsize低的话 清晰度是会受影响,这个没有办法。预览尺寸设的小了,底层压力就小,预览更流畅。
[java] view
plaincopyprint?
package org.yanzi.util;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
public class MyCamPara {
private static final String tag = "yan";
private CameraSizeComparator sizeComparator = new CameraSizeComparator();
private static MyCamPara myCamPara = null;
private MyCamPara(){
}
public static MyCamPara getInstance(){
if(myCamPara == null){
myCamPara = new MyCamPara();
return myCamPara;
}
else{
return myCamPara;
}
}
public Size getPreviewSize(List<Camera.Size> list, int th){
Collections.sort(list, sizeComparator);
int i = 0;
for(Size s:list){
if((s.width > th) && equalRate(s, 1.33f)){
Log.i(tag, "最终设置预览尺寸:w = " + s.width + "h = " + s.height);
break;
}
i++;
}
return list.get(i);
}
public Size getPictureSize(List<Camera.Size> list, int th){
Collections.sort(list, sizeComparator);
int i = 0;
for(Size s:list){
if((s.width > th) && equalRate(s, 1.33f)){
Log.i(tag, "最终设置图片尺寸:w = " + s.width + "h = " + s.height);
break;
}
i++;
}
return list.get(i);
}
public boolean equalRate(Size s, float rate){
float r = (float)(s.width)/(float)(s.height);
if(Math.abs(r - rate) <= 0.2)
{
return true;
}
else{
return false;
}
}
public class CameraSizeComparator implements Comparator<Camera.Size>{
//按升序排列
public int compare(Size lhs, Size rhs) {
// TODO Auto-generated method stub
if(lhs.width == rhs.width){
return 0;
}
else if(lhs.width > rhs.width){
return 1;
}
else{
return -1;
}
}
}
}
对上面这个工具类注释如下:
1,是个单例模式类。调用示例:
[java] view
plaincopyprint?
Size pictureS = MyCamPara.getInstance().getPictureSize(pictureSizes, 800);
myParam.setPictureSize(pictureS.width, pictureS.height);
2,程序首先对预览尺寸的list进行升序排序,因为实际中发现,有的手机提供的是升序有的是降序。
3,通过equalRate(Size s, float rate)保证Size的长宽比率。一般而言这个比率为1.333/1.7777即通常说的4:3和16:9比率。
4、在getPreviewSize()函数里增加判断if((s.width > th) && equalRate(s, 1.33f)),除保证比率外,还保证用户需要设置的尺寸宽度最小值。这个大家根据需要随便改。
相关文章推荐
- Android ListView工作原理完全解析
- Android项目打包成APK文件
- android 进程/线程管理(二)----关于线程的迷思
- 需要根据字典获得drawable,只能写if-else吗
- [深入理解Android卷一全文-第三章]深入理解init
- Android Studio 1.2使用过程问题总结
- Android错误_adb不是内部或外部命令,也不是可运行的程序
- 超越系统权限----Android黑名单电话拦截
- [深入理解Android卷一全文-第三章]深入理解init
- Android 下拉框的实现
- [深入理解Android卷一 全文-第二章]深入理解JNI
- [深入理解Android卷一 全文-第二章]深入理解JNI
- Android_打开DDMS没有文件夹显示
- Android 菜单——上下文菜单、选择菜单以及子菜单
- [深入理解Android卷一全文-第一章]阅读前的准备工作
- Android 属性动画总小结
- 关于Android5.x适配的一点小问题(NDK error: SIGABRT)
- Android AsyncTask usage
- android自定义渐变圆环进度条
- Android差量更新