Android: сделанная фотография больше, чем превью

Я пытаюсь сделать снимок напрямую с помощью API камеры, но это предварительный просмотр, который я получил:

& это изображение, снятое после звонка takePicture() который больше, чем сам предварительный просмотр:

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

Я использую этот метод, чтобы выбрать оптимальный оптимальный размер предварительного просмотра перед запуском предварительного просмотра камеры:

public static Camera.Size getBestAspectPreviewSize(int displayOrientation,
                                                   int width,
                                                   int height,
                                                   Camera.Parameters parameters) {
    double targetRatio = (double) width / height;
    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;
    if (displayOrientation == 90 || displayOrientation == 270) {
        targetRatio = (double) height / width;
    }
    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
    Collections.sort(sizes,
            Collections.reverseOrder(new SizeComparator()));
    for (Camera.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 < 0.0d) {
            break;
        }
    }
    return (optimalSize);
}

И этот метод, чтобы выбрать подходящий размер изображения:

public static Camera.Size getBiggestSafePictureSize(Camera.Parameters parameters) {
    Camera.Size result = null;
    long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    long availableMemory = Runtime.getRuntime().maxMemory() - used;
    for (Camera.Size size : parameters.getSupportedPictureSizes()) {
        int newArea = size.width * size.height;
        long neededMemory = newArea * 4 * 4; // newArea * 4 Bytes/pixel * 4 needed copies of the bitmap (for safety :) )
        if (neededMemory > availableMemory)
            continue;
        if (result == null) {
            result = size;
        } else {
            int resultArea = result.width * result.height;
            if (newArea > resultArea) {
                result = size;
            }
        }
    }
    return (result);
}

& это элемент предварительного просмотра камеры в макете:

<FrameLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/cameraPreview"></FrameLayout>

& Я следую официальной документации для создания самого предварительного просмотра камеры

Итак, как заставить предварительный просмотр камеры показывать точную фотографию, которая будет сделана?

2 ответа

Решение

Наконец то я нашел это:)

в соответствии с этим ответом и я цитирую:

В то время как типичная камера имеет соотношение сторон 4:3, предварительный просмотр также может быть доступен в соотношениях 5:3 и 16:9, и это, кажется, достигается путем фактического расширения горизонтального поля зрения...

Поэтому нам нужно найти размер предварительного просмотра и размер изображения, оба с соотношением сторон 4:3, чтобы иметь возможность использовать полный угол камеры, поэтому я изменил свой код следующим образом:

public static Camera.Size determineBestPreviewSize(Camera.Parameters parameters) {
    List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
    return determineBestSize(sizes);
}

public static Camera.Size determineBestPictureSize(Camera.Parameters parameters) {
    List<Camera.Size> sizes = parameters.getSupportedPictureSizes();
    return determineBestSize(sizes);
}

protected static Camera.Size determineBestSize(List<Camera.Size> sizes) {
    Camera.Size bestSize = null;
    long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    long availableMemory = Runtime.getRuntime().maxMemory() - used;
    for (Camera.Size currentSize : sizes) {
        int newArea = currentSize.width * currentSize.height;
        long neededMemory = newArea * 4 * 4; // newArea * 4 Bytes/pixel * 4 needed copies of the bitmap (for safety :) )
        boolean isDesiredRatio = (currentSize.width / 4) == (currentSize.height / 3);
        boolean isBetterSize = (bestSize == null || currentSize.width > bestSize.width);
        boolean isSafe = neededMemory < availableMemory;
        if (isDesiredRatio && isBetterSize && isSafe) {
            bestSize = currentSize;
        }
    }
    if (bestSize == null) {
        return sizes.get(0);
    }
    return bestSize;
}

Вы должны запустить один и тот же цикл для размеров, возвращаемых parameters.getSupportedPictureSizes()и не полагаться на размер изображения по умолчанию. Кроме того, я предпочел бы найти лучшую соответствующую пару размеров предварительного просмотра / изображения и позволить обрезать изображение на экране, если это соотношение сторон не соответствует соотношению сторон cameraPreview раскладка.

Другие вопросы по тегам