# Copyright 2014 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import its.image
import its.caps
import its.device
import its.objects
import os.path
import math

def main():
    """Capture auto and manual shots that should look the same.

    Manual shots taken with just manual WB, and also with manual WB+tonemap.

    In all cases, the general color/look of the shots should be the same,
    however there can be variations in brightness/contrast due to different
    "auto" ISP blocks that may be disabled in the manual flows.
    """
    NAME = os.path.basename(__file__).split(".")[0]

    with its.device.ItsSession() as cam:
        props = cam.get_camera_properties()
        its.caps.skip_unless(its.caps.manual_sensor(props) and
                             its.caps.manual_post_proc(props) and
                             its.caps.per_frame_control(props))

        # Converge 3A and get the estimates.
        debug = its.caps.debug_mode()
        largest_yuv = its.objects.get_largest_yuv_format(props)
        if debug:
            fmt = largest_yuv
        else:
            match_ar = (largest_yuv['width'], largest_yuv['height'])
            fmt = its.objects.get_smallest_yuv_format(props, match_ar=match_ar)
        sens, exp, gains, xform, focus = cam.do_3a(get_results=True)
        xform_rat = its.objects.float_to_rational(xform)
        print "AE sensitivity %d, exposure %dms" % (sens, exp/1000000.0)
        print "AWB gains", gains
        print "AWB transform", xform
        print "AF distance", focus

        # Auto capture.
        req = its.objects.auto_capture_request()
        cap_auto = cam.do_capture(req, fmt)
        img_auto = its.image.convert_capture_to_rgb_image(cap_auto)
        its.image.write_image(img_auto, "%s_auto.jpg" % (NAME))
        xform_a = its.objects.rational_to_float(
                cap_auto["metadata"]["android.colorCorrection.transform"])
        gains_a = cap_auto["metadata"]["android.colorCorrection.gains"]
        print "Auto gains:", gains_a
        print "Auto transform:", xform_a

        # Manual capture 1: WB
        req = its.objects.manual_capture_request(sens, exp, focus)
        req["android.colorCorrection.transform"] = xform_rat
        req["android.colorCorrection.gains"] = gains
        cap_man1 = cam.do_capture(req, fmt)
        img_man1 = its.image.convert_capture_to_rgb_image(cap_man1)
        its.image.write_image(img_man1, "%s_manual_wb.jpg" % (NAME))
        xform_m1 = its.objects.rational_to_float(
                cap_man1["metadata"]["android.colorCorrection.transform"])
        gains_m1 = cap_man1["metadata"]["android.colorCorrection.gains"]
        print "Manual wb gains:", gains_m1
        print "Manual wb transform:", xform_m1

        # Manual capture 2: WB + tonemap
        gamma = sum([[i/63.0,math.pow(i/63.0,1/2.2)] for i in xrange(64)],[])
        req["android.tonemap.mode"] = 0
        req["android.tonemap.curveRed"] = gamma
        req["android.tonemap.curveGreen"] = gamma
        req["android.tonemap.curveBlue"] = gamma
        cap_man2 = cam.do_capture(req, fmt)
        img_man2 = its.image.convert_capture_to_rgb_image(cap_man2)
        its.image.write_image(img_man2, "%s_manual_wb_tm.jpg" % (NAME))
        xform_m2 = its.objects.rational_to_float(
                cap_man2["metadata"]["android.colorCorrection.transform"])
        gains_m2 = cap_man2["metadata"]["android.colorCorrection.gains"]
        print "Manual wb+tm gains:", gains_m2
        print "Manual wb+tm transform:", xform_m2

        # Check that the WB gains and transform reported in each capture
        # result match with the original AWB estimate from do_3a.
        for g,x in [(gains_a,xform_a),(gains_m1,xform_m1),(gains_m2,xform_m2)]:
            assert(all([abs(xform[i] - x[i]) < 0.05 for i in range(9)]))
            assert(all([abs(gains[i] - g[i]) < 0.05 for i in range(4)]))

if __name__ == '__main__':
    main()