Android full screen camera - while keeping the camera selected ratio
Asked Answered
Z

2

6

We are trying to build something similar to Instagram Camera screen. i.e allow the user taking square photos. While doing it out U.i must be able to let the user see the camera on fullScreen mode. We want to force the user to take an image in a portrait mode

Getting camera possible ratio's

We are calculating the best ratio available from camera by

   private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) h / w;

    if (sizes == null) {
        return null;
    }

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    for (Camera.Size size : sizes) {
        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);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

Make it full screen.

public FrameLayout setCameraLayout(int width, int height) {
     float newProportion = (float) width / (float) height;
     // Get the width of the screen
     int screenWidth =     this.customCameraActivity.getWindowManager().getDefaultDisplay()
            .getWidth();
     int screenHeight =    this.customCameraActivity.getWindowManager().getDefaultDisplay()
            .getHeight();
      float screenProportion = (float) screenWidth / (float) screenHeight;
      // Get the SurfaceView layout parameters
      ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)preview.getLayoutParams();
    

     if (newProportion > screenProportion) {
        lp.width = screenWidth;
        lp.height = (int) ((float) screenWidth / newProportion);
     } else {
        lp.width = (int) (newProportion * (float) screenHeight);
        lp.height = screenHeight;
    }
   
    //calculate the amount that takes to make it full screen (in the `height` parameter)
    float propHeight = screenHeight / lp.height;
   
    //make it full screen(
    lp.width = (int)(lp.width * propHeight);
    lp.height = (int)(lp.height * propHeight);

    frameLayout.setLayoutParams(lp);
    return frameLayout;

}

setCameraLayout callers

OnCreate from the Activity and afterwards surfaceChanged

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
                           int height) {
    if (getHolder().getSurface() == null) {
        return;
    }
    try {
        cameraManager.getCamera().stopPreview();
    } catch (Exception e) {
        // tried to stop a non-existent preview
    }

    try {
        Camera.Parameters cameraSettings = cameraManager.getCamera().getParameters();

        cameraSettings.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        this.cameraView.setCameraLayout(mPreviewSize.width, mPreviewSize.height);
        cameraManager.getCamera().setParameters(cameraSettings);
        cameraManager.getCamera().setPreviewDisplay(holder);

        cameraManager.getCamera().startPreview();
    } catch (Exception e) {
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}

Goal

Fullscreen camera preview on phone.

The problem

Now we are getting the preview with no distortion which is GOOD! and it has the same height as the phone as well which is also GOOD!. But! the width of the preview is bigger than the phone width (of-course) so it turns out the the center of the camera is not on the center of the phone. Possible solutions we have thought about:

  1. move the layout left to negative position to make the preview center in the center of the screen.
  2. crop the layout and draw only the center of the new preview that should be visible to the phone screens

Any ideas how to overcome this issue?

Zeller answered 30/3, 2015 at 17:23 Comment(4)
Hi, any chance you could share your whole code please? I'm stuck with the same issue :/ Thank youParch
Hey, you may check this blog post. shakedos.com/2015/Aug/26/… The code is not up to date but should solves your issueZeller
thanks. is that yours?Parch
Its Shaked's blog. He did some work for us regarding to this issue.Zeller
L
7

I managed successfully center the preview by setting gravity of SurfaceView:

FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(wid, hei);
lp.gravity = Gravity.CENTER;
mSv.setLayoutParams(lp);

The code snippet is taken from here, and you're welcome to use the code if you have the patience to decipher it. I think I was solving similar issues (preview rotation, distortion, fit-in/fill)

Good Luck.

Lent answered 5/4, 2015 at 18:48 Comment(3)
That GitHub piece tries to solve the particular problem I had, so it may not fit your situation 100%, but the idea is related, Look at 'readme.md' here: github.com/seanpjanson/AndyCam if you can use some ideas from there.Lent
We have checked this. It works! the question is how to convert screen coordinates into camera coordinate is till open. maybe you have some idea about that as well?Zeller
When I worked with it (a long time ago) I did not use coordinates, basically just two rectangles: the preview (wid/hei values in CamVw.surfaceChanged) and the rectangle whose wid/hei comes back from Camera.Size prvwSz() method. Assuming you always center one into another, the only problem I was solving was if my preview would fit-in (black stripes on sides) or fill screen aka pan&scan, basically full screen is filled and portion of preview 'overflows'.Lent
S
1

If I'm understanding from the code snippets, you are re-instantiating the camera everytime the user changes orientation or rotates the camera. Is there any reason to do that?

Why not restrict the preview to portrait only and have an overlaying view that rotates? I am pretty sure that is what others (Instagram,Snapchat, etc.) do. I will edit with an example of this, if I can find it.

Seeing answered 7/4, 2015 at 20:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.