Android kamera yönü nasıl doğru ayarlanır?


90

Android'de kamera yönünü cihaz yönüne göre ayarlamak istiyorum ancak hiçbir şey çalışmıyor gibi görünüyor. Yüzeyi ve kamera parametrelerini döndürmeye çalıştım ancak portre modunda kamera önizlemesi her zaman ters geliyor. Doğru olması için saat yönünde 90 derece döndürmem gerekiyor. İşte şu anda kullandığım kod sadece yatay modda çalışıyor.

    SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {          
        initCamera();           
    }

    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.2;
        double targetRatio = (double) w / h;
        if (sizes == null)
            return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            Log.d(TAG, "Checking size " + size.width + "w " + size.height
                    + "h");
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the
        // requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Camera.Parameters parameters = camera.getParameters();

        List<Size> sizes = parameters.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(sizes, width, height);         
        Log.d(TAG, "Surface size is " + width + "w " + height + "h");
        Log.d(TAG, "Optimal size is " + optimalSize.width + "w " + optimalSize.height + "h");           
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);           
        // parameters.setPreviewSize(width, height);            
        camera.setParameters(parameters);
        camera.startPreview();
    }
};  

6
AFAIK kamera önizlemesi yalnızca manzara modunda, en azından 2.2 ve öncesi için çalışır. Bu yüzden kamera önizlemesi yapan etkinliklerin sistem bildirim çubuğunu gizleme eğiliminde olduğunu ve başlıkları olmadığını düşünüyorum ... görünüşe göre portre olmasına rağmen bunların "gerçekten" manzara olduklarını düşünüyorum.
Reuben Scratton

Yanıtlar:


71

Diğer üyeden ve benim sorunum:

Kamera Döndürme sorunu, farklı Cihazlara ve belirli Sürüme bağlıdır.

Sürüm 1.6: Döndürme Sorununu düzeltmek için ve çoğu cihaz için iyidir

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
        {   
            p.set("orientation", "portrait");
            p.set("rotation",90);
        }
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
        {                               
            p.set("orientation", "landscape");          
            p.set("rotation", 90);
        }

Sürüm 2.1: cihaz türüne bağlıdır, örneğin, XPeria X10 ile sorunu çözemez, ancak X8 ve Mini için iyidir

Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
camera.setParameters(parameters);

Sürüm 2.2: tüm cihazlar için değil

camera.setDisplayOrientation(90);

http://code.google.com/p/android/issues/detail?id=1193#c42


3
buradaki versiyonla ne demek istiyorsun?
Md. Sulayman

31

Javadocs'tan setDisplayOrientation(int)(API seviyesi 9 gerektirir):

 public static void setCameraDisplayOrientation(Activity activity,
         int cameraId, android.hardware.Camera camera) {
     android.hardware.Camera.CameraInfo info =
             new android.hardware.Camera.CameraInfo();
     android.hardware.Camera.getCameraInfo(cameraId, info);
     int rotation = activity.getWindowManager().getDefaultDisplay()
             .getRotation();
     int degrees = 0;
     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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
         result = (info.orientation + degrees) % 360;
         result = (360 - result) % 360;  // compensate the mirror
     } else {  // back-facing
         result = (info.orientation - degrees + 360) % 360;
     }
     camera.setDisplayOrientation(result);
 }

1
@Derzu sınıf CameraInfoI yayınlanmıştır yöntem API düzeyi 9. gerektirir böylece, API düzeyinde 9 kadar tanıtılan değildi
Jason Robinson

2
result = (360 - result) % 360; // compensate the mirrorgerektiğini silinmiş , ön kamerası görüntüleri aksi olan yanlış döndürülmüş
stevo.mit

@ stevo.mit bunu birden fazla cihazda doğruladınız mı? Bu kodu rotasyon için birkaç kez kullandım ve yanlış bir rotasyonla karşılaşmadım.
Jason Robinson

2
@ Jason Robinson API seviyesinin 9'un üzerinde olduğu bazı modeller listem var ama yine de bu yöntemin bir etkisi yok. Donanımla ilgili sorunu bilmiyorum. Cihaz listesi rotation_issue_models = Arrays.asList ("GT-S5360", "GT-S6802", "GT-S5830C", "GT-S5830I", "DROID2", "GLOBAL", "XT557", "Desire HD", " PC36100 "," GT-I9000 "," ADR6350 "," Mi-One Plus "," SGH-T989 "," GT-I9100 "," GT-I9001 ");
Vikram

1
@AbdulMohsin developer.android.com/reference/android/hardware/… , özellikle CAMERA_FACING_BACK ve CAMERA_FACING_FRONT adresine bakın.
Jason Robinson

25

Bu çözüm , Android'in tüm sürümleri için çalışacaktır . Tüm Android cihazlarda çalışmasını sağlamak için Java'daki yansımayı kullanabilirsiniz:

Temel olarak, belirli bir yöntemi çağırmak yerine, Android 2.2 setDisplayOrientation öğesini çağırmak için bir yansıma sarmalayıcı oluşturmalısınız.

Yöntem:

    protected void setDisplayOrientation(Camera camera, int angle){
    Method downPolymorphic;
    try
    {
        downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });
        if (downPolymorphic != null)
            downPolymorphic.invoke(camera, new Object[] { angle });
    }
    catch (Exception e1)
    {
    }
}

Ve camera.setDisplayOrientation (x) kullanmak yerine setDisplayOrientation (kamera, x) kullanın :

    if (Integer.parseInt(Build.VERSION.SDK) >= 8)
        setDisplayOrientation(mCamera, 90);
    else
    {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            p.set("orientation", "portrait");
            p.set("rotation", 90);
        }
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            p.set("orientation", "landscape");
            p.set("rotation", 90);
        }
    }   

1
Diğer kısım, bazı 2.1 cihazlarda çalışır ancak TÜMÜNDE çalışmaz (yukarıdaki maydenec açıklamasına bakın).
Eric Chen

1
Bence p tipiktir Camera.Parameters. Şu satırı eklemeyi deneyin:Camera.Parameters p = camera.getParameters();
Şehrish Khan

6

Sekmelerde tarama yapmak için ZBar'ı kullanırken sorunla karşılaştım. Kamera yönlendirme sorunu. Aşağıdaki kodu kullanarak sorunu çözebildim. Bu kod parçacığının tamamı değildir, lütfen bundan yalnızca yardım alın.

 public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
     if (isPreviewRunning) {
            mCamera.stopPreview();
        }

 setCameraDisplayOrientation(mCamera);

        previewCamera();

    }



 public void previewCamera() {

        try {
            // Hard code camera surface rotation 90 degs to match Activity view
            // in portrait
            mCamera.setPreviewDisplay(mHolder);
            mCamera.setPreviewCallback(previewCallback);
            mCamera.startPreview();
            mCamera.autoFocus(autoFocusCallback);
            isPreviewRunning = true;
        } catch (Exception e) {
            Log.d("DBG", "Error starting camera preview: " + e.getMessage());
        }


    }


public void setCameraDisplayOrientation(android.hardware.Camera camera) {
        Camera.Parameters parameters = camera.getParameters();

        android.hardware.Camera.CameraInfo camInfo =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(getBackFacingCameraId(), camInfo);


        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        int rotation = display.getRotation();
        int degrees = 0;
        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 (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (camInfo.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (camInfo.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }




    private int getBackFacingCameraId() {
        int cameraId = -1;
        // Search for the front facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {

                cameraId = i;
                break;
            }
        }
        return cameraId;
    }

5

Sonunda Google'ın kamera uygulamasını kullanarak bunu düzelttim. Bir sensör kullanarak telefonun yönünü alır ve ardından EXIF ​​etiketini uygun şekilde ayarlar. Kameradan çıkan JPEG otomatik olarak yönlendirilmez.

Ayrıca, kamera önizlemesi yalnızca manzara modunda düzgün çalışır. Aktivite düzeninizin dikey olarak yönlendirilmesine ihtiyacınız varsa, oryantasyon sensöründen gelen değeri kullanarak manuel olarak yapmanız gerekecektir.


2
hey, yönelim sensörünü kullanarak kamera yönü nasıl alınır? lütfen kodunuzu paylaşın ...
Rishi


4
Yardım için teşekkürler, ancak benim sorunum symsung telefonlarında portre modunda fotoğraf çekerken fotoğrafın ekranımda 90 derece döndürülmüş olarak görüntülenmesi. Bu yüzden, kameranın yönünü elde etmeye çalışıyorum, bu yüzden portre modu için fotoğraf 90 derece döndürüldü
Rishi

5

bu çözüme bak

 public static void setCameraDisplayOrientation(Activity activity,
                                                   int cameraId, android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

Ön taraftaki kamerayı tuttuğunuz için teşekkürler. Bu sorunumu çözdü
Louis CAD

Hoş geldiniz @LouisCAD, çözümümün probleminizi çözdüğünü görmekten mutluluk duyarız.
Mudassir Khan

4

Bu sorun uzun zaman önce çözüldü, ancak tüm parçaları bir araya getirmek için bazı zorluklarla karşılaştım, bu yüzden işte benim son çözümüm, umarım bu başkalarına yardımcı olur:

public void startPreview() {
        try {
            Log.i(TAG, "starting preview: " + started);

            // ....
            Camera.CameraInfo camInfo = new Camera.CameraInfo();
            Camera.getCameraInfo(cameraIndex, camInfo);
            int cameraRotationOffset = camInfo.orientation;
            // ...

            Camera.Parameters parameters = camera.getParameters();
            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
            Camera.Size previewSize = null;
            float closestRatio = Float.MAX_VALUE;

            int targetPreviewWidth = isLandscape() ? getWidth() : getHeight();
            int targetPreviewHeight = isLandscape() ? getHeight() : getWidth();
            float targetRatio = targetPreviewWidth / (float) targetPreviewHeight;

            Log.v(TAG, "target size: " + targetPreviewWidth + " / " + targetPreviewHeight + " ratio:" + targetRatio);
            for (Camera.Size candidateSize : previewSizes) {
                float whRatio = candidateSize.width / (float) candidateSize.height;
                if (previewSize == null || Math.abs(targetRatio - whRatio) < Math.abs(targetRatio - closestRatio)) {
                    closestRatio = whRatio;
                    previewSize = candidateSize;
                }
            }

            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            int degrees = 0;
            switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break; // Natural orientation
            case Surface.ROTATION_90:
                degrees = 90;
                break; // Landscape left
            case Surface.ROTATION_180:
                degrees = 180;
                break;// Upside down
            case Surface.ROTATION_270:
                degrees = 270;
                break;// Landscape right
            }
            int displayRotation;
            if (isFrontFacingCam) {
                displayRotation = (cameraRotationOffset + degrees) % 360;
                displayRotation = (360 - displayRotation) % 360; // compensate
                                                                    // the
                                                                    // mirror
            } else { // back-facing
                displayRotation = (cameraRotationOffset - degrees + 360) % 360;
            }

            Log.v(TAG, "rotation cam / phone = displayRotation: " + cameraRotationOffset + " / " + degrees + " = "
                    + displayRotation);

            this.camera.setDisplayOrientation(displayRotation);

            int rotate;
            if (isFrontFacingCam) {
                rotate = (360 + cameraRotationOffset + degrees) % 360;
            } else {
                rotate = (360 + cameraRotationOffset - degrees) % 360;
            }

            Log.v(TAG, "screenshot rotation: " + cameraRotationOffset + " / " + degrees + " = " + rotate);

            Log.v(TAG, "preview size: " + previewSize.width + " / " + previewSize.height);
            parameters.setPreviewSize(previewSize.width, previewSize.height);
            parameters.setRotation(rotate);
            camera.setParameters(parameters);
            camera.setPreviewDisplay(mHolder);
            camera.startPreview();

            Log.d(TAG, "preview started");

            started = true;
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

'Umarım bu başkalarına yardımcı olur' Hayır, olmayacak. Kod parçanız bağlamdan çıkarılır. Örneğin, 'isFrontFacingCam' nereden geliyor?
seanpj

4
Bence bu başka bir konu aslında, bu gerçekten ilk problemle karşılaştırıldığında hiçbir şey değil. Bunu android.hardware.Camera.CameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT adresinden edinebilirsiniz. Bunun için üzgünüm.
Louis GRIGNON
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.