'How to set Exposure on Camera2 api

I want to set camera exposure.When camera starts i want to set higher values and when it stops it is set to lower value.So i used the below code.On emulator it is showing range of -9 to 9 but when i attached physical usb camera it is showing 0 value for lower range and higher range. I am trying to get exposure time range it is showing null also . Range exposure_time= cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);

 public  void setExposure(Context context, double exposureAdjustment)  {
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        try {
            camId = manager.getCameraIdList()[0];
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        try {
            cameraCharacteristics = manager.getCameraCharacteristics(camId);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }



        Range<Integer> range1 = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
              
        Log.d(TAG,"range1" +range1);

        Integer minExposure = range1.getLower();
        Log.d(TAG,"minExposure" +minExposure);

        Integer maxExposure = range1.getUpper();
        Log.d(TAG,"maxExposure" +maxExposure);
    
        if (minExposure != 0 || maxExposure != 0) {
            float newCalculatedValue = 0;
            if (exposureAdjustment >= 0) {
                newCalculatedValue = (float) (maxExposure * exposureAdjustment);


            } else {
           
                newCalculatedValue = (float) (minExposure  * exposureAdjustment);
            }

            if (requestBuilder != null) {
                CaptureRequest captureRequest = requestBuilder.build();
                try {
                    captureSession.setRepeatingRequest(captureRequest, captureCallback, null);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
               
                requestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, (int) newCalculatedValue);
                Log.d(TAG,"New Calculated VAlue "+newCalculatedValue);
                try {
                    captureSession.capture(captureRequest,captureCallback,null);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }


            }
        }
    }


Solution 1:[1]

First, you need to find out the available auto exposure modes. You can do this by :

final int[] availableAeModes = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES);
    for(int mode : availableAeModes){
      Timber.d("AE mode : %d",mode);
    }

The meaning of these integer values you can map here. You would only be able to control the exposure manually, if among the available ae modes, the value of CONTROL_AE_MODE_OFF is present.

Otherwise, you won't be able to control the exposure.

Now, I am assuming that the CONTROL_AE_MODE_OFF is an available mode on your camera.

You can control the exposure by manipulating these two parameters (there are some other parameters as well, through which you can control the exposure, however, these two have worked perfectly for me) :

  1. SENSOR_EXPOSURE_TIME
  2. SENSOR_SENSITIVITY

For setting SENSOR_SENSITIVITY, check the range supported by your camera by :

final Range<Integer>  isoRange = 

characteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
    if(null != isoRange) {
      Timber.d("iso range => lower : %d, higher : %d",isoRange.getLower(),isoRange.getUpper());
    } else {
      Timber.d("iso range => NULL NOT SUPPORTED");
    }

For setting SENSOR_EXPOSURE_TIME, check the range supported by your camera by:

   final Range<Long>  exposureTimeRange = characteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
    if(null!=exposureTimeRange){
      Timber.d("exposure time range => lower : %d, higher : %d",exposureTimeRange.getLower(),exposureTimeRange.getUpper());
    }else{
      Timber.d("exposure time range => NULL NOT SUPPORTED");
    }

Now, you have the range of both exposure time and sensitivity. The next step is to configure the preview with these values.

This is how you configure your preview :

final CaptureRequest.Builder previewRequest =
//it's important to set the manual template, because you want to change exposure manually

     this.cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_MANUAL);
      previewRequest.addTarget(this.previewReader.getSurface());
      previewRequest.set(JPEG_ORIENTATION, 0);
//setting ae mode to off state
      previewRequest.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
//we don't want to handle white balance manually, so set the white balance mode to auto
      previewRequest.set(CaptureRequest.CONTROL_AWB_MODE,
              CaptureRequest.CONTROL_AWB_MODE_AUTO);
//setting sensor sensitivity
        previewRequest.set(CaptureRequest.SENSOR_SENSITIVITY, <YOUR_SELECTED_SENSITIVITY>);
//setting sensor exposure time
previewRequest.set(CaptureRequest.SENSOR_EXPOSURE_TIME, <YOUR_SELECTED_EXPOSURE_TIME>);

      this.previewCaptureSession.setRepeatingRequest(previewRequest.build(),
              null, this.cameraHandler);

Note : You can see that I use the template as TEMPLATE_MANUAL. Once, the template is set to manual. All three auto processes, namely, auto-exposure, auto-white-balance and auto-focus, will become manual. The above code, doesn't take care of setting focus, since, I used it on a camera which didn't have auto-focus. If your camera has auto-focus, then you will have to handle setting the focus separately.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 shubham sharma