Ниже приведены скриншоты при использовании текстурного вида в camera2 apis. В полноэкранном режиме предварительный просмотр растягивается, но он работает при использовании более низкого разрешения (второе изображение). Как использовать этот предварительный просмотр в полноэкранном режиме, не растягивая его.
Предварительный просмотр растягивается в camera2 apis
Ответ 1
Ниже ответа предполагается, что вы находитесь только в портретном режиме.
Ваш вопрос:
Как использовать предварительный просмотр в полноэкранном режиме без растягивания
Позвольте разбить его на две вещи:
- Вы хотите, чтобы предварительный просмотр заполнил экран
- Предварительный просмотр не может быть искажен
Сначала вам нужно знать, что это невозможно без урожая, если ваше окно просмотра вашего устройства имеет другое соотношение сторон с любым доступным разрешением, предоставляемым камерой.
Поэтому я бы предположил, что вы принимаете обрезку предварительного просмотра.
Шаг 1. Получите список доступных разрешений.
StreamConfigurationMap map = mCameraCharacteristics.get(
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map == null) {
throw new IllegalStateException("Failed to get configuration map: " + mCameraId);
}
Size[] sizes = map.getOutputSizes(SurfaceTexture.class);
Теперь вы получаете список доступных разрешений (размеров) вашей камеры устройства.
Шаг 2. Найдите наилучшее соотношение сторон
Идея состоит в том, чтобы зацикливать размеры и посмотреть, какой из них лучше всего подходит. Вам, вероятно, нужно написать собственную реализацию "лучших приемов".
Я не собираюсь предоставлять какой-либо код здесь, так как то, что у меня есть, сильно отличается от вашего варианта использования. Но в идеале это должно быть примерно так:
Size findBestSize (Size[] sizes) {
//Logic goes here
}
Шаг 3. Скажите API-интерфейсу камеры, что вы хотите использовать этот размер
//...
textureView.setBufferSize(bestSize.getWidth(), bestSize.getHeight());
Surface surface = textureView.getSurface();
try {
mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
mSessionCallback, null);
} catch (final Exception e) {
//...
}
Шаг 4: Сделайте свой предварительный просмотр за пределами области просмотра
Тогда это не связано с API Camera2. Мы " SurfaceView
" предварительный просмотр, позволяя SurfaceView
/TextureView
за пределы TextureView
просмотра устройства.
Сначала разместите SurfaceView
или TextureView
в RelativeLayout
.
Используйте ниже, чтобы расширить его за пределы экрана, после того как вы получите соотношение сторон с шага 2.
Обратите внимание, что в этом случае вам, вероятно, нужно знать это соотношение сторон, прежде чем вы даже начнете работу с камерой.
//Suppose this value is obtained from Step 2.
//I simply test here by hardcoding a 3:4 aspect ratio, where my phone has a thinner aspect ratio.
float cameraAspectRatio = (float) 0.75;
//Preparation
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int screenWidth = metrics.widthPixels;
int screenHeight = metrics.heightPixels;
int finalWidth = screenWidth;
int finalHeight = screenHeight;
int widthDifference = 0;
int heightDifference = 0;
float screenAspectRatio = (float) screenWidth / screenHeight;
//Determines whether we crop width or crop height
if (screenAspectRatio > cameraAspectRatio) { //Keep width crop height
finalHeight = (int) (screenWidth / cameraAspectRatio);
heightDifference = finalHeight - screenHeight;
} else { //Keep height crop width
finalWidth = (int) (screenHeight * cameraAspectRatio);
widthDifference = finalWidth - screenWidth;
}
//Apply the result to the Preview
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) cameraView.getLayoutParams();
lp.width = finalWidth;
lp.height = finalHeight;
//Below 2 lines are to center the preview, since cropping default occurs at the right and bottom
lp.leftMargin = - (widthDifference / 2);
lp.topMargin = - (heightDifference / 2);
cameraView.setLayoutParams(lp);
Если вы не заботитесь о результате шага 2, вы можете фактически проигнорировать шаги с 1 по 3 и просто используйте библиотеку там, пока вы можете настроить его соотношение сторон. (Похоже, что это лучший, но я еще не пробовал)
Я проверил, используя мою разветвленную библиотеку. Не изменяя код моей библиотеки, мне удалось сделать полноэкранный просмотр только с помощью шага 4:
И предварительный просмотр сразу после съемки не искажает, потому что предварительный просмотр также выходит за пределы вашего экрана.
Но выходное изображение будет включать область, которую вы не видите в предварительном просмотре, что имеет смысл.
Код с шага 1-го шага 3 обычно ссылается на Google CameraView.
Ответ 2
Это общая проблема на некоторых устройствах. Я заметил это в основном на samsung. Вы можете использовать трюк с настройкой преобразования на вашем TextureView
чтобы сделать его centerCrop похожим на поведение ImageView
Ответ 3
Я понял, что это был ваш пороблем. Вероятно, вы пытались что-то вроде этого:
textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int j) {
cam.startPreview(surfaceTexture, i, j);
cam.takePicture();
}
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) { }
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; }
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { }
});