Android - предварительный просмотр камеры сбоку
Я использую Preview для отображения того, что камера видит на экране.
Я могу заставить все работать нормально, создать поверхность, установить поверхность и отобразить поверхность.
Однако он всегда отображает изображение под неправильным углом 90 градусов в портретном режиме.
Как на картинке:
Я знаю, что с помощью следующего кода изображение будет прямым:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Однако у меня есть предварительный просмотр внутри действия, в котором есть другие элементы, и не имеет смысла отображать мою активность в альбомном режиме. (По умолчанию отключено)
Так что мне было интересно, есть ли способ изменить ориентацию предварительного просмотра? И оставил ли остальная часть моей Активности правильно показанной в Портретном режиме?
Или вообще повернуть превью так, чтобы оно отображалось правильно?
7 ответов
This issue appeared to start out as a bug with certain hardware see here but can be overcome by using the call to mCamera.setDisplayOrientation(degrees) available in API 8. So this is how I implement it:
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (isPreviewRunning) {
mCamera.stopPreview();
}
Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}
if(display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}
if(display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
previewCamera();
}
And the previewCamera method :
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
isPreviewRunning = true;
} catch(Exception e) {
Log.d(APP_CLASS, "Cannot start preview", e);
}
}
Это было в HTC Desire, и мне приходилось вначале вставлять операторы регистрации в каждую из проверок ротации, чтобы сказать, что такое ротация, а затем отлаживать на устройстве и наблюдать за выводом logCat, пока я поворачивал устройство. Для HTC Desire, 0 был телефон, как вы и ожидали (портрет), 90 градусов поворачивал телефон на 90 градусов по часовой стрелке (я предполагал, что это было бы по часовой стрелке). В коде, который вы увидите, мне не нужно было поворачивать дисплей, когда телефон был на 90 или 180 градусов - устройство, казалось, справилось с этим самостоятельно. Только одна точка не работает должным образом: поворот на 270 градусов происходит, когда вы поворачиваете устройство на 90 градусов по часовой стрелке, и вращение дисплея показывает, что все в порядке, но если вы поворачиваете устройство на 270 градусов против часовой стрелки, оно, похоже, не компенсирует его должным образом.
PS Обратите внимание на смену ширины и высоты в соответствующих поворотах.
Попробуйте установить ориентацию дисплея. Это решает мою проблему.
mCamera.setDisplayOrientation(90);
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
try {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
попробуй этот код
Я сделал это по совету mCamera.setDisplayOrientation(90); но также повернул растровое изображение, потому что по какой-то причине другие подходы не работают для меня в версии 2.3.3.
Для поворота растрового изображения я сделал это:
Matrix matrix = new Matrix();
matrix.postRotate(90);
imageView1 = new ImageView(this);
Bitmap bitmap = BitmapFactory.decodeFile(files[i].getAbsolutePath());
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 80, 80, true);
imageView1.setImageBitmap(scaledBitmap);
У меня проблема с передней камерой (перевернутая проблема). Тогда я использую этот метод
public void setCameraDisplayOrientation(Activity activity , int icameraId , Camera camera1s)
{
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(icameraId, cameraInfo);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0; // k
switch (rotation)
{
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
// cameraType=CAMERATYPE.FRONT;
result = (cameraInfo.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
}
else
{ // back-facing
result = (cameraInfo.orientation - degrees + 360) % 360;
}
// displayRotate=result;
camera.setDisplayOrientation(result);
}
Я сравнил свой код с учебным и, наконец, исправил, поместив следующий код в мой AndroidManifext.xml: <activity>
тег:
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">
Я думаю, что значение SENSOR_ORIENTATION объяснит, какое значение следует использовать для поворота вместо жесткого кодирования на 90 градусов
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
if (manager == null) {
Log.i(TAG, "camera manager is null");
return;
}
for (String id: manager.getCameraIdList()) {
CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
Integer orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
Log.i(TAG, "camera sensor orientation is " + orientation);
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
Camera.Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager) getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(h, w);
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(w, h);
mCamera.setDisplayOrientation(0);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(h, w);
mCamera.setDisplayOrientation(270);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(w, h);
mCamera.setDisplayOrientation(180);
}
previewCamera();
}
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
//Log.d(APP_CLASS, "Cannot start preview", e);
e.printStackTrace();
}
}
Этот кусок линии работал для меня отлично
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 180);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 360);
}