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