Проблема ориентации камеры в 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.
Пример : Скольжение.с контекстом.)нагрузка (uri).в(книги);
дополнительные : 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
проведя много времени с большим количеством решений для задачи вращения изображения я, наконец, нашел два простых решения. Нам не нужно делать никаких дополнительных работ. 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, чтобы сохранить рисунок и показать ориентация @результат = ориентация на вид предварительного просмотра камеры @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; }кто-то вопрос о коде, пожалуйста, скажите мне.
Comments