Android: сделанная фотография больше, чем предварительный просмотр
Я пытаюсь захватить фотографии непосредственно с помощью api камеры, но это предварительный просмотр, который я получил:
![enter image description here]()
& это изображение, сделанное после вызова takePicture()
, которое больше, чем сам предварительный просмотр:
![enter image description here]()
(примечание: я обрезал высоту предыдущих двух фотографий, чтобы улучшить читаемость вопроса и сохранил ширину как есть)
Я использую этот метод утилиты для выбора оптимального размера предварительного просмотра перед запуском предварительного просмотра камеры:
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>
& Я следую официальной документации для создания самого предварительного просмотра камеры
Итак, как заставить предварительный просмотр камеры показывать точную фотографию, которая будет сделана?
Ответы
Ответ 1
Наконец, я нашел его:)
в соответствии с этим ответом, и я цитирую:
Пока типичная камера имеет формат 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;
}
Ответ 2
Вы должны запустить тот же цикл над размерами, возвращаемыми parameters.getSupportedPictureSizes()
, и не полагаться на размер изображения по умолчанию. Кроме того, я бы предпочел бы наилучшую соответствующую пару размеров предварительного просмотра/изображения, и пусть изображение будет обрезано на экране, если это соотношение сторон не соответствует формату формата cameraPreview
.