# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/utils/Image.ipynb.

# %% auto 0
__all__ = ['isBase64', 'handle_string_to_bytes_and_decode', 'handle_string_to_bytes_and_encode', 'to_bytes', 'crop_square',
           'are_same_image']

# %% ../../nbs/utils/Image.ipynb 2
from PIL.Image import Image

# %% ../../nbs/utils/Image.ipynb 3
from typing import Union
import types
import PIL
import numpy as np

import os
import io
import base64

from nbdev.showdoc import patch_to

# %% ../../nbs/utils/Image.ipynb 4
def isBase64(s):
    try:
        return base64.b64encode(base64.b64decode(s)) == s
    except Exception:
        return False


def handle_string_to_bytes_and_decode(data: Union[str, bytes]):
    if isinstance(data, str):
        data = bytes(data)

    if isBase64(data):
        data = base64.b64decode(data)

    return data


def handle_string_to_bytes_and_encode(data: Union[str, bytes]):
    if isinstance(data, str):
        data = bytes(data)

    if not isBase64(data):
        data = base64.b64encode(data)

    return data

# %% ../../nbs/utils/Image.ipynb 5
def to_bytes(self) -> bytes:
    byte_arr = io.BytesIO()

    if not self.area:
        self.area = self

    self.area.save(byte_arr, format=self.format)

    self.data = byte_arr.getvalue()

    return self.data


def crop_square(self):
    width, height = self.size  # Get dimensions

    new_edge = min(width, height)

    left = (width - new_edge) / 2
    top = (height - new_edge) / 2
    right = (width + new_edge) / 2
    bottom = (height + new_edge) / 2

    # Crop the center of the image
    self.area = self.crop((left, top, right, bottom))

    self.to_bytes()

    return self.area

# %% ../../nbs/utils/Image.ipynb 6
@patch_to(Image, cls_method=True)
def from_image_file(cls, image_path: str) -> Image:
    if not os.path.exists(image_path):
        raise FileNotFoundError(image_path)

    with open(image_path, "rb") as file:
        data = file.read()

    data = handle_string_to_bytes_and_decode(data)

    im = PIL.Image.open(io.BytesIO(data))

    im.to_bytes = types.MethodType(to_bytes, im)
    im.crop_square = types.MethodType(crop_square, im)

    return im

# %% ../../nbs/utils/Image.ipynb 9
@patch_to(Image, cls_method=True)
def from_bytestr(cls, data: Union[str, bytes]) -> Image:
    data = handle_string_to_bytes_and_decode(data)

    im = PIL.Image.open(io.BytesIO(data))

    im.to_bytes = types.MethodType(to_bytes, im)
    im.crop_square = types.MethodType(crop_square, im)

    return im

# %% ../../nbs/utils/Image.ipynb 11
def are_same_image(image1, image2, threshold=0, return_difference: bool = False):
    try:
        img_chop = PIL.ImageChops.difference(image1, image2)

        if return_difference:
            return img_chop

        if np.sum(np.array(img_chop.getdata())) == threshold:
            return True
        return False

    except ValueError as e:
        print(e)
        return False
