Подтвердить что ты не робот

Правильный ли код образца setDisplayOrientation?

Страница для Camera.setDisplayOrientation содержит следующий пример кода, в котором говорится, что использование этого параметра "сделает изображение камеры в той же ориентации, что и дисплей":

 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;
     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);
 }

Однако у меня были проблемы с его использованием, иногда изображение выглядело с ног на голову. После некоторой пробной ошибки я обнаружил, что правильный код будет (заменяем последние 8 строк метода):

    int result = (360 + info.orientation - degrees) % 360;
    camera.setDisplayOrientation(result);

(Это означает, что расчет для обратных камер также подходит для фронтальных камер). Комментарий "компенсировать зеркало" немного странный, поскольку зеркалирование не может быть отменено путем вращения, эта операция сворачивает только повороты на 90 ° и 270 ° что на самом деле не имеет смысла для меня.

Итак, вопрос: действительно ли образец неправильный или я что-то не хватает? Я пробовал его на нескольких устройствах, как на задних, так и на фронтальных камерах и на всех поддерживаемых ориентациях, поэтому я знаю, что мой код IS за работой. Одна маленькая деталь, о которой стоит упомянуть: все мои устройства вернулись на 90 ° как info.orientation.

EDIT: Здесь - мой код, связанный с камерой, я протестировал его на Nexus One и Samsung Galaxy S Plus. Он используется в моем 3D-приложении для отслеживания головы, предварительный просмотр показан в левом нижнем углу и всегда должен иметь правильную ориентацию.

РЕШЕНИЕ (вроде): Похоже, что код верен, но мой тестовый телефон (Samsung Galaxy S Plus) возвращает неверное значение для передней камеры CameraInfo.orientation. Существует много связанных дискуссий о том, что предварительный просмотр отображается вверх дном на этой модели (примеры здесь и здесь). Способ исправления состоит в том, чтобы включить возможность поворота изображения вручную.

4b9b3361

Ответ 1

Отказанный фрагмент, который я использовал и применял в моем проекте, не является проблемой в моих обстоятельствах.

Для всех устройств (Galaxy Note, Galaxy S III, Galaxy Nexus, Galaxy Ace II, Nexus S), которые я использовал для тестирования, info.Orientation все возвращают 270 на фронтальную камеру и 90 на задней камере.

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

Для неправильной ориентации в предварительном просмотре камеры, пожалуйста, обратитесь к этому решению:

Решение для неправильной ориентации в предварительном просмотре камеры:

Сначала убедитесь, что info.Orientation вернет 270 на фронтальную камеру, 90 на задней камере. Затем попробуйте настроить режим предварительного просмотра камеры (или аналогичный класс, который обрабатывает предварительный просмотр), в альбомную.

Таким образом, когда вы просматриваете код, вы найдете:

degree = 90 для ориентации экрана, info.Orientation = 270 для передней камеры. Затем вы получите result = (270 - 90 + 360) % 360, result = 180, что означает, что он будет поворачивать часы 180 для просмотра передней камеры, что позволит исправить проблему перевернутой передней камеры.

Решение для неправильной ориентации в результатах фотосъемки камеры:

Если этот info.Orientation применим к вам, проблема может быть:

  • Для некоторых устройств Samsung (или других) (например, Galaxy Note, Galaxy SIII) камера будет записывать только Ориентировочный тег вместо вращения реальных пикселей.
  • Если вы используете переднюю камеру и используете вышеприведенный код, она отображает предварительный просмотр с правильной ориентацией, но при отображении снимка будет отображаться изображение "вверх ногами".

Решение:

/**
 *
 * Get the orientation from EXIF
 * @param filepath
 * @return orientation
 */
public int getExifOrientation(String filepath) {
    int degree = 0;
    ExifInterface exif = null;
    try {
        exif = new ExifInterface(filepath);
    } catch (IOException ex) {
        Log.e("EXIF info", "cannot read exif", ex);
    }
    if (exif != null) {
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
        if (orientation != -1) {
            // We only recognize a subset of orientation tag values.
            switch(orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                degree = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                degree = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                degree = 270;
                break;
            }
        }
    } else {
        degree = 1;
    }
    Log.i("EXIF info", "Orientation degrees: " + degree);
    return degree;
}

Тогда

if (isFromCamera) {

    if (fromFrontCam) {
        // try change here if the orientation still wrong, -90 means rotate counter-clockwise 90 degrees.
        matrix.preRotate(-90);
     } else {
        matrix.preRotate(90);
     }
} else {
    // read EXIF data
    getExifOrientation(path)
    // don't forget to handle the situation that some devices won't write exif data
    matrix.preRotate(degree);
}