2011-04-04 28 views
12

Estoy en una cámara App el que la toma de fotografías básicas. Tengo un problema cuando obtengo el mejor tamaño de vista previa óptimo.Imagen distorsionada con la cámara y getOptimalPreviewSize

De hecho, con este primer código:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    if (isPreviewRunning) { 
     mCamera.stopPreview(); 
    } 
    Camera.Parameters parameters = mCamera.getParameters(); 
    mCamera.setParameters(parameters); 
    mCamera.startPreview(); 
    isPreviewRunning = true; 
} 

La imagen tiene una buena calidad:

http://img689.imageshack.us/i/04042011172937.jpg/

Pero, con este código:

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
    final double ASPECT_TOLERANCE = 0.05; 
    double 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; 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    // Now that the size is known, set up the camera parameters and begin 
    // the preview. 
    if (isPreviewRunning) { 
     mCamera.stopPreview(); 
    } 
    Camera.Parameters parameters = mCamera.getParameters(); 

    List<Size> sizes = parameters.getSupportedPreviewSizes(); 
    Size optimalSize = getOptimalPreviewSize(sizes, w, h); 
    parameters.setPreviewSize(optimalSize.width, optimalSize.height); 

    mCamera.setParameters(parameters); 
    mCamera.startPreview(); 
    isPreviewRunning =true; 
} 

El cuadro está totalmente distorsionado:

http://img97.imageshack.us/i/04042011173220.jpg/

¿Cómo puedo resolver este problema?

estoy usando un HTC Desire HD.

Es probablemente mi método de ahorro también? :

PictureCallback mPictureCallbackJpeg = new PictureCallback() {  
     public void onPictureTaken(byte[] imageData, Camera camera) { 
    .... 

    BitmapFactory.Options options=new BitmapFactory.Options(); 
          options.inSampleSize = 5; 
          Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0,imageData.length,options); 
          FileOutputStream fOut = new FileOutputStream(path + "/"+fl); 
          BufferedOutputStream bos = new BufferedOutputStream(fOut); 


    myImage.compress(CompressFormat.JPEG, 100, bos); 
    bos.flush(); 
    bos.close(); 
    .... 
} 

Gracias

+0

¿Ha resuelto este problema? –

+0

Es un proyecto antiguo, pero parece que el código de Seantron funciona. Pruébalo;) –

Respuesta

26

acabo a través sufrieron el mismo problema, y ​​se le ocurrió una solución similar, pero más ligero de peso. Sin embargo, no veo nada malo con su método de ahorro.

private Camera.Size getBestPreviewSize(int width, int height) 
{ 
     Camera.Size result=null;  
     Camera.Parameters p = camera.getParameters(); 
     for (Camera.Size size : p.getSupportedPreviewSizes()) { 
      if (size.width<=width && size.height<=height) { 
       if (result==null) { 
        result=size; 
       } else { 
        int resultArea=result.width*result.height; 
        int newArea=size.width*size.height; 

        if (newArea>resultArea) { 
         result=size; 
        } 
       } 
      } 
     } 
    return result; 

} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
    //This line helped me set the preview Display Orientation to Portrait 
      //Only works API Level 8 and higher unfortunately. 

    camera.setDisplayOrientation(90); 

    Camera.Parameters parameters = camera.getParameters(); 
    Camera.Size size = getBestPreviewSize(width, height); 
    parameters.setPreviewSize(size.width, size.height); 
    camera.setParameters(parameters); 
    camera.startPreview(); 

} 
+2

Tuve un problema con getOptimalPreviewSize en HTC Desire. La función getSupportedPreviewSizes devuelve tamaños: 1280x720, 840x480, 768: 432, etc. La llamada getOptimalPreviewSize (480,800) devuelve 1280x720. Como resultado, la llamada de setPreviewDisplay bloquea la aplicación (era necesario reiniciar el dispositivo para restaurar la funcionalidad de la cámara). Como resultado, solía getBestPreviewSize con una pequeña modificación: if ((Tamano.Width <= ancho && size.height <= altura) || (size.height <= ancho && Tamano.Width <= altura)) {... Funciona bien. – dvpublic

+0

Otra razón más por la cual odio el desarrollo de Android, pero gracias por esa información. ¿Qué sistema operativo en el HTC Desire por cierto? – Seantron

+0

Era deseo de HTC con Android 2.2.2 – dvpublic

5

La mejor manera es conseguir el tamaño de vista previa con la relación de aspecto más cercano:

Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) { 
     Camera.Size result=null; 
     float dr = Float.MAX_VALUE; 
     float ratio = (float)width/(float)height; 

     for (Camera.Size size : parameters.getSupportedPreviewSizes()) { 
      float r = (float)size.width/(float)size.height; 
      if(Math.abs(r - ratio) < dr && size.width <= width && size.height <= height) { 
       dr = Math.abs(r - ratio); 
       result = size; 
      } 
     } 

     return result; 
    } 

Cuando los parámetros de anchura y altura son el tamaño de su superficie.

+1

Esto hace mostrar la relación de aspecto correcta, pero cuando captura la foto de sus cultivos de los lados de la misma. ¿Cómo harías para evitar que eso suceda? –

+0

Lo mismo pasa conmigo. Will, ¿pudiste resolver tu problema? – Prateek

+0

@WillJamieson también debe elegir el tamaño de la imagen de la lista devuelta por getSupportedPictureSizes(). Este tamaño puede ser diferente del tamaño de vista previa elegido (generalmente más grande), pero debe mantener la misma relación de aspecto. –

Cuestiones relacionadas