91 votes

Comment définir correctement l'orientation de l'appareil photo Android ?

Je veux définir l'orientation de la caméra en fonction de l'orientation de l'appareil dans Android mais rien ne semble fonctionner. J'ai essayé de faire pivoter la Surface ainsi que les paramètres de l'appareil photo mais l'aperçu de l'appareil photo en mode portrait est toujours à l'envers. Il faudrait que je le fasse pivoter de 90 degrés dans le sens des aiguilles d'une montre pour qu'il soit correct. Voici le code que j'utilise actuellement et qui fonctionne uniquement en mode paysage.

    SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {          
        initCamera();           
    }

    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.2;
        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) {
            Log.d(TAG, "Checking size " + size.width + "w " + size.height
                    + "h");
            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;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Camera.Parameters parameters = camera.getParameters();

        List<Size> sizes = parameters.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(sizes, width, height);         
        Log.d(TAG, "Surface size is " + width + "w " + height + "h");
        Log.d(TAG, "Optimal size is " + optimalSize.width + "w " + optimalSize.height + "h");           
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);           
        // parameters.setPreviewSize(width, height);            
        camera.setParameters(parameters);
        camera.startPreview();
    }
};

6 votes

Pour l'instant, l'aperçu de la caméra ne fonctionne réellement qu'en mode paysage, du moins pour les versions 2.2 et antérieures. Je suppose que c'est la raison pour laquelle les activités qui ont un aperçu de l'appareil photo ont tendance à cacher la barre de notification du système et n'ont pas de titres... bien qu'elles soient apparemment en mode portrait, je pense qu'elles sont "vraiment" en mode paysage.

71voto

maydenec Points 985

De l'autre membre et de mon problème :

Le problème de rotation de la caméra dépend de différents appareils et de certaines versions.

Version 1.6 : pour corriger le problème de rotation, et il est bon pour la plupart des appareils

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
        {   
            p.set("orientation", "portrait");
            p.set("rotation",90);
        }
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
        {                               
            p.set("orientation", "landscape");          
            p.set("rotation", 90);
        }

Version 2.1 : dépend du type d'appareil, par exemple, il n'est pas possible de résoudre le problème avec le XPeria X10, mais il est bon pour le X8 et le Mini.

Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);

Version 2.2 : pas pour tous les appareils

camera.setDisplayOrientation(90);

http://code.google.com/p/Android/issues/detail?id=1193#c42

4 votes

Que voulez-vous dire par la version ici ?

31voto

Jason Robinson Points 10878

Dans les Javadocs de setDisplayOrientation(int) (Nécessite le niveau 9 de l'API) :

 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
     int degrees = 0;
     switch (rotation) {
         case Surface.ROTATION_0: degrees = 0; break;
         case Surface.ROTATION_90: degrees = 90; break;
         case Surface.ROTATION_180: degrees = 180; break;
         case Surface.ROTATION_270: degrees = 270; break;
     }

     int result;
     if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }

1 votes

@Derzu La classe CameraInfo n'a pas été introduite avant le niveau 9 de l'API, donc la méthode que j'ai postée nécessite le niveau 9 de l'API.

2 votes

result = (360 - result) % 360; // compensate the mirror devrait être supprimé les photos de la caméra frontale sont autrement rotation incorrecte

0 votes

@stevo.mit avez-vous vérifié cela sur plusieurs appareils ? J'ai utilisé ce code pour la rotation un certain nombre de fois et je n'ai pas rencontré de rotation incorrecte.

25voto

hnviet Points 1107

Cette solution fonctionnera pour tous versions d'Android. Vous pouvez utiliser la réflexion en Java pour le faire fonctionner sur tous les appareils Android :

En fait, vous devez créer un wrapper de réflexion pour appeler la méthode Android 2.2 setDisplayOrientation, au lieu d'appeler la méthode spécifique.

La méthode :

    protected void setDisplayOrientation(Camera camera, int angle){
    Method downPolymorphic;
    try
    {
        downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });
        if (downPolymorphic != null)
            downPolymorphic.invoke(camera, new Object[] { angle });
    }
    catch (Exception e1)
    {
    }
}

Et au lieu d'utiliser camera.setDisplayOrientation(x) utiliser setDisplayOrientation(caméra, x) :

    if (Integer.parseInt(Build.VERSION.SDK) >= 8)
        setDisplayOrientation(mCamera, 90);
    else
    {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            p.set("orientation", "portrait");
            p.set("rotation", 90);
        }
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            p.set("orientation", "landscape");
            p.set("rotation", 90);
        }
    }

1 votes

L'autre partie fonctionne sur certains appareils 2.1 mais pas TOUS (voir l'explication de maydenec ci-dessus).

1 votes

Je pense que P est de type Camera.Parameters . Essayez d'ajouter la ligne suivante : Camera.Parameters p = camera.getParameters();

6voto

DeepakPanwar Points 228

J'ai été confronté à ce problème lorsque j'utilisais ZBar pour scanner dans les onglets. Problème d'orientation de la caméra. En utilisant le code ci-dessous, j'ai pu résoudre le problème. Il ne s'agit pas de l'extrait de code complet, s'il vous plaît prendre seulement l'aide de ce.

 public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
     if (isPreviewRunning) {
            mCamera.stopPreview();
        }

 setCameraDisplayOrientation(mCamera);

        previewCamera();

    }

 public void previewCamera() {

        try {
            // Hard code camera surface rotation 90 degs to match Activity view
            // in portrait
            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            mCamera.autoFocus(autoFocusCallback);
            isPreviewRunning = true;
        } catch (Exception e) {
            Log.d("DBG", "Error starting camera preview: " + e.getMessage());
        }

    }

public void setCameraDisplayOrientation(android.hardware.Camera camera) {
        Camera.Parameters parameters = camera.getParameters();

        android.hardware.Camera.CameraInfo camInfo =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(getBackFacingCameraId(), camInfo);

        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        int rotation = display.getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (camInfo.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (camInfo.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    private int getBackFacingCameraId() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {

                cameraId = i;
                break;
            }
        }
        return cameraId;
    }

5voto

Abhinav Points 10339

J'ai finalement résolu ce problème en utilisant l'application caméra de Google. Elle récupère l'orientation du téléphone à l'aide d'un capteur, puis définit la balise EXIF en conséquence. Le JPEG qui sort de l'appareil photo n'est pas orienté automatiquement.

En outre, l'aperçu de l'appareil photo ne fonctionne correctement qu'en mode paysage. Si vous avez besoin que la présentation de votre activité soit orientée en mode portrait, vous devrez le faire manuellement en utilisant la valeur du capteur d'orientation.

2 votes

Comment obtenir l'orientation de la caméra en utilisant le capteur d'orientation ? s'il vous plaît, partagez votre code...

0 votes

4 votes

Merci pour votre aide, mais mon problème est que lorsque je prends une photo sur un téléphone symsung en mode portrait, la photo est affichée avec une rotation de 90 degrés sur mon écran. J'essaie donc d'obtenir l'orientation de l'appareil photo et de faire pivoter la photo de 90 degrés en mode portrait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X