Android - предварительный просмотр камеры сбоку


123

Я использую предварительный просмотр, чтобы отобразить то, что камера видит на экране.

Я могу заставить все работать нормально, поверхность создана, поверхность установлена, и поверхность отображается.

Однако в портретном режиме изображение всегда отображается под неправильным углом 90 градусов.

Такие как на картинке:

альтернативный текст

Я знаю, что использование следующего кода исправит картину:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Однако у меня есть предварительный просмотр в Activity, в котором есть другие элементы, и нет смысла отображать мое Activity в ландшафтном режиме. (По умолчанию отключено)

Так что мне было интересно, есть ли способ просто изменить ориентацию предварительного просмотра? И оставить остальную часть моей деятельности правильно отображаемой в портретном режиме?

Или все-таки повернуть превью, чтобы он отображался правильно?


Ответы:


145

Эта проблема, похоже, началась как ошибка с определенным оборудованием, см. Здесь, но ее можно преодолеть, используя вызов mCamera.setDisplayOrientation (степени), доступный в API 8. Вот как я ее реализую:

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 Обратите внимание на смену ширины и высоты при соответствующих поворотах.


7
но setDisplayOrientation (степень); метод поддерживает форму 2.2, а как насчет более ранней версии ?? parameters.setRotation (90); parameters.set («ориентация», «портрет»); не работают. Если у вас есть решение для более низких версий, пожалуйста, помогите мне.
Vikram

1
Я реализовал в своем приложении предварительный просмотр, который всегда будет отображаться в портретном режиме. Я всегда поворачивал экран на 90 градусов, и, похоже, это работало на каждом устройстве, пока мы не протестировали его на HTC Desire C. Поскольку я не рассчитываю на то, что устройство сейчас сможет это проверить, я хотел бы, чтобы вы пояснили, исправит ли это вас Предлагаю наконец то HTC Desire поработал. Спасибо!
argenkiwi

13
mCamera.setParameters(parameters);Заявление врезаться моим приложение, так как размеры поверхности не действительный размера предварительного просмотра для моего телефона (может быть , потому , что я держу в строке состояния виден?). Однако я обнаружил, что использование mCamera.setDisplayOrientation(90)then mCamera.setPreviewDisplay(mSurfaceHolder);без настройки параметров тоже работает!
Никопико

3
было бы чище с оператором switch
Сиаваш

2
Не предполагает ли это, что предварительный просмотр на ВСЕХ устройствах находится боком? потому что на некоторых устройствах он сбоку, а на других - вправо ... есть ли способ проверить, совпадает ли ориентация камеры по умолчанию с портретной стороной телефона?
Сиаваш 07

16

попробуй установить ориентацию дисплея. Это решает мою проблему.

 mCamera.setDisplayOrientation(90);

5
во время сохранения сохраняет портретное изображение в альбомной ориентации. Какое-либо решение?
Akanksha Rathore

@Akanksha: этот флаг применяется только для предварительного просмотра. Это не меняет ориентацию буфера, возвращенного в onPreviewFrame()илиonPictureTaken()
Alex Cohn

13
 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();
     }
}

попробуйте этот код


3
во время сохранения сохраняет портретное изображение в альбомной ориентации. Какое-либо решение?
Akanksha Rathore

@Akanksha, это, вероятно, связано с параметрами EXIF.
EpicPandaForce

4

У меня была проблема с передней камерой (проблема перевернутой). Затем я использовал следующий метод, описанный в Android Docs -

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);


    }

3
Этот метод
взят

@VinceFior Что-то не так, если он отправляет из официального документа?
Ранджит Кумар

1
@RanjithKumar: Не особо, я просто хотел отдать должное источнику и указать людей на него для большего контекста. :)
VinceFior 06

3

Я сделал это по совету 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);

0

Я сравнил свой код с учебным, и, наконец, исправил, поместив следующий код в мой AndroidManifext.xml: В <activity>теге:

android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">

0
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();
    }
}

0

Я думаю, что значение 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);
        }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.