2015-03-10 3 views
1

После съемки фотографии, когда устройство находится в портрете, используя API-интерфейс камеры и предварительный просмотр SurfaceView, созданное изображение поворачивается на 90 градусов. Я понимаю, что это проблема, связанная с некоторыми телефонами Android, включая Samsung Galaxy S5. Я разрабатываю - есть несколько вопросов о переполнении стека об этом - see here и here. Было предложено, чтобы файл изображения содержал метаданные EXIF, которые будут указывать ориентацию, которую он повернул, чтобы вы могли использовать это, чтобы повернуть изображение назад, чтобы получить правильную ориентацию. Я сделал именно это, но по какой-то причине ExifInterface.TAG_ORIENTATION - 1 - ORIENTATION_NORMAL. Поэтому я не могу определить, сколько изображения нужно повернуть, чтобы оно работало на всех устройствах. Хотя это решение, похоже, сработало для других. Что я сделал не так, или как еще можно решить эту проблему?Растровое изображение поворачивается после фотосъемки с камерой

Некоторые псевдокод:

//in onCreate 
camera = getCameraInstance(); 
setCameraDisplayOrientation(this, cameraID, camera); 

//in OnClickListener 
camera.takePicture(null, null, picCallback); 

//callback: 
onPictureTaken { 
    //create a File using getExternalStoragePublicDirectory(PICTURES) + "appname" - create directory if doesn't exist 
    //write file to disk via FileOutputStream 

    //attempt to correct the image orientation if needed 
    Bitmap correctBitmap = getCorrectOrientationBitmap(picFile.getAbsolutePath()); 
} 

public Bitmap getCorrectOrientationBitmap(String photoFilePath) { 
    // Read EXIF Data 
    ExifInterface exif = null; 
    try { 
     exif = new ExifInterface(photoFilePath); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     return null; 
    } 
    String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION); 
    //problem: orientation is 1 - ORIENTATION_NORMAL despite the fact the image is rotated to the right 90 degrees 
    //rotate the image based on EXIF orientation 
} 

//later on 
myImageView.setImageBitmap(correctBitmap); 
//shows image rotated to the right because getCorrectOrientationBitmap didn't rotate it 
+0

http://stackoverflow.com/questions/14066038/why-image-captured-using-camera-intent-gets-rotated-on-some-devices-in-android внимательно читает все ответы .. u не получают правильный bmp.ORIENT .. см. запрос контента на «mediaStore» по ссылке .. это samsung only issue AFAIK –

+0

@RobertRowntree Я не использую 'MediaStore' – Joey

ответ

0

Перед съемке требуется setDisplayOrientation() в соответствии с ориентацией текущего устройства. Это не делается автоматически и по умолчанию всегда устанавливается на 0 градусов, что обычно соответствует ландшафтной ориентации.

Это не Galaxy s5 вопрос

+0

Я уже называл' setDisplayOrientation'. Будет обновлен код, чтобы показать это. – Joey

+0

и все еще проблема? –

+0

Да, у меня было это в моем коде, прежде чем отправлять вопрос – Joey

0

--EDIT-- в моем коде ...

matrix.postRotate (вращение);

использует значение для «вращения», которое возвращает код felix из его курсора.

я думаю, что ваши фотографии есть URI .... смотреть на интерфейс против использования статического значения атр для типа ....

public static int getOrientation(Context context, Uri photoUri) { 
    /* it's on the external media. */ 
    Cursor cursor = context.getContentResolver().query(photoUri, 
      new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null); 
    if(null == cursor){ 
     return -1; 
    } 
    if (cursor.getCount() != 1) { 
     return -1; 
    } 

.....

if (getOrientation(mctx, mURI) != 0 && != -1) doRotate(); 


public doRotate(){ 
    Bitmap lbit = 
    BitmapFactory.decodeStream(            getContentResolver().openInputStream(_uri),null,options); 
    Log.i(TAG, "Rotating... " + rotation); 
    lbit = lbit.copy(Bitmap.Config.ARGB_8888, true); 
    Matrix matrix = new Matrix(); 
    matrix.postRotate(rotation); 
    lbit = Bitmap.createBitmap(lbit, 0, 0, lbit.getWidth(), 
    lbit.getHeight(), matrix, true); 
    Picture.setBmp(lbit); 

    cursor.moveToFirst(); 
    return cursor.getInt(0); 
    } 
} 
+0

'cursor' является' null', когда я пытаюсь это сделать. Если я использую метод getRotation из ответа Felix, он возвращает '0', но' mediaCursor' не является нулевым. – Joey

+0

Felix = хорошее возможное решение для u. если mediaCursor не равен нулю, попробуйте использовать возвращаемое значение для вращения вращения, как в коде Felix. Обратите внимание, что решение, которое я получил, было построено на коде из felix, я думаю. Я не мог найти другого объяснения для ротации на новых планшетах samsung, и код felix решил эту проблему. Мой код может быть полезен дословно, но я пытался упаковать что-то, что имело бы смысл. Поймите, к чему пришел Феликс. –

+0

Его код 'getRotation' никогда не использует' selectedImage'' Uri' - это всегда возвращает ориентацию последней фотографии в галерее, а не фотография, сделанная в приложении. – Joey

0

Я играл с этой проблемой некоторое время назад и разместил код камеры на GitHub here. Вопрос заключается в том, что вы имеете дело с 3-мя различными организациями: ориентация

  • поверхности - зависит от ориентации устройства в момент
  • просмотр ширина/высота вы получаете от 'surfaceChanged'
  • окончательной ориентации изображения, как вы получите от ' takePicture»

В примере упоминался, I rotate the final изображений такого же количество, как я вращал preview at the beginning. Я не тестировал его на S5, поэтому, если вы пойдете так, пожалуйста, сообщите мне, работает ли он там.

Еще одна вещь, есть проблема с некоторыми таблетками (see readme.md), где некоторые имеют 'natural' orientation landscape (Nex7 1Gen), где другие (Nex7 2Gen) имеют портрет, такой же, как и телефоны.

Good Luck

0

При использовании изображения обратного вызова вместо камеры захвата намерения, EXIF ​​ориентации не установлена. Но, с другой стороны, вы можете точно знать ориентацию устройства, когда пользователь нажал кнопку «захват» или ее эквивалент.

Это становится еще проще, если ваша деятельность заблокирована в портретной ориентации - вы можете безоговорочно применить поворот на 90 °.

Поворот растровых изображений может быть довольно дорогим с точки зрения как памяти, так и производительности, поэтому, если ваш вариант использования удовлетворен установкой правильного TAG_ORIENTATION, тогда просто примените это изменение к сохраненному изображению. Обратите внимание, что ExifInterface работает с файлами, а не byte[], поэтому контровертично вы должны сначала сохранить буфер, затем применить поворот и снова сохранить.

+0

Было бы замечательно, если бы я всегда мог гарантировать, что каждый телефон будет поворачивать изображение 90 вправо при съемке фотографии в операции, которая заблокирована в портрете. Можете ли вы подтвердить, что это будет так - из моих исследований это звучит так, как это поведение (ошибка?) Существует только в нескольких телефонах (особенно Samsung). – Joey

+0

Ответ отрицательный, к сожалению. Рассмотрите планшеты с «естественным» ориентационным ландшафтом, в то время как другие планшеты (обычно 7 «) по умолчанию для портрета. Не задание' TAG_ORIENTATION' в обратном вызове является законным, но установка его в соответствии с текущей ориентацией устройства также является законной. –

Смежные вопросы