Camera in Android, how to get best size, preview size, picture size, view size, image distorted
Asked Answered
P

4

20

having image distorted when mixing a view from OpenGL and the Android camera to get an image of both when using the takepicture method. I checked and found that the camera picture was set to 640X480 and the openGL view and the camera preview was both set to 1280x720.

so I set the camera picture size to 1280x720 and the result was perfect. however I can't set the size in code because each Android device will be different and every device the settings for both preview size and picture size have to be selected from a list of supported sizes.

what is the best way to do this considering that there are three variables here, the screen size of the activity layout, the camera preview size, and the picture size.

is it best to use a match_parent or fitXY for the FrameLayout size and only work with two variables, the preview size and picture size?

notice that several of the width and height combinations in preview sizes and picture sizes are the same. for example 1280 x 720 exists in both preview and picture, is it always the case that there will be matches in both sizes?

 List<Size> previewSizes = mCamera.getParameters().getSupportedPreviewSizes();

 List<Size> imageSizes = mCamera.getParameters().getSupportedPictureSizes();

 // layout in the activity that the cameraView will placed in
 int layoutWidth = frameLayout.getWidth();
 int layoutHeight = frameLayout.getHeight();

for example in one Android tablet after measurement these are the results for the 3 variables used

size of layout viewGroup in activity as result of measurement

 1280 x 736

supported picture sizes

 320 x 240
 640 x 480
 1024 x 768
 1280 x 720 << best size in my example to use
 1280 x 768
 1280 x 920
 1600 x 1200
 2048 x 1536
 2560 x 1440
 2560 x 1536
 2560 x 1920  << native resolution of hardware camera

supported preview sizes

 176 x 144
 320 x 240
 352 x 288
 480 x 320
 480 x 368
 640 x 480
 800 x 480
 800 x 600
 864 x 480
 864 x 576
 960 x 540
 1280 x 720 << best size in my example to use
 1280 x 768
 1280 x 960
Petulant answered 10/2, 2014 at 2:59 Comment(2)
Would this generate a "Not bound to a valid camera" error?Epsomite
How was mCamera constructed?Epsomite
O
19

Most often, but not always, there is correspondence between picture aspect ratios and preview aspect ratios. You can be assured that at least some of them are classic 4:3 ratios (e.g. 640x480). Support for 16:9 is also widely available.

The screen may have different aspect ratio. To fill it with a camera image correctly, it is widely accepted to add black margins (same approach is used in YouTube). Alternatively, you may crop the camera image to fill the whole screen.

Note that the screen size (as reported in tech specs for the variety of devices) is not always actually available for your image display. For example, the system menus, and title bar, etc. may take their share of the screen real estate. The immersive mode is available on some devices, and its behavior depends on the system version. You may expect that future developments of Android, e.g. second screen support, will make the game even more interesting.

So, the answers to your specific questions:

is it best to use a match_parent or fitXY for the FrameLayout size and only work with two variables, the preview size and picture size? - no.

is it always the case that there will be matches in both sizes? - yes, but maybe this size is not optimal.

Even if your camera supports different "wide" picture sizes, 1280x720 preview and 2560x1440 picture may be the best match, both precisely at 16:9. Usually, the quality of picture at small size is not significantly better than preview at that same size, so you may choose to save the preview frame if 1280x720 is what you really need.

If you can forgo takePicture(), your app will be much more responsive.

Otter answered 10/2, 2014 at 11:45 Comment(0)
D
4

I think the best way to get preview size, picture size is the Camera was set up to support all Android devices. It means the preview size, picture size you decide to set up is appropriate with the popular format that All Devices supported, ex. is 1280x720 etc.

As in following codes, is the ex. what I used.

// start preview with new settings
    try {
        // set preview size and make any resize, rotate or
        // reformatting changes here
        Camera.Parameters parameters = mCamera.getParameters();

        for (Camera.Size size : parameters.getSupportedPictureSizes()) {
            // 640 480
            // 960 720
            // 1024 768
            // 1280 720
            // 1600 1200
            // 2560 1920
            // 3264 2448
            // 2048 1536
            // 3264 1836
            // 2048 1152
            // 3264 2176
            if (1600 <= size.width & size.width <= 1920) {
                parameters.setPreviewSize(size.width, size.height);
                parameters.setPictureSize(size.width, size.height);
                break;
            }
        }
        // Set parameters for camera
        CustomCamera.mCamera.setParameters(parameters);

        Camera.Size size = CustomCamera.mCamera.getParameters().getPictureSize();

        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e) {
        e.printStackTrace();
    }

Best size depend on Camera MP. So I think should use default if using Camera.

Deepseated answered 1/7, 2015 at 3:48 Comment(3)
Hi dude, Ur code worked but, inside the if condition i have to use other way around if (size.width <= 800) {Thorathoracic
Hi it working fine but when i use this image size in the preview and result are different . It gave more image that i captured.Frankforter
.getSupportedPictureSizes() and .getSupportedPreviewSizes() can be different (most often they are)Wilkison
R
2

Possible algorithm:

1) get output area aspect ratio (=width/height)

2) iterate through supported sizes:

Choose biggest one with close aspect ratio(+-5%, for example) If nothing close or resolution too low - just make yor surface(that you draw frames to) be same aspect ratio as biggest supported size and center it in parent view

Howewer, there are preview sizes & picture sizes. If you wish them to have same aspect ratio - then better choice is to use selected picture size aspect ratio in 1) This way you'll probably have to center your surface in parent view

Hope that helps)

Rhianna answered 10/2, 2014 at 4:32 Comment(6)
what do you mean by this? ratio (=width/height) 2) Unseat
Aspect ratio = width/height. What's not obvious?Rhianna
I got lost at your '2)' you are just enumerating your point. ;)Unseat
"choose the biggest one" is now no longer always advisable as this can easily produce 15 Megapixel images which is overkill for most applications.Falstaffian
@Falstaffian depends on definition of 'best size'Rhianna
im facing blank screen if i choose higher preview and picture quality from listInnutrition
S
0

I had the same issue and I found this excellent solution here: http://www.java2s.com/example/android/camera/get-optimal-preview-size-by-width-and-height.html

I just had to handle camera landscape by swapping width and height before calling this function:

public static Camera.Size getOptimalPreviewSize(
        List<Camera.Size> sizes, int w, int h) {
    // Use a very small tolerance because we want an exact match.
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null)
        return null;

    Camera.Size optimalSize = null;/*  w  w  w  .ja va  2 s .c  om*/

    // Start with max value and refine as we iterate over available preview sizes. This is the
    // minimum difference between view and camera height.
    double minDiff = Double.MAX_VALUE;

    // Target view height
    int targetHeight = h;

    // Try to find a preview size that matches aspect ratio and the target view size.
    // Iterate over all available sizes and pick the largest size that can fit in the view and
    // still maintain the aspect ratio.
    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);
        }
    }

    // Cannot find preview size that matches the aspect ratio, ignore the requirement
    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;
}

...
// get optional sizes list
...

    if (SensorOrientation == 90 || SensorOrientation == 270) {
        // SWAP
        int tmp = mwidth;
        mwidth = mheight;
        mheight = tmp;
    }

    return getOptimalPreviewSize(sizes, mheight, mwidth);
Seve answered 1/7, 2021 at 10:46 Comment(1)
How are height and width chosen for this one?Kizzykjersti

© 2022 - 2024 — McMap. All rights reserved.