В моем приложении у меня есть предварительный просмотр камеры на SurfaceView, и он работает почти так же, как я хочу, с одной странно раздражающей проблемой:
Когда я вхожу в вид камеры на моем Sony Xperia или в моем тестированииSamsung S7 (эмулятор выглядит нормально) показывает корректный предварительный просмотр.Когда я вращаю его, предварительный просмотр вращается правильно, когда я поворачиваю его назад, предварительный просмотр теряет свои пропорции, и вид искажается.После первого поворота, каждый раз, когда он поворачивается назад, у меня возникают такие же искажения.
Подход, который работает до сих пор, заключается в том, что я использую масштабирование моего SurfaceView:
FrameLayout.LayoutParams newScale = new FrameLayout.LayoutParams(width, height, Gravity.CENTER );
mTextureView.setLayoutParams(newScale);
mTextureView.setScaleX( xScale);
mTextureView.setScaleY( yScale);
Затем я создаюcaptureSession:
mCaptureSession = cameraCaptureSession;
try {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRectangle);
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest, getCaptureCallback(), mBackgroundHandler);
} catch (CameraAccessException e) {
// and so on.
}
Очевидно, что к этому моменту я очень расстроился, поэтому я чертовски записывал свои вращения, и это то, где я очень запутался.
Этовыглядит хорошо:
========================
View Dimensions (720, 1184)
Sensor Dimensions: (3984, 5512)
Final size: 720, 1280
========================
View ratio: 1.7777778 previewRatio: 1.6444445 scale: 1.0
Image preview size is (720, 1184) scale is: (1.0) image size is (720, 1280)
Image scale is (1.3835341, 0.925) Max Image is (3984, 5512) cropRectangle is (441, 0 -> 3543, 5512)
Затем я поворачиваю его:
========================
View Dimensions (1184, 720)
Sensor Dimensions: (5512, 3984)
Final size: 1280, 720
========================
View ratio: 0.5625 previewRatio: 0.6081081 scale: 1.0
Image preview size is (1184, 720) scale is: (1.0) view size is (1280, 720)
Image scale is (0.925, 1.3835342) Max Image is (5512, 3984) cropRectangle is (0, 441 -> 5512, 3543)
Теперь я поворачиваю его назад:
========================
View Dimensions (720, 1184)
Sensor Dimensions: (3984, 5512)
Final size: 720, 1280
========================
View ratio: 1.7777778 previewRatio: 1.6444445 scale: 1.0
Image preview size is (720, 1184) scale is: (1.0) view size is (720, 1280)
Image scale is (1.3835341, 0.925) Max Image is (3984, 5512) cropRectangle is (441, 0 -> 3543, 5512)
Эти шкалы и этот прямоугольник кадрирования выглядят абсолютно идентичнымидля меня, но по какой-то причине последнее изображение искажено гораздо шире, как будто шкала Х была ближе к 1,8 или около того.Я могу повернуть назад в альбомную ориентацию в любом направлении, и она выглядит хорошо, затем вернуться к портрету, и все снова становится жирным.
Мне интересно, характерно ли это для камеры, пытающейся выполнить автокоррекцию, но яЯ получаю короткие идеи о том, как устранить эту проблему в дальнейшем.Как я могу убедить свой телефон, что после его поворота дважды он должен показывать те же пропорции, что и в первом случае?
Обновление: если я использую setXScale и устанавливаю его на 1.0 во втором запуске вместоЗначение, которое он имел на первом, выглядит правильно.Но когда я сравниваю матрицу преобразования SurfaceView, когда пропорции изображения плохие и когда они хорошие, они идентичны, так что это выглядит как компенсация плохого масштабирования в предварительном просмотре.Я могу изменить способ масштабирования, чтобы начальный предварительный просмотр был слишком узким, а пропорции были правильными после поворота, но опять же это не очень помогло, потому что мне нужно было переключаться между портретом и пейзажем без искажения изображенияКажется, это должно быть поведение по умолчанию.Открытие представления в альбомной ориентации ведет себя примерно так же - искажается при первом открытии, а затем нормально.
Кажется, что CaptureSession каждый раз корректно создается заново.
Второе обновление: вызовdumpsys SurfaceFlinger
показывает возможную причину:
-------------------------------------------------------------------------------
Layer name
Z | Comp Type | Disp Frame (LTRB) | Source Crop (LTRB)
-------------------------------------------------------------------------------
SurfaceView - com.myapp.CameraActivity#0 4294967294 | Device | 0 0 720 1184 | 0.0 0.0 960.0 720.0
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Таким образом, здесь выглядит так, как будто проблема заключается в том, что исходная обрезка слишком мала для размера рамки дисплея, отсюда растянутое изображение.Мое устройство считает, что оно получает изображение с разрешением 1280x720, но по какой-то причине Source Crop указывает на меньший размер.Может ли это быть связано с пропорциями датчика?Нужно ли выбирать только размеры, соответствующие соотношению датчиков?