2014-11-21 13 views
3

我正在開發一款在SurfaceView上繪製相機的應用程序。一開始我發現了觀點的麻煩。他們沒有正確顯示。所以我使用了下面的方法來修正長寬比問題:Android中正確的寬高比

注意:這個方法在幾個地方被發現是爲了糾正Android相機的寬高比。

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

    // Check wheter is portrait or landscape 
    if (orientation == 1) 
     targetRatio = (double) h/w; 
    else 
     targetRatio = (double) w/h; 

    if (sizes == null) 
     return null; 

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

    int targetHeight = h; 

    // Try to find an size match aspect ratio and size 
    for (Size size : sizes) { 
     double ratio = (double) size.width/size.height; 
     if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 
      continue; 
     if (Math.abs(size.height - targetHeight) < minDiff) { 
      optimalSize = size; 
      minDiff = Math.abs(size.height - targetHeight); 
     } 
    } 

    // Cannot find the one match the aspect ratio, ignore the requirement 
    if (optimalSize == null) { 
     minDiff = Double.MAX_VALUE; 
     for (Size size : sizes) { 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 
    } 
    return optimalSize; 
} 

這工作完美,我的相機顯示正確。但是我發現新的設備存在問題,比如LG G3。它有一個決議,該方法認爲是最appropiate之一,但它顯示的圖像與郵筒在人像模式中,像下面的圖片顯示:

enter image description here

這究竟是爲什麼?如何在縱向模式下解決這個郵筒問題?

+0

您可以選擇裁剪圖像而不是顯示黑色邊距。 – 2014-11-21 10:03:42

+0

怎樣才能做到這一點?這將是我的解決方案之一。第一個,莊稼形象。第二個,試着將它放在我考慮寬度的空間中。 – Sonhja 2014-11-21 11:05:50

+0

裁剪預覽的可靠方法涉及使用[SurfaceTexture](http://developer.android.com/reference/android/graphics/Sur​​faceTexture.html)。 – 2014-11-21 11:12:34

回答

3

除非該代碼中存在錯誤,否則您會得到「最佳」結果。

手機相機的縱橫比不能保證與手機屏幕的縱橫比相匹配。

這只是決定最佳結果的標準。該代碼是Google的建議,用於確定在手機屏幕上顯示的最佳相機分辨率。

您可能不同意Google。在這種情況下,您需要編寫自己的算法來決定什麼是最佳的相機分辨率。您可能會優化縱橫比,或沿寬度或高度的分辨率。您可以嘗試適合屏幕,或者可以剪切圖像的一些部分以填充整個屏幕。隨你便。

注意:您發佈的嘗試代碼找到一個攝像頭分辨率是屏幕的高寬比的10%以內具有相匹配的屏幕是最接近的高度。 如果屏幕縱橫比在10%以內沒有相機分辨率,則會選取高度與屏幕最接近的相匹配的相機分辨率。在這種情況下,你的柱子周圍會有明顯的黑色條紋。

+0

你的回答讓我想到了解決方案。我使用寬度和高度調整它,現在它的工作原理是我想要的! – Sonhja 2014-11-21 12:18:43

1

在我的情況下,我在同一個活動中有其他視圖,所以我想先修復相機預覽佈局的尺寸。在佈局中,您需要提供所需的最大尺寸(重量)。

我創建了確定最佳預覽大小對於給定的目標視圖當前的寬度和高度,並且還活動取向的任何照相機的另一種方法:

public static Size getOptimalPreviewSize(List<Camera.Size> cameraPreviewSizes, int targetWidth, int targetHeight, boolean isActivityPortrait) { 
    if (CommonUtils.isEmpty(cameraPreviewSizes)) { 
     return null; 
    } 

    int optimalHeight = Integer.MIN_VALUE; 
    int optimalWidth = Integer.MIN_VALUE; 

    for (Camera.Size cameraPreviewSize : cameraPreviewSizes) { 
     boolean isCameraPreviewHeightBigger = cameraPreviewSize.height > cameraPreviewSize.width; 
     int actualCameraWidth = cameraPreviewSize.width; 
     int actualCameraHeight = cameraPreviewSize.height; 

     if (isActivityPortrait) { 
      if (!isCameraPreviewHeightBigger) { 
       int temp = cameraPreviewSize.width; 
       actualCameraWidth = cameraPreviewSize.height; 
       actualCameraHeight = temp; 
      } 
     } else { 
      if (isCameraPreviewHeightBigger) { 
       int temp = cameraPreviewSize.width; 
       actualCameraWidth = cameraPreviewSize.height; 
       actualCameraHeight = temp; 
      } 
     } 

     if (actualCameraWidth > targetWidth || actualCameraHeight > targetHeight) { 
      // finds only smaller preview sizes than target size 
      continue; 
     } 

     if (actualCameraWidth > optimalWidth && actualCameraHeight > optimalHeight) { 
      // finds only better sizes 
      optimalWidth = actualCameraWidth; 
      optimalHeight = actualCameraHeight; 
     } 
    } 

    Size optimalSize = null; 

    if (optimalHeight != Integer.MIN_VALUE && optimalWidth != Integer.MIN_VALUE) { 
     optimalSize = new Size(optimalWidth, optimalHeight); 
    } 

    return optimalSize; 
} 

此使用自定義尺寸的對象,因爲Android的Size可用在API 21之後。

public class Size { 

    private int width; 
    private int height; 

    public Size(int width, int height) { 
     this.width = width; 
     this.height = height; 
    } 

    public int getHeight() { 
     return height; 
    } 

    public int getWidth() { 
     return width; 
    } 

} 

您可以通過偵聽其全局佈局更改來確定視圖的寬度和高度,然後可以設置新維度。這也說明了如何以編程方式確定活動的方向:

cameraPreviewLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
      @Override 
      public void onGlobalLayout() { 
       // gets called after layout has been done but before display. 
       cameraPreviewLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 

       boolean isActivityPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; 
       Size optimalCameraPreviewSize = CustomUtils.getOptimalPreviewSize(cameraPreview.getCameraSizes(), cameraPreviewLayout.getWidth(), cameraPreviewLayout.getHeight(), isActivityPortrait); 
       if (optimalCameraPreviewSize != null) { 
        LinearLayout.LayoutParams cameraPreviewLayoutParams = new LinearLayout.LayoutParams(optimalCameraPreviewSize.getWidth(), optimalCameraPreviewSize.getHeight()); 
        cameraPreviewLayout.setLayoutParams(cameraPreviewLayoutParams); 
       } 
      } 
     }); 

您還需要旋轉攝像頭的取向,這是另一個問題。