Android Camera API ISO Setting

https://stackoverflow.com/questions/2978095/android-camera-api-iso-setting

exif this.mCameraParameter.get("cur-iso");

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.

shareimprove this answer
 
    
parameters.get("iso-values") returns NULL on a HTC Desire. Any other ideas? – radhoo Oct 5 '11 at 11:22
    
@radhoo Desire should support ISO. See my answer below to retrieve a list of valid ISO values (and the keywords) from camera.parameters.flatten(). – j.c May 9 '14 at 14:38

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
}
shareimprove this answer
 
    
Shouldn't iso_keyword be "iso-mode" instead of "iso" for google galaxy nexus keywords? – Fatih Ozcan Jun 21 at 6:39

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<String> {

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

shareimprove this answer
 

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");
shareimprove this answer
 
    
For reference, on my two phones (both samsung models), the acceptable values are prefixed "ISO", and 800 is available on one but not both while neither support 1600. – Jules Feb 28 '14 at 15:19

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.

shareimprove this answer
 
    
I am not entirely sure if the exposure setting would achieve the same results with the iso setting, it could be possible. However the desire is running 2.1 and the setExposureCompensation is available to API level 8 which is 2.2 So there must be another way in 2.1 to do it. Thanks for your answer – ee3509 Jun 4 '10 at 23:20
原文地址:https://www.cnblogs.com/jukan/p/7171490.html