1# Copyright 2014 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import math
16import os.path
17import its.caps
18import its.device
19import its.image
20import its.objects
21import numpy as np
22
23NAME = os.path.basename(__file__).split(".")[0]
24
25
26def main():
27    """Capture auto and manual shots that should look the same.
28
29    Manual shots taken with just manual WB, and also with manual WB+tonemap.
30
31    In all cases, the general color/look of the shots should be the same,
32    however there can be variations in brightness/contrast due to different
33    "auto" ISP blocks that may be disabled in the manual flows.
34    """
35
36    with its.device.ItsSession() as cam:
37        props = cam.get_camera_properties()
38        its.caps.skip_unless(its.caps.read_3a(props) and
39                             its.caps.per_frame_control(props))
40        mono_camera = its.caps.mono_camera(props)
41
42        # Converge 3A and get the estimates.
43        debug = its.caps.debug_mode()
44        largest_yuv = its.objects.get_largest_yuv_format(props)
45        if debug:
46            fmt = largest_yuv
47        else:
48            match_ar = (largest_yuv["width"], largest_yuv["height"])
49            fmt = its.objects.get_smallest_yuv_format(props, match_ar=match_ar)
50        sens, exp, gains, xform, focus = cam.do_3a(get_results=True,
51                                                   mono_camera=mono_camera)
52        xform_rat = its.objects.float_to_rational(xform)
53        print "AE sensitivity %d, exposure %dms" % (sens, exp/1000000.0)
54        print "AWB gains", gains
55        print "AWB transform", xform
56        print "AF distance", focus
57
58        # Auto capture.
59        req = its.objects.auto_capture_request()
60        cap_auto = cam.do_capture(req, fmt)
61        img_auto = its.image.convert_capture_to_rgb_image(cap_auto)
62        its.image.write_image(img_auto, "%s_auto.jpg" % (NAME))
63        xform_a = its.objects.rational_to_float(
64                cap_auto["metadata"]["android.colorCorrection.transform"])
65        gains_a = cap_auto["metadata"]["android.colorCorrection.gains"]
66        print "Auto gains:", gains_a
67        print "Auto transform:", xform_a
68
69        # Manual capture 1: WB
70        req = its.objects.manual_capture_request(sens, exp, focus)
71        req["android.colorCorrection.transform"] = xform_rat
72        req["android.colorCorrection.gains"] = gains
73        cap_man1 = cam.do_capture(req, fmt)
74        img_man1 = its.image.convert_capture_to_rgb_image(cap_man1)
75        its.image.write_image(img_man1, "%s_manual_wb.jpg" % (NAME))
76        xform_m1 = its.objects.rational_to_float(
77                cap_man1["metadata"]["android.colorCorrection.transform"])
78        gains_m1 = cap_man1["metadata"]["android.colorCorrection.gains"]
79        print "Manual wb gains:", gains_m1
80        print "Manual wb transform:", xform_m1
81
82        # Manual capture 2: WB + tonemap
83        gamma = sum([[i/63.0, math.pow(i/63.0, 1/2.2)] for i in xrange(64)], [])
84        req["android.tonemap.mode"] = 0
85        req["android.tonemap.curve"] = {
86                "red": gamma, "green": gamma, "blue": gamma}
87        cap_man2 = cam.do_capture(req, fmt)
88        img_man2 = its.image.convert_capture_to_rgb_image(cap_man2)
89        its.image.write_image(img_man2, "%s_manual_wb_tm.jpg" % (NAME))
90        xform_m2 = its.objects.rational_to_float(
91                cap_man2["metadata"]["android.colorCorrection.transform"])
92        gains_m2 = cap_man2["metadata"]["android.colorCorrection.gains"]
93        print "Manual wb+tm gains:", gains_m2
94        print "Manual wb+tm transform:", xform_m2
95
96        # Check that the WB gains and transform reported in each capture
97        # result match with the original AWB estimate from do_3a.
98        for g, x in [(gains_m1, xform_m1), (gains_m2, xform_m2)]:
99            assert all([abs(xform[i] - x[i]) < 0.05 for i in range(9)])
100            assert all([abs(gains[i] - g[i]) < 0.05 for i in range(4)])
101
102        # Check that auto AWB settings are close
103        assert all([np.isclose(xform_a[i], xform[i], rtol=0.25, atol=0.1) for i in range(9)])
104        assert all([np.isclose(gains_a[i], gains[i], rtol=0.25, atol=0.1) for i in range(4)])
105
106if __name__ == "__main__":
107    main()
108
109