Android - Kamera Vorschau ist seitwärts


123

Ich verwende eine Vorschau, um anzuzeigen, was die Kamera auf dem Bildschirm sieht.

Ich kann alles zum Laufen bringen, die Oberfläche erstellen, die Oberfläche einstellen und die Oberfläche wird angezeigt.

Im Hochformat wird das Bild jedoch immer in einem falschen 90-Grad-Winkel angezeigt.

Wie auf dem Bild:

Alt-Text

Mir ist bewusst, dass die Verwendung des folgenden Codes das Bild gerade macht:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Ich habe jedoch die Vorschau in einer Aktivität, die andere Elemente enthält, und es ist nicht sinnvoll, meine Aktivität im Querformat anzuzeigen. (Standardmäßig deaktiviert)

Ich habe mich also gefragt, ob es überhaupt eine Möglichkeit gibt, die Ausrichtung der Vorschau zu ändern. Und den Rest meiner Aktivität im Porträtmodus korrekt anzeigen lassen?

Oder um die Vorschau so zu drehen, dass sie korrekt angezeigt wird?


Antworten:


145

Dieses Problem schien als Fehler mit bestimmter Hardware zu beginnen ( siehe hier) , kann jedoch durch den Aufruf von mCamera.setDisplayOrientation (Grad) in API 8 behoben werden. So implementiere ich es:

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

Dies war auf einem HTC Desire und ich musste zunächst Protokollierungsanweisungen in jede der Rotationsprüfungen eingeben, um zu sagen, was die Rotation war, und dann auf dem Gerät debuggen und die logCat-Ausgabe beobachten, während ich das Gerät drehte. Für das HTC Desire war 0 das Telefon, wie Sie es erwartet hatten (Porträt), 90 Grad drehten das Telefon um 90 Grad gegen den Uhrzeigersinn (ich hatte angenommen, es wäre im Uhrzeigersinn gewesen). Im Code sehen Sie, dass ich bei 90 oder 180 Grad keine Drehung des Displays durchführen musste - das Gerät schien dies selbst zu handhaben. Nur ein Punkt funktioniert nicht richtig: Die Drehung um 270 Grad ist, wenn Sie das Gerät um 90 Grad im Uhrzeigersinn drehen und die Drehung des Displays gegenläufig ist. Wenn Sie das Gerät jedoch um 270 Grad gegen den Uhrzeigersinn drehen, scheint es dies nicht richtig zu kompensieren.

PS Beachten Sie den Wechsel von Breite und Höhe in den entsprechenden Umdrehungen.


7
aber setDisplayOrientation (Grad); Methode unterstützt Form 2.2, was ist mit niedrigerer Version? parameters.setRotation (90); parameters.set ("Orientierung", "Porträt"); arbeiten nicht. Wenn Sie eine Lösung für niedrigere Versionen haben, helfen Sie mir bitte.
Vikram

1
Ich habe in meiner App eine Vorschau implementiert, die immer im Hochformat angezeigt wird. Ich habe den Bildschirm immer um 90 Grad gedreht und dies schien auf jedem Gerät zu funktionieren, bis wir es auf dem HTC Desire C getestet haben. Da ich jetzt nicht auf das Gerät zähle, um dies zu testen, möchte ich Sie bitten, zu klären, ob dies Sie behebt Schlagen Sie vor, endlich gut auf das HTC-Verlangen funktioniert. Vielen Dank!
Argenkiwi

13
Die mCamera.setParameters(parameters);Anweisung stürzt meine App ab, weil die Oberflächenabmessungen keine gültige Vorschaugröße für mein Telefon sind (möglicherweise, weil ich die Statusleiste sichtbar halte?). Ich fand jedoch, dass die Verwendung mCamera.setDisplayOrientation(90)dann mCamera.setPreviewDisplay(mSurfaceHolder);ohne Einstellung der Parameter auch funktioniert!
Nicopico

3
wäre sauberer mit einer switch-Anweisung
Siavash

2
Geht dies nicht davon aus, dass die Vorschau auf ALLEN Geräten seitlich ist? Gibt es eine Möglichkeit, zu überprüfen, ob die Standardkameraausrichtung eines Geräts mit der Hochformat-Seite des Telefons übereinstimmt oder nicht?
Siavash

16

Versuchen Sie, die Ausrichtung der Anzeige einzustellen. Es löst mein Problem.

 mCamera.setDisplayOrientation(90);

5
Zum Zeitpunkt des Speicherns wird das Hochformat im Querformat gespeichert. Irgendeine Lösung?
Akanksha Rathore

@Akanksha: Dieses Flag gilt nur für die Vorschau. Es ändert nicht die Ausrichtung des Puffers, der in onPreviewFrame()oderonPictureTaken()
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();
     }
}

Versuchen Sie diesen Code


3
Zum Zeitpunkt des Speicherns wird das Hochformat im Querformat gespeichert. Irgendeine Lösung?
Akanksha Rathore

@Akanksha, das hat wahrscheinlich mit den EXIF-Parametern zu tun.
EpicPandaForce

4

Ich hatte ein Problem mit der Frontkamera (Upside-Down-Problem). Dann habe ich die folgende Methode verwendet, die in Android Docs dokumentiert ist -

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
Diese Methode stammt aus der
Kameradokumentation

@VinceFior Stimmt etwas nicht, wenn er aus einem offiziellen Dokument schreibt?
Ranjith Kumar

1
@RanjithKumar Nicht besonders, ich wollte nur die Quelle würdigen und die Leute dort auf mehr Kontext hinweisen. :)
VinceFior

3

Ich habe es mit Ratschlägen von mCamera.setDisplayOrientation (90) gemacht. aber auch die Bitmap gedreht, weil aus irgendeinem Grund die anderen Ansätze für mich in Version 2.3.3 nicht funktionieren.

Zum Drehen der Bitmap habe ich folgendes gemacht:

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

Ich habe meinen Code mit dem Tutorial verglichen und als letztes wurde der folgende Code in meine AndroidManifext.xml eingefügt: Im <activity>Tag:

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

Ich denke, der SENSOR_ORIENTATION- Wert erklärt, welcher Wert für die Drehung verwendet werden soll, anstatt auf 90 Grad fest zu codieren

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);
        }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.