Android - попередній перегляд камери збоку


123

Я використовую попередній перегляд для відображення того, що бачить камера на екрані.

Я можу зробити все, що працює нормально, створена поверхня, встановлений поверхню та відображається поверхня.

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

Такі як на малюнку:

alt текст

Мені відомо, що за допомогою наступного коду буде встановлено малюнок прямо:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Однак у мене є попередній перегляд діяльності, в якому є інші елементи, і це не має сенсу для відображення моєї активності в альбомному режимі. (Вимкнено за замовчуванням)

Тож мені було цікаво, чи все-таки просто змінити орієнтацію попереднього перегляду? І залишити решту моєї активності правильно відображеною в портретному режимі?

Або все одно повернути попередній перегляд, щоб він відображався правильно?


Відповіді:


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, як щодо нижчої версії ?? parametri.setRotation (90); parametri.set ("орієнтація", "портрет"); не працюють. Якщо у вас є рішення для нижчих версій, будь ласка, допоможіть мені.
Вікрам

1
Я здійснив попередній перегляд свого додатка, який завжди відображатиметься в портретному режимі. Я завжди обертав екран на 90 градусів, і це, здавалося, працює на кожному пристрої, поки ми не протестували його на HTC Desire C. Оскільки я зараз не розраховую на пристрій, щоб перевірити це, я хотів би, щоб ви уточнили, чи це виправити припустимо, нарешті, добре попрацювали над бажанням HTC. Дякую!
argenkiwi

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

3
буде чистішим із заявою переключення
Siavash

2
Чи не передбачає це, що попередній перегляд є ВСЕ на всіх пристроях? бо це на деяких пристроях збоку, а на інших .... вгору, чи є можливість перевірити, чи орієнтована камера пристрою за замовчуванням, розташована з портретною стороною телефону чи ні?
Сіаваш

16

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

 mCamera.setDisplayOrientation(90);

5
під час збереження це зберігає портретне зображення в пейзажі. Будь-яке рішення?
Аканкша Ратхор

@Akanksha: цей прапор стосується лише попереднього перегляду. Це не змінює орієнтацію буфера, який повернувся onPreviewFrame()абоonPictureTaken()
Алекс Кон

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, можливо, це стосується параметрів EXIF.
EpicPandaForce

4

У мене виникли проблеми з фронтальною камерою (виправлення вниз). Тоді я використав наступний метод, задокументований в Документах Android -

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
Цей метод походить із документації на камеру: developer.android.com/reference/android/hardware/…
VinceFior

@VinceFior Щось не так, якщо він публікує офіційний документ?
Ранджіт Кумар

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

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.