Поворот поверхности камерыПросмотреть в портрет - PullRequest
12 голосов
/ 17 сентября 2011

Я просмотрел несколько сообщений об изменении ориентации камеры при виде с поверхности, но я взял свой код из примеров по адресу:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html

Функция, которая обеспечивает размеры выглядит следующим образом ...

    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

Моя проблема заключается в том, что при изменении ориентации устройства изображение предварительного просмотра остается в горизонтальном положении. Я попытался установить ориентацию камеры, но это привело к очень странным результатам. Кто-нибудь знает, что мне нужно изменить, чтобы правильно повернуть?

Ответы [ 7 ]

32 голосов
/ 14 марта 2013

Код для правильной настройки ориентации предварительного просмотра камеры немного сложен, так как он должен учитывать

  1. Относительная ориентация сенсора и «естественная» ориентация устройства (как правило, книжная ориентация для телефонов и, как правило, альбомная ориентация для планшетов)
  2. Текущая ориентация пользовательского интерфейса устройства (книжная, альбомная или наоборот)
  3. Независимо от того, является ли рассматриваемая камера передней или задней камерой (поскольку поток предварительного просмотра передается по горизонтали)

Документация для Camera.setDisplayOrientation содержит пример кода для правильного решения этой проблемы. Я воспроизводлю это здесь:

public static void setCameraDisplayOrientation(Activity activity,
     int cameraId, android.hardware.Camera camera) {

   android.hardware.Camera.CameraInfo info = 
       new android.hardware.Camera.CameraInfo();

   android.hardware.Camera.getCameraInfo(cameraId, info);

   int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
   int degrees = 0;

   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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
       result = (info.orientation + degrees) % 360;
       result = (360 - result) % 360;  // compensate the mirror
   } else {  // back-facing
       result = (info.orientation - degrees + 360) % 360;
   }
   camera.setDisplayOrientation(result);
}

Вызывайте это после того, как ваш UI нарисован (onSurfaceChanged будет работать как индикатор) или пользовательский интерфейс устройства будет вращаться (onConfigurationChanged будет работать как индикатор).

8 голосов
/ 19 ноября 2011

Мне удалось решить проблему с вращением, поместив следующий код в onSurfaceChanged ():

    if (mHolder.getSurface() == null) {
        // preview surface does not exist
        return;
    }

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        // ignore: tried to stop a non-existent preview
    }

    // make any resize, rotate or reformatting changes here
    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {

        mCamera.setDisplayOrientation(90);

    } else {

        mCamera.setDisplayOrientation(0);

    }
    // start preview with new settings
    try {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();

    } catch (Exception e) {
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }

НО это создало другую проблему, или, лучше сказать, не решило проблему, хотя ориентировалось правильнопредварительное изображение все еще занимало столько же места, сколько и альбомная.В итоге я просто сдался и заставил альбомную ориентацию с помощью:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

в onCreate () и разработал мой макет для ландшафта.Желаем удачи, и я надеюсь, что у кого-то есть ответ на эту вторичную проблему!

6 голосов
/ 24 августа 2012

Попробуйте, но я попробовал в Samsung Galaxy Tab

public void surfaceCreated(SurfaceHolder holder)
{
   // The Surface has been created, acquire the camera and tell it where to draw.
   mCamera = Camera.open();

   Parameters params = mCamera.getParameters();

   if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
   {
    params.set("orientation", "portrait");
    mCamera.setDisplayOrientation(90);
   }

    try
      {
      mCamera.setPreviewDisplay(holder);
      }
      catch (IOException exception)
      {
        mCamera.release();
        mCamera = null;
      }

}
2 голосов
/ 21 ноября 2017

Ну, я делаю это!

Я решил эту проблему таким образом в методе SurfaceCreated ()

 public void surfaceCreated(SurfaceHolder holder) {
    try {

        camera = Camera.open();
    } catch (RuntimeException e) {
        System.err.println(e);
        return;
    }
    Camera.Parameters param;
    param = camera.getParameters();
    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
    {
        param.set("orientation", "portrait");
        setCameraDisplayOrientation(this,1,camera);
    }
    camera.setParameters(param);

    try {
        camera.setPreviewDisplay(surfaceHolder);
        camera.startPreview();
    } catch (Exception e) {
        System.err.println(e);
        return;
    }
}

добавить этот метод ниже

 public static void setCameraDisplayOrientation(Activity activity,
                                               int cameraId, android.hardware.Camera camera) {

    android.hardware.Camera.CameraInfo info =
            new android.hardware.Camera.CameraInfo();

    android.hardware.Camera.getCameraInfo(cameraId, info);

    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;

    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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {  // back-facing
        result = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(result);
}

3: убедитесь, что вы добавили разрешение камеры для поддержки нуга в упражнении до того, как это упражнение вызывает вызов не вызывать разрешение для камеры в этом упражнении, потому что вызов создан как действие, и ваше разрешение будет в ожидании открытия камеры

2 голосов
/ 23 марта 2016

Пожалуйста, попробуйте это ..

@Override
 public void surfaceChanged(SurfaceHolder holder,
                       int format, int width, int height)
{
// TODO Auto-generated method stub

if(previewing)
{
    camera.stopPreview();
    previewing = false;
}
 Camera.Parameters parameters = camera.getParameters();
      Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
   int or=cameraInfo.orientation;
     // You need to choose the most appropriate previewSize for your app
   // .... select one of previewSizes here
           /* parameters.setPreviewSize(previewSize.width, previewSize.height);*/
   if(display.getRotation() == Surface.ROTATION_0)
    {

    camera.setDisplayOrientation(90);
    or=90;
    }

    if(display.getRotation() == Surface.ROTATION_180)
    {
        camera.setDisplayOrientation(270);
    or=270;
    }
    if(display.getRotation() == Surface.ROTATION_270)
    {
        camera.setDisplayOrientation(180);
        or=180;
    }

  parameters.setRotation(or);

  camera.setParameters(parameters);
 try
{
        camera.setPreviewDisplay(cameraSurfaceHolder);
        camera.startPreview();
        previewing = true;
    }
    catch (IOException e)
    {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
2 голосов
/ 14 марта 2013

Я решил эту проблему, добавив:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

К событию onCreate.

0 голосов
/ 13 декабря 2018

Только добавьте это

mCamera.setDisplayOrientation(90);
...