В портретном режиме изображения выглядят вертикально растянутыми и в ландшафтном режиме он выглядит горизонтально растянутым.
Хотя после захвата изображение появляется в надлежащем размере.
Как решить эту проблему?
В портретном режиме изображения выглядят вертикально растянутыми и в ландшафтном режиме он выглядит горизонтально растянутым.
Хотя после захвата изображение появляется в надлежащем размере.
Как решить эту проблему?
Вам нужно выбрать размер предварительного просмотра, соответствующий размеру вашего дисплея. Я бы предложил изменить настройку размера предварительного просмотра в соответствии с вашим SurfaceView, а не наоборот. Хотя данные предварительного просмотра просто прекрасны, он не искажен, он будет искажен, когда он попадает на поверхность с различным соотношением сторон.
Если у вас полноэкранное представление, вы должны найти, что камера имеет размер предварительного просмотра, соответствующий этому размеру - по крайней мере, будет один с тем же соотношением сторон. Например, если на вашем экране 640x480, размер предварительного просмотра 320x240 не будет растянут на полноэкранном SurfaceView.
Вам нужно ограничить размер предварительного просмотра на основе (1) доступных размеров предварительного просмотра (2) вашего представления. Вот мое решение, если оно вам еще нужно:
private class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
private void startPreview() {
try {
/**
* Orientation should be adjusted, see http://stackoverflow.com/questions/20064793/how-to-fix-camera-orientation/26979987#26979987
*/
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size previewSize = null;
float closestRatio = Float.MAX_VALUE;
int targetPreviewWidth = isLandscape() ? getWidth() : getHeight();
int targetPreviewHeight = isLandscape() ? getHeight() : getWidth();
float targetRatio = targetPreviewWidth / (float) targetPreviewHeight;
Log.v(TAG, "target size: " + targetPreviewWidth + " / " + targetPreviewHeight + " ratio:" + targetRatio);
for (Camera.Size candidateSize : previewSizes) {
float whRatio = candidateSize.width / (float) candidateSize.height;
if (previewSize == null || Math.abs(targetRatio - whRatio) < Math.abs(targetRatio - closestRatio)) {
closestRatio = whRatio;
previewSize = candidateSize;
}
}
Log.v(TAG, "preview size: " + previewSize.width + " / " + previewSize.height);
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
}
Я исправил это, добавив это перед вызовом camera.startPreview():
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(yourSurfaceView.getWidth(), yourSurfaceView.getHeight());
camera.setParameters(parameters);
Это может помочь кому-то.
просто добавьте следующую функцию, чтобы установить соотношение сторон и размер предварительного просмотра
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Size size : sizes) {
double ratio = (double) size.getWidth() / size.getHeight();
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.getHeight() - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.getHeight() - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.getHeight() - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.getHeight() - targetHeight);
}
}
}
return optimalSize;
}
использовать как это
final CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
final StreamConfigurationMap map =
characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
// For still image captures, we use the largest available size.
final Size largest =
Collections.max(
Arrays.asList(map.getOutputSizes(ImageFormat.YUV_420_888)),
new CompareSizesByArea());
sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
// Danger, W.R.! Attempting to use too large a preview size could exceed the camera
// bus' bandwidth limitation, resulting in gorgeous previews but the storage of
// garbage capture data.
/* previewSize =
chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
inputSize.getWidth(),
inputSize.getHeight());*/
previewSize = getOptimalPreviewSize(Arrays.asList(map.getOutputSizes(SurfaceTexture.class)),textureView.getWidth(),textureView.getHeight());
} catch (final CameraAccessException e) {
Log.e(TAG, "Exception!" + e);
} catch (final NullPointerException e) {
// Currently an NPE is thrown when the Camera2API is used but not supported on the
// device this code runs.
// TODO(andrewharp): abstract ErrorDialog/RuntimeException handling out into new method and
// reuse throughout app.
ErrorDialog.newInstance(getString(R.string.camera_error))
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
throw new RuntimeException(getString(R.string.camera_error));
}
Решение простое! Если вы используете viewview на панели действий, это может быть проблемой. Я использую эту строку, и я могу ее исправить, но я не тестирую ее с помощью панели действий.
используйте это:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
Если вы говорите о предварительном просмотре, попробуйте установить размер SurfaceView таким же, как размер предварительного просмотра камеры. Таким образом, предварительный просмотр не следует масштабировать.