6

Since this hasn't clear answer, and stackoverflow hasn't questions / answers about Camera 2 API Gamma, I ask for solution to modify Brightness, Contrast and Gamma using Android Camera 2 API.
My code to get range and step:

Rational controlAECompensationStep = characteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP);
if (controlAECompensationStep != null) {
    compensationStep = controlAECompensationStep.doubleValue();
}

Range<Integer> controlAECompensationRange = characteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
if (controlAECompensationRange != null) {
    minCompensationRange = controlAECompensationRange.getLower();
    maxCompensationRange = controlAECompensationRange.getUpper();
}

My method to set Brightness in percents:

public void setBrightness(int value) {
    int brightness = (int) (minCompensationRange + (maxCompensationRange - minCompensationRange) * (value / 100f));
    previewRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, brightness);
    applySettings();
}
private void applySettings() {
    try {
        captureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

But this approach doesn't work correctly. Image becomes green, like here.


I described all what I found in documentation (demo .apk included).

Community
  • 1
  • 1
Volodymyr Kulyk
  • 6,201
  • 3
  • 34
  • 61
  • You can try Spectaculum, it works with Camera2 API: https://github.com/protyposis/Spectaculum?utm_source=android-arsenal.com&utm_medium=referral&utm_campaign=4529 – Umair Adil Mar 16 '17 at 12:09
  • @UmairAdil thank you for response. but it isn't what I actually want. – Volodymyr Kulyk Mar 16 '17 at 12:37
  • @VladimirKulyk I have gone through and installed the apk on Nexus 5x device and B+, B- works fine. No green color? – Anurag Singh Mar 21 '17 at 05:34
  • @AnuragSingh ok :D looks like I set `AutoWhiteBalance` to `false` if changing B, G or C manually. It makes my preview green. – Volodymyr Kulyk Mar 21 '17 at 08:07
  • Sorry I didn't get it. If you need to update apk, please do so? – Anurag Singh Mar 21 '17 at 09:13
  • @AnuragSingh this apk is my camera2 test application. I use functionality from it in my current project, where I set `CaptureRequest.CONTROL_AWB_MODE` `CaptureRequest.CONTROL_AWB_MODE_OFF`, than I modify B, G or C and get [green](https://www.dropbox.com/s/xelc71a72qkoipp/20170321_095250.png?dl=0) result. – Volodymyr Kulyk Mar 21 '17 at 09:20

1 Answers1

7

My mistake was in changing Auto White Balance Mode(AWB) to CONTROL_AWB_MODE_OFF before modifying Brightness(B), Gamma(G) or Contrast(C).
Do not set OFF mode for AWB, use AUTO or other from possible modes.


get current B in percents

public int getBrightnessValue() {
    int absBRange = maxCompensationRange - minCompensationRange;
    int value = getValue(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION);
    return 100 * (value - minCompensationRange) / absBRange;
}

set B in percents

public void setBrightness(int value) {
    int brightness = (int) (minCompensationRange + (maxCompensationRange - minCompensationRange) * (value / 100f));
    previewRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, brightness);
    applySettings();
 }

set C in percents

//set def channels (used for contrast)
TonemapCurve tc = previewRequestBuilder.get(CaptureRequest.TONEMAP_CURVE);
if (tc != null) {
    channels = new float[3][];
    for (int chanel = TonemapCurve.CHANNEL_RED; chanel <= TonemapCurve.CHANNEL_BLUE; chanel++) {
        float[] array = new float[tc.getPointCount(chanel) * 2];
        tc.copyColorCurve(chanel, array, 0);
        channels[chanel] = array;
    }
}


public void setContrast(int value) {
    final int minContrast = 0;
    final int maxContrast = 1;

    if (channels == null || value > 100 || value < 0) {
        return;
    }

    float contrast = minContrast + (maxContrast - minContrast) * (value / 100f);

    float[][] newValues = new float[3][];
    for (int chanel = TonemapCurve.CHANNEL_RED; chanel <= TonemapCurve.CHANNEL_BLUE; chanel++) {
        float[] array = new float [channels[chanel].length];
        System.arraycopy(channels[chanel], 0, array, 0, array.length);
        for (int i = 0; i < array.length; i++) {
            array[i] *= contrast;
        }
        newValues[chanel] = array;
    }
    TonemapCurve tc = new TonemapCurve(newValues[TonemapCurve.CHANNEL_RED], newValues[TonemapCurve.CHANNEL_GREEN], newValues[TonemapCurve.CHANNEL_BLUE]);
    previewRequestBuilder.set(CaptureRequest.TONEMAP_MODE, CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
    previewRequestBuilder.set(CaptureRequest.TONEMAP_CURVE, tc);
    applySettings();
}

private void applySettings() {
    captureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);
}

G is still in progress.


Code examples above may be not 100% correct, if you have better solutions or found a bug, please let me know ;)

Volodymyr Kulyk
  • 6,201
  • 3
  • 34
  • 61