Проблема ориентации камеры в Android
Я создаю приложение, которое использует камеру для съемки. Вот мой исходный код для этого:
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);
On onActivityResult()
метод, я использую BitmapFactory.decodeStream()
для пикапа изображения.
когда я запускаю свое приложение на Nexus one, оно работает хорошо. Но когда я работаю на Samsung Galaxy S или HTC Inspire 4G, направление изображения неверно.
- захват с портретным режимом, реальное изображение (сохранить на SD-карте) всегда вращается на 90 градусов.
просмотр изображения после съемки --------- реального изображения на SD-карте
- захват с ландшафтным режимом, все хорошо.
просмотр изображения после съемки --------- реального изображения на SD-карте
14 ответов
есть довольно много подобных тем и вопросов здесь. Поскольку вы не пишете свою собственную камеру, я думаю, что это сводится к следующему:
некоторые устройства поворачивают изображение перед его сохранением, в то время как другие просто добавляют тег ориентации в данные exif фотографии.
Я бы рекомендовал проверить данные exif фотографии и особенно искать
ExifInterface exif = new ExifInterface(SourceFileName); //Since API Level 5
String exifOrientation = exif.getAttribute(ExifInterface.TAG_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);
}
}
если ширина растрового изображения больше высоты, возвращаемое изображение находится в ландшафте, поэтому я поворачиваю его на 90 градусов.
надеюсь, что это поможет кому-либо еще с этой проблемой.
необходимы две вещи:
предварительный просмотр камеры нужно то же самое, что и вращение. Установите это по
camera.setDisplayOrientation(result);
-
Сохранить изображение, захваченное в качестве предварительного просмотра камеры. Сделайте это через
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);
надеюсь, что это поможет.
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);
другой вариант-повернуть растровое изображение на экране результатов следующим образом:
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);
У меня тоже такие же проблемы для некоторых устройств:
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;
}
нет больше проверки данных exif фотографии. Полегче с скольжения.
Google представил нам библиотеку загрузчика изображений для Android, разработанную bumptech по имени скольжения как библиотека, рекомендованная Google. Он использовался во многих проектах с открытым исходным кодом Google до сих пор, включая официальное приложение Google I/O 2014.
Ex: Скольжение.с контекстом.)загрузить (uri).into (imageview);
дополнительные : https://github.com/bumptech/glide
попробуйте так : статический Uri image_uri; статическое растровое изображение 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);
}
надеюсь, это поможет!! Спасибо
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;
}
}
надеюсь, это поможет.Спасибо!
просто столкнитесь с той же проблемой здесь, фрагмент кода ниже работает для меня:
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();
}
}
}
надеюсь, это поможет:)
попробуйте это в обратном вызове surfaceChanged:
Camera.Parameters parameters=mCamera.getParameters();
if(this.getResources().getConfiguration().orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){
parameters.setRotation(90);
}else{
parameters.setRotation(0);
}
mCamera.setParameters(parameters);
два однолинейных решения с использованием Picasso и glide library
проведя много времени с большим количеством решений для задачи вращения изображения я, наконец, нашел два простых решения. Нам не нужно делать никаких дополнительных работ. Picasso и Glide - очень мощная библиотека для обработки изображений в вашем приложении. Он будет читать данные EXIF изображения и автоматически вращает изображения.
использование библиотеки glide https://github.com/bumptech/glide
Glide.with(this).load("http url or sdcard url").into(imgageView);
использование библиотеки Пикассо https://github.com/square/picasso
Picasso.with(context).load("http url or sdcard url").into(imageView);
код функционально для ландшафта и портрета @frontCameraID = переменная получила классический метод для показа камеры
@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());
}
}
метод для поворота ориентации y для сохранения ориентации изображения и дисплея @result = ориентация на вид предварительного просмотра камеры @rotationPicture = вращение, необходимое для правильного сохранения изображения
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;
}
кто-то вопрос о коде, пожалуйста, скажите мне.