# Path: imgProcessor/transformations.py
# def toNoUintArray(arr):
#     '''
#     cast array to the next higher integer array
#     if dtype=unsigned integer
#     '''
#     d = arr.dtype
#     if d.kind == 'u':
#         arr = arr.astype({1: np.int16,
#                           2: np.int32,
#                           4: np.int64}[d.itemsize])
#     return arr
# 
# def toUIntArray(img, dtype=None, cutNegative=True, cutHigh=True,
#                 range=None, copy=True):
#     '''
#     transform a float to an unsigned integer array of a fitting dtype
#     adds an offset, to get rid of negative values
# 
#     range = (min, max) - scale values between given range
# 
#     cutNegative - all values <0 will be set to 0
#     cutHigh - set to False to rather scale values to fit
#     '''
#     mn, mx = None, None
#     if range is not None:
#         mn, mx = range
# 
#     if dtype is None:
#         if mx is None:
#             mx = np.nanmax(img)
#         dtype = np.uint16 if mx > 255 else np.uint8
# 
#     dtype = np.dtype(dtype)
#     if dtype == img.dtype:
#         return img
# 
#     # get max px value:
#     b = {'uint8': 255,
#          'uint16': 65535,
#          'uint32': 4294967295,
#          'uint64': 18446744073709551615}[dtype.name]
# 
#     if copy:
#         img = img.copy()
# 
#     if range is not None:
#         img = np.asfarray(img)
#         img -= mn
#         # img[img<0]=0
#         # print np.nanmin(img), np.nanmax(img), mn, mx, range, b
# 
#         img *= b / (mx - mn)
#         # print np.nanmin(img), np.nanmax(img), mn, mx, range, b
#         img = np.clip(img, 0, b)
# 
#     else:
#         if cutNegative:
#             img[img < 0] = 0
#         else:
#             # add an offset to all values:
#             mn = np.min(img)
#             if mn < 0:
#                 img -= mn  # set minimum to 0
# 
#         if cutHigh:
#             #ind = img > b
#             img[img > b] = b
#         else:
#             # scale values
#             mx = np.nanmax(img)
#             img = np.asfarray(img) * (float(b) / mx)
# 
#     img = img.astype(dtype)
# 
# #     if range is not None and cutHigh:
# #         img[ind] = b
#     return img
# 
# def toGray(img):
#     '''
#     weights see
#     https://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-prese
#     http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor
#     '''
#     return np.average(img, axis=-1, weights=(0.299,  # red
#                                              0.587,  # green
#                                              0.114)  # blue
#                       ).astype(img.dtype)


import cv2
import numpy as np
from six import string_types
from imgProcessor.transformations import toNoUintArray, toUIntArray, toGray
from PIL import Image  # todo: save 32float TIFF without needing PIL

        #         from_file = True
        #         try:
        #             ftype = img[img.find('.'):]
        #             img = READERS[ftype](img)[0]
        #         except KeyError:
        # open with openCV
        # grey - 8 bit
        if dtype in (None, "noUint") or np.dtype(dtype) != np.uint8:
            c |= cv2.IMREAD_ANYDEPTH
        img2 = cv2.imread(img, c)
        if img2 is None:
            raise IOError("image '%s' is not existing" % img)
        img = img2

    elif color == 'gray' and img.ndim == 3:  # multi channel img like rgb
        # cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #cannot handle float64
        img = toGray(img)
    # transform array to uint8 array due to openCV restriction
    if dtype is not None:
        if isinstance(img, np.ndarray):
            img = _changeArrayDType(img, dtype, cutHigh=False)

    return img


def imwrite(name, arr, dtype=None, **kwargs):
    if dtype in (float, np.float64, np.float32):
        # save as 32bit float tiff
        Image.fromarray(np.asfarray(arr)).save(name)
    else:

# Path: imgProcessor/transformations.py
# def toNoUintArray(arr):
#     '''
#     cast array to the next higher integer array
#     if dtype=unsigned integer
#     '''
#     d = arr.dtype
#     if d.kind == 'u':
#         arr = arr.astype({1: np.int16,
#                           2: np.int32,
#                           4: np.int64}[d.itemsize])
#     return arr
# 
# def toUIntArray(img, dtype=None, cutNegative=True, cutHigh=True,
#                 range=None, copy=True):
#     '''
#     transform a float to an unsigned integer array of a fitting dtype
#     adds an offset, to get rid of negative values
# 
#     range = (min, max) - scale values between given range
# 
#     cutNegative - all values <0 will be set to 0
#     cutHigh - set to False to rather scale values to fit
#     '''
#     mn, mx = None, None
#     if range is not None:
#         mn, mx = range
# 
#     if dtype is None:
#         if mx is None:
#             mx = np.nanmax(img)
#         dtype = np.uint16 if mx > 255 else np.uint8
# 
#     dtype = np.dtype(dtype)
#     if dtype == img.dtype:
#         return img
# 
#     # get max px value:
#     b = {'uint8': 255,
#          'uint16': 65535,
#          'uint32': 4294967295,
#          'uint64': 18446744073709551615}[dtype.name]
# 
#     if copy:
#         img = img.copy()
# 
#     if range is not None:
#         img = np.asfarray(img)
#         img -= mn
#         # img[img<0]=0
#         # print np.nanmin(img), np.nanmax(img), mn, mx, range, b
# 
#         img *= b / (mx - mn)
#         # print np.nanmin(img), np.nanmax(img), mn, mx, range, b
#         img = np.clip(img, 0, b)
# 
#     else:
#         if cutNegative:
#             img[img < 0] = 0
#         else:
#             # add an offset to all values:
#             mn = np.min(img)
#             if mn < 0:
#                 img -= mn  # set minimum to 0
# 
#         if cutHigh:
#             #ind = img > b
#             img[img > b] = b
#         else:
#             # scale values
#             mx = np.nanmax(img)
#             img = np.asfarray(img) * (float(b) / mx)
# 
#     img = img.astype(dtype)
# 
# #     if range is not None and cutHigh:
# #         img[ind] = b
#     return img
# 
# def toGray(img):
#     '''
#     weights see
#     https://en.wikipedia.org/wiki/Grayscale#Colorimetric_.28luminance-prese
#     http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor
#     '''
#     return np.average(img, axis=-1, weights=(0.299,  # red
#                                              0.587,  # green
#                                              0.114)  # blue
#                       ).astype(img.dtype)


# Path: imgProcessor/imgIO.py
import cv2
import numpy as np
from six import string_types
from imgProcessor.transformations import toNoUintArray, toUIntArray, toGray
from PIL import Image  # todo: save 32float TIFF without needing PIL

        #         from_file = True
        #         try:
        #             ftype = img[img.find('.'):]
        #             img = READERS[ftype](img)[0]
        #         except KeyError:
        # open with openCV
        # grey - 8 bit
        if dtype in (None, "noUint") or np.dtype(dtype) != np.uint8:
            c |= cv2.IMREAD_ANYDEPTH
        img2 = cv2.imread(img, c)
        if img2 is None:
            raise IOError("image '%s' is not existing" % img)
        img = img2

    elif color == 'gray' and img.ndim == 3:  # multi channel img like rgb
        # cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #cannot handle float64
        img = toGray(img)
    # transform array to uint8 array due to openCV restriction
    if dtype is not None:
        if isinstance(img, np.ndarray):
            img = _changeArrayDType(img, dtype, cutHigh=False)

    return img


def imwrite(name, arr, dtype=None, **kwargs):
    if dtype in (float, np.float64, np.float32):
        # save as 32bit float tiff
        Image.fromarray(np.asfarray(arr)).save(name)
    else:

        return cv2.imwrite(name, toUIntArray(arr, dtype=dtype, **kwargs))
