Android कैमरा ओरिएंटेशन को ठीक से कैसे सेट करें?


90

मैं एंड्रॉइड में डिवाइस ओरिएंटेशन के अनुसार कैमरा ओरिएंटेशन सेट करना चाहता हूं लेकिन कुछ भी काम नहीं कर रहा है। मैंने सतह के साथ-साथ कैमरा मापदंडों को घुमाने की कोशिश की, लेकिन पोर्ट्रेट मोड में कैमरा पूर्वावलोकन हमेशा उल्टा आता है। मुझे इसे सही करने के लिए इसे 90 डिग्री दक्षिणावर्त घुमाने की आवश्यकता होगी। यहां वह कोड है जिसका मैं अभी उपयोग कर रहा हूं जो केवल लैंडस्केप मोड में काम करता है।

    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 कैमरा पूर्वावलोकन केवल सही मायने में परिदृश्य में काम करता है, कम से कम 2.2 और पहले के लिए। मैं अनुमान लगाता हूं कि यही कारण है कि कैमरा पूर्वावलोकन करने वाली गतिविधियां सिस्टम नोटिफिकेशन बार को छिपाने के लिए होती हैं और शीर्षक नहीं होते हैं ... जाहिरा तौर पर चित्र होने के बावजूद मुझे लगता है कि वे "वास्तव में" परिदृश्य हैं।
रूबेन स्क्रैटन

जवाबों:


71

अन्य सदस्य और मेरी समस्या से:

कैमरा रोटेशन मुद्दा विभिन्न डिवाइसेस और निश्चित संस्करण पर निर्भर करता है।

संस्करण 1.6: रोटेशन समस्या को ठीक करने के लिए, और यह अधिकांश उपकरणों के लिए अच्छा है

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

संस्करण 2.1: उपकरणों के प्रकार पर निर्भर करता है, उदाहरण के लिए, Caner XPeria X10 के साथ समस्या को ठीक कर सकता है, लेकिन यह X8 और मिनी के लिए अच्छा है

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

संस्करण 2.2: सभी उपकरणों के लिए नहीं

camera.setDisplayOrientation(90);

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


3
यहाँ संस्करण से आपका क्या मतलब है?
एमडी। सुलेमान

31

Javadocs से setDisplayOrientation(int)(API स्तर 9 की आवश्यकता है):

 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 CameraInfoएपीआई स्तर 9 तक कक्षा शुरू नहीं की गई थी, इसलिए मैंने जिस विधि को पोस्ट किया है उसके लिए एपीआई स्तर 9 की आवश्यकता है।
जेसन रॉबिन्सन

2
result = (360 - result) % 360; // compensate the mirrorहटा दिया जाना चाहिए , फ्रंट कैमरे से चित्रों को अन्यथा गलत तरीके से घुमाया जाता है
stevo.mit

@ stevo.mit क्या आपने कई उपकरणों पर इसे सत्यापित किया है? मैंने कई बार रोटेशन के लिए इस कोड का उपयोग किया है और गलत रोटेशन का सामना नहीं किया है।
जेसन रॉबिन्सन

2
@ जेसन रॉबिन्सन मेरे पास कुछ मॉडल सूची है जिन पर एपीआई स्तर 9 से ऊपर है, लेकिन फिर भी इस पद्धति का कोई प्रभाव नहीं है। मौसम के हार्डवेयर से जुड़े मुद्दे को न जानें। डिवाइस सूची रोटेशन_इस्यू_मॉडल्स = एरेसेस.सलिस्ट ("GT-S5360", "GT-S6802", "GT-S5830C", "GT-S5830I", "GROID2", "GLOBAL", "XT557", "इच्छा HD", " PC36100 "," GT-I9000 "," ADR6350 "," Mi-One Plus "," SGH-T989 "," GT-I9100 "," GT-I9001 ");
विक्रम

1
@AbdulMohsin डेवलपर को देखें ।android.com/reference/android/hardware/… , विशेष रूप से CAMERA_FACING_BACK और CAMERA_FACING_FRONT।
जेसन रॉबिन्सन

25

यह समाधान एंड्रॉइड के सभी संस्करणों के लिए काम करेगा । आप सभी Android उपकरणों के लिए काम करने के लिए जावा में प्रतिबिंब का उपयोग कर सकते हैं:

मूल रूप से आपको एंड्रॉइड 2.2 setDisplayOrientation को कॉल करने के लिए एक प्रतिबिंब आवरण बनाना चाहिए, बजाय विशिष्ट विधि को कॉल करने के।

विधि:

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

और उपयोग करने के बजाए camera.setDisplayOrientation (x) उपयोग setDisplayOrientation (कैमरा, एक्स) :

    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
दूसरा भाग कुछ 2.1 उपकरणों पर काम करता है, लेकिन सभी नहीं (ऊपर मेडनक स्पष्टीकरण देखें)।
एरिक चेन

1
मुझे लगता है कि पी टाइप का है Camera.Parameters। निम्नलिखित पंक्ति को जोड़ने का प्रयास करें:Camera.Parameters p = camera.getParameters();
सेहरिश खान

6

मुझे उस समस्या का सामना करना पड़ा जब मैं टैब में स्कैनिंग के लिए ZBar का उपयोग कर रहा था। कैमरा उन्मुखीकरण मुद्दा। नीचे दिए गए कोड का उपयोग करके मैं समस्या को हल करने में सक्षम था। यह संपूर्ण कोड स्निपेट नहीं है, कृपया केवल इसकी सहायता लें।

 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

मैंने अंततः Google के कैमरा ऐप का उपयोग करके इसे ठीक किया। यह सेंसर का उपयोग करके फोन का अभिविन्यास प्राप्त करता है और फिर EXIF ​​टैग को उचित रूप से सेट करता है। जेपीईजी जो कैमरे से निकलता है वह स्वचालित रूप से उन्मुख नहीं होता है।

इसके अलावा, कैमरा पूर्वावलोकन केवल लैंडस्केप मोड में ठीक से काम करता है। यदि आपको चित्र में उन्मुख होने के लिए आपकी गतिविधि लेआउट की आवश्यकता है, तो आपको ओरिएंटेशन सेंसर से मूल्य का उपयोग करके इसे मैन्युअल रूप से करना होगा।


2
हे, कैसे अभिविन्यास सेंसर का उपयोग कर कैमरा उन्मुखीकरण पाने के लिए ?? कृपया अपना कोड साझा करें ...
ऋषि

@ ऋषि इस लिंक को देखें stackoverflow.com/questions/9055460/…
PiyushMishra

4
मदद के लिए धन्यवाद, लेकिन मेरा मुद्दा है जब उस समय चित्र मोड में सिसुंग फोन पर फोटो ले रहा है, तो फोटो को मेरी स्क्रीन पर 90 डिग्री घुमाया हुआ प्रदर्शित किया जाता है। इसलिए, मैं कैमरे का ओरिएंटेशन पाने की कोशिश कर रहा हूं, इसलिए इमेज मोड के लिए रोटेटेड फोटो 90 डिग्री
Rishi

5

इस समाधान की जाँच करें

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

फ्रंट फेसिंग कैमरा को संभालने के लिए धन्यवाद। इससे मेरी समस्या हल हो गई
लुई सीएडी

आपका स्वागत है @LouisCAD को यह देखकर खुशी हुई कि मेरा समाधान आपकी समस्या का समाधान करता है।
मुदस्सिर खान

4

यह समस्या बहुत समय पहले हल हो गई थी, लेकिन मुझे सभी टुकड़ों को एक साथ रखने के लिए कुछ कठिनाइयों का सामना करना पड़ा, इसलिए यहां मेरा अंतिम समाधान है, मुझे आशा है कि इससे अन्य लोगों को मदद मिलेगी:

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

'मुझे उम्मीद है कि यह दूसरों की मदद करेगा' नहीं, यह नहीं होगा। आपके कोड ऑफ कॉन्ट्रेक्ट को संदर्भ से बाहर निकाला गया है। उदाहरण के लिए,'FrontFacingCam 'कहाँ से आ रहा है?
सीनपज

4
मुझे लगता है कि यह वास्तव में एक अन्य विषय है, यह वास्तव में प्रारंभिक समस्या की तुलना में कुछ भी नहीं है। आप इसे android.hardware.Camera.CameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT से प्राप्त कर सकते हैं। इसके लिए क्षमा करें।
लुई GRIGNON
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.