Android - Xem trước máy ảnh nằm ngang


123

Tôi đang sử dụng Bản xem trước để hiển thị những gì camera nhìn thấy trên màn hình.

Tôi có thể làm mọi thứ hoạt động tốt, bề mặt được tạo, bộ bề mặt và bề mặt được hiển thị.

Tuy nhiên, nó luôn hiển thị hình ảnh ở góc 90 độ không chính xác ở chế độ dọc.

Chẳng hạn như trong hình:

văn bản thay thế

Tôi biết rằng sử dụng mã sau đây sẽ đặt hình ảnh thẳng:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

Tuy nhiên, tôi có Bản xem trước trong một Hoạt động có các yếu tố khác trong đó và nó không có ý nghĩa đối với Hoạt động của tôi được hiển thị ở chế độ ngang. (Nó bị tắt theo mặc định)

Vì vậy, tôi đã tự hỏi là có cách nào để thay đổi định hướng của Bản xem trước không? Và để phần còn lại của Hoạt động của tôi được hiển thị chính xác trong chế độ Chân dung?

Hoặc dù sao để xoay xem trước để nó được hiển thị chính xác?


Câu trả lời:


145

Vấn đề này dường như bắt đầu như một lỗi với phần cứng nhất định có thể thấy ở đây nhưng có thể khắc phục bằng cách sử dụng lệnh gọi đến mCamera.setDisplayOrientation (độ) có sẵn trong API 8. Vì vậy, đây là cách tôi triển khai:

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

Đây là trên HTC Desire và ban đầu tôi phải đưa vào các báo cáo ghi nhật ký trong mỗi lần kiểm tra xoay vòng để nói xoay vòng là gì và sau đó gỡ lỗi trên thiết bị và xem đầu ra logCat trong khi tôi xoay thiết bị. Đối với HTC Desire, 0 là điện thoại như bạn mong đợi (chân dung), 90 độ đang xoay điện thoại 90 độ COUNTER-CLOCKWISE (Tôi đã cho rằng nó sẽ có chiều kim đồng hồ). Trong mã bạn sẽ thấy tôi không cần thực hiện bất kỳ thao tác xoay màn hình nào khi điện thoại ở 90 hoặc 180 độ - thiết bị dường như tự xử lý việc này. Chỉ có một điểm không hoạt động đúng: Xoay 270 độ là khi bạn xoay thiết bị 90 độ theo chiều kim đồng hồ và bộ đếm xoay màn hình hiển thị ổn, nhưng nếu bạn xoay thiết bị 270 độ ngược chiều kim đồng hồ, nó sẽ không xuất hiện để bù cho đúng.

PS Lưu ý sự hoán đổi chiều rộng và chiều cao trong các góc quay thích hợp.


7
nhưng setDisplayOrientation (độ); Phương thức hỗ trợ mẫu 2.2, còn phiên bản thấp hơn thì sao ?? tham số.setRotation (90); tham số.set ("định hướng", "chân dung"); không hoạt động Nếu bạn có bất kỳ giải pháp cho các phiên bản thấp hơn xin vui lòng giúp tôi.
Vikram

1
Tôi đã triển khai bản xem trước trên ứng dụng của mình, nó sẽ luôn hiển thị ở chế độ dọc. Tôi luôn xoay màn hình 90 độ và điều này dường như hoạt động trên mọi thiết bị cho đến khi chúng tôi thử nghiệm nó trên HTC Desire C. Vì hiện tại tôi không dựa vào thiết bị để kiểm tra điều này, tôi muốn bạn làm rõ nếu điều này khắc phục bạn đề nghị cuối cùng đã làm việc tốt trên mong muốn của HTC. Cảm ơn!
argenkiwi

13
Câu mCamera.setParameters(parameters);lệnh làm sập ứng dụng của tôi, vì kích thước bề mặt không phải là kích thước xem trước hợp lệ cho điện thoại của tôi (có thể do tôi giữ thanh trạng thái hiển thị?). Tuy nhiên, tôi thấy rằng sử dụng mCamera.setDisplayOrientation(90)sau đó mCamera.setPreviewDisplay(mSurfaceHolder);mà không thiết lập các tham số làm việc quá!
nicopico

3
sẽ sạch hơn với câu lệnh chuyển đổi
Siavash

2
Điều này không cho rằng bản xem trước nằm ngang trên TẤT CẢ các thiết bị? đối với thiết bị nằm nghiêng trên một số thiết bị và ở bên phải trên các thiết bị khác .... có cách nào để kiểm tra xem thiết bị mặc định có định hướng camera theo hướng dọc với cạnh dọc của điện thoại hay không?
Siavash

16

cố gắng đặt hướng hiển thị. Nó giải quyết vấn đề của tôi.

 mCamera.setDisplayOrientation(90);

5
tại thời điểm lưu nó lưu hình ảnh chân dung trong phong cảnh. Có giải pháp nào không?
Akanksha Rathore

@Akanksha: cờ này chỉ áp dụng cho hiển thị xem trước. Nó không thay đổi hướng của bộ đệm được trả về trong onPreviewFrame()hoặconPictureTaken()
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();
     }
}

thử mã này


3
tại thời điểm lưu nó lưu hình ảnh chân dung trong phong cảnh. Có giải pháp nào không?
Akanksha Rathore

@Akanksha có lẽ phải làm với các tham số EXIF.
EpicPandaForce 9/2/2016

4

Tôi gặp vấn đề với Camera trước (Vấn đề lộn ngược). Sau đó, tôi đã sử dụng phương pháp sau được ghi lại trong Tài liệu Android -

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
Phương pháp này xuất phát từ tài liệu máy ảnh: developer.android.com/reference/android/hardware/,
VinceFior 19/03/2016

@VinceFior Bất cứ điều gì sai nếu anh ấy đăng từ tài liệu chính thức?
Ranjith Kumar

1
@RanjithKumar Không đặc biệt, tôi chỉ muốn cung cấp tín dụng cho nguồn và hướng mọi người đến đó để có thêm bối cảnh. :)
VinceFior

3

Tôi đã làm điều đó nhờ lời khuyên của mCamera.setDisplayOrientation (90); nhưng cũng xoay bitmap vì một số lý do, các cách tiếp cận khác không hoạt động với tôi trong phiên bản 2.3.3.

Để xoay bitmap tôi đã làm điều này:

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

Tôi đã so sánh mã của mình với hướng dẫn và cái cuối cùng đã sửa nó là đưa mã sau vào AndroidManifext.xml của tôi: Trong <activity>thẻ:

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

Tôi nghĩ rằng giá trị SENSOR_ORIENTATION sẽ giải thích giá trị nào sẽ được sử dụng cho vòng quay thay vì mã hóa cứng đến 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);
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.