2016-02-05 136 views
2

现在我正在玩API和谷歌和即时通讯有一些问题与我的代码的相机。我有两个不同的CameraSessions,一个用于视频,另一个用于图像。为了更有效地做到这一点,我将代码更改为使用独特的会话并使应用程序更高效。Camera PreviewView在某些安卓设备上被拉伸

完成此操作后,我的相机预览效果不佳。当Im使用4:3的宽高比时,我的预览会变得很高。换句话说,当Im使用16:9的比例时,它看起来很好。 在这两种情况下,我的照片看起来很好,我的意思是,预览不能正常工作,但是我拍摄的照片具有正确的宽高比。

我已经检查不同岗位同样的问题: Camera Preview Stretched on Few Android Devices

Camera display/preview in full screen does not maintain aspect ratio - image is skewed, stretched in order to fit on the screen

但不同的答案没有帮助我。我知道问题出在我的onMeasure() , setTransformMatrix() or OnLayoutChangeListener()方法中,但我不知道我做错了什么。

忽略关于旋转的代码,现在它的动态。它总是以其他条件进入。

这里是我的代码:

private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() { 
    @Override 
    public void onLayoutChange(View v, int left, int top, int right, 
           int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 

     Log.d(TAG, "[onLayoutChange] " + mCameraUI.getTextureView().getMeasuredWidth() + "x" + mCameraUI.getTextureView().getMeasuredHeight()); 

     int width = right - left; 
     int height = bottom - top; 
     if (mPreviewWidth != width || mPreviewHeight != height 
       || (mOrientationResize != mPrevOrientationResize) 
       || mAspectRatioResize || mOrientationChanged) { 

      Log.i(TAG, "[onLayoutChange] Layout changed"); 
      mPreviewWidth = width; 
      mPreviewHeight = height; 
      Log.i(TAG, "[onLayoutChange] Preview size: "+ mPreviewWidth + "x" + mPreviewHeight); 
      setTransformMatrix(width, height); 
      mController.onScreenSizeChanged((int) mSurfaceTextureUncroppedWidth, 
        (int) mSurfaceTextureUncroppedHeight); 
      mAspectRatioResize = false; 
      mOrientationChanged = true; 
     } 
    } 
}; 

的setTransform

private void setTransformMatrix(int width, int height) { 


    Log.i(TAG, "Screen: " + mPreviewWidth + "x" + mPreviewHeight); 

    mMatrix = new Matrix(); 
    //mCameraUI.getTextureView().getTransform(mMatrix); 
    float scaleX = 1f, scaleY = 1f; 
    float scaledTextureWidth, scaledTextureHeight; 

    mAspectRatio= (float)height/(float)width; 
    if (mAspectRatio==(4f/3f)){ 

      scaledTextureWidth = Math.max(width, 
        (int) (height/mAspectRatio)); 
      scaledTextureHeight = Math.max(height, 
        (int) (width * mAspectRatio)); 
     Log.i(TAG, "[PhotoUIManager]: Aspect Ratio 4:3=" + scaledTextureWidth + "x" + scaledTextureHeight); 
    } 
    else{ 
     scaledTextureWidth = Math.max(width, 
       (int) (height/mAspectRatio)); 
     scaledTextureHeight = Math.max(height, 
       (int) (width * mAspectRatio)); 
     Log.i(TAG, "[PhotoUIManager]: Aspect Ratio 16:9=" + scaledTextureWidth + "x" + scaledTextureHeight); 
    }  


    if (mSurfaceTextureUncroppedWidth != scaledTextureWidth || mSurfaceTextureUncroppedHeight != scaledTextureHeight) { 
     Log.e(TAG,"mi SurfaceWidth = " + mSurfaceTextureUncroppedWidth + "and mi scaledWidth=" + scaledTextureWidth); 
     Log.e(TAG,"mi SurfaceHeigh = " + mSurfaceTextureUncroppedHeight + "and mi scaledHeight=" + scaledTextureHeight); 
     mSurfaceTextureUncroppedWidth = scaledTextureWidth; 
     mSurfaceTextureUncroppedHeight = scaledTextureHeight; 
     Log.e(TAG,"Surfaces: " + mSurfaceTextureUncroppedWidth + "x" + mSurfaceTextureUncroppedHeight); 
     if (mSurfaceTextureSizeListener != null) { 
      mSurfaceTextureSizeListener.onSurfaceTextureSizeChanged(
        (int) mSurfaceTextureUncroppedWidth, (int) mSurfaceTextureUncroppedHeight); 
     } 
    } 
    scaleX = scaledTextureWidth/width; 
    scaleY = scaledTextureHeight/height; 
    mMatrix.setScale(scaleX, scaleY, scaledTextureWidth/2, scaledTextureHeight/2); 
    Log.e(TAG, "scale: X= " + scaleX + " Y=" + scaleY + "Width= " + scaledTextureWidth + "Height= " + scaledTextureHeight); 

    // init the position (this seems to be necessary too when the ratio is 16/9 
    mCameraUI.getTextureView().setX(0); 
    mCameraUI.getTextureView().setY(0); 

    // Translate the preview with the rotation is aspect ration is 4/3 
    if (mAspectRatio == 4f/3f) { 
     Log.e(TAG, "aspect ratio standard"); 
     float verticalTranslateOffset = (mCameraUI.getTextureView().getMeasuredHeight() - scaledTextureHeight)/2; 
     float horizontalTranslateOffset = (mCameraUI.getTextureView().getMeasuredWidth() - scaledTextureWidth)/2; 
     int rotation = CameraUtil.getDisplayRotation(mActivity); 
     switch (rotation) { 
      case 0: 
       // phone portrait; translate the preview up 
       mCameraUI.getTextureView().setY(-verticalTranslateOffset); 
       mFaceView.setStandardPreviewTranslationOffset(-verticalTranslateOffset); 
       mFocusView.setStandardPreviewTranslationOffset(-verticalTranslateOffset); 
       break; 
      case 90: 
       // phone landscape: translate the preview left 
       mCameraUI.getTextureView().setX(-horizontalTranslateOffset); 
       mFaceView.setStandardPreviewTranslationOffset(-horizontalTranslateOffset); 
       mFocusView.setStandardPreviewTranslationOffset(-horizontalTranslateOffset); 
       break; 
      case 180: 
       // phone upside down: translate the preview bottom 
       mCameraUI.getTextureView().setY(verticalTranslateOffset); 
       mFaceView.setStandardPreviewTranslationOffset(verticalTranslateOffset); 
       mFocusView.setStandardPreviewTranslationOffset(verticalTranslateOffset); 
       break; 
      case 270: 
       // reverse landscape: translate the preview right 
       mCameraUI.getTextureView().setX(horizontalTranslateOffset); 
       mFaceView.setStandardPreviewTranslationOffset(horizontalTranslateOffset); 
       mFocusView.setStandardPreviewTranslationOffset(horizontalTranslateOffset); 
       break; 
     } 

    } else { 
     Log.e(TAG, "aspect ratio full"); 
     mFaceView.setStandardPreviewTranslationOffset(0); 
     mFocusView.setStandardPreviewTranslationOffset(0); 
    } 

    mRenderOverlay.updateLayout(); 
    mCameraUI.getTextureView().setTransform(mMatrix); 

    RectF previewRect = new RectF(0, 0, width, height); 

    mController.onPreviewRectChanged(CameraUtil.rectFToRect(previewRect)); 

} 

onMeasure

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    int width = MeasureSpec.getSize(widthMeasureSpec); 
    int height = MeasureSpec.getSize(heightMeasureSpec); 

    Log.d(TAG, "onMeasure PREVIOUS. Width x Height [" + widthMeasureSpec + " = " + width + "x" + heightMeasureSpec + " = " + height + "]"); 

    int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation(); 
    boolean isInHorizontal = Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation; 

    int newWidth; 
    int newHeight; 

    if (isInHorizontal) { 

     newHeight = getMeasuredHeight(); 
     newWidth = (int) (newHeight * mAspectRatio); 
    } else { 

     newWidth = getMeasuredWidth(); 
     newHeight = (int) (newWidth * mAspectRatio); 
    } 

    setMeasuredDimension(newWidth, newHeight); 
    Log.d(TAG, "onMeasure. Width x Height [" + newWidth + "x" + newHeight + "]"); 

} 

回答

1

解决了!

我有我的纹理的缓冲区大小的默认值,刚刚重新启动时,我in​​icializated一个新的会议,或改变后的比例。但纹理的宽度和高度值不会随比率更新,因此它会一次又一次地变形。

我解决了它改变我的默认缓冲区大小与我更新总是我更改比率的PreviewSizes。

public void createCameraPreviewSession(Size previewsize, Surface recordingSurface) { 
    try { 
     if (mCaptureSession != null) { 
      mCaptureSession.stopRepeating(); 
      mCaptureSession.close(); 
      mCaptureSession = null; 
     } 

     SurfaceTexture texture = mTextureView.getSurfaceTexture(); 
     assert texture != null; 

     List<Surface> surfaces = new ArrayList<Surface>(); 

     // We configure the size of default buffer to be the size of camera preview we want. 
     texture.setDefaultBufferSize(previewsize.getWidth(),previewsize.getHeight()); 
     ; 
     // This is the output Surface we need to start preview. 
     Surface surface = new Surface(texture); 
.......