Android - Kamera önizlemesi yan taraftadır


123

Kameranın ekranda gördüklerini görüntülemek için bir Önizleme kullanıyorum.

Her şeyin düzgün çalışmasını sağlayabilirim, yüzey oluşturulmuş, yüzey seti ve yüzey görüntülenir.

Ancak, portre modunda her zaman resmi 90 derecelik yanlış bir açıyla görüntüler.

Resimdeki gibi:

alternatif metin

Aşağıdaki kodu kullanmanın resmi düzelteceğinin farkındayım:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Bununla birlikte, içinde başka unsurlar bulunan bir Aktivite içinde Önizlemeye sahibim ve Aktivitemin manzara modunda görüntülenmesi mantıklı değil. (Varsayılan olarak devre dışıdır)

Öyleyse merak ediyordum da Önizlemenin yönünü değiştirmenin bir yolu var mı? Ve Aktivitemin geri kalanını Portre modunda doğru şekilde görüntülenmeye bırakacak mıyım?

Ya da önizlemeyi doğru görüntülenecek şekilde döndürmek mi?


Yanıtlar:


145

Bu sorun belli donanımıyla ilgili bir hata olarak işe başlamak göründü burada göremiyor ama bu bunu uygulamaya nasıl Yani mCamera.setDisplayOrientation çağrısı API 8'de kullanılmaya (derece) kullanılarak aşılabilir:

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

Bu bir HTC Desire üzerindeydi ve rotasyonun ne olduğunu söylemek için başlangıçta her bir rotasyon kontrolüne günlük kaydı ifadeleri koymam ve ardından cihazda hata ayıklamam ve cihazı döndürürken logCat çıkışını izlemem gerekiyordu. HTC Desire için, 0 beklediğiniz gibi telefondu (portre), 90 derece telefonu 90 derece SAAT YÖNÜNÜN TERSİNE çeviriyordu (saat yönünde olacağını varsaymıştım). Kodda, telefon 90 veya 180 derecedeyken herhangi bir ekran rotasyonu yapmam gerekmediğini göreceksiniz - cihaz bunu kendisi hallediyor gibiydi. Yalnızca bir nokta düzgün çalışmıyor: Cihazı saat yönünde 90 derece döndürdüğünüzde 270 derece dönüş ve ekran dönüşü iyi durumda ancak cihazı saat yönünün tersine 270 derece döndürürseniz, bunu düzgün bir şekilde telafi ediyormuş gibi görünmüyor.

PS Genişlik ve yüksekliğin uygun dönüşlerde değiştirilmesine dikkat edin.


7
ancak setDisplayOrientation (derece); yöntem form 2.2'yi destekler, peki ya alt sürüm? parameters.setRotation (90); parameters.set ("oryantasyon", "portre"); çalışmıyor. Daha düşük sürümler için herhangi bir çözümünüz varsa lütfen bana yardım edin.
Vikram

1
Uygulamamda her zaman dikey modda gösterilecek bir önizleme uyguladım. Ekranı her zaman 90 derece döndürüyordum ve bu, HTC Desire C'de test edene kadar her cihazda çalışıyor gibiydi. Bunu test etmek için şimdi cihaza güvenmediğim için, bunun sizi düzeltip düzeltmediğini açıklamanızı rica ediyorum. önerisi nihayet HTC arzusu üzerinde iyi çalıştı. Teşekkürler!
argenkiwi

13
mCamera.setParameters(parameters);Yüzey boyutları benim telefon için geçerli bir önizleme boyutu olmadığından açıklamada, Uygulamamı çökmesine (ı görünür durum çubuğu tutmak çünkü belki?). Ancak, ben kullanarak bulundu mCamera.setDisplayOrientation(90)sonra mCamera.setPreviewDisplay(mSurfaceHolder);parametresi ayarlamadan çok çalıştı!
nicopico

3
bir anahtar ifadesiyle daha temiz olur
Siavash

2
Bu, önizlemenin TÜM cihazlarda yanlamasına olduğunu varsaymaz mı? çünkü bazı cihazlarda yana doğru ve diğerlerinde yukarı doğru .... bir cihazın varsayılan kamera yönünün telefonun dikey tarafıyla aynı hizada olup olmadığını kontrol etmenin bir yolu var mı?
Siavash

16

ekran yönünü ayarlamayı deneyin. Sorunumu çözüyor.

 mCamera.setDisplayOrientation(90);

5
kaydetme anında portre görüntüsünü yatay olarak kaydeder. Herhangi bir çözüm var mı?
Akanksha Rathore

@Akanksha: bu bayrak yalnızca önizleme görüntüsü için geçerlidir. Geri gönderilen tamponun yönünü değiştirmez onPreviewFrame()veyaonPictureTaken()
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();
     }
}

bu kodu dene


3
kaydetme anında portre görüntüsünü yatay olarak kaydeder. Herhangi bir çözüm var mı?
Akanksha Rathore

@Akanksha muhtemelen EXIF ​​parametreleriyle ilgisi var.
EpicPandaForce

4

Ön Kamera ile ilgili bir sorun yaşıyordum (Baş aşağı sorunu). Sonra Android Dokümanlar'da belgelenen aşağıdaki yöntemi kullandım -

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
Bu yöntem kamera belgelerinden gelir: developer.android.com/reference/android/hardware/…
VinceFior

@VinceFior Resmi belgeden gönderirse bir sorun var mı?
Ranjith Kumar

1
@RanjithKumar Özellikle değil, sadece kaynağa itibar etmek ve daha fazla bağlam için oradaki insanları yönlendirmek istedim. :)
VinceFior

3

MCamera.setDisplayOrientation (90) dan tavsiye alarak yaptım; ama aynı zamanda bitmap'i de döndürdü çünkü bazı nedenlerden dolayı diğer yaklaşımlar 2.3.3 sürümünde benim için çalışmıyor.

Bit eşlemi döndürmek için şunu yaptım:

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

Kodumu öğretici bir kodla karşılaştırdım ve sonunda düzeltilen şey, aşağıdaki kodu AndroidManifext.xml'ime yerleştirmekti: <activity>Etikette:

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

Bence SENSOR_ORIENTATION değeri, 90 dereceye kodlama yerine döndürme için hangi değerin kullanılacağını açıklayacak

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);
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.