2012-04-23 23 views
15

Tengo esta aplicación que se ejecuta en modo vertical y como parte de una actividad tengo un objeto de cámara que se ejecuta como un fragmento en él.Cámara frontal de Android que toma fotos invertidas

Tengo la opción de cambiar de cámara frontal a trasera y al tomar fotos con la cámara posterior todo está bien y bien.

Cuando tomo fotos con la cámara frontal, se invierten 180 grados. Ahora sé que esto es probablemente algo que tiene que ver con la orientación en modo vertical, pero tenerlo en el paisaje simplemente mataría la idea de mi aplicación.

¿Hay alguna posibilidad de que esto se pueda corregir, por lo que la imagen tomada es la misma que la que ve en la vista previa?

 listener = new OrientationEventListener(this.getActivity(),SensorManager.SENSOR_DELAY_NORMAL){ 

     @Override 
     public void onOrientationChanged(int orientation) { 
      // TODO Auto-generated method stub 
      if (orientation == ORIENTATION_UNKNOWN) return; 
      android.hardware.Camera.CameraInfo info = 
        new android.hardware.Camera.CameraInfo(); 
      android.hardware.Camera.getCameraInfo(mCurrentCamera, info); 
      orientation = (orientation + 45)/90 * 90; 
      int rotation = 0; 
      if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { 
       rotation = (info.orientation - orientation + 360) % 360; 
      } else { // back-facing camera 
       rotation = (info.orientation + orientation) % 360; 
      } 
      if (mCamera.getParameters() != null){ 
      Camera.Parameters mParameters = mCamera.getParameters(); 

      mParameters.setRotation(rotation); 
      mCamera.setParameters(mParameters); 
      } 
     } 

    }; 
    listener.enable(); 
    if (listener.canDetectOrientation()) 
     Log.d("Orientation Possible", "Orientation Possible"); 

El problema es que, después de intentar tomar una foto, esta cosa falla. Además, si se ejecuta durante un tiempo solo en modo de vista previa, se bloquea de nuevo. También debería añadir, que en otro método estoy haciendo esto.

public void switchCamera(Camera camera) { 
    setCamera(camera); 
    try { 
     camera.setPreviewDisplay(mHolder); 
    } catch (IOException exception) { 
     Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
    } 
    Camera.Parameters parameters = camera.getParameters(); 
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 

    requestLayout(); 


    try{ 
     camera.setParameters(parameters); 
    } 
    catch (RuntimeException ex){ 
     Log.d("Preview", "Failure to set proper parameters"); 
     //need to improve this method 
     if (mSupportedPreviewSizes != null) { 
      Camera.Size cs = mSupportedPreviewSizes.get(0); 
      parameters.setPreviewSize(cs.width, cs.height); 
      camera.setParameters(parameters); 
      requestLayout(); 
      //int tempheight = mPreviewSize.height; 
      //mPreviewSize.height = mPreviewSize.width; 
      //mPreviewSize.width = tempheight; 

     } 
    } 

Esto se denomina cuando se cambia de una cámara a otra (viceversa). ¿Podría esto interferir con el oyente del evento de orientación?

Además, al guardar la imagen tomada, esto es lo que llamo. Antes solo tomaba los datos como un parámetro, pero intenté que tomaran también la orientación de la pantalla. El problema es que la orientación de la pantalla siempre es 90, sin importar qué. Por lo tanto, el mapa de bits siempre se girará 90 grados (lo cual es ideal para tomar fotos con la cámara trasera) pero lo invertirá cuando lo tome con la cámara frontal. ¿Se podría implementar una solución en esta función?

public static Bitmap MakeSquare(byte[] data, int orientation) { 
    int width; 
    int height; 
    // Rotate photo 
    Matrix matrix = new Matrix(); 
    matrix.postRotate(orientation); 
    // Convert ByteArray to Bitmap 
    Bitmap bitPic = BitmapFactory.decodeByteArray(data, 0, data.length); 
    width = bitPic.getWidth(); 
    height = bitPic.getHeight(); 


    // Create new Bitmap out of the old one 
    Bitmap bitPicFinal = Bitmap.createBitmap(bitPic, 0, 0, width, height,matrix, true); 
    bitPic.recycle(); 
    int desWidth; 
    int desHeight; 
    desWidth = bitPicFinal.getWidth(); 
    desHeight = desWidth; 
    Bitmap croppedBitmap = Bitmap.createBitmap(bitPicFinal, 0,bitPicFinal.getHeight()/2 - bitPicFinal.getWidth()/2,desWidth, desHeight); 
    croppedBitmap = Bitmap.createScaledBitmap(croppedBitmap, 528, 528, true); 
    return croppedBitmap; 
} 

Respuesta

34

Bien, bien. Parece que me he encargado de eso.He utilizado el asesoramiento de esto: Android, front and back camera Orientation , Landscape

Y cambiado de función MakeSquare a esto:

public static Bitmap MakeSquare(byte[] data, int cameraID) { 
    int width; 
    int height; 
    Matrix matrix = new Matrix(); 
    Camera.CameraInfo info = new Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraID, info); 
    // Convert ByteArray to Bitmap 
    Bitmap bitPic = BitmapFactory.decodeByteArray(data, 0, data.length); 
    width = bitPic.getWidth(); 
    height = bitPic.getHeight(); 

    // Perform matrix rotations/mirrors depending on camera that took the photo 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) 
    { 
     float[] mirrorY = { -1, 0, 0, 0, 1, 0, 0, 0, 1}; 
     Matrix matrixMirrorY = new Matrix(); 
     matrixMirrorY.setValues(mirrorY); 

     matrix.postConcat(matrixMirrorY); 
    } 

    matrix.postRotate(90); 


    // Create new Bitmap out of the old one 
    Bitmap bitPicFinal = Bitmap.createBitmap(bitPic, 0, 0, width, height,matrix, true); 
    bitPic.recycle(); 
    int desWidth; 
    int desHeight; 
    desWidth = bitPicFinal.getWidth(); 
    desHeight = desWidth; 
    Bitmap croppedBitmap = Bitmap.createBitmap(bitPicFinal, 0,bitPicFinal.getHeight()/2 - bitPicFinal.getWidth()/2,desWidth, desHeight); 
    croppedBitmap = Bitmap.createScaledBitmap(croppedBitmap, 528, 528, true); 
    return croppedBitmap; 
} 

Esto parece funcionar y hacer el truco. Aunque no estoy seguro de que esta sea la mejor manera, estoy contento con eso. Ahora todo lo que tengo que hacer es descubrir por qué no está tomando la relación de aspecto adecuada cuando se usa la cámara frontal.

+0

¡Gracias, amigo! ¿Tiene alguna información sobre cómo funciona esta solución en 'todos' los dispositivos? – marino

+1

Resolvió mi problema de rotación de la imagen de la cámara frontal (y) –

+0

este es el mejor ... gracias – tsanzol

2

dar a estos enlaces intentarlo:

http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)

http://developer.android.com/reference/android/hardware/Camera.Parameters.html#setRotation(int)

Específicamente, aquí es un trozo de verborrea desde el enlace setRotation.

"Si las aplicaciones quieren rotar la imagen para que coincida con la orientación de lo que los usuarios ven, las aplicaciones deben usar OrientationEventListener y Camera.CameraInfo. El valor de OrientationEventListener es relativo a la orientación natural del dispositivo. CameraInfo.orientation es el ángulo entre la orientación de la cámara y la orientación natural del dispositivo. La suma de los dos es el ángulo de rotación para la cámara trasera La diferencia de los dos es el ángulo de rotación de la cámara frontal. Tenga en cuenta que las imágenes JPEG de las cámaras frontales no se reflejan como en la vista previa ".

Utilicé este código tal como está, no lo modifiqué en absoluto. Mi cámara es mejor ahora, todavía necesita un poco de TLC. Tampoco tengo funcionalidad frontal todavía.

¡Buena suerte!

+0

Gracias, ya he echado un vistazo a ellos e intenté implementar un oyente de onOrientationChanged de la forma en que lo aconsejaron, pero sigo teniendo bloqueos. He editado mi publicación para mostrar mi código – Valentin

Cuestiones relacionadas