Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zxing Camera in Portrait mode on Android

I want to show portrait orientation on Zxing's camera.

How can this be done?

like image 667
Roy Lee Avatar asked Apr 27 '13 13:04

Roy Lee


4 Answers

Here's how it works.

Step 1: Add following lines to rotate data before buildLuminanceSource(..) in decode(byte[] data, int width, int height)

DecodeHandler.java:

byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++)
        rotatedData[x * height + height - y - 1] = data[x + y * width];
}
int tmp = width;
width = height;
height = tmp;

PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(rotatedData, width, height);

Step 2: Modify getFramingRectInPreview().

CameraManager.java

rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;

Step 3: Disable the check for Landscape Mode in initFromCameraParameters(...)

CameraConfigurationManager.java

//remove the following
if (width < height) {
  Log.i(TAG, "Display reports portrait orientation; assuming this is incorrect");
  int temp = width;
  width = height;
  height = temp;
}

Step 4: Add following line to rotate camera insetDesiredCameraParameters(...)

CameraConfigurationManager.java

camera.setDisplayOrientation(90);

Step 5: Do not forget to set orientation of activity to portrait. I.e: manifest

like image 175
Roy Lee Avatar answered Oct 14 '22 00:10

Roy Lee


To support all orientation and change automatically when rotating the activity do this, all you have to modify is the CameraManager.javaclass.

And remove this method getCurrentOrientation() from CaptureActivity.java

In CameraManager.java Create this variable:

int resultOrientation;

Add this to the openDriver(..) method:

setCameraDisplayOrientation(context, Camera.CameraInfo.CAMERA_FACING_BACK, theCamera);//this can be set after camera.setPreviewDisplay(); in api13+.

****Create this method**** Link: http://developer.android.com/reference/android/hardware/Camera.html

public static void setCameraDisplayOrientation(Context context,int cameraId, android.hardware.Camera camera) {
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
    android.hardware.Camera.getCameraInfo(cameraId, info);
    Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
    int degrees = 0;
    switch (display.getRotation()) {
    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;
    }


    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        resultOrientation = (info.orientation + degrees) % 360;
        resultOrientation = (360 - resultOrientation) % 360;  // compensate the mirror
    } else {  // back-facing
        resultOrientation = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(resultOrientation);
}

****Now modify getFramingRectInPreview()****

if(resultOrientation == 180 || resultOrientation == 0){//to work with landScape and reverse landScape
            rect.left = rect.left * cameraResolution.x / screenResolution.x;
            rect.right = rect.right * cameraResolution.x / screenResolution.x;
            rect.top = rect.top * cameraResolution.y / screenResolution.y;
            rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
        }else{
            rect.left = rect.left * cameraResolution.y / screenResolution.x;
            rect.right = rect.right * cameraResolution.y / screenResolution.x;
            rect.top = rect.top * cameraResolution.x / screenResolution.y;
            rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
        }

And modify this method public PlanarYUVLuminanceSource buildLuminanceSource(..)

if(resultOrientation == 180 || resultOrientation == 0){//TODO: This is to use camera in landScape mode
        // Go ahead and assume it's YUV rather than die.
        return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top, rect.width(), rect.height(), false);
    }else{
        byte[] rotatedData = new byte[data.length];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++)
                rotatedData[x * height + height - y - 1] = data[x + y * width];
        }
        int tmp = width;
        width = height;
        height = tmp;
        return new PlanarYUVLuminanceSource(rotatedData, width, height, rect.left, rect.top, rect.width(), rect.height(), false);
    }
like image 22
Rensodarwin Avatar answered Oct 14 '22 00:10

Rensodarwin


You can use my fork of zxlib https://github.com/rusfearuth/zxing-lib-without-landscape-only. I disabled landscape mode only. You can set landscape/portrait and see correct camera view.

like image 5
Rusfearuth Avatar answered Oct 13 '22 22:10

Rusfearuth


Adding camera.setDisplayOrientation(90); in CameraConfigurationManager.java worked for me.

like image 3
Samit Dawane Avatar answered Oct 14 '22 00:10

Samit Dawane