2016-01-06 48 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