web-dev-qa-db-fra.com

Caméra Android résultant image devrait être tourné après la capture?

J'écris une application Android qui utilise l'appareil photo. Je règle l’orientation de l’affichage de la caméra sur 90, mon activité est en mode portrait:

camera.setDisplayOrientation(90);

Je reçois une image d’aperçu bien orientée, mais l’image résultante subit une rotation de -90 degrés (dans le sens inverse des aiguilles d’une montre) et 

exif.getAttribute(ExifInterface.TAG_ORIENTATION)

retourne ORIENTATION_NORMAL
Est-ce le comportement attendu? Devrais-je faire pivoter l'image résultante après la capture? 

Appareil - Nexus S, API - 10

24
GetUsername

Le problème est que l'orientation de la caméra est un désastre complet (tout comme la capture d'une image) car les OEM ne respectent pas la norme. Les téléphones HTC fonctionnent dans un sens, les téléphones Samsung dans un sens différent, la ligne Nexus semble adhérer quel que soit le fournisseur choisi. Les ROM basées sur CM7 sont conformes à la norme, quel que soit le matériel utilisé, mais vous avez l’idée. Vous devez en quelque sorte déterminer quoi faire en fonction du téléphone/de la ROM. Voir la discussion ici: Caméra Android rotation inexplicable sur la capture de certains appareils (pas dans EXIF)

13
Kaediil

Essaye ça

try {
        File f = new File(imagePath);
        ExifInterface exif = new ExifInterface(f.getPath());
        int orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        int angle = 0;

        if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
            angle = 90;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
            angle = 180;
        } else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
            angle = 270;
        }

        Matrix mat = new Matrix();
        mat.postRotate(angle);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 2;

        Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f),
                null, options);
        bitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
                bmp.getHeight(), mat, true);
        ByteArrayOutputStream outstudentstreamOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100,
                outstudentstreamOutputStream);
        imageView.setImageBitmap(bitmap);

    } catch (IOException e) {
        Log.w("TAG", "-- Error in setting image");
    } catch (OutOfMemoryError oom) {
        Log.w("TAG", "-- OOM Error in setting image");
    }

Ça va marcher 

22
Ameer

J'ai eu le même problème que vous, mais j'ai résolu le problème.
Vous devriez utiliser le même code:

Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(90);
camera.setParameters(parameters);

J'espère que vous pouvez utiliser ce code aussi.

6
leonkuehn
camera.setDisplayOrientation(90);

J'ai codé l'application uniquement pour le mode Portrait. 

Cela fera tourner la caméra à 90 degrés et que cela pourrait ne pas convenir à tous les appareils sous Android Pour obtenir l'aperçu correct pour tous les appareils Android, utilisez le code suivant, référencé sur le site des développeurs.

Ci-dessous, vous devez envoyer votre activité, cameraId = back est 0 et pour caméra frontale est 1

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;
    //int currentapiVersion = Android.os.Build.VERSION.SDK_INT;
        // do something for phones running an SDK before Lollipop
        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);
} 

Voici comment définir setDisplayOrientation pour la caméra 

Vous pouvez maintenant avoir des difficultés à enregistrer l'image capturée dans l'orientation correcte, ce qui constitue un bogue dans Camera API pour prendre en charge tous les périphériques sous Android . que vous pouvez surmonter en suivant les étapes ci-dessous  

PLS NOTE EXIF ​​VALUE NE VOUS DONNERA PAS UNE VALEUR CORRECTE DANS TOUS LES APPAREILS, cela vous aiderait donc

int CameraEyeValue = setPhotoOrientation(CameraActivity.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back

En utilisant le même concept que nous avons utilisé auparavant pour DisplayOrientation 

public int setPhotoOrientation(Activity activity, int cameraId) {
    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;
    // do something for phones running an SDK before Lollipop
    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;
    }

    return result;
}

Donc, votre méthode finale PictureCallBack devrait ressembler à 

private PictureCallback getPictureCallback() {
    PictureCallback picture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            //make a new picture file
            File pictureFile = getOutputMediaFile();

            if (pictureFile == null) {
                return;
            }
            try {
                //write the file
                FileOutputStream fos = new FileOutputStream(pictureFile);
                Bitmap bm=null;

                // COnverting ByteArray to Bitmap - >Rotate and Convert back to Data
                if (data != null) {
                    int screenWidth = getResources().getDisplayMetrics().widthPixels;
                    int screenHeight = getResources().getDisplayMetrics().heightPixels;
                    bm = BitmapFactory.decodeByteArray(data, 0, (data != null) ? data.length : 0);

                    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                        // Notice that width and height are reversed
                        Bitmap scaled = Bitmap.createScaledBitmap(bm, screenHeight, screenWidth, true);
                        int w = scaled.getWidth();
                        int h = scaled.getHeight();
                        // Setting post rotate to 90
                        Matrix mtx = new Matrix();

                        int CameraEyeValue = setPhotoOrientation(AndroidCameraExample.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back
                        if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation
                            if (CameraEyeValue == 270) {
                                mtx.postRotate(90);
                            } else if (CameraEyeValue == 90) {
                                mtx.postRotate(270);
                            }
                        }else{
                                mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation
                        }

                        bm = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, true);
                    }else{// LANDSCAPE MODE
                        //No need to reverse width and height
                        Bitmap scaled = Bitmap.createScaledBitmap(bm, screenWidth, screenHeight, true);
                        bm=scaled;
                    }
                }
                // COnverting the Die photo to Bitmap



                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                bm.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                byte[] byteArray = stream.toByteArray();
                fos.write(byteArray);
                //fos.write(data);
                fos.close();

                Toast toast = Toast.makeText(myContext, "Picture saved: " + pictureFile.getName(), Toast.LENGTH_LONG);
                toast.show();

            } catch (FileNotFoundException e) {
            } catch (IOException e) {
            }

            //refresh camera to continue preview
            mPreview.refreshCamera(mCamera);
            mPreview.setCameraDisplayOrientation(CameraActivity.this,GlobalCameraId,mCamera);
        }
    };
    return picture;
}

Fonctionne uniquement en mode Portrait avec les appareils photo avant et arrière. L'image est tournée en mode portrait uniquement avec l'orientation Portrait correcte sur tous les appareils Android. 

Pour LandScape, vous pouvez le définir comme référence et apporter des modifications dans le bloc ci-dessous. 

   if(cameraFront) { // As Front camera is Mirrored so Fliping the Orientation
         if (CameraEyeValue == 270) {
             mtx.postRotate(90); //change Here 
          } else if (CameraEyeValue == 90) {
             mtx.postRotate(270);//change Here 
           }
        }else{
           mtx.postRotate(CameraEyeValue); // CameraEyeValue is default to Display Rotation //change Here 
        }
1
vignesh waran