Soru Android kamera oryantasyonu nasıl ayarlanır?


Kamera yönelimini Android'de 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 baş aşağı geliyor. Doğru olması için saat yönünde 90 derece döndürmem gerek. İşte şu an 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();
    }
};  

82
2018-01-10 10:47


Menşei


AFAIK kamera önizlemesi, en azından 2.2 ve daha erken bir zamanda, manzarada gerçekten çalışır. Bu yüzden kamera önizlemesi yapan etkinliklerin sistem bildirim çubuğunu gizleme ve başlıklara sahip olmadıkları yönündedir. Bu yüzden görünüşte portre olmasına rağmen "gerçekten" manzara olduklarını düşünüyorum. - Reuben Scratton


Cevaplar:


Diğer üyeden ve benim sorunumdan:

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

Sürüm 1.6: Döndürme Sorunu 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: Örneğin, XPeria X10 ile sorunu çözemezsiniz, 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


68
2018-02-28 10:48



Problemi çözdü. - Huy Tower
Buradaki sürümden ne demek istiyorsun? - Md. Sulayman


İçin Javadocs’dan 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);
 }

31
2018-04-18 21:29



@Derzu Sınıf CameraInfo API seviyesi 9'a kadar tanıtılmadı, bu yüzden gönderdiğim yöntem API düzey 9'u gerektiriyor. - Jason Robinson
Nexus 7 için çalışmıyor ... ne yapmalı? / - Nipun Gogia
result = (360 - result) % 360; // compensate the mirror olmalı silindi, ön kameradan gelen resimler başka türlü yanlış döndürülmüş - stevo.mit
@ Jason Robinson Api seviyesinin 9'un üzerinde olduğu bazı model listeleme var ama yine de bu yöntemin bir etkisi yok. Donanımı ile ilgili sorunları hava durumu 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
@AbdulMohsin Bakın developer.android.com/reference/android/hardware/...özellikle CAMERA_FACING_BACK ve CAMERA_FACING_FRONT. - Jason Robinson


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

Temel olarak, belirli yöntemi çağırmak yerine Android 2.2 setDisplayOrientation öğesini çağırmak için bir yansıma sarıcı oluşturmanız gerekir.

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 kullanmak yerine camera.setDisplayOrientation (x) kullanım setDisplayOrientation (kamera, x) :

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

25
2017-08-09 05:49



Diğer kısım, 2.1 cihaz üzerinde çalışmaktadır, fakat TÜMÜ değil (yukarıda maydenec'in açıklamasına bakınız). - Eric Chen
P türü hangisi? - Derzu
Sanırım p tipte Camera.Parameters. Aşağıdaki satırı eklemeyi deneyin: Camera.Parameters p = camera.getParameters(); - Sehrish Khan


Sekmelerde taramak için ZBar kullanırken sorunu yaşadım. Kamera yönelimi sorunu. Aşağıdaki kodu kullanarak sorunu çözmeyi başardım. Bu, kod snippet'in tamamı değil, lütfen sadece bundan 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;
    }

6
2017-07-07 00:25





Bunu Google'ın kamera uygulamasını kullanarak düzelttim. Bir sensör kullanarak telefonun yönünü alır ve EXIF ​​etiketini uygun şekilde ayarlar. Fotoğraf makinesinden çıkan JPEG otomatik olarak yönlendirilmiyor.

Ayrıca, kamera önizlemesi sadece manzara modunda düzgün çalışır. Portre düzeninde yönlendirilmek için aktivite düzeninize ihtiyacınız varsa, bunu yönlendirme sensöründen gelen değeri kullanarak manuel olarak yapmanız gerekecektir.


5
2018-03-18 09:36



hey, yön bulma sensörünü kullanarak kamera yönünü nasıl elde edilir ?? lütfen kodunuzu paylaşın ... - Rishi
@Rishi bu bağlantıya bakın stackoverflow.com/questions/9055460/... - PiyushMishra
Yardımın için teşekkürler, ancak sorunum o zaman fotoğrafın ekranında 90 derece döndürülmüşken, o zaman portre modunda symsung telefonlarında fotoğraf çekerken. Bu yüzden, kameranın yönünü değiştirmeye çalışıyorum, portre modu için 90 derece fotoğraf döndürdüm. - Rishi


Bu problem uzun zaman önce çözüldü, ancak tüm parçaları bir araya getirmemde bazı zorluklarla karşılaştım bu yüzden buradaki 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());
        }
    }

4
2017-11-17 18:55



'Umarım bu başkalarına yardım eder' Hayır, olmaz. Kod parçanız bağlamdan çıkarılır. Örneğin, 'isFrontFacingCam' nereden geliyor? - seanpj
Bence bu başka bir konu aslında, bu başlangıç ​​problemine kıyasla gerçekten bir şey değil. Bunu android.hardware.Camera.CameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT adresinden alabilirsiniz. Bunun için üzgünüm. - Louis GRIGNON


bu çözümü kontrol et

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

3
2017-07-11 09:55



Öne bakan kamera için teşekkürler. Bu benim sorunumu çözdü - Louis CAD
Çözümümün sizin sorununuzu çözdüğünü görmek için @LouisCAD memnuniyetle karşılıyorsunuz. - justchill