5

I am making a Camera app in Android and have used the following function to get the preview size:

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

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

    int targetHeight = h;

    // Try to find an size match aspect ratio and size
    for (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 the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

And I set the size like this:

Size s = getOptimalPreviewSize(parameters.getSupportedPreviewSizes(), w, h);
parameters.setPreviewSize(s.width, s.height);

But the problem is that when I run my app, the camera preview quality is really poor. How do i get the same preview quality as I get when I run my default camera app on my phone, in other words, I want a high resolution Camera preview in my app.

I am even not sure whether the preview size is the cause of this problem.

NOTE: The function to get the preview size is taken from sample programs from Android Docs.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
Ram Patra
  • 16,266
  • 13
  • 66
  • 81

1 Answers1

11

That algorithm is not the greatest.

The default algorithm in my CWAC-Camera library is now:

  public static Camera.Size getBestAspectPreviewSize(int displayOrientation,
                                                     int width,
                                                     int height,
                                                     Camera.Parameters parameters,
                                                     double closeEnough) {
    double targetRatio=(double)width / height;
    Camera.Size optimalSize=null;
    double minDiff=Double.MAX_VALUE;

    if (displayOrientation == 90 || displayOrientation == 270) {
      targetRatio=(double)height / width;
    }

    List<Size> sizes=parameters.getSupportedPreviewSizes();

    Collections.sort(sizes,
                     Collections.reverseOrder(new SizeComparator()));

    for (Size size : sizes) {
      double ratio=(double)size.width / size.height;

      if (Math.abs(ratio - targetRatio) < minDiff) {
        optimalSize=size;
        minDiff=Math.abs(ratio - targetRatio);
      }

      if (minDiff < closeEnough) {
        break;
      }
    }

    return(optimalSize);
  }

This:

  • Takes into account portrait versus landscape

  • Starts with the highest resolution previews and works its way down

  • Can be tailored via closeEnough to opt for higher resolution as opposed to best matching the aspect ratio of the preview area

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Do i need to use CWAC Camera Library to use this function? I am getting an error for SizeComparator when i tried using your function instead of mine directly without including your library? – Ram Patra Jan 25 '14 at 18:49
  • @Ramswaroop: No, you are welcome to copy that into your own project. – CommonsWare Jan 25 '14 at 18:50
  • I am getting an error "SizeComparator() cannot be resolved to a type", How do I resolve this? – Ram Patra Jan 26 '14 at 05:26
  • 2
    It's defined later in the same file. Copy the whole class in, not just the function shown in the answer (https://github.com/commonsguy/cwac-camera/blob/master/camera/src/com/commonsware/cwac/camera/CameraUtils.java). – fadden Jan 26 '14 at 17:04
  • @Ramswaroop: Oh, sorry about that. As fadden points out, it is defined at the bottom of the `CameraUtils` class he linked to. – CommonsWare Jan 26 '14 at 17:29
  • I used the function but no luck, i am still not getting a clear preview, what to do, shall i submit you my code? – Ram Patra Jan 30 '14 at 19:03
  • @Ramswaroop: First, determine what resolution you are getting for the previews. If the resolution is sufficiently high, and the preview is not "clear" by your standards, I do not know what to tell you. If, however, your resolution is coming out very low, perhaps try a higher value for `closeEnough`, or otherwise determine why the algorithm is not choosing a higher resolution. – CommonsWare Jan 30 '14 at 19:06
  • I tried with `closeEnough` value as `0.0d`, can you suggest a more appropriate value. – Ram Patra Jan 31 '14 at 07:12
  • @Ramswaroop: Something that gives you the results that you want. Or, come up with your own algorithm. There is nothing magic about mine. It just does a few things better than the one whose code you started with. – CommonsWare Jan 31 '14 at 13:01
  • I used your library and am getting preview dimension as `width:1280, height:720` and picture dimension as `width:3264, height:2448` in both Portrait and Landscape mode. These dimensions are maximum among all, so i think the cause of the problem is something different, my preview quality is still poor, is there any way to set the bits per pixel on the surface or something which would improve the preview quality. Thanks for your time helping me. – Ram Patra Feb 01 '14 at 18:52
  • @Ramswaroop: I have no idea. – CommonsWare Feb 01 '14 at 18:55
  • it works well in back camera but it also has issue with front camera!! – Hardik Gajera Feb 14 '15 at 11:53