Android - Pratinjau kamera miring


123

Saya menggunakan Pratinjau untuk menampilkan apa yang dilihat kamera di layar.

Saya bisa mendapatkan semuanya bekerja dengan baik, permukaan dibuat, permukaan diatur dan permukaan ditampilkan.

Namun itu selalu menampilkan gambar pada sudut 90 derajat yang salah dalam mode potret.

Seperti pada gambar:

alt teks

Saya sadar bahwa menggunakan kode berikut akan mengatur gambar secara lurus:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Namun saya memiliki Pratinjau dalam Aktivitas yang memiliki elemen lain di dalamnya dan tidak masuk akal jika Aktivitas saya ditampilkan dalam mode lanskap. (Ini dinonaktifkan secara default)

Jadi saya bertanya-tanya apakah ada cara untuk mengubah orientasi Pratinjau? Dan membiarkan sisa Aktivitas saya ditampilkan dengan benar dalam mode Potret?

Atau tetap memutar pratinjau agar ditampilkan dengan benar?


Jawaban:


145

Masalah ini tampaknya dimulai sebagai bug dengan perangkat keras tertentu, lihat di sini, tetapi dapat diatasi dengan menggunakan panggilan ke mCamera.setDisplayOrientation (derajat) yang tersedia di API 8. Jadi begini cara saya mengimplementasikannya:

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

Ini ada di HTC Desire dan saya awalnya harus memasukkan pernyataan pencatatan di setiap pemeriksaan rotasi untuk mengatakan apa rotasi itu dan kemudian men-debug pada perangkat dan melihat keluaran logCat saat saya memutar perangkat. Untuk HTC Desire, 0 adalah telepon seperti yang Anda harapkan (potret), 90 derajat memutar telepon 90 derajat COUNTER-CLOCKWISE (Saya berasumsi itu searah jarum jam). Dalam kode yang akan Anda lihat, saya tidak perlu melakukan rotasi tampilan saat ponsel berada pada 90 atau 180 derajat - perangkat sepertinya menangani ini sendiri. Hanya satu titik yang tidak berfungsi dengan benar: Rotasi 270 derajat adalah saat Anda memutar perangkat 90 derajat searah jarum jam dan tampilan rotasi berlawanan dengan itu, tetapi jika Anda memutar perangkat 270 derajat berlawanan arah jarum jam, tampaknya tidak mengimbangi dengan benar.

PS Perhatikan pertukaran lebar dan tinggi dalam rotasi yang sesuai.


7
tapi setDisplayOrientation (derajat); Metode mendukung formulir 2.2, bagaimana dengan versi yang lebih rendah ?? parameter.setRotation (90); parameter.set ("orientasi", "potret"); tidak bekerja. Jika Anda memiliki solusi untuk versi yang lebih rendah tolong bantu saya.
Vikram

1
Saya menerapkan pratinjau di aplikasi saya yang akan selalu ditampilkan dalam mode potret. Saya selalu memutar layar 90 derajat dan ini sepertinya berfungsi pada setiap perangkat sampai kami mengujinya pada HTC Desire C. Karena saya tidak mengandalkan perangkat sekarang untuk menguji ini, saya ingin Anda mengklarifikasi jika ini memperbaiki Anda Sarankan akhirnya keinginan HTC berhasil dengan baik. Terima kasih!
argenkiwi

13
The mCamera.setParameters(parameters);pernyataan kecelakaan app saya, karena dimensi permukaan tidak ukuran pratinjau berlaku untuk telepon saya (mungkin karena saya menjaga status bar terlihat?). Namun, saya menemukan bahwa menggunakan mCamera.setDisplayOrientation(90)then mCamera.setPreviewDisplay(mSurfaceHolder);tanpa mengatur parameter juga berfungsi!
nicopico

3
akan lebih bersih dengan pernyataan sakelar
Siavash

2
Bukankah ini mengasumsikan bahwa pratinjau di SEMUA perangkat? karena itu menyamping di beberapa perangkat dan kanan atas di perangkat lain .... apakah ada cara untuk memeriksa untuk melihat apakah orientasi kamera default perangkat sejajar dengan sisi potret ponsel atau tidak?
Siavash

16

coba atur orientasi tampilan. Ini memecahkan masalah saya.

 mCamera.setDisplayOrientation(90);

5
pada saat menyimpannya, ini akan menyimpan gambar potret dalam lanskap. Ada solusi?
Akanksha Rathore

@Akanksha: tanda ini hanya berlaku untuk tampilan pratinjau. Itu tidak mengubah orientasi buffer yang dikembalikan onPreviewFrame()atauonPictureTaken()
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();
     }
}

coba kode ini


3
pada saat menyimpannya, ini akan menyimpan gambar potret dalam lanskap. Ada solusi?
Akanksha Rathore

@Akanksha itu mungkin ada hubungannya dengan parameter EXIF.
EpicPandaForce

4

Saya mengalami masalah dengan Kamera depan (Masalah terbalik). Kemudian saya menggunakan metode berikut yang didokumentasikan di 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
Metode ini berasal dari dokumentasi kamera: developer.android.com/reference/android/hardware/…
VinceFior

@VinceFior Ada yang salah jika dia memposting dari dokumen resmi?
Ranjith Kumar

1
@RanjithKumar Tidak terlalu, saya hanya ingin memberikan kredit kepada sumber dan mengarahkan orang ke sana untuk lebih banyak konteks. :)
VinceFior

3

Saya melakukannya dengan mengambil saran dari mCamera.setDisplayOrientation (90); tetapi juga memutar bitmap karena untuk beberapa alasan pendekatan yang lain tidak berfungsi untuk saya di versi 2.3.3.

Untuk memutar bitmap saya melakukan ini:

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

Saya telah membandingkan kode saya dengan tutorial dan yang akhirnya memperbaikinya adalah menempatkan kode berikut ke AndroidManifext.xml saya: Di <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

Saya pikir nilai SENSOR_ORIENTATION akan menjelaskan nilai apa yang akan digunakan untuk rotasi daripada hardcode hingga 90 derajat

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);
        }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.