Android zxing - предварительный просмотр/просмотр панорамы камеры растягивается/искажается

Мне удалось использовать здесь ответ, чтобы повернуть предварительный просмотр камеры на портрет: http://code.google.com/p/zxing/issues/detail?id=178#c46

однако сам предварительный просмотр растягивается/искажается - высота, по-видимому, растягивается, чтобы заполнить поле (но может быть, что ширина слишком велика для экрана, и она сжимается, чтобы соответствовать)

Есть ли способ "обернуть" контент, а не растянуть его, чтобы он соответствовал представлению поверхности?

EDIT: я отсортировал его, изменив метод findBestPreviewSizeValue в "CameraConfigurationManager" и изменив точки X и Y (спасибо sean owen за указатель ниже!), вот код:

private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString,
  Point screenResolution) {
int bestX = 0;
int bestY = 0;
int diff = Integer.MAX_VALUE;
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {

  previewSize = previewSize.trim();
  int dimPosition = previewSize.indexOf('x');
  if (dimPosition < 0) {
    Log.w(TAG, "Bad preview-size: " + previewSize);
    continue;
  }

  int newX;
  int newY;
  try {
    newY = Integer.parseInt(previewSize.substring(0, dimPosition));
    newX = Integer.parseInt(previewSize.substring(dimPosition + 1));
    //original:
    //newX = Integer.parseInt(previewSize.substring(0, dimPosition));
    //newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
  } catch (NumberFormatException nfe) {
    Log.w(TAG, "Bad preview-size: " + previewSize);
    continue;
  }

  int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
  if (newDiff == 0) {
    bestX = newY;
    bestY = newX;
    //original:
    //bestX = newX;
    //bestY = newY;
    break;
  } else if (newDiff < diff) {
    bestX = newY;
    bestY = newX;
    //original:
    //bestX = newX;
    //bestY = newY;
    diff = newDiff;
  }

}

if (bestX > 0 && bestY > 0) {
  return new Point(bestX, bestY);
}
return null;
}

Ответы

Ответ 1

Вам нужно сделать еще немного, чтобы заставить это работать, чем просто настроить режим просмотра в портретном режиме. Например, вам нужно выбрать соответствующий размер предварительного просмотра сейчас, когда он будет выполнен в портретном, а не ландшафтном.

Упаковка, безусловно, нежелательна? Нет, вы не можете заставить его обернуть; он всегда будет выводить изображение предварительного просмотра на SurfaceView, растягивая при необходимости. Я полагаю, вы могли бы переопределить многие из этого кода, чтобы сделать что-то другое, но это было бы довольно сложно.

Ответ 2

У меня была такая же проблема, но я смог ее решить, инвертируя соотношение сторон в файле CameraConfigurationManager.java внутри findBestPreviewSizeValue, меняя этот

 float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;

к этому

 float screenAspectRatio = (float) screenResolution.y / (float) screenResolution.x;

Я нашел решение здесь.

http://bighow.net/4660010-Android_zxing___portrait_camera_preview_surfaceview_is_stretched_warped.html

Ответ 3

Вы можете получить размер Priview с помощью этой функции:

закрытый список mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();

if (mSupportedPreviewSizes != null) {
                mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
            }

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            double targetRatio = (double) h / w;

            if (sizes == null)
                return null;

            Camera.Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = h;

            for (Camera.Size size : sizes) {
                double ratio = (double) size.height / size.width;
                if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                    continue;

                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }

            if (optimalSize == null) {
                minDiff = Double.MAX_VALUE;
                for (Camera.Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                    }
                }
            }

            return optimalSize;
        }


            float ratio;
            if (mPreviewSize.height >= mPreviewSize.width)
                ratio = (float) mPreviewSize.height / (float) mPreviewSize.width;
            else
                ratio = (float) mPreviewSize.width / (float) mPreviewSize.height;

            after getting ratio set your size in 

            protected void onMeasure(int widthMeasureSpec, int                              heightMeasureSpec) {

            setMeasuredDimension((int) (width * ratio), height);
            }

Ответ 4

Мне удалось заставить это работать, изменив код ниже в CameraConfigurationManager.java:

float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;

To:

float screenAspectRatio = (float) screenResolution.y / (float) screenResolution.x;

и

float aspectRatio = (float) maybeFlippedWidth / (float) maybeFlippedHeight;

TO:

float aspectRatio = (float) maybeFlippedHeight / (float) maybeFlippedWidth;

Я сделал это рядом с этим сообщением: Zxing Camera в портретном режиме на Android

Надеюсь, что это поможет другим.

Ответ 5

Причиной деформации может быть то, что соотношение сторон предварительного просмотра камеры не соответствует формату отображения.

Максимальное соотношение сторон экрана мобильного телефона составляет 4: 3, например 2560x1440, 1920x1080 и т.д. Когда вы используете параметр parameter.setPreviewSize(ширина, высота), чтобы установить размер предварительного просмотра камеры, если значение height: width не равно вашему размеру экрана телефона, изображение камеры будет деформировано для заполнения экрана.