Android - podgląd aparatu jest boczny


123

Używam podglądu, aby wyświetlić to, co kamera widzi na ekranie.

Mogę uzyskać wszystko działające poprawnie, utworzoną powierzchnię, ustawioną i wyświetloną.

Jednak zawsze wyświetla obraz pod nieprawidłowym kątem 90 stopni w trybie portretowym.

Tak jak na zdjęciu:

tekst alternatywny

Zdaję sobie sprawę, że użycie poniższego kodu wyrówna obraz:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Jednak mam podgląd w działaniu, które zawiera inne elementy i nie ma sensu, aby moje działanie było wyświetlane w trybie poziomym. (Jest domyślnie wyłączony)

Zastanawiałem się więc, czy w ogóle można po prostu zmienić orientację podglądu? I pozostawić resztę mojej aktywności poprawnie wyświetlaną w trybie portretowym?

A może w ogóle obrócić podgląd, żeby był poprawnie wyświetlany?


Odpowiedzi:


145

Wydawało się, że ten problem zaczyna się jako błąd z pewnym sprzętem, patrz tutaj, ale można go rozwiązać, używając wywołania mCamera.setDisplayOrientation (stopnie) dostępnego w API 8. Tak więc implementuję to:

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

Było to na HTC Desire i musiałem początkowo wprowadzić zapisy logowania w każdym sprawdzeniu rotacji, aby powiedzieć, jaka jest rotacja, a następnie debugowałem na urządzeniu i oglądałem wyjście logCat, gdy obracałem urządzenie. W przypadku HTC Desire, 0 był telefonem, jak można się spodziewać (portret), 90 stopni obracało telefon o 90 stopni w kierunku przeciwnym do ruchu wskazówek zegara (zakładałem, że byłby zgodny z ruchem wskazówek zegara). W kodzie zobaczysz, że nie musiałem obracać wyświetlacza, gdy telefon był ustawiony pod kątem 90 lub 180 stopni - urządzenie wydawało się radzić sobie z tym samo. Tylko jeden punkt nie działa poprawnie: obrót o 270 stopni ma miejsce, gdy obrócisz urządzenie o 90 stopni w prawo, a obrót wyświetlacza jest zgodny, ale jeśli obrócisz urządzenie o 270 stopni w lewo, wydaje się, że nie kompensuje to właściwie.

PS Zwróć uwagę na zamianę szerokości i wysokości w odpowiednich obrotach.


7
ale setDisplayOrientation (stopień); metoda obsługuje formę 2.2, a co z niższą wersją? parameters.setRotation (90); parameters.set ("orientacja", "portret"); nie działają. Jeśli masz jakieś rozwiązanie dla niższych wersji, pomóż mi.
Vikram

1
Zaimplementowałem podgląd w mojej aplikacji, który zawsze będzie wyświetlany w trybie portretowym. Zawsze obracałem ekran o 90 stopni i wydawało się, że działa to na każdym urządzeniu, dopóki nie przetestowaliśmy go na HTC Desire C. Ponieważ nie liczę teraz na urządzenie, aby to przetestować, chciałbym, abyś wyjaśnił, czy to cię naprawi Sugeruję wreszcie działał dobrze na pragnienie HTC. Dzięki!
argenkiwi

13
mCamera.setParameters(parameters);Stwierdzenie awarii mojej aplikacji, ponieważ wymiary powierzchniowe nie są ważne rozmiar podglądu do mojego telefonu (może dlatego, że utrzymanie pasek stanu widoczny?). Jednak okazało się, że używanie mCamera.setDisplayOrientation(90)wtedy mCamera.setPreviewDisplay(mSurfaceHolder);bez ustawiania parametrów też działa!
nicopico

3
byłoby czystsze z instrukcją przełącznika
Siavash

2
Czy to nie zakłada, że ​​podgląd jest wyświetlany bokiem na WSZYSTKICH urządzeniach? bo na niektórych urządzeniach jest bokiem, a na innych w prawo ... czy istnieje sposób sprawdzenia, czy domyślna orientacja aparatu urządzenia jest zgodna z pionową stroną telefonu, czy nie?
Siavash,

16

spróbuj ustawić orientację wyświetlacza. To rozwiązuje mój problem.

 mCamera.setDisplayOrientation(90);

5
w momencie zapisywania zapisuje obraz portretowy w układzie poziomym. jakieś rozwiązanie?
Akanksha Rathore

@Akanksha: ta flaga dotyczy tylko wyświetlania podglądu. Nie zmienia orientacji bufora zwróconego w onPreviewFrame()oronPictureTaken()
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();
     }
}

wypróbuj ten kod


3
w momencie zapisywania zapisuje obraz portretowy w układzie poziomym. jakieś rozwiązanie?
Akanksha Rathore

@Akanksha to prawdopodobnie ma związek z parametrami EXIF.
EpicPandaForce

4

Miałem problem z przednią kamerą (problem do góry nogami). Następnie użyłem następującej metody udokumentowanej w Dokumentach Androida -

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
Ta metoda pochodzi z dokumentacji aparatu: developer.android.com/reference/android/hardware/…
VinceFior

@VinceFior Coś nie tak, jeśli post z oficjalnego dokumentu?
Ranjith Kumar

1
@RanjithKumar Nieszczególnie, chciałem tylko wymienić źródło i wskazać tam ludziom szerszy kontekst. :)
VinceFior

3

Zrobiłem to, korzystając z porady mCamera.setDisplayOrientation (90); ale także obróciłem bitmapę, ponieważ z jakiegoś powodu inne podejścia nie działają dla mnie w wersji 2.3.3.

Aby obrócić bitmapę, zrobiłem to:

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

Porównałem mój kod z tutorialem i ostatecznie naprawiłem to, że umieściłem następujący kod w moim AndroidManifext.xml: W <activity>tagu:

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

Myślę, że wartość SENSOR_ORIENTATION wyjaśni, jaką wartość należy użyć do obrotu zamiast zakodowania na stałe do 90 stopni

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);
        }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.