Android 相机 API ISO 设置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2978095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 08:09:10  来源:igfitidea点击:

Android Camera API ISO Setting?

androidcameraiso

提问by ee3509

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.

有谁知道在 Android SDK 中从哪里控制相机的 ISO 设置?这应该是可能的,因为 HTC Desire 上的原生相机应用程序具有 ISO 设置。

回答by szia

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.

你应该看看方法flatten(), unflatten(), get(String key), set(String key, String value)in android.hardware.Camera.Parameters。还要考虑那个类源代码。这可能会让事情变得更清楚。

First you need to obtain the Camera.Parameters. Unflatten it to a Stringand investigate it. I am developing on a HTC Desire as well an get the following String:

首先,您需要获取Camera.Parameters. 将其展开为 aString并进行调查。我正在 HTC Desire 上开发,并得到以下内容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-valuesto retrieve the supported values and a key isowhich holds the current value.

所以基本上有一个键被调用iso-values来检索支持的值和一个iso保存当前值的键。

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.

参考未展平的参数,我假设iso和曝光补偿设置之间存在差异。

回答by j.c

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:

到目前为止(KK 4.4.2)android 没有官方 API 来管理 ISO。
ISO 管理完全取决于设备,到目前为止我测试的 8/18 设备根本不支持 ISO 设置。
调查Camera.getParameters().flatten()字符串检查有效关键字,每个设备可以使用不同的关键字!!
大多数设备使用“iso-values”关键字来定义逗号分隔的可能值列表以与“iso”关键字一起使用,如下所示:

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).

其他一些设备使用“iso-mode-values”和“iso”关键字(Galaxy Nexus)。
我还发现了一个使用“iso-speed-values”和“iso-speed”的设备(Micromax A101)。
另一个让我伤心的是“nv-picture-iso-values”->“nv-picture-iso”(LG双P990)。

Follow sziaanswer on how to use these keywords.

按照sziaanswer 了解如何使用这些关键字。

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
}

回答by Zdravko Donev

since I had the same problem of finding if the device has an ISOparameter I looked at this answer https://stackoverflow.com/a/23567103/3976589and 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 isoand values(sometimes only those words, sometimes something additional).

因为我在查找设备是否有ISO参数时遇到了同样的问题,所以我查看了这个答案https://stackoverflow.com/a/23567103/3976589并看到 @jc 通过列出一些参数解决了 8/18 设备的问题他在不同的设备上发现的。根据该列表,我发现每个参数都包含单词isovalues有时只有这些单词,有时还有其他内容)。

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 ISOparameter, if it exists. Furthermore if the parameter exists I can take the supported ISOvalues and if I want to set one of those values i.e. change the camera parameter, I can just remove the -valuesat the end of the iso-valuesparameter and then I can change the ISOvalue successfully.

因此,如果我列出所有相机参数并搜索包含这两个词的字符串,我将知道ISO参数的名称是什么(如果存在)。此外,如果参数存在,我可以采用支持的ISO值,如果我想设置这些值之一,即更改相机参数,我可以删除参数-values末尾的iso-values,然后我可以ISO成功更改值。

I will now share my code for this task. First a snippet that retrieves a list with supported ISOvalues.

我现在将分享我的这个任务的代码。首先是检索具有支持ISO值的列表的片段。

    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 ISOvalues. In my application I needed to pick the lowest ISO. Here is my solution:

此代码段仅列出了支持的ISO值。在我的应用程序中,我需要选择最低的 ISO。这是我的解决方案:

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 myComparatoris 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:

myComparator是一个比较两个字符串并按降序对数组进行排序的类。所有字母词都在开头,所有数字都在结尾。这是我的实现:

// 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

干杯! @ee3509

回答by tmanthey

szias answer is correct.

szias 的回答是正确的。

Only

仅有的

String supportedIsoValues = camParams.get("iso-values"); 

returns null on some devices.

在某些设备上返回 null。

Nevertheless you can set the iso by

不过你可以通过设置iso

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

我不知道所有设备都支持“800”还是“1600”

you can check what you did by

你可以检查你做了什么

String newVAlue = camParams.get("iso");

回答by Charles Merriam

Forgive my ignorance, but how is this different from "exposure compensation" set via setExposureCompensation()? Wikipediahas some of the conversion formulas you might find useful.

请原谅我的无知,但这与通过 setExposureCompensation() 设置的“曝光补偿”有何不同? 维基百科有一些您可能会觉得有用的转换公式。