Would anyone know where to control the ISO setting for the camera from in the Android SDK ? It should be possible as the native camera application on the HTC Desire has ISO settings.
问题:
回答1:
you should take a look at the methods flatten()
, unflatten()
, get(String key)
, set(String key, String value)
in android.hardware.Camera.Parameters
. Also consider the source code of that class. It might make things clearer.
First you need to obtain the Camera.Parameters
. Unflatten it to a String
and investigate it. I am developing on a HTC Desire as well an get the following String
:
sharpness-max=30;zoom=0;taking-picture-zoom=0;zoom-supported=true;sharpness-min=0;sharpness=10;contrast=5;whitebalance=auto;jpeg-quality=100;preview-format-values=yuv420sp;jpeg-thumbnail-quality=75;preview-format=yuv420sp;preview-size=640x480;focal-length=3.53;iso=auto;meter-mode=meter-center;front-camera-mode=mirror;flash-mode-values=off,auto,on,torch;preview-frame-rate-values=15;preview-frame-rate=15;focus-mode-values=auto,infinity;jpeg-thumbnail-width=640;jpeg-thumbnail-size-values=640x480,512x384,384x288,0x0;zoom-ratios=100,114,131,151,174,200;saturation-def=5;preview-size-values=1280x720,800x480,768x432,720x480,640x480,576x432,480x320,400x240,384x288,352x288,320x240,272x272,240x240,240x160,176x144,160x120;smart-contrast=off;picture-size-values=2592x1952,2592x1456,2592x1936,2592x1728,2592x1552,2048x1536,2048x1360,2048x1216,2048x1152,1600x1200,1584x1056,1280x960,1280x848,1280x768,1280x720,1024x768,640x480,640x416,640x384,640x368,512x384,400x400,272x272;contrast-min=0;min-exposure-compensation=-4;brightness-min=0;antibanding=auto;taking-picture-zoom-min=0;saturation-min=1;contrast-max=10;vertical-view-angle=42.5;taking-picture-zoom-max=21;contrast-def=5;brightness-max=6;horizontal-view-angle=54.8;brightness=3;jpeg-thumbnail-height=480;cam-mode=0;focus-mode=auto;sharpness-def=10;front-camera-mode-values=mirror,reverse;picture-format-values=jpeg;saturation-max=10;max-exposure-compensation=4;exposure-compensation=0;exposure-compensation-step=0.5;flash-mode=off;effect-values=none,mono,negative,solarize,sepia,posterize,aqua;meter-mode-values=meter-average,meter-center,meter-spot;picture-size=2592x1952;max-zoom=5;effect=none;saturation=5;whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight;picture-format=jpeg;brightness-def=3;iso-values=auto,deblur,100,200,400,800,1250;enable-caf=off;antibanding-values=off,50hz,60hz,auto
So basically there is a key called iso-values
to retrieve the supported values and a key iso
which holds the current value.
You can do the following:
Camera cam = Camera.open(); Camera.Parameters camParams = cam.getParameters(); String supportedIsoValues = camParams.get("iso-values"); //supported values, comma separated String camParams.set("iso", (String)newValue); cam.setParameters(camParams);
And with reference to the unflattened parameters I would assume that there is a difference between the iso and exposure compensation settings.
回答2:
By now (KK 4.4.2) android has no official APIs to manage ISO.
ISO management is a totally device dependant matter, and 8/18 devices i tested so far doesn't support ISO settings at all.
Investigate Camera.getParameters().flatten()
String to check valid keywords, every device can use different keywords!!
Most devices use "iso-values" keyword to define a comma separated list-of-possible-values to use with "iso" keyword, like this:
param.set("iso", valid_value_from_list);
Some other devices uses "iso-mode-values" and "iso" keywords (Galaxy Nexus).
I found also a device that uses "iso-speed-values" and "iso-speed" (Micromax A101).
Another one that make me sad is "nv-picture-iso-values" -> "nv-picture-iso" (LG dual P990).
Follow szia answer on how to use these keywords.
Here's some code i use to get a list of valid values using known keywords:
String flat = param.flatten(); String[] isoValues = null; String values_keyword=null; String iso_keyword=null; if(flat.contains("iso-values")) { // most used keywords values_keyword="iso-values"; iso_keyword="iso"; } else if(flat.contains("iso-mode-values")) { // google galaxy nexus keywords values_keyword="iso-mode-values"; iso_keyword="iso"; } else if(flat.contains("iso-speed-values")) { // micromax a101 keywords values_keyword="iso-speed-values"; iso_keyword="iso-speed"; } else if(flat.contains("nv-picture-iso-values")) { // LG dual p990 keywords values_keyword="nv-picture-iso-values"; iso_keyword="nv-picture-iso"; } // add other eventual keywords here... if(iso_keyword!=null) { // flatten contains the iso key!! String iso = flat.substring(flat.indexOf(values_keyword)); iso = iso.substring(iso.indexOf("=")+1); if(iso.contains(";")) iso = iso.substring(0, iso.indexOf(";")); isoValues = iso.split(","); } else { // iso not supported in a known way }
回答3:
szias answer is correct.
Only
String supportedIsoValues = camParams.get("iso-values");
returns null on some devices.
Nevertheless you can set the iso by
Camera cam = Camera.open(); Camera.Parameters camParams = cam.getParameters(); camParams.set("iso", "400"); // values can be "auto", "100", "200", "400", "800", "1600" cam.setParameters(camParams);
I do not know whether "800" or "1600" is supported on all devices
you can check what you did by
String newVAlue = camParams.get("iso");
回答4:
since I had the same problem of finding if the device has an ISO
parameter I looked at this answer https://stackoverflow.com/a/23567103/3976589 and saw that @j.c had solved the problem for 8/18 devices by listing some parameters that he had found on different devices. Based on that listing I found that each paramter contains the words iso
and values
(sometimes only those words, sometimes something additional).
So if I list all of the camera parameters and search for a strings that contain both words I will know what is the name of the ISO
parameter, if it exists. Furthermore if the parameter exists I can take the supported ISO
values and if I want to set one of those values i.e. change the camera parameter, I can just remove the -values
at the end of the iso-values
parameter and then I can change the ISO
value successfully.
I will now share my code for this task. First a snippet that retrieves a list with supported ISO
values.
private String ISOValuesParameter = null; private String ISOParameter = null; private String ISOValues = null; private void initCamera() { Camera mCamera = Camera.open(); // this will list supported values String ISOvalues = getISOValues(); textViewISO = (TextView) findViewById(R.id.viewISO); textViewISO.setText(ISOvalues); // setting Minimum ISO value if(ISOValuesParameter != null) { Camera.Parameters params = mCamera.getParameters(); ISOParameter = ISOValuesParameter.replace("-values", ""); params.set(ISOParameter, getMinISO()); mCamera.setParameters(params); // get the updated ISO value params = mCamera.getParameters(); String ISO = params.get(ISOParameter); Toast.makeText(this,"ISO set to: " + ISO, Toast.LENGTH_SHORT).show(); } } // returns a list with supported ISO values private String getISOValues() { ISOValuesParamter = getISOValuesParameter(); Camera.Parameters params = mCamera.getParameters(); ISOValues = params.get(ISOValuesParamter); return ISOValues!=null ? ISOValues : "ISO not supported"; } // this will return the name of the ISO parameter containing supported ISO values private String getISOValuesParameter() { Camera.Parameters params = mCamera.getParameters(); String flatten = params.flatten(); String[] paramsSeparated = flatten.split(";"); for(String cur : paramsSeparated) { if(cur.contains("iso") && cur.contains("values")) { return cur.substring(0,cur.indexOf('=')); } } return null; }
This snippet only lists the supported ISO
values. In my application I needed to pick the lowest ISO. Here is my solution:
private String getMinISO() { if(ISOValues == null) { return null; } String[] ISOarray = ISOValues.split(","); Arrays.sort(ISOarray, myComparator); String minISO = ISOarray[ISOarray.length-1]; return minISO; }
Here myComparator
is a class that compares two strings and sorts the array in descending order. All alphabet words are at the beginning and all numbers are at the end. Here is my implementation:
// Singelton class public class MyComparator implements Comparator { private static MyComparator myComparator = null; private MyComparator() {} @Override public int compare(String a, String b) { return compareString(a,b); } public static int compareString(String a, String b) { if (a.length() > b.length()) return -1; if (a.length() == b.length()) { if (a.compareTo(b) > 0) return -1; else if (a.compareTo(b) == 0) return 0; } return 1; } public static synchronized MyComparator getInstance() { if(myComparator==null) { myComparator = new MyComparator(); } return myComparator; } }
I hope my answer helps other people. :)
Cheers! @ee3509
回答5:
Forgive my ignorance, but how is this different from "exposure compensation" set via setExposureCompensation()? Wikipedia has some of the conversion formulas you might find useful.