#! /usr/bin/env python
#
# Perceptual image hash calculation tool based on algorithm descibed in
# Block Mean Value Based Image Perceptual Hashing by Bian Yang, Fan Gu and Xiamu Niu
#
# Copyright 2014 Commons Machinery http://commonsmachinery.se/
# Distributed under an MIT license, please see LICENSE in the top dir.

import sys
import os
_APP_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
sys.path.insert(0, _APP_PATH)

import argparse

import PIL.Image as Image

import blockhash.constants
import blockhash.core
import blockhash.utility

def _main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        '--quick',
        action='store_true',
        help='Use quick hashing method. Default: False')

    parser.add_argument(
        '--bits',
        type=int, default=blockhash.constants.DEFAULT_BITS,
        help='Create hash of size N^2 bits.')

    parser.add_argument(
        '--size',
        help='Resize image to specified size before hashing, e.g. 256x256')

    parser.add_argument(
        '--interpolation',
        type=int,
        default=1,
        choices=[1, 2, 3, 4],
        help='Interpolation method: 1 - nearest neightbor, 2 - bilinear, 3 - bicubic, 4 - antialias. Default: 1')

    parser.add_argument(
        '--debug',
        action='store_true',
        help='Print hashes as 2D maps (for debugging)')

    parser.add_argument(
        'filenames',
        nargs='+')

    args = parser.parse_args()

    if args.interpolation == 1:
        interpolation = Image.NEAREST
    elif args.interpolation == 2:
        interpolation = Image.BILINEAR
    elif args.interpolation == 3:
        interpolation = Image.BICUBIC
    elif args.interpolation == 4:
        interpolation = Image.ANTIALIAS

    if args.quick:
        method = blockhash.core.blockhash_even
    else:
        method = blockhash.core.blockhash

    for fn in args.filenames:
        with Image.open(fn) as im:
            im = blockhash.utility.normalize_image(im)

            if args.size:
                size = args.size.split('x')
                size = (int(size[0]), int(size[1]))
                im = im.resize(size, interpolation)

            hash_ = method(im, args.bits)

        print('{hash}  {fn}'.format(fn=fn, hash=hash_))

        if args.debug:
            bin_hash = '{:0{width}b}'.format(int(hash_, 16), width=args.bits ** 2)
            map = [bin_hash[i:i+args.bits] for i in range(0, len(bin_hash), args.bits)]
            print("")
            print("\n".join(map))
            print("")

if __name__ == '__main__':
    _main()
