My code sets all the exposure characteristics.
Two issues:
When I run the code on a Pixel 3 (Android 10), the resulting image appears nearly 2 stops lighter than the same scene captured on an OnePlus 6T (Android 9.0). Inspection of the resulting EXIF data shows identical exposure settings in both images.
I tried to force the gamma curve by setting tonemmap curves, thinking that may be the source of the difference, but that does not seem to work on either device (based on setting gamma to 1, which should lead to a very flat image).
Any / all suggestions are welcome! I am STUMPED.
set(requestBuilder,CaptureRequest.CONTROL_MODE,CONTROL_MODE_AUTO );
set(requestBuilder,CaptureRequest.CONTROL_CAPTURE_INTENT, CONTROL_CAPTURE_INTENT_MANUAL);
set(requestBuilder,CaptureRequest.CONTROL_AE_MODE,CONTROL_AE_MODE_OFF);
set(requestBuilder,CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
set(requestBuilder,CaptureRequest.SENSOR_EXPOSURE_TIME, (long) (exposureSettings.shutterSpeed * nanosPerSecond));
set(requestBuilder,CaptureRequest.LENS_APERTURE, exposureSettings.fStop);
set(requestBuilder,CaptureRequest.SENSOR_SENSITIVITY, Math.round(exposureSettings.iso));
setGamma(requestBuilder, 1.0f); //fixme:
set(requestBuilder,CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,0);
set(requestBuilder,CaptureRequest.CONTROL_AF_MODE,CONTROL_AF_MODE_OFF);
set(requestBuilder,CaptureRequest.LENS_FOCUS_DISTANCE,0.0f);// infinity
set(requestBuilder,CaptureRequest.CONTROL_AWB_MODE,CONTROL_AWB_MODE_DAYLIGHT);
set(requestBuilder,CaptureRequest.LENS_FOCAL_LENGTH, availableFocalLengths[0]);//todo:support multiple focal lengths.
requestBuilder.addTarget(imageCaptureSurface);
imageCaptureRequest = requestBuilder.build();
//
//
public <T> void set(@NonNull CaptureRequest.Builder requestBuilder,
@NonNull CaptureRequest.Key<T> key,
T value)
{ Log.d(TAG,String.format("requestBuilder.set(key:%s = %s)",key.getName(),value));
requestBuilder.set(key, value);
}
//
static CaptureRequest.Builder setGamma(CaptureRequest.Builder builder,
float gamma)
{ int curveSize = 16;
builder.set(CaptureRequest.TONEMAP_MODE,
CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
setToneMapCurves(builder,
gammaCurve(gamma,curveSize), //red
gammaCurve(gamma,curveSize), //green
gammaCurve(gamma,curveSize)); //blue all same.
return builder;
}
//
static CaptureRequest.Builder setToneMapCurves(CaptureRequest.Builder builder,
float[] redCurve,
float[] greenCurve,
float[] blueCurve)
{ TonemapCurve toneMapCurve = new TonemapCurve(redCurve,greenCurve,blueCurve);
builder.set(CaptureRequest.TONEMAP_CURVE,toneMapCurve);
return builder;
}
//
private static float[] gammaCurve(float gamma, int numPoints)
{ int idx = 0;
Log.i(TAG, String.format("Using gamma of %f to build tone map curve.",gamma));
if (gamma > 0)
{ float curve[] = new float[numPoints*2];//
for (float inValue = 0f; inValue <= 1.0f; inValue += 1.0f / (numPoints - 1))
{
curve[idx++] = inValue;
curve[idx++] = (float) Math.pow(inValue, gamma);
if (debug)
Log.d(TAG, String.format("Added tone curve point [%d]:(%f, %f)",
idx - 2, inValue, curve[idx - 1]));
}
return curve;
}
// sRGB curve approximates gamma = 1/2.2, with small linear front.
if (gamma == -1.0f) //sRGB
{ float curve[] =
{ 0.0000f, 0.0000f, //stick the small linear section in here
0.0667f, 0.2864f,
0.1333f, 0.4007f,
0.2000f, 0.4845f,
0.2667f, 0.5532f,
0.3333f, 0.6125f,
0.4000f, 0.6652f,
0.4667f, 0.7130f,
0.5333f, 0.7569f,
0.6000f, 0.7977f,
0.6667f, 0.8360f,
0.7333f, 0.8721f,
0.8000f, 0.9063f,
0.8667f, 0.9389f,
0.9333f, 0.9701f,
1.0000f, 1.0000f
};
return curve;
}
return null;
}