Android - Camera provide upside down data on back

2019-07-09 01:17发布

问题:

I am rendering camera preview on GLSurfaceView everything works fine but camera preview show upside down on some device specially on Nexus 5X . I have checked this solution Android - Camera preview is sideways . This is my code for handling orientation problem

 private void setCameraDisplayOrientation() {
    Constants.debugLog(TAG_DEBUG, "setCameraDisplayOrientation");
    Constants.debugLog(TAG, "setCameraDisplayOrientation ");

    if (camera == null) {
        Constants.debugLog(TAG + " Owncamera", "setCameraDisplayOrientation - camera null");
        return;
    }

    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(currentCameraId, info);

    WindowManager winManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    int rotation = winManager.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;
    }

    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        this.cameraOrientation = 2;
    } else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
        this.cameraOrientation = 1;
    }

    Constants.debugLog(TAG_DEBUG, "result: " + result + "  this.cameraOrientation == " + this.cameraOrientation);
    Constants.debugLog(TAG, "result: " + result + "  this.cameraOrientation == " + this.cameraOrientation);
    //Log.e("camera_orient", "res: "+ result);
    camera.setDisplayOrientation(result);
}

From the Camera.CameraInfo info class, i can get orientation . For maximum device the values i get on portrait mode is "for front camera = 270, back camera = 90 "" but on Nexus 5X it provide camera orientation 270,270 for both front & back camera. Beside on other devices my camera provide result value 90 for both front and back camera in portrait mode but for Nexus 5x front camera 90 back camera 270. I have also tried by setting value fixed 90 on camera.setDisplayOrientation(90); Nexus 5X device but don't work How to handle this problem so that all device camera orientation will be same and i won't get any rotated image ??

回答1:

Try

1. First of all, add methods (writeFile, processImage and getCorrectCameraOrientation) defined below

2. Calculate camera orientation after capturing photo and update onPictureTaken**

@Override
public void onPictureTaken (final byte[] data, final Camera camera) {

    int rotationAngle = getCorrectCameraOrientation (this, info);

3. Create file and update photo angle using rotationAngle

File file = new File (folder, fileName);

try {
    file.createNewFile ();
}
catch (IOException e) {
    e.printStackTrace ();
}

writeFile (data, file);
processImage (file, rotationAngle, compressRatio);

writeFile

public static void writeFile (byte[] data, File file) throws IOException {

    BufferedOutputStream bos = null;

    try {
        FileOutputStream fos = new FileOutputStream (file);
        bos = new BufferedOutputStream (fos);
        bos.write (data);
    }
    finally {
        if (bos != null) {
            try {
                bos.flush ();
                bos.close ();
            }
            catch (Exception e) {
            }
        }
    }
}

processImage

public static void processImage (File file, int rotationAngle, int compressionRatio) {

    BufferedOutputStream bos = null;

    try {

        Bitmap bmp = BitmapFactory.decodeFile (file.getPath ());

        Matrix matrix = new Matrix ();
        matrix.postRotate (rotationAngle);

        bmp = Bitmap.createBitmap (bmp, 0, 0, bmp.getWidth (), bmp.getHeight (), matrix, true);

        FileOutputStream fos = new FileOutputStream (file);
        bmp.compress (Bitmap.CompressFormat.PNG, compressionRatio, fos);
    }
    catch (IOException e) {
        e.printStackTrace ();
    }
    catch (OutOfMemoryError t) {
        t.printStackTrace ();
    }
    catch (Throwable t) {
        t.printStackTrace ();
    }
    finally {
        if (bos != null) {
            try {
                bos.flush ();
                bos.close ();
            }
            catch (Exception e) {
            }
        }
    }
}

getCorrectCameraOrientation

    public static int getCorrectCameraOrientation (Activity activity, Camera.CameraInfo info) {

    int rotation = activity.getWindowManager ().getDefaultDisplay ().getRotation ();
    int degrees = 0;

    if (hasValidRotation (rotation)) {
        degrees = rotation * 90;
    }

    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (info.orientation + degrees) % 360;
        result = (360 - result) % 360;
    }
    else {
        result = (info.orientation - degrees + 360) % 360;
    }

    return result;
}


回答2:

Reason of problem: By default maximum devices return an image with 90 degree default orientation while using camera api 1. I am not sure about this in case of using camera api 2. But in case of Nexus 5x and some rare device (using camera api 1) , It return image with 270 degree default rotation which is an exceptional case on some specific model device. SO you have to add an addition rotation of 180 degree for Nexus 5X. Please check printing the log of image orientation of Nexus 5X.