<div dir="ltr"><div dir="ltr">Hi David,<div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 16 Nov 2020 at 16:49, David Plowman <<a href="mailto:david.plowman@raspberrypi.com">david.plowman@raspberrypi.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">When parts of an image saturate then the image brightness no longer<br>
increases linearly with increased exposure/gain. Having calculated a<br>
linear gain value it's better then to try it, allowing for saturating<br>
regions, and if necessary increase the gain some more. We repeat this<br>
several times.<br>
<br>
Signed-off-by: David Plowman <<a href="mailto:david.plowman@raspberrypi.com" target="_blank">david.plowman@raspberrypi.com</a>><br></blockquote><div><br></div><div>Reviewed-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com">naush@raspberrypi.com</a>></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
---<br>
 src/ipa/raspberrypi/controller/rpi/agc.cpp | 34 +++++++++++++++-------<br>
 1 file changed, 24 insertions(+), 10 deletions(-)<br>
<br>
diff --git a/src/ipa/raspberrypi/controller/rpi/agc.cpp b/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
index 1037f968..93b46a28 100644<br>
--- a/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
+++ b/src/ipa/raspberrypi/controller/rpi/agc.cpp<br>
@@ -422,17 +422,21 @@ void Agc::fetchAwbStatus(Metadata *image_metadata)<br>
 }<br>
<br>
 static double compute_initial_Y(bcm2835_isp_stats *stats, AwbStatus const &awb,<br>
-                               double weights[])<br>
+                               double weights[], double gain)<br>
 {<br>
        bcm2835_isp_stats_region *regions = stats->agc_stats;<br>
        // Note how the calculation below means that equal weights give you<br>
        // "average" metering (i.e. all pixels equally important).<br>
        double R_sum = 0, G_sum = 0, B_sum = 0, pixel_sum = 0;<br>
        for (int i = 0; i < AGC_STATS_SIZE; i++) {<br>
-               R_sum += regions[i].r_sum * weights[i];<br>
-               G_sum += regions[i].g_sum * weights[i];<br>
-               B_sum += regions[i].b_sum * weights[i];<br>
-               pixel_sum += regions[i].counted * weights[i];<br>
+               double counted = regions[i].counted;<br>
+               double r_sum = std::min(regions[i].r_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);<br>
+               double g_sum = std::min(regions[i].g_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);<br>
+               double b_sum = std::min(regions[i].b_sum * gain, ((1 << PIPELINE_BITS) - 1) * counted);<br>
+               R_sum += r_sum * weights[i];<br>
+               G_sum += g_sum * weights[i];<br>
+               B_sum += b_sum * weights[i];<br>
+               pixel_sum += counted * weights[i];<br>
        }<br>
        if (pixel_sum == 0.0) {<br>
                LOG(RPiAgc, Warning) << "compute_initial_Y: pixel_sum is zero";<br>
@@ -476,11 +480,21 @@ void Agc::computeGain(bcm2835_isp_stats *statistics, Metadata *image_metadata,<br>
        target_Y =<br>
                config_.Y_target.Eval(config_.Y_target.Domain().Clip(lux.lux));<br>
        target_Y = std::min(EV_GAIN_Y_TARGET_LIMIT, target_Y * ev_gain);<br>
-       double initial_Y = compute_initial_Y(statistics, awb_,<br>
-                                            metering_mode_->weights);<br>
-       gain = std::min(10.0, target_Y / (initial_Y + .001));<br>
-       LOG(RPiAgc, Debug) << "Initially Y " << initial_Y << " target " << target_Y<br>
-                          << " gives gain " << gain;<br>
+<br>
+       // Do this calculation a few times as brightness increase can be<br>
+       // non-linear when there are saturated regions.<br>
+       gain = 1.0;<br>
+       for (int i = 0; i < 8; i++) {<br>
+               double initial_Y = compute_initial_Y(statistics, awb_,<br>
+                                                    metering_mode_->weights, gain);<br>
+               double extra_gain = std::min(10.0, target_Y / (initial_Y + .001));<br>
+               gain *= extra_gain;<br>
+               LOG(RPiAgc, Debug) << "Initial Y " << initial_Y << " target " << target_Y<br>
+                                  << " gives gain " << gain;<br>
+               if (extra_gain < 1.01) // close enough<br>
+                       break;<br>
+       }<br>
+<br>
        for (auto &c : *constraint_mode_) {<br>
                double new_target_Y;<br>
                double new_gain =<br>
-- <br>
2.20.1<br>
<br>
_______________________________________________<br>
libcamera-devel mailing list<br>
<a href="mailto:libcamera-devel@lists.libcamera.org" target="_blank">libcamera-devel@lists.libcamera.org</a><br>
<a href="https://lists.libcamera.org/listinfo/libcamera-devel" rel="noreferrer" target="_blank">https://lists.libcamera.org/listinfo/libcamera-devel</a><br>
</blockquote></div></div>