Android - ตัวอย่างกล้องอยู่ด้านข้าง


123

ฉันใช้ Preview เพื่อแสดงสิ่งที่กล้องเห็นบนหน้าจอ

ฉันสามารถทำให้ทุกอย่างทำงานได้ดีสร้างพื้นผิวชุดพื้นผิวและพื้นผิวจะปรากฏขึ้น

อย่างไรก็ตามจะแสดงภาพในมุม 90 องศาที่ไม่ถูกต้องเสมอในโหมดแนวตั้ง

เช่นในภาพ:

ข้อความแสดงแทน

ฉันทราบว่าการใช้รหัสต่อไปนี้จะทำให้ภาพตรง:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

อย่างไรก็ตามฉันมีการแสดงตัวอย่างภายในกิจกรรมที่มีองค์ประกอบอื่น ๆ อยู่และมันไม่สมเหตุสมผลที่กิจกรรมของฉันจะแสดงในโหมดแนวนอน (ปิดใช้งานโดยค่าเริ่มต้น)

ดังนั้นฉันจึงสงสัยว่ามีการเปลี่ยนทิศทางของ Preview หรือไม่? และปล่อยให้กิจกรรมที่เหลือของฉันแสดงอย่างถูกต้องในโหมดแนวตั้งหรือไม่?

หรือจะหมุนตัวอย่างเพื่อให้แสดงอย่างถูกต้อง?


คำตอบ:


145

ปัญหานี้ดูเหมือนจะเริ่มต้นจากข้อผิดพลาดกับฮาร์ดแวร์บางตัวดูที่นี่แต่สามารถเอาชนะได้โดยใช้การเรียกไปที่ mCamera.setDisplayOrientation (degrees) ที่มีอยู่ใน API 8 ดังนั้นนี่คือวิธีที่ฉันใช้:

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

สิ่งนี้อยู่ใน HTC Desire และฉันต้องใส่ข้อความบันทึกในการตรวจสอบการหมุนแต่ละครั้งในขั้นต้นเพื่อบอกว่าการหมุนคืออะไรจากนั้นจึงดีบักบนอุปกรณ์และดูเอาต์พุต logCat ในขณะที่ฉันหมุนอุปกรณ์ สำหรับ HTC Desire 0 เป็นโทรศัพท์อย่างที่คุณคาดหวัง (แนวตั้ง) 90 องศากำลังหมุนโทรศัพท์ 90 องศา COUNTER-CLOCKWISE (ฉันคิดว่ามันน่าจะเป็นตามเข็มนาฬิกา) ในรหัสคุณจะเห็นว่าฉันไม่จำเป็นต้องหมุนหน้าจอใด ๆ เมื่อโทรศัพท์อยู่ที่ 90 หรือ 180 องศา - ดูเหมือนว่าอุปกรณ์จะจัดการได้เอง มีเพียงจุดเดียวเท่านั้นที่ทำงานไม่ถูกต้อง: การหมุน 270 องศาคือเมื่อคุณหมุนอุปกรณ์ตามเข็มนาฬิกา 90 องศาและตัวนับการหมุนจอแสดงผลที่ใช้ได้ แต่ถ้าคุณหมุนอุปกรณ์ 270 องศาทวนเข็มนาฬิกาดูเหมือนว่าจะชดเชยไม่ถูกต้อง

ปล. สังเกตการสลับความกว้างและความสูงในการหมุนที่เหมาะสม


7
แต่ setDisplayOrientation (องศา); method รองรับแบบ 2.2 แล้วรุ่นต่ำกว่าล่ะ ?? parameters.setRotation (90); parameters.set ("การวางแนว", "แนวตั้ง"); ไม่ทำงาน หากคุณมีวิธีแก้ปัญหาสำหรับรุ่นที่ต่ำกว่าโปรดช่วยฉันด้วย
Vikram

1
ฉันใช้การแสดงตัวอย่างในแอปของฉันซึ่งจะแสดงในโหมดแนวตั้งเสมอ ฉันหมุนหน้าจอ 90 องศาตลอดเวลาและดูเหมือนว่าจะใช้ได้กับทุกอุปกรณ์จนกว่าเราจะทดสอบกับ HTC Desire C เนื่องจากฉันไม่ได้นับอุปกรณ์ในตอนนี้เพื่อทดสอบสิ่งนี้ฉันขอให้คุณชี้แจงว่าคุณสามารถแก้ไขได้หรือไม่ แนะนำในที่สุดก็ทำงานได้ดีตามความต้องการของ HTC ขอบคุณ!
argenkiwi

13
mCamera.setParameters(parameters);คำสั่งผิดพลาด app ของฉันเพราะขนาดพื้นผิวที่ไม่ได้เป็นขนาดการแสดงตัวอย่างที่ถูกต้องสำหรับโทรศัพท์ของฉัน (อาจจะเพราะผมเก็บแถบสถานะที่มองเห็น?) แต่ผมพบว่าการใช้mCamera.setDisplayOrientation(90)แล้วmCamera.setPreviewDisplay(mSurfaceHolder);โดยไม่ต้องตั้งค่าพารามิเตอร์ทำงานมากเกินไป!
nicopico

3
จะสะอาดกว่าด้วยคำสั่งสวิตช์
Siavash

2
นี่ไม่ถือว่าการแสดงตัวอย่างอยู่ด้านข้างบนอุปกรณ์ทั้งหมดใช่หรือไม่ เนื่องจากเป็นด้านข้างในอุปกรณ์บางรุ่นและขึ้นอยู่กับอุปกรณ์อื่น ๆ .... มีวิธีตรวจสอบเพื่อดูว่าการวางแนวกล้องเริ่มต้นของอุปกรณ์สอดคล้องกับด้านแนวตั้งของโทรศัพท์หรือไม่?
Siavash

16

พยายามตั้งค่าการวางแนวการแสดงผล มันช่วยแก้ปัญหาของฉันได้

 mCamera.setDisplayOrientation(90);

5
ในขณะบันทึกจะบันทึกภาพแนวตั้งในแนวนอนวิธีแก้ปัญหาใด ๆ
Akanksha Rathore

@Akanksha: แฟล็กนี้ใช้กับการแสดงตัวอย่างเท่านั้น ไม่เปลี่ยนการวางแนวของบัฟเฟอร์ที่ส่งคืนonPreviewFrame()หรือonPictureTaken()
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();
     }
}

ลองใช้รหัสนี้


3
ในขณะบันทึกจะบันทึกภาพแนวตั้งในแนวนอนวิธีแก้ปัญหาใด ๆ
Akanksha Rathore

@Akanksha ที่น่าจะเกี่ยวข้องกับพารามิเตอร์ EXIF
EpicPandaForce

4

ฉันมีปัญหากับกล้องหน้า (ปัญหากลับหัว) จากนั้นฉันใช้วิธีการต่อไปนี้ที่บันทึกไว้ใน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
วิธีนี้มาจากเอกสารของกล้อง: developer.android.com/reference/android/hardware/…
VinceFior

@VinceFior มีอะไรผิดปกติถ้าเขาโพสต์จากเอกสารอย่างเป็นทางการ?
Ranjith Kumar

1
@RanjithKumar ไม่โดยเฉพาะอย่างยิ่งฉันแค่อยากให้เครดิตกับแหล่งที่มาและชี้ให้คนที่นั่นดูบริบทเพิ่มเติม :)
VinceFior

3

ฉันทำตามคำแนะนำของ mCamera.setDisplayOrientation (90); แต่ยังหมุนบิตแมปด้วยเพราะเหตุผลบางประการวิธีอื่น ๆ ไม่ได้ผลสำหรับฉันในเวอร์ชัน 2.3.3

สำหรับการหมุนบิตแมปฉันทำสิ่งนี้:

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

ฉันได้เปรียบเทียบรหัสของฉันกับบทช่วยสอนและในที่สุดสิ่งที่แก้ไขได้คือการใส่รหัสต่อไปนี้ลงใน AndroidManifext.xml ของฉัน: ใน<activity>แท็ก:

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

ฉันคิดว่าค่าSENSOR_ORIENTATIONจะอธิบายค่าที่จะใช้สำหรับการหมุนแทนการเข้ารหัสเป็น 90 องศา

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);
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.