2014-12-29 433 views
0

我在我的應用程序上使用自定義相機預覽,它幾乎可以在所有設備上正常工作,對於HTC-One,我得到一個壞的剪輯,原始照片不匹配預覽顯示在頂部。預覽相機HTC-One剪切圖像

它只發生在這個設備上,這是我的預覽相機的代碼和關於發生了什麼的圖片。

在此先感謝有人可以給我的任何幫助。

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 

private final String TAG = "CameraPreview"; 

private SurfaceHolder mHolder; 
private Camera mCamera; 
private Context context; 
private Camera.Size mPreviewSize; 
private List<Camera.Size> mSupportedPreviewSizes; 

public CameraPreview(Context context) { 
    super(context); 
    this.context = context; 
    mHolder = getHolder(); 
    mHolder.addCallback(this); 
} 

public void setCamera(Camera camera) { 
    mCamera = camera; 
    if (mCamera != null) { 

     mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
     for (Camera.Size str : mSupportedPreviewSizes) { 
      Log.e(TAG, str.width + "/" + str.height); 
     } 

     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); 
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); 

    if (mSupportedPreviewSizes != null) { 
     mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); 
    } 

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

    setMeasuredDimension(width, (int) (width * ratio)); 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 

    if (mHolder.getSurface() == null) { 
     // preview surface does not exist 
     return; 
    } 

    // stop preview before making changes 
    try { 
     mCamera.stopPreview(); 
    } catch (Exception e) { 
     // ignore: tried to stop a non-existent preview 
    } 

    // set preview size and make any resize, rotate or reformatting changes here 
    // start preview with new settings 
    try { 
     Camera.Parameters parameters = mCamera.getParameters(); 
     parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
     parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 

     mCamera.setParameters(parameters); 
     mCamera.setDisplayOrientation(90); 
     mCamera.setPreviewDisplay(mHolder); 
     mCamera.startPreview(); 

    } catch (Exception e) { 
     Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
    } 
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
} 

public void setFlash(String flashMode) { 
    Camera.Parameters params = mCamera.getParameters(); 
    params.setFlashMode(flashMode); 
    mCamera.setParameters(params); 
} 

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; 


    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 - h) < minDiff) { 
      optimalSize = size; 
      minDiff = Math.abs(size.height - h); 
     } 
    } 

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

    return optimalSize; 
} 

public void switchCamera(Camera camera) { 
    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
    if (display.getRotation() == Surface.ROTATION_0) { 
     camera.setDisplayOrientation(90); 
    } else if (display.getRotation() == Surface.ROTATION_270) { 
     camera.setDisplayOrientation(180); 
    } 

    setCamera(camera); 
    try { 
     camera.setPreviewDisplay(mHolder); 
    } catch (IOException exception) { 
     Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
    } 
} 
} 

enter image description here

回答

0

相機預覽大小和圖片大小是兩個不同的參數,您可以通過setPictureSize()和setPreviewSize()API的更新。但是,如果用戶不更改這些尺寸,它將使用默認值。

在這種情況下,您正在通過根據某些寬高比計算最佳預覽尺寸來更新預覽尺寸。但是你沒有更新圖片尺寸,所以它會使用默認的圖片尺寸。

如果圖片大小和預覽大小寬高比不同,那麼捕獲的圖片肯定與預覽不同。因此,通過計算與預覽尺寸相同縱橫比的最佳圖片尺寸來更新圖片尺寸。