Камера Android: снимок не соответствует предварительному просмотру

У меня проблема с камерой на Android, в основном, когда я делаю фотографию с помощью класса Camera, снятое выходное изображение на самом деле показывает больше, чем предварительный просмотр. Лучше всего было бы сказать, что предварительный просмотр обрезан. Как мне это исправить?

Я запускал приложение на Samsung Galaxy S4, Samsung Galaxy S3, HTC One M8 и Nexus One, и у всех была одна и та же проблема. (Все под управлением Android 4.0 ICS)

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

Камера, которую я пытаюсь создать, является портретной, поэтому я установил для displayOrientation значение 90.

Код, который я использую для определения размера предварительного просмотра и размера выходной фотографии, выглядит следующим образом (я полагаю, что проблема, скорее всего, где-то здесь):

public static Camera.Size getBestAspectPreviewSize(int displayOrientation,
                                                 int width,
                                                 int height,
                                                 Camera.Parameters parameters,
                                                 double closeEnough) {
double targetRatio=(double)width / height;
Camera.Size optimalSize=null;
double minDiff=Double.MAX_VALUE;

if (displayOrientation == 90 || displayOrientation == 270) {
  targetRatio=(double)height / width;
}

List<Size> sizes=parameters.getSupportedPreviewSizes();

Collections.sort(sizes,
                 Collections.reverseOrder(new SizeComparator()));

for (Size size : sizes) {
  double ratio=(double)size.width / size.height;

  if (Math.abs(ratio - targetRatio) < minDiff) {
    optimalSize=size;
    minDiff=Math.abs(ratio - targetRatio);
  }

  if (minDiff < closeEnough) {
    break;
  }
}

return(optimalSize);
}


 public static Camera.Size getLargestPictureSize(CameraHost host,
                                              Camera.Parameters parameters,
                                              boolean enforceProfile) {
Camera.Size result=null;

for (Camera.Size size : parameters.getSupportedPictureSizes()) {

  // android.util.Log.d("CWAC-Camera",
  // String.format("%d x %d", size.width, size.height));

  if (!enforceProfile
      || (size.height <= host.getDeviceProfile()
                             .getMaxPictureHeight() && size.height >= host.getDeviceProfile()
                                                                          .getMinPictureHeight())) {
    if (result == null) {
      result=size;
    }
    else {
      int resultArea=result.width * result.height;
      int newArea=size.width * size.height;

      if (newArea > resultArea) {
        result=size;
      }
    }
  }
}

if (result == null && enforceProfile) {
  result=getLargestPictureSize(host, parameters, false);
}

return(result);
 }

Класс сравнения размеров:

private static class SizeComparator implements
  Comparator<Camera.Size> {
@Override
public int compare(Size lhs, Size rhs) {
  int left=lhs.width * lhs.height;
  int right=rhs.width * rhs.height;

  if (left < right) {
    return(-1);
  }
  else if (left > right) {
    return(1);
  }

  return(0);
}
}

Это использует cwac-camera и SimpleCameraHost без изменений.

Любая помощь приветствуется!


person David Xu    schedule 07.06.2014    source источник


Ответы (1)


Как мне это исправить?

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

Цитирование документации:

Исходное поведение по умолчанию для CameraFragment и CameraView заключалось в том, чтобы отображать весь предварительный просмотр, предоставленный базовым Camera API. Поскольку соотношение сторон кадров предварительного просмотра может отличаться от соотношения сторон CameraView, это приводит к эффекту «почтового ящика», когда фон будет просвечиваться по одной оси по бокам.

Новое поведение по умолчанию заключается в том, чтобы полностью заполнить CameraView за счет обрезки части фактического кадра предварительного просмотра, что известно как «предварительный просмотр без полей» (украденная терминология из мира печатных СМИ).

Чтобы контролировать это поведение:

  • Пусть ваш CameraHost вернется true или false из useFullBleedPreview()

  • Или вызовите useFullBleedPreview() на своем SimpleCameraHost.Builder, передав значение boolean для использования по умолчанию.

Обратите внимание, что useFullBleedPreview() не затрагивает фотографии и видео, снятые этой библиотекой. Следовательно, если useFullBleedPreview() возвращает true, изображение или видео может содержать дополнительный контент по краям, который не был виден при предварительном просмотре.

person CommonsWare    schedule 07.06.2014
comment
Я заставил useFullBleedPreview() возвращать false , но у меня все еще есть та же проблема. Как вы думаете, это как-то связано с зумом? Или это потому, что превью обрезано, а снимок нет? - person David Xu; 07.06.2014
comment
@DavidXu: Если ваш предварительный просмотр не изменился, значит, что-то не так — либо вы неправильно отключаете предварительный просмотр без полей, либо в библиотеке есть ошибка. - person CommonsWare; 07.06.2014
comment
Я переопределил useFullBleedPreview() в своем пользовательском CameraHost, чтобы он возвращал false, разве этого не должно быть достаточно? - person David Xu; 07.06.2014
comment
@DavidXu: Так и должно быть. Ваш предварительный просмотр отображается в виде почтового ящика (т. е. белые полосы с одной стороны)? - person CommonsWare; 07.06.2014
comment
Нет, это не так. Экран полностью заполнен предварительным просмотром камеры. Работает на Galaxy S4 с 4.0 ICS. - person David Xu; 07.06.2014
comment
@DavidXu: Загрузите демонстрационный проект и попробуйте его там. Если вы можете воспроизвести проблему с демонстрационным проектом, сообщите об ошибке. Если демонстрационный проект работает правильно после того, как вы измените настройку предварительного просмотра без полей, значит, с вашим проектом что-то еще не так. - person CommonsWare; 07.06.2014
comment
Хорошо, только что протестировал демо cwac-camera. Та же проблема. Вокруг объектов, которые я сфотографировал на сохраненном изображении, есть пробел, которого не было в предварительном просмотре. Кроме того, предварительный просмотр фронтальной камеры в cwac-demo сжат по вертикали. - person David Xu; 07.06.2014
comment
@DavidXu: Ну, предварительный просмотр должен быть сжат вертикально вниз с отключенным предварительным просмотром без полей, если это то, что заставляет работать соотношения сторон. Насколько я понимаю, ваш предварительный просмотр не изменился, когда вы применили это к своему собственному приложению. Помимо этого, я предполагаю, что это функция базовой логики Camera. Все, что я делаю, это запрашиваю предварительный просмотр и изображение, и при отключенном предварительном просмотре без полей я ничего не делаю, чтобы обрезать ни предварительный просмотр, ни изображение. - person CommonsWare; 07.06.2014
comment
Я сделал фотографию с fullBleedPreview = false и fullBleedPreview = true с демонстрационным проектом cwac-camera. Я выровнял 2 айфона рядом друг с другом и поместил ручки выше, совместив край превью с краями 2 айфонов и ручек. Когда я сделал фото и посмотрел на результат, на изображении больше, чем на превью. Оба с fullBleedPreview = false и true. Сделанное изображение выглядит так: puu.sh/9iYNq/a57a8cfc89.png, тогда как края должны быть согласовано с телефонами. - person David Xu; 07.06.2014
comment
@DavidXu: Я хочу сказать, что это может не иметь никакого отношения к моей библиотеке. Я имею в виду, что я получаю те же результаты с приложением «Камера» на своем Nexus 4 — изображение имеет больше, чем предварительный просмотр. В зависимости от характера того, что я вижу с помощью приложения «Камера», соотношение сторон различается (предварительный просмотр и изображение), поэтому вы получите разные результаты по определению. Вы можете обрезать изображение по своему усмотрению, основываясь на соотношении сторон, которое вы используете для предварительного просмотра, если хотите. Моя библиотека не делает этого автоматически (не стесняйтесь подавать запрос на улучшение, если хотите). - person CommonsWare; 07.06.2014
comment
@DavidXu: Мой ответ заключался в том, чтобы просто убедиться, что вы сравниваете яблоки с яблоками, а не полная обрезка является источником ваших трудностей. - person CommonsWare; 07.06.2014
comment
Ясно - тогда я, вероятно, сам обрежу изображение, я также протестировал родное приложение камеры на своем Galaxy S4, и оно работает, как и ожидалось, поэтому я не уверен, в чем именно проблема :) - person David Xu; 07.06.2014
comment
@DavidXu: измерьте соотношение сторон предварительного просмотра и изображения. Соотношение изображения можно рассчитать из полученного файла изображения; соотношение предварительного просмотра необходимо будет измерить с помощью линейки (если оно не полноэкранное). Если эти соотношения идентичны, то предварительный просмотр будет соответствовать изображению, и это было достигнуто либо путем обрезки, либо путем выбора размеров изображения и предварительного просмотра с одинаковым соотношением. Если соотношения не идентичны, то по определению либо картинка, либо превью покажет что-то другое, чего нет. - person CommonsWare; 07.06.2014
comment
@DavidXu: Вы, безусловно, можете рассмотреть возможность сохранения того же соотношения сторон в качестве критерия при выборе размера изображения и предварительного просмотра. Если вы выберете те, которые имеют одинаковое соотношение, предварительный просмотр и изображение должны совпадать в том, что они показывают (в любом случае, с выключенным предварительным просмотром без полей). Однако производители устройств не обязаны предлагать хороший размер предварительного просмотра и хороший размер изображения, которые имеют одинаковое соотношение сторон. - person CommonsWare; 07.06.2014
comment
Спасибо за все, я решил это, обрезав соотношение сторон выходного изображения. Теперь работает отлично! Отличная библиотека, кстати! - person David Xu; 08.06.2014
comment
@DavidXu: я рад, что у вас все получилось! - person CommonsWare; 08.06.2014