我的应用程序需要以纵向方式捕获一些给定大小的图片(比方说WxH)。
在一般情况下,相机不支持我想要的尺寸WxH,因此我需要裁剪拍摄的照片以符合我的规格。
这个看似简单的程序让我对预览和图片大小和格式之间的“好”相关问题感到疯狂。 让我解释一下:
我需要输出图像的格式(让我们给出一些数字:800x600),我必须以纵向屏幕方向拍摄照片。默认情况下,我的相机处于横向模式,因此它拍摄的宽度远大于高度。但是因为我想要一个肖像预览,我需要旋转图像,因此我得到的图像的高度远大于宽度(我想是原始图像的转置)。
在这种情况下,我需要从一个更大的垂直扩展矩形切割一个水平扩展的矩形,我想通过一个可加入的大预览来做到这一点。
从图片中裁剪出图像的问题并没有吓到我(暂时),平均问题是用户在预览中看到的内容与相机实际捕获的内容之间的匹配。
我需要的每部手机:
- 根据所需的图像格式选择合适的相机图片尺寸
- 根据图像尺寸和格式选择合适的相机预览尺寸
- 隐藏将被裁剪的预览部分
并且具有无失真和大预览的约束。
一般怎么办?
我的想法和尝试:
主要算法步骤是:
- 获知所需格式后的最佳图片尺寸
- 一旦知道图片尺寸
,即可获得最佳预览尺寸
- 隐藏不可预览的部分
- 裁剪图像
尝试方法1)
A)通过最小化面积差异得到最佳图像尺寸(我还可以检查纵横比亲和力不是很重要)。 (大小是与Camera.Size不同的自定义类型)
public Size getOptimalPictureSize(List<Camera.Size> sizes) {
Size opt = new Size();
float objf = Float.MAX_VALUE;
float v;
for(Camera.Size s : sizes){
if(s.height<target_size.width || s.width<target_size.height)
continue;
v = (s.height-target_size.width)*s.width + (s.width-target_size.height)*target_size.width;
if(v<objf){
opt.width=s.width;
opt.height=s.height;
objf=v;
}
}
return opt;
}
B)通过在不同宽高比(相对于图片尺寸)中找到最佳折衷,我获得了最佳预览尺寸:
@Override
public Size getOptimalPreviewSize(Size picSize,List<android.hardware.Camera.Size> sizes) {
Size opt = new Size();
double objf = Double.MAX_VALUE;
double aspratio = picSize.getAspectRatio();
double v;
for(Camera.Size s : sizes){
v = Math.abs( ((double)s.width)/((double)s.height) - aspratio )/(Math.max(((double)s.width)/((double)s.height), aspratio));
if(v<objf){
objf=v;
opt.width=s.width;
opt.height=s.height;
}
}
return opt;
}
C)隐藏仅显示可捕获部分的方法....(稍后讨论)
**试验2)**
A)我通过最小化最佳性函数来获得图片和预览尺寸,该最佳性函数同时加权相机图像宽高比和所需图像之间的不匹配以及预览和图像宽高比之间的不匹配。
public void setOptimalCameraSizes(List<Camera.Size> preview_sizes,List<Camera.Size> picture_sizes,Size preview_out, Size picture_out) {
double objf=Double.MAX_VALUE;
double tmp;
for(Camera.Size pts : picture_sizes){
for(Camera.Size pws : preview_sizes){
tmp = percv(((double)pws.height)/((double)pws.width),target_size.getAspectRatio())
+ percv(((double)pws.width)/((double)pws.height),((double)pts.width)/((double)pts.height));
if(tmp<objf){
preview_out.set(pws.width, pws.height);
picture_out.set(pts.width, pts.height);
objf=tmp;
}
}
}
}
,其中
percv(a,b)= | a-b | / max(| a |,| b |)测量相对偏差(因此是无量纲的)。
C)一些隐藏方法......
好的,这两种尺寸选择方法是我发现的最好并且选择了好的尺寸,但它们存在来自相机横向方向的生理问题......它们只能产生垂直的矩形图像,这意味着当我绘制时预览我可以得到两个案例:
1.我设置表面尺寸,以免扭曲预览图像 - &gt;由于巨大的高度,这反映在图像可见的非常小的有效区域(因此用户体验受到伤害)
2.我设置了最大可能宽度 - &gt;我可以获得(取决于预览宽高比)扭曲的预览,但比案例1大得多。
如何避免这些问题?
我在算法(隐藏阶段)的C阶段工作,我试图:
试用版1 :让相机预览超出屏幕尺寸。这将允许我在感兴趣的区域中进行任意缩放并使屏幕裁剪为预览。我尝试使用scrollview,但它不起作用,我不知道为什么。拓扑结构很简单,一个根滚动视图,在一个带有附加表面视图的FrameLayout内,但表面总是填满屏幕,导致可怕的扭曲。
试用版2 :捕获相机框并通过覆盖onPreviewFrame(。)方法直接操作它们:我在锁定画布时遇到了一个错误的错误(IllegalArgumentException)
我该如何解决这个问题?