В портретном режиме изображения выглядят вертикально растянутыми и в ландшафтном режиме он выглядит горизонтально растянутым.
Хотя после захвата изображение появляется в надлежащем размере.
Как решить эту проблему?
В портретном режиме изображения выглядят вертикально растянутыми и в ландшафтном режиме он выглядит горизонтально растянутым.
Хотя после захвата изображение появляется в надлежащем размере.
Как решить эту проблему?
Вам нужно выбрать размер предварительного просмотра, соответствующий размеру вашего дисплея. Я бы предложил изменить настройку размера предварительного просмотра в соответствии с вашим 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 таким же, как размер предварительного просмотра камеры. Таким образом, предварительный просмотр не следует масштабировать.