2014-12-29 2 views
0

Я использую пользовательский предварительный просмотр камеры в своем приложении, он отлично работает практически во всех устройствах, для HTC-One У меня плохой срез, исходное фото не соответствует тому, что предварительный просмотр показан сверху.Предварительный просмотр камеры HTC-One cuts image

Это происходит только на этом устройстве, это код моей камеры предварительного просмотра и изображение о том, что происходит.

Заранее благодарим за любую помощь, которую кто-то может мне дать.

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. Но если пользователь не изменит эти размеры, он будет использовать значения по умолчанию.

В этом случае вы обновляете размер предварительного просмотра, вычисляя оптимальный размер предварительного просмотра на основе некоторого соотношения сторон. Но вы не обновляете размер изображения, поэтому он будет использовать размер изображения по умолчанию.

Если размер изображения и пропорции предварительного просмотра не совпадают, определенно захваченное изображение отличается от предварительного просмотра. Так что обновите размер изображения, также рассчитывая оптимальный размер изображения с тем же соотношением сторон, что и размер предварительного просмотра.

Смежные вопросы