Android zxing-人像照相机预览/表面视图拉伸/扭曲

Android zxing-人像照相机预览/表面视图拉伸/扭曲,android,surfaceview,zxing,portrait,stretching,Android,Surfaceview,Zxing,Portrait,Stretching,我已设法使用此处的答案将相机预览旋转为纵向: 但是预览本身是拉伸/扭曲的-高度似乎在拉伸以填充框(但可能是宽度太大,无法容纳屏幕,并且正在挤压) 有没有办法“包装”内容,而不是使其拉伸以适应surfaceview 编辑:我通过更改“CameraConfiguration Manager”中的“findBestPreviewSizeValue”方法并反转X点和Y点(感谢sean owen提供下面的指针!)对其进行排序,代码如下: private static Point findBestPrev

我已设法使用此处的答案将相机预览旋转为纵向:

但是预览本身是拉伸/扭曲的-高度似乎在拉伸以填充框(但可能是宽度太大,无法容纳屏幕,并且正在挤压)

有没有办法“包装”内容,而不是使其拉伸以适应surfaceview

编辑:我通过更改“CameraConfiguration Manager”中的“findBestPreviewSizeValue”方法并反转X点和Y点(感谢sean owen提供下面的指针!)对其进行排序,代码如下:

private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString,
  Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {

  previewSize = previewSize.trim();
  int dimPosition = previewSize.indexOf('x');
  if (dimPosition < 0) {
    Log.w(TAG, "Bad preview-size: " + previewSize);
    continue;
  }

  int newX;
  int newY;
  try {
    newY = Integer.parseInt(previewSize.substring(0, dimPosition));
    newX = Integer.parseInt(previewSize.substring(dimPosition + 1));
    //original:
    //newX = Integer.parseInt(previewSize.substring(0, dimPosition));
    //newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
  } catch (NumberFormatException nfe) {
    Log.w(TAG, "Bad preview-size: " + previewSize);
    continue;
  }

  int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
  if (newDiff == 0) {
    bestX = newY;
    bestY = newX;
    //original:
    //bestX = newX;
    //bestY = newY;
    break;
  } else if (newDiff < diff) {
    bestX = newY;
    bestY = newX;
    //original:
    //bestX = newX;
    //bestY = newY;
    diff = newDiff;
  }

}

if (bestX > 0 && bestY > 0) {
  return new Point(bestX, bestY);
}
return null;
}
私有静态点findBestPreviewSizeValue(CharSequence previewSizeValueString,
点(分辨率){
int-bestX=0;
int-bestY=0;
int diff=整数最大值;
for(字符串预览大小:逗号_模式.split(previewSizeValueString)){
previewSize=previewSize.trim();
int-dimPosition=previewSize.indexOf('x');
如果(dimPosition<0){
Log.w(标记“错误预览大小:”+previewSize);
继续;
}
int-newX;
int-newY;
试一试{
newY=Integer.parseInt(previewSize.substring(0,dimPosition));
newX=Integer.parseInt(previewSize.substring(dimPosition+1));
//原件:
//newX=Integer.parseInt(previewSize.substring(0,dimPosition));
//newY=Integer.parseInt(previewSize.substring(dimPosition+1));
}捕获(NumberFormatException nfe){
Log.w(标记“错误预览大小:”+previewSize);
继续;
}
int newDiff=Math.abs(newX-screensolution.x)+Math.abs(newY-screensolution.y);
如果(newDiff==0){
bestX=新的;
贝西=纽克斯;
//原件:
//bestX=newX;
//bestY=newY;
打破
}else if(newDiff0&&最佳值>0){
返回新点(bestX、bestY);
}
返回null;
}

要使其正常工作,您需要做更多的工作,而不仅仅是将预览设置为纵向模式。例如,您需要选择一个合适的预览大小,因为它是纵向的,而不是横向的


包装肯定是不可取的?不,你不能把它包起来;它将始终将整个预览图像投射到
SurfaceView
,如果需要,进行拉伸。我想您可以重新实现许多代码来做一些不同的事情,但这将是相当困难的。

我也有同样的问题,但我可以通过在findBestPreviewSizeValue中反转CameraConfiguration Manager.java文件的纵横比来解决它

 float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;
对此

 float screenAspectRatio = (float) screenResolution.y / (float) screenResolution.x;
我在这里找到了解决办法


您可以通过此功能获取Priview size:

私有列表mSupportedPreviewSizes=参数。getSupportedPreviewSizes()

if(mSupportedPreviewSizes!=null){
mPreviewSize=getOptimalPreviewSize(MSSupportedPreviewSize、宽度、高度);
}
私人相机。大小getOptimalPreviewSize(列表大小,整数w,整数h){
最终双纵横比公差=0.1;
双目标率=(双)高/低;
如果(大小==null)
返回null;
照相机。大小优化大小=空;
double minDiff=double.MAX_值;
int targetHeight=h;
用于(相机尺寸:尺寸){
双倍比率=(双倍)size.height/size.width;
if(数学绝对值(比率-目标比率)>纵横比公差)
继续;
if(数学绝对值(尺寸高度-目标光)=mPreviewSize.width)
比率=(float)mPreviewSize.height/(float)mPreviewSize.width;
其他的
比率=(浮动)mPreviewSize.width/(浮动)mPreviewSize.height;
在获得比例后,设置您的尺码
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
设置测量尺寸((int)(宽度*比率)、高度);
}

我通过在
CameraConfigurationManager.java
中更改下面的代码,成功地实现了这一点:

float-screenspectratio=(float)screensolution.x/(float)screensolution.y

致:

致:

我在这篇文章的旁边做了这件事:


希望这对其他人有所帮助。

变形的原因可能是相机的预览纵横比与显示器的纵横比不匹配


手机屏幕的大部分纵横比为4:3,如2560x1440、1920x1080等。当您使用parameter.setPreviewSize(width,height)设置相机预览尺寸时,如果height:width的值不等于手机屏幕的纵横比,相机的图片将变形以填充屏幕

谢谢你的快速回答:)你能详细说明一下合适的预览尺寸吗?我在问题中的链接中执行的代码更改似乎工作正常,我以前使用的代码似乎工作正常,他们扫描二维码/条形码没有问题,实际上,我的预览看起来有点拉伸/挤压。在您提到设置适当的预览大小后,我查看了“findBestPreviewSizeValue”方法,基本上交换了点的X和Y值,并对其进行了排序:)我将用代码更新上面的问题
if (mSupportedPreviewSizes != null) {
                mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
            }

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            double targetRatio = (double) h / w;

            if (sizes == null)
                return null;

            Camera.Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = h;

            for (Camera.Size size : sizes) {
                double ratio = (double) size.height / size.width;
                if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                    continue;

                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }

            if (optimalSize == null) {
                minDiff = Double.MAX_VALUE;
                for (Camera.Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                    }
                }
            }

            return optimalSize;
        }


            float ratio;
            if (mPreviewSize.height >= mPreviewSize.width)
                ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
            else
                ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;

            after getting ratio set your size in 

            protected void onMeasure(int widthMeasureSpec, int                              heightMeasureSpec) {

            setMeasuredDimension((int) (width * ratio), height);
            }
float screenAspectRatio = (float) screenResolution.y / (float) screenResolution.x;
float aspectRatio = (float) maybeFlippedWidth / (float) maybeFlippedHeight;
float aspectRatio = (float) maybeFlippedHeight / (float) maybeFlippedWidth;