Изображение камеры Android должно быть повернуто после захвата?
Я пишу приложение для Android, которое использует камеру.
Я устанавливаю ориентацию дисплея камеры до 90, моя активность в портретной ориентации:
camera.setDisplayOrientation(90);
Я получаю хорошо ориентированное изображение предварительного просмотра, но результирующее изображение поворачивается на -90 градусов (против часовой стрелки) и
exif.getAttribute(ExifInterface.TAG_ORIENTATION)
возвращает ORIENTATION_NORMAL
Ожидается ли поведение? Должен ли я поворачивать изображение после захвата?
Устройство - Nexus S, API - 10
Ответы
Ответ 1
Проблема заключается в том, что ориентация камеры является полной катастрофой (как и захват изображения), поскольку OEM-производители не придерживаются стандарта. Телефоны HTC делают что-то в одном направлении, телефоны Samsung делают это по-другому, линия Nexus, похоже, придерживается независимо от того, какой производитель, ПЗУ на CM7, я думаю, следую стандарту, независимо от того, какое оборудование, но вы получаете эту идею. Вы должны определить, что делать на основе телефона/ПЗУ. Смотрите обсуждение здесь: Камера Android необъяснимого вращения при захвате для некоторых устройств (не в EXIF)
Ответ 2
Попробуйте это
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");
}
Он будет работать
Ответ 3
У меня была такая же проблема, как и вы, но я исправил ее.
Вы должны использовать тот же код:
Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(90);
camera.setParameters(parameters);
Надеюсь, вы тоже сможете использовать этот код.
Ответ 4
camera.setDisplayOrientation(90);
Я закодировал приложение только для портретного режима.
Поверните камеру на 90 градусов, и это может привести к неспособности всех устройств в Android
Чтобы получить правильный просмотр для всех устройств Android, используйте следующий код, который ссылается на сайт разработчиков.
Ниже вы должны отправить свою активность, cameraId = назад - 0, а для фронтальной камеры - 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);
}
Вот как установить setDisplayOrientation для камеры
Теперь у вас могут возникнуть проблемы с сохранением захваченного изображения в правильной ориентации, что является ошибкой в API-интерфейсе камеры для поддержки всех устройств в Android. можно преодолеть с помощью шагов ниже
PLS ПРИМЕЧАНИЕ EXIF VALUE НЕ ДАЕТ ВАМ ПРАВИЛЬНОЕ ЗНАЧЕНИЕ В ВСЕХ УСТРОЙСТВАХ, поэтому это поможет вам
int CameraEyeValue = setPhotoOrientation(CameraActivity.this, cameraFront==true ? 1:0); // CameraID = 1 : front 0:back
Используя ту же концепцию, которую мы использовали ранее для 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;
}
Итак, ваш окончательный метод PictureCallBack должен выглядеть как
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;
}
Как работает только для портретного режима с использованием передней и задней камеры. Изображение поворачивается только в портретном режиме с правильной ориентацией на портрет во всех устройствах Android.
Для LandScape вы можете сделать это как ссылку и внести изменения в нижеуказанный блок
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
}