I have extended a SurfaceView for displaying the camera feed for a very simple camera application. To find the optimal preview size for each device, I used this sample code which is used in almost all the open source camera apps I have seen:
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.width - width) < minDiff) {
screenWidth = size.width;
screenHeight = size.height;
minDiff = Math.abs(size.width - width);
}
}
Everything works perfectly up to this point.
Now, due to the nature of the application, I have to keep two bitmaps in the memory during the course of a session and for the sake of simplicity(avoiding memory issues during testing) I used the same code for the PICTURE SIZE(replaced the getSupportedPreviewSizes() with getSupportedPictureSizes()). Everything works great on most of the devices though I have to decide some other way to choose the optimum picture size for each device.
Recently, while testing on an Nexus 4 device, this above loop failed in choosing the optimum picture size. Upon investigation, I found out that the getSupportedPictureSizes() functions returns a value i.e 1280*960 which is not actually supported by the Nexus 4 camera. So, how does one solve this issue? I mean, isn't this function supposed to ONLY return those values which the CAMERA of the device supports? I am sure there will be other devices with the same issue which I won't be able to test on. Any clues as to how this issue should be resolved?
UPDATE:
Whats happening is that it accepts the wrong parameter without any error and the image that it returns is distorted, I will try to get a picture here as well. Also, there are no runtime exceptions.
I have the same problem on an LG Lucid (model number VS840 4G). Basically, getSupportedPictureSizes()
returns these sizes:
Size Aspect Ratio
2560x1920 (1.3333333333333333)
3072x1728 (1.7777777777777777)
2048x1536 (1.3333333333333333)
2304x1296 (1.7777777777777777)
1536x864 (1.7777777777777777)
1280x960 (1.3333333333333333)
640x480 (1.3333333333333333)
If we call setPictureSize()
with any of the sizes with a 1.7 aspect ratio, the camera hardware throws no errors, but it returns an image that is distorted:
I tried a number of techniques to get the camera driver to admit this size was not really supported, including checking the result of getPictureSize()
and getSupportedPictureFormats()
after calling setParameters()
. I couldn't find anything that gave away this behavior.
To work around this, we now mimic the behavior of the stock Camera app: we attempt to find a "preferred" size from the getSupportedPictureSizes()
list before falling back to selecting the largest (as computed by width * height). Since the preferred sizes all have an aspect ratio of 1.333 (4:3), this works around the issue on this device.
See the Camera app source where it sets the value (line 111) and the hardcoded sizes it prefers (line 63) for the exact implementation.
I believe 1280x960 picture is supported by the secondary, face camera on Nexus 4. I don't know why the device reports "mixed" sizes, usually each camera answers for itself.
I can confirm that there are some devices that lie about their camera capabilities, though I have more experience with preview sizes than picture sizes.
When you choose a wrong size, different things may happen. Sometimes, you will get a RuntimeException on camera.setParameters()
if you choose an unsupported size. Sometimes, the device will silently accept the parameters, but if you ask getParameters()
after that, you will find the picture size did not change, or is not what you asked. Some devices lie even further: they pretend to set the required size, but the actual output is different. E.g. Galaxy Nexus pretends to support 320x240 video, but the buffers you get in the preview callback are of size 640x480.
Another "nice" feature of Nexus 4 is that it is, apparently, sensitive to android.camera.front
feature (see Frontal Camera Image Distortion)
I have reproduced your logic with a Nexus 4 v.4.2.2 (JDQ39); there is no problem with picture size 1280x960 either camera. Note that the picture orientation is not exactly what one could expect, but your question does not mention fiddling with camera orientation.
what's actually up there,
BUT, summed up:
thanks Google!
- some devices support 1.33
- some devices support 1.77
in my test scenario, a Nexus 4 with 4.3 and another one with 4.4 both are NOT supporting 1.33, BUT 1.77 ...
i cannot say how many devices are out there, or which is actually the unsupported type (above it's mentioned different way) .. so basically only option.
let the user decide. if there are problems -> offer an option to change aspect ratio.
i did it this way now.
hope this helps someone -> good luck :)