studio - ¿La imagen resultante de la cámara de Android debe rotarse después de la captura?
open camera android developer (4)
Estoy escribiendo una aplicación de Android que utiliza la cámara. Estoy configurando la orientación de la pantalla de la cámara en 90, mi actividad es en orientación vertical:
camera.setDisplayOrientation(90);
Obtengo una imagen de vista previa bien orientada, pero la imagen resultante se gira a -90 grados (en sentido contrario a las agujas del reloj) y
exif.getAttribute(ExifInterface.TAG_ORIENTATION)
devuelve ORIENTATION_NORMAL
¿Es el comportamiento esperado? ¿Debo rotar la imagen resultante después de la captura?
Dispositivo - Nexus S, API - 10
El problema es que la orientación de la cámara es un completo desastre (ya que está capturando una imagen) porque los OEM no se adhieren a la norma. Los teléfonos HTC hacen las cosas de una manera, los teléfonos Samsung lo hacen de una manera diferente, la línea Nexus parece adherirse sin importar qué proveedor, las ROM basadas en CM7 creo que siguen el estándar sin importar qué hardware, pero entienden la idea. Tienes que determinar qué hacer en función del teléfono / ROM. Vea la discusión aquí: Rotación inexplicable de la cámara de Android en la captura de algunos dispositivos (no en EXIF)
Prueba esto
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");
}
Funcionará
Tuve el mismo problema que tú, pero lo arreglé.
Debes usar el mismo código:
Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(90);
camera.setParameters(parameters);
Espero que puedas usar este código también.
camera.setDisplayOrientation(90);
He codificado la aplicación sólo para el modo de retrato.
Hará que la cámara gire a 90 grados y esto puede resultar en que no sea adecuado para todos los dispositivos en Android. Para obtener la Vista previa correcta para todos los dispositivos Android, use el siguiente código que se encuentra en el sitio de los desarrolladores.
Debajo tienes que enviar tu actividad, cameraId = back es 0 y para la cámara frontal es 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);
}
Así es como se configura el setDisplayOrientation para la cámara.
Ahora puede tener problemas para guardar la imagen capturada en la orientación correcta, que es un error en la API de la cámara para admitir todos los dispositivos en Android. Puedes superar usando los pasos a continuación
PLS NOTE EXIF VALUE NO LE DA CORREGIR EL VALOR EN TODOS LOS DISPOSITIVOS, así que esto le ayudaría
int CameraEyeValue = setPhotoOrientation(CameraActivity.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back
Usando el mismo concepto que usamos antes para 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;
}
Así que tu último método de PictureCallBack debería verse como
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;
}
Como funciona solo para el modo de retrato usando la cámara frontal y trasera La imagen se gira solo al modo de retrato con la orientación vertical correcta en todos los dispositivos Android.
Para LandScape puede hacer esto como referencia y realizar cambios en el bloque de abajo
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
}