Problème d'orientation de la caméra sur Android
je construis une application qui utilise la caméra pour prendre des photos. Voici mon code source pour le faire:
File file = new File(Environment.getExternalStorageDirectory(),
imageFileName);
imageFilePath = file.getPath();
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(intent, ACTIVITY_NATIVE_CAMERA_AQUIRE);
sur onActivityResult()
méthode, j'utilise BitmapFactory.decodeStream()
pour capter l'image.
quand J'exécute mon application sur Nexus one, il fonctionne bien. Mais quand je cours sur Samsung Galaxy S ou HTC Inspire 4G, la direction de l'image n'est pas correcte.
- Capture en mode portrait, L'image réelle (enregistrer sur la carte SD)) il tourne toujours à 90 degrés.
aperçu de l'Image après coup --------- Réelle de l'image sur la carte SD
- Capture avec le mode paysage, tout va bien.
aperçu de l'Image après coup --------- Réelle de l'image sur la carte SD
14 réponses
il y a pas mal de sujets et de sujets similaires ici. Puisque vous n'écrivez pas votre propre caméra, je pense que cela se résume à ceci:
certains appareils tournent l'image avant de la sauvegarder, tandis que d'autres ajoutent simplement la balise d'orientation dans les données exif de la photo.
je recommande de vérifier les données exif de la photo et de chercher en particulier pour
ExifInterface exif = new ExifInterface(SourceFileName); //Since API Level 5
String exifOrientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
puisque la photo s'affiche correctement dans votre application, Je ne suis pas assurez-vous où est le problème, mais cela devrait certainement vous mettre sur le droit chemin!
je viens de rencontrer le même problème, et j'ai utilisé ceci pour corriger l'orientation:
public void fixOrientation() {
if (mBitmap.getWidth() > mBitmap.getHeight()) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
mBitmap = Bitmap.createBitmap(mBitmap , 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
}
}
si la largeur du Bitmap est supérieure à la hauteur, l'image retournée est dans le paysage, donc je la tourne de 90 degrés.
espère que cela aidera quelqu'un d'autre avec cette question.
il y a deux choses nécessaires:
-
l'aperçu de la caméra doit être le même que votre rotation. Mettez ceci par
camera.setDisplayOrientation(result);
-
enregistrez l'image capturée en preview de votre appareil photo. Faites ceci via
Camera.Parameters
.int mRotation = getCameraDisplayOrientation(); Camera.Parameters parameters = camera.getParameters(); parameters.setRotation(mRotation); //set rotation to save the picture camera.setDisplayOrientation(result); //set the rotation for preview camera camera.setParameters(parameters);
Espère que ça aide.
int rotate = 0;
try {
File imageFile = new File(sourcepath);
ExifInterface exif = new ExifInterface(
imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
bitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
une autre option est de faire tourner le bitmap dans l'écran résultat comme ceci:
ImageView img=(ImageView)findViewById(R.id.ImageView01);
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.refresh);
// Getting width & height of the given image.
int w = bmp.getWidth();
int h = bmp.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
mtx.postRotate(90);
// Rotating Bitmap
Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);
BitmapDrawable bmd = new BitmapDrawable(rotatedBMP);
img.setImageDrawable(bmd);
j'ai aussi ce type de problème pour certains appareils:
private void rotateImage(final String path) {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(Conasants.bm1, 1000,
700, true);
Bitmap rotatedBitmap = null;
try {
ExifInterface ei = new ExifInterface(path);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(),
matrix, true);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(),
matrix, true);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(),
matrix, true);
break;
default:
rotatedBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(),
matrix, true);
break;
}
} catch (Throwable e) {
e.printStackTrace();
}
cropImage.setImageBitmap(rotatedBitmap);
rotatedBitmap = null;
Conasants.bm1 = null;
}
plus de vérification des données exif de la photo. Allez-y doucement avec Glide .
Google nous a présenté une bibliothèque de chargeur D'Image pour Android développé par bumptech nommé Glide comme une bibliothèque recommandée par Google. Il a été utilisé dans de nombreux projets Google open source jusqu'à présent, y compris L'application officielle Google I/O 2014.
Ex: Planer.avec(contexte).charge(uri).dans (imageview);
pour plus : https://github.com/bumptech/glide
Essayez par ici : statique Uri image_uri; image statique taken_image=null;
image_uri=fileUri; // file where image has been saved
taken_image=BitmapFactory.decodeFile(image_uri.getPath());
try
{
ExifInterface exif = new ExifInterface(image_uri.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch(orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200);
RotateBitmap(taken_image, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200);
RotateBitmap(taken_image, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200);
RotateBitmap(taken_image, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
taken_image=decodeScaledBitmapFromSdCard(image_uri.getPath(), 200, 200);
RotateBitmap(taken_image, 0);
break;
}
}
catch (OutOfMemoryError e)
{
Toast.makeText(getActivity(),e+"\"memory exception occured\"",Toast.LENGTH_LONG).show();
}
public Bitmap RotateBitmap(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
round_Image = source;
round_Image = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
public void setCameraPicOrientation(){
int rotate = 0;
try {
File imageFile = new File(mCurrentPhotoPath);
ExifInterface exif = new ExifInterface(
imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
} catch (Exception e) {
e.printStackTrace();
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
int targetW = 640;
int targetH = 640;
/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
/* Figure out which way needs to be reduced less */
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW/targetW, photoH/targetH);
}
/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
/* Decode the JPEG file into a Bitmap */
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
bitmap= Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
/* Associate the Bitmap to the ImageView */
imageView.setImageBitmap(bitmap);
}
Espère que cela va vous aider!! Merci
public static int mOrientation = 1;
OrientationEventListener myOrientationEventListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.takephoto);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
myOrientationEventListener
= new OrientationEventListener(getApplicationContext()) {
@Override
public void onOrientationChanged(int o) {
// TODO Auto-generated method stub
if(!isTablet(getApplicationContext()))
{
if(o<=285 && o>=80)
mOrientation = 2;
else
mOrientation = 1;
}
else
{
if(o<=285 && o>=80)
mOrientation = 1;
else
mOrientation = 2;
}
}
};
myOrientationEventListener.enable();
}
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout
& Configuration.SCREENLAYOUT_SIZE_MASK)
>= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
}
j'espère que cela aidera.Merci!
juste rencontrer le même problème ici, le code snippet ci-dessous fonctionne pour moi:
private static final String[] CONTENT_ORIENTATION = new String[] {
MediaStore.Images.ImageColumns.ORIENTATION
};
static int getExifOrientation(ContentResolver contentResolver, Uri uri) {
Cursor cursor = null;
try {
cursor = contentResolver.query(uri, CONTENT_ORIENTATION, null, null, null);
if (cursor == null || !cursor.moveToFirst()) {
return 0;
}
return cursor.getInt(0);
} catch (RuntimeException ignored) {
// If the orientation column doesn't exist, assume no rotation.
return 0;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
espérons que cela aide :)
Essayer dans la surfaceChanged rappel:
Camera.Parameters parameters=mCamera.getParameters();
if(this.getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
parameters.setRotation(90);
}else{
parameters.setRotation(0);
}
mCamera.setParameters(parameters);
deux Une ligne de solutions à l'aide de Picasso et de la glisse de la bibliothèque
après avoir passé beaucoup de temps avec beaucoup de solutions pour le problème de rotation d'image, j'ai finalement trouvé deux solutions simples. Nous n'avons pas besoin de faire des travaux supplémentaires. Picasso et Glide sont une bibliothèque très puissante pour manipuler des images dans votre application inclut. Il lira les données image EXIF et fera tourner les images.
utilisant la bibliothèque de plané https://github.com/bumptech/glide
Glide.with(this).load("http url or sdcard url").into(imgageView);
utilisation de la bibliothèque Picasso https://github.com/square/picasso
Picasso.with(context).load("http url or sdcard url").into(imageView);
le code est fonctionnel pour paysage et portrait @frontCameraID = variable a obtenu la méthode classique pour montrer à la caméra voulu
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(holder.getSurface() == null) {
return;
}
try{
camera.stopPreview();
} catch (Exception e){
}
try{
int orientation = getDisplayOrientation(frontCameraID);
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
if (parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
parameters.setRotation(rotationPicture);
camera.setParameters(parameters);
camera.setDisplayOrientation(orientation);
camera.startPreview();
} catch (Exception e) {
Log.i("ERROR", "Camera error changed: " + e.getMessage());
}
}
méthode pour obtenir l'orientation y rotation pour enregistrer l'orientation de l'image et de l'affichage @résultat = orientation sur l'aperçu de la caméra @rotationPicture = rotation nécessaire pour sauvegarder l'image correctement
private int getDisplayOrientation(int cameraId) {
android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = ((Activity) context).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;
rotationPicture = (360 - result) % 360;
} else {
result = (info.orientation - degrees + 360) % 360;
rotationPicture = result;
}
return result;
}
Quelqu'un a une question sur le code, s'il vous plaît dites-moi.