Android Camera2 превью иногда поворачивается на 90 градусов
Я работаю над некоторым приложением, используя Android Camera2 API. До сих пор я был в состоянии получить предварительный просмотр в TextureView
, Приложение по умолчанию в ландшафтном режиме. При использовании эмулятора предварительный просмотр будет отображаться в обратном порядке. На моем физическом Nexus 5 предварительный просмотр обычно отображается правильно (альбомная, а не перевернутая), но иногда он поворачивается на 90 градусов, но растягивается до размеров экрана. Я думал, что это должно быть легко, и думал, что следующий код вернет необходимую информацию о текущей ориентации:
// display rotation
getActivity().getWindowManager().getDefaultDisplay().getRotation();
// sensor orientation
mManager.getCameraCharacteristics(mCameraId).get(CameraCharacteristics.SENSOR_ORIENTATION);
... Я был очень удивлен, когда увидел, что приведенный выше код всегда возвращается 1
для поворота дисплея и 90
для ориентации датчика, независимо от того, был ли предварительный просмотр повернут на 90 градусов или нет. (В эмуляторе ориентация датчика всегда равна 270, что имеет смысл, если я принимаю 90 как правильную ориентацию). Я также проверил ширину и высоту внутри onMeasure
в AutoMeasureTextureView ( взятом из примера Android2 Camera2), который я использую для создания моего TextureView. Но тоже не повезло - ширина и высота сообщаются изнутри onMeasure
всегда одинаковы независимо от вращения предварительного просмотра. Так что я не знаю, как решить эту проблему. Кто-нибудь есть идея, что может быть причиной случайных всплесков в моей ориентации предварительного просмотра?
[Редактировать] Деталь, которую я только что узнал: всякий раз, когда предварительный просмотр появляется повернутым onSurfaceTextureSizeChanged
в TextureView.SurfaceTextureListener
Кажется, не позвонили. В документации для onSurfaceTextureSizeChanged
говорят, что этот метод вызывается всякий раз, когда SurfaceTexture
Размер буферов изменен. У меня есть метод createCameraPreviewSession
(скопировано из примера Android2 Camera2), в котором я устанавливаю размер буфера по умолчанию для моей текстуры как
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
Из моего вывода журнала я могу сказать, что onSurfaceTextureSizeChanged
вызывается именно после этого - однако не всегда... (или установка размера буфера по умолчанию иногда молча завершается ошибкой?).
3 ответа
Я думаю, что могу ответить на свой собственный вопрос: я создавал свой фрагмент Camera2 по примеру Android2 Camera2. Тем не менее, я на самом деле не рассматривал метод configureTransform
быть важным, так как, в отличие от примера кода, мое приложение все равно вынуждено работать в ландшафтном режиме. Оказалось, что это предположение было неверным. Так как имея configureTransform
Реинтегрированный в мой код, я больше не испытывал икоты.
Обновление: Оригинальный пример на страницах документации Android, похоже, больше не существует. Я обновил ссылку, которая сейчас указывает на код на Github.
Я следил за всем textureView.setTransform(matrix)
Метод, указанный выше, и это сработало. Тем не менее, я также смог вручную установить вращение, используя гораздо более простой textureView.setRotation(270)
без необходимости создавать Matrix
,
Я также сталкивался с подобной проблемой на устройстве Nexus. Ниже код работает для меня. Вызовите эту функцию перед открытием камеры. А также на Resume ().
private void transformImage (int width, int height) {
if (textureView == null) {
return;
} else try {
{
Matrix matrix = new Matrix();
int rotation = getWindowManager().getDefaultDisplay().getRotation();
RectF textureRectF = new RectF(0, 0, width, height);
RectF previewRectF = new RectF(0, 0, textureView.getHeight(), textureView.getWidth());
float centerX = textureRectF.centerX();
float centerY = textureRectF.centerY();
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
previewRectF.offset(centerX - previewRectF.centerX(), centerY - previewRectF.centerY());
matrix.setRectToRect(textureRectF, previewRectF, Matrix.ScaleToFit.FILL);
float scale = Math.max((float) width / width, (float) height / width);
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
textureView.setTransform(matrix);
}
} catch (Exception e) {
e.printStackTrace();
}
}