2016-01-06 82 views
7

我的问题很简单:如何以1:1的比例获得Android Camera2?

如何获得一个Android android.hardware.Camera2以1:1分的比例,并没有像Instagram的变形?

我使用GoogeSamples项目android-Camera2Basic进行了测试。但是,当我以1:1的比例更改预览时,图像会变形。有没有人有这个想法?

enter image description here

+1

“但是,当我改变预览用1:1的比例图像变形” - 我们不能帮你调试代码,除非您提供的代码,因为一部分的[最小的,完整的,可核查示例](http://stackoverflow.com/help/mcve)。一般来说,答案是让SurfaceView或TextureView与镜头外的图像具有相同的纵横比,但使用负边距或等效的渲染技巧仅显示来自相机。 – CommonsWare

+0

谢谢@CommonsWare。使用负边距可以纠正我的问题。我在回答中发布我的代码。 –

+0

@ lopez.mikhael你如何改变宽高比?看看http://stackoverflow.com/questions/41221284/how-to-change-aspect-ratio-of-camera2-preview –

回答

2

谢谢@CommonsWare。

我遵循你的建议使用负边距(顶部和底部),它的工作原理。

为了做到这一点,我刚刚更新AutoFitTextureView的GoogeSamples项目android-Camera2Basic这样:

public class AutoFitTextureView extends TextureView { 

    //... 
    private boolean mWithMargin = false; 

    //... 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, widthMeasureSpec); 
     int width = MeasureSpec.getSize(widthMeasureSpec); 
     int height = MeasureSpec.getSize(heightMeasureSpec); 
     int margin = (height - width)/2; 

     if(!mWithMargin) { 
      mWithMargin = true; 
      ViewGroup.MarginLayoutParams margins = ViewGroup.MarginLayoutParams.class.cast(getLayoutParams()); 
      margins.topMargin = -margin; 
      margins.bottomMargin = -margin; 
      margins.leftMargin = 0; 
      margins.rightMargin = 0; 
      setLayoutParams(margins); 
     } 

     if (0 == mRatioWidth || 0 == mRatioHeight) { 
      setMeasuredDimension(width, height); 
     } else { 
      if (width < height) { 
       setMeasuredDimension(width, width * mRatioHeight/mRatioWidth); 
      } else { 
       setMeasuredDimension(height * mRatioWidth/mRatioHeight, height); 
      } 
     } 
    } 
} 

enter image description here

+2

嗨! 我有同样的问题。我添加了AutoFitTextureView的实现,但它仍然没有工作。你能否提供一些更多的应用程序代码来以相机方式进行相机预览和图片? 谢谢! –

+0

当我这样做,我在预览底部得到一个黑色的酒吧..任何想法? – Dave

0

像这样创建自定义纹理观点:

public class AutoFitTextureView extends TextureView { 

    private int mCameraWidth = 0; 
    private int mCameraHeight = 0; 
    private boolean mSquarePreview = false; 

    public AutoFitTextureView(Context context) { 
     this(context, null); 
    } 

    public AutoFitTextureView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    public void setAspectRatio(int width, int height, boolean squarePreview) { 
     if (width < 0 || height < 0) { 
      throw new IllegalArgumentException("Size cannot be negative."); 
     } 
     mCameraWidth = width; 
     mCameraHeight = height; 
     mSquarePreview = squarePreview; 
     requestLayout(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     int width = MeasureSpec.getSize(widthMeasureSpec); 
     int height = MeasureSpec.getSize(heightMeasureSpec); 
     if (0 == mCameraWidth || 0 == mCameraHeight) { 
      setMeasuredDimension(width, height); 
     } else { 
      /** 
      * Vertical orientation 
      */ 
      if (width < height) { 
       if (mSquarePreview) { 
        setTransform(squareTransform(width, height)); 
        setMeasuredDimension(width, width); 
       } else { 
        setMeasuredDimension(width, width * mCameraHeight/mCameraWidth); 
       } 
      } 
      /** 
      * Horizontal orientation 
      */ 
      else { 
       if (mSquarePreview) { 
        setTransform(squareTransform(width, height)); 
        setMeasuredDimension(height, height); 
       } else { 
        setMeasuredDimension(height * mCameraWidth/mCameraHeight, height); 
       } 
      } 
     } 
    } 

    private Matrix setupTransform(int sw, int sh, int dw, int dh) { 
     Matrix matrix = new Matrix(); 
     RectF src = new RectF(0, 0, sw, sh); 
     RectF dst = new RectF(0, 0, dw, dh); 
     RectF screen = new RectF(0, 0, dw, dh); 

     matrix.postRotate(-90, screen.centerX(), screen.centerY()); 
     matrix.mapRect(dst); 

     matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER); 
     matrix.mapRect(src); 

     matrix.setRectToRect(screen, src, Matrix.ScaleToFit.FILL); 
     matrix.postRotate(-90, screen.centerX(), screen.centerY()); 

     return matrix; 
    } 

    private Matrix squareTransform(int viewWidth, int viewHeight) { 
     Matrix matrix = new Matrix(); 

     if (viewWidth < viewHeight) { 
      MyLogger.log(AutoFitTextureView.class, "Horizontal"); 
      matrix.setScale(1, (float) mCameraHeight/(float) mCameraWidth, viewWidth/2, viewHeight/2); 
     } else { 
      MyLogger.log(AutoFitTextureView.class, "Vertical"); 
      matrix.setScale((float) mCameraHeight/(float) mCameraWidth, 1, viewWidth/2, viewHeight/2); 
     } 

     return matrix; 
    } 
} 

并调用调用setAspectRatio您在活动/片段的纹理视图。

if (mVideoSize.width > mVideoSize.height) { 
    mTextureView.setAspectRatio(mVideoSize.height, mVideoSize.width, true); 
} else { 
    mTextureView.setAspectRatio(mVideoSize.width, mVideoSize.height, true); 
} 
mCamera.setPreviewTexture(mTextureView.getSurfaceTexture()); 
mCamera.startPreview(); 
+1

嗨米凯尔!我尝试实施您的解决方案,但不起作用。您可以发布或寄给我一个完整的实施吗?这将是太棒了! – anthony

相关问题