import config, image, histogram, canny, hough, tiff, pupil

def black_out_circle(Image *image, int x, y, r1, r2):
    int w = image->w
    int h = image->h

    int sum = 0, n = 0

    for int j = 0; j < h; j++:
        for int i = 0; i < w ; i++:
            int dx = i - x
            int dy = j - y
            int d = sqrt(dx * dx + dy * dy)
            if d <= r2 and d >= r1:
                int c = image->data.b[i + j * w]
                sum += c
                n++
    sum /= n

    for int j = 0; j < h; j++:
        for int i = 0; i < w ; i++:
            int dx = i - x
            int dy = j - y
            int d = sqrt(dx * dx + dy * dy)
            if d <= r2:
                int alpha = r2 * (d - r1) / (r2 - r1)
                if alpha < 0: alpha = 0
                int c = image->data.b[i + j * w]
                image->data.b[i + j * w] = c * alpha / r2 + sum * (r2 - alpha) / r2

def dim_above_horizon(Image *image, int y, V a):
    int w = image->w

    for int j = 0; j < y; j++:
        V val = (j - y) * (j - y) * a
        val = 255 - val
        if val < 0: val = 0
        for int i = 0; i < w ; i++:
            int c = image->data.b[i + j * w]
            image->data.b[i + j * w] = c * val / 255

Image *def find_iris(Image const *orig_image, char const *what,
    int px, py, pr, *out_ix, *out_iy, *out_ir):
    Image *image = image_copy(orig_image)
    int w = image->w
    int h = image->h

    int min_r = pr * 1.5

    # Blackout the pupil first
    black_out_circle(image, px, py, pr, min_r)

    if what and strstr(what, "blackout"):
        char name[MAX_PATH]
        get_image_name(image, "blackout", name)
        save_tiff_luminance(name, image)

    int IRIS_HOUGH_THRESHOLD = 200

    adjust_luminance(image, min_r * min_r * pi, w * h * 0.01)

    # That's a hack so bright iris patterns cause less edges
    threshold_above(image, 128, 128)

    #Image *accum = cumulate(image, 3, 3)
    Image *accum = image

    if what and strstr(what, "irisprep"):
        char name[MAX_PATH]
        get_image_name(image, "irisprep", name)
        save_tiff_luminance(name, accum)

    int hrun = longest_horizontal_run(accum, w * 0.1, 191)
    int vrun = longest_vertical_run(accum, h * 0.1, 191)

    Image *result = canny(accum, 3, 15, 1, 0, what)
    #threshold_below(result, 7, 0)
    #threshold_above(result, 8, 255)
    threshold_below(result, 6, 0)
    threshold_above(result, 7, 255)

    if what and strstr(what, "iriscanny"):
        char name[MAX_PATH]
        get_image_name(image, "iriscanny", name)
        save_tiff_luminance(name, result)

    remove_streaks(result, what, 6, 6, 6, 10, 10, 10, 10, 2, 10, False)

    if what and strstr(what, "irisstreaks"):
        char name[MAX_PATH]
        get_image_name(image, "irisstreaks", name)
        save_tiff_luminance(name, result)

    #adjust_luminance(result, 1, 1)
    #shift_multiply_shift_image(result, 2, 0)

    int cx = 0, cy = 0, cr = 0
    int ax, ay, bx, by
    bounds_bigger_than_threshold(result, 0, &ax, &ay, &bx, &by)

    # make sure the pupil area is covered
    # TODO: in fact, the area to use for the accum (the above) and possible
    # iris center should be separated..
    if px - pr < ax: ax = px - pr
    if py - pr < ay: ay = py - pr
    if px + pr > bx: bx = px + pr
    if py - pr > by: by = py + pr

    printf("Iris must be within: %d %d %d %d\n", ax, bx, ay, by)
    if bx - ax >= min_r and by - ay >= min_r:

        # FIXME: actually, the area for the "center" is much smaller. There's no
        # point to e.g. let it lie outside the pupil

        int max_r = pr * 8
        if max_r > (bx - ax) / 2: max_r = (bx - ax) / 2

        # No point making the radius bigger than half the biggest run
        int run = max(hrun, vrun)
        if max_r > run / 2:
            max_r = run / 2
        # OTOH, it shouldn't be too small.. blah..
        run = min(hrun, vrun)
        if max_r < run / 2:
            max_r = run / 2
        printf("Iris radius assumed to be no more than %d (%d/%d).\n", max_r,
                hrun, vrun)

        # Hack: We dim pixels far above the horizontal line through the pupil
        # center, since the actual circle outline mostly can contribute from
        # the center.
        dim_above_horizon(result, py, 240.0 / pr / pr / 4) # 240 at double radius
        if what and strstr(what, "dimmed"):
            char name[MAX_PATH]
            get_image_name(image, "dimmed", name)
            save_tiff_luminance(name, result)
    
        Vector *circles = hough_circle(result, min_r, max_r, ax, bx, ay, by,
            IRIS_HOUGH_THRESHOLD, pr * 1.3, px, py,
            what, "irisaccums", "irisaccums")

        printf("%d possible circles\n", circles->count)

        int debug = False
        find_best_circle(circles, &cx, &cy, &cr, 1, px, py, pr, 10, debug)

    Image *rgb = BtoRGB(orig_image)
    Color red = {255, 0, 0}
    draw_location(rgb, px, py, red)
    draw_circle(rgb, px - pr, py - pr, px + pr, py + pr, red)
    Color green = {0, 192, 0}
    draw_location(rgb, cx, cy, green)
    draw_circle(rgb, cx - cr, cy - cr, cx + cr, cy + cr, green)
    *out_ix = cx
    *out_iy = cy
    *out_ir = cr
    return rgb