





"""simple docstring"""





import os
import sys
import warnings
from dataclasses import dataclass, field
from io import BytesIO
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Union

import numpy as np
import pyarrow as pa

from .. import config
from ..download.streaming_download_manager import xopen
from ..table import array_cast
from ..utils.file_utils import is_local_path
from ..utils.py_utils import first_non_null_value, no_op_if_value_is_null, string_to_dict


if TYPE_CHECKING:
							import PIL.Image

							from .features import FeatureType


_UpperCamelCase					      =   None
_UpperCamelCase					      =   '<' if sys.byteorder == 'little' else '>'
# Origin: https://github.com/python-pillow/Pillow/blob/698951e19e19972aeed56df686868f1329981c12/src/PIL/Image.py#L3126 minus "|i1" which values are not preserved correctly when saving and loading an image
_UpperCamelCase					      =   [
    np.dtype('|b1'),
    np.dtype('|u1'),
    np.dtype('<u2'),
    np.dtype('>u2'),
    np.dtype('<i2'),
    np.dtype('>i2'),
    np.dtype('<u4'),
    np.dtype('>u4'),
    np.dtype('<i4'),
    np.dtype('>i4'),
    np.dtype('<f4'),
    np.dtype('>f4'),
    np.dtype('<f8'),
    np.dtype('>f8'),
]
@dataclass
class 		SCREAMING_SNAKE_CASE_				:
				"""simple docstring"""
				__snake_case :							List[str]									=		True
				__snake_case :							str									=		None
				# Automatically constructed
				__snake_case :							Optional[Any]									=		"""PIL.Image.Image"""
				__snake_case :							str									=		pa.struct({"""bytes""": pa.binary(), """path""": pa.string()} )
				__snake_case :							Optional[Any]									=		field(default="""Image"""							,	init=UpperCamelCase__							,	repr=UpperCamelCase__ )




				def __call__(  self	:Optional[Any]      ):
											return self.pa_type




				def        __lowercase	(  self	:int    ,     __lowercase	:Union[str, bytes, dict, np.ndarray, "PIL.Image.Image"]      ):



											if config.PIL_AVAILABLE:
																		import PIL.Image
											else:
																		raise ImportError('''To support encoding images, please install \'Pillow\'.'''      )

											if isinstance(__A    ,     __A      ):
																		__lowerCamelCase   :   Any       =np.array(__A      )

											if isinstance(__A    ,     __A      ):
																		return {"path": value, "bytes": None}
											elif isinstance(__A    ,     __A      ):
																		return {"path": None, "bytes": value}
											elif isinstance(__A    ,     np.ndarray      ):
																		# convert the image array to PNG/TIFF bytes
																		return encode_np_array(__A      )
											elif isinstance(__A    ,     PIL.Image.Image      ):
																		# convert the PIL image to bytes (default format is PNG/TIFF)
																		return encode_pil_image(__A      )
											elif value.get('''path'''      ) is not None and os.path.isfile(value['''path''']      ):
																		# we set "bytes": None to not duplicate the data if they're already available locally
																		return {"bytes": None, "path": value.get('''path'''      )}
											elif value.get('''bytes'''      ) is not None or value.get('''path'''      ) is not None:
																		# store the image bytes, and path is used to infer the image format using the file extension
																		return {"bytes": value.get('''bytes'''      ), "path": value.get('''path'''      )}
											else:
																		raise ValueError(
																		    f'An image sample should have one of \'path\' or \'bytes\' but they are missing or None in {value}.'      )




				def        __lowercase	(  self	:Tuple    ,     __lowercase	:dict    ,     __lowercase	:Optional[Any]=None      ):



											if not self.decode:
																		raise RuntimeError('''Decoding is disabled for this feature. Please use Image(decode=True) instead.'''      )

											if config.PIL_AVAILABLE:
																		import PIL.Image
											else:
																		raise ImportError('''To support decoding images, please install \'Pillow\'.'''      )

											if token_per_repo_id is None:
																		__lowerCamelCase   :   Optional[Any]       ={}

											__lowerCamelCase     ,    __lowerCamelCase   :   List[Any]       =value['''path'''], value['''bytes''']
											if bytes_ is None:
																		if path is None:
																									raise ValueError(f'An image should have one of \'path\' or \'bytes\' but both are None in {value}.'      )
																		else:
																									if is_local_path(__A      ):
																																__lowerCamelCase   :   Dict       =PIL.Image.open(__A      )
																									else:
																																__lowerCamelCase   :   Union[str, Any]       =path.split('''::'''      )[-1]
																																try:
																																							__lowerCamelCase   :   Dict       =string_to_dict(__A    ,     config.HUB_DATASETS_URL      )['''repo_id''']
																																							__lowerCamelCase   :   Optional[int]       =token_per_repo_id.get(__A      )
																																except ValueError:
																																							__lowerCamelCase   :   Optional[Any]       =None
																																with xopen(__A    ,     '''rb'''    ,     use_auth_token=__A      ) as f:
																																							__lowerCamelCase   :   Any       =BytesIO(f.read()      )
																																__lowerCamelCase   :   List[str]       =PIL.Image.open(bytes_      )
											else:
																		__lowerCamelCase   :   Optional[int]       =PIL.Image.open(BytesIO(bytes_      )      )
											image.load()  # to avoid "Too many open files" errors
											return image




				def        __lowercase	(  self	:str      ):
											from .features import Value

											return (
											    self
											    if self.decode
											    else {
											        "bytes": Value('''binary'''      ),
											        "path": Value('''string'''      ),
											    }
											)




				def        __lowercase	(  self	:List[Any]    ,     __lowercase	:Union[pa.StringArray, pa.StructArray, pa.ListArray]      ):



											if pa.types.is_string(storage.type      ):
																		__lowerCamelCase   :   Tuple       =pa.array([None] * len(__A      )    ,     type=pa.binary()      )
																		__lowerCamelCase   :   List[str]       =pa.StructArray.from_arrays([bytes_array, storage]    ,     ['''bytes''', '''path''']    ,     mask=storage.is_null()      )
											elif pa.types.is_binary(storage.type      ):
																		__lowerCamelCase   :   str       =pa.array([None] * len(__A      )    ,     type=pa.string()      )
																		__lowerCamelCase   :   List[str]       =pa.StructArray.from_arrays([storage, path_array]    ,     ['''bytes''', '''path''']    ,     mask=storage.is_null()      )
											elif pa.types.is_struct(storage.type      ):
																		if storage.type.get_field_index('''bytes'''      ) >= 0:
																									__lowerCamelCase   :   str       =storage.field('''bytes'''      )
																		else:
																									__lowerCamelCase   :   List[str]       =pa.array([None] * len(__A      )    ,     type=pa.binary()      )
																		if storage.type.get_field_index('''path'''      ) >= 0:
																									__lowerCamelCase   :   Union[str, Any]       =storage.field('''path'''      )
																		else:
																									__lowerCamelCase   :   str       =pa.array([None] * len(__A      )    ,     type=pa.string()      )
																		__lowerCamelCase   :   str       =pa.StructArray.from_arrays([bytes_array, path_array]    ,     ['''bytes''', '''path''']    ,     mask=storage.is_null()      )
											elif pa.types.is_list(storage.type      ):
																		__lowerCamelCase   :   Optional[Any]       =pa.array(
																		    [encode_np_array(np.array(__A      )      )['''bytes'''] if arr is not None else None for arr in storage.to_pylist()]    ,     type=pa.binary()    ,     )
																		__lowerCamelCase   :   str       =pa.array([None] * len(__A      )    ,     type=pa.string()      )
																		__lowerCamelCase   :   Any       =pa.StructArray.from_arrays(
																		    [bytes_array, path_array]    ,     ['''bytes''', '''path''']    ,     mask=bytes_array.is_null()      )
											return array_cast(__A    ,     self.pa_type      )




				def        __lowercase	(  self	:Tuple    ,     __lowercase	:pa.StructArray      ):



											@no_op_if_value_is_null
											def path_to_bytes(__lowercase	:Tuple      ):
																		with xopen(__A    ,     '''rb'''      ) as f:
																									__lowerCamelCase   :   Tuple       =f.read()
																		return bytes_

											__lowerCamelCase   :   Optional[int]       =pa.array(
											    [
											        (path_to_bytes(x['''path''']      ) if x['''bytes'''] is None else x['''bytes''']) if x is not None else None
											        for x in storage.to_pylist()
											    ]    ,     type=pa.binary()    ,     )
											__lowerCamelCase   :   int       =pa.array(
											    [os.path.basename(__A      ) if path is not None else None for path in storage.field('''path'''      ).to_pylist()]    ,     type=pa.string()    ,     )
											__lowerCamelCase   :   str       =pa.StructArray.from_arrays([bytes_array, path_array]    ,     ['''bytes''', '''path''']    ,     mask=bytes_array.is_null()      )
											return array_cast(__A    ,     self.pa_type      )



def 					lowerCAmelCase_      (   ):


							'''simple docstring'''







							if config.PIL_AVAILABLE:
														import PIL.Image
							else:
														raise ImportError('''To support encoding images, please install \'Pillow\'.''' )

							global _IMAGE_COMPRESSION_FORMATS
							if _IMAGE_COMPRESSION_FORMATS is None:
														PIL.Image.init()
														__lowerCamelCase   :   Optional[int]       =list(set(PIL.Image.OPEN.keys() ) & set(PIL.Image.SAVE.keys() ) )
							return _IMAGE_COMPRESSION_FORMATS



def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				"PIL.Image.Image" ):


							'''simple docstring'''







							__lowerCamelCase   :   List[Any]       =BytesIO()
							if image.format in list_image_compression_formats():
														__lowerCamelCase   :   Optional[Any]       =image.format
							else:
														__lowerCamelCase   :   Optional[Any]       ='''PNG''' if image.mode in ['''1''', '''L''', '''LA''', '''RGB''', '''RGBA'''] else '''TIFF'''
							image.save(UpperCamelCase__     ,    format=UpperCamelCase__ )
							return buffer.getvalue()



def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				"PIL.Image.Image" ):


							'''simple docstring'''







							if hasattr(UpperCamelCase__     ,    '''filename''' ) and image.filename != "":
														return {"path": image.filename, "bytes": None}
							else:
														return {"path": None, "bytes": image_to_bytes(UpperCamelCase__ )}



def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				np.ndarray ):


							'''simple docstring'''







							if config.PIL_AVAILABLE:
														import PIL.Image
							else:
														raise ImportError('''To support encoding images, please install \'Pillow\'.''' )

							__lowerCamelCase   :   str       =array.dtype
							__lowerCamelCase   :   Tuple       =dtype.byteorder if dtype.byteorder != '''=''' else _NATIVE_BYTEORDER
							__lowerCamelCase   :   Optional[Any]       =dtype.kind
							__lowerCamelCase   :   Tuple       =dtype.itemsize

							__lowerCamelCase   :   Optional[Any]       =None

							# Multi-channel array case (only np.dtype("|u1") is allowed)
							if array.shape[2:]:
														__lowerCamelCase   :   str       =np.dtype('''|u1''' )
														if dtype_kind not in ["u", "i"]:
																					raise TypeError(
																					    F'Unsupported array dtype {dtype} for image encoding. Only {dest_dtype} is supported for multi-channel arrays.' )
														if dtype is not dest_dtype:
																					warnings.warn(F'Downcasting array dtype {dtype} to {dest_dtype} to be compatible with \'Pillow\'' )
    # Exact match
							elif dtype in _VALID_IMAGE_ARRAY_DTPYES:
														__lowerCamelCase   :   List[Any]       =dtype
							else:  # Downcast the type within the kind (np.can_cast(from_type, to_type, casting="same_kind") doesn't behave as expected, so do it manually)
														while dtype_itemsize >= 1:
																					__lowerCamelCase   :   Optional[Any]       =dtype_byteorder + dtype_kind + str(UpperCamelCase__ )
																					__lowerCamelCase   :   List[Any]       =np.dtype(UpperCamelCase__ )
																					if dest_dtype in _VALID_IMAGE_ARRAY_DTPYES:
																												warnings.warn(F'Downcasting array dtype {dtype} to {dest_dtype} to be compatible with \'Pillow\'' )
																												break
																					else:
																												dtype_itemsize //= 2

							if dest_dtype is None:
														raise TypeError(
														    F'Cannot convert dtype {dtype} to a valid image dtype. Valid image dtypes: {_VALID_IMAGE_ARRAY_DTPYES}' )
							__lowerCamelCase   :   str       =PIL.Image.fromarray(array.astype(UpperCamelCase__ ) )
							return {"path": None, "bytes": image_to_bytes(UpperCamelCase__ )}



def 					lowerCAmelCase_      (   SCREAMING_SNAKE_CASE							:				Union[List[str], List[dict], List[np.ndarray], List["PIL.Image.Image"]] ):


							'''simple docstring'''







							if config.PIL_AVAILABLE:
														import PIL.Image
							else:
														raise ImportError('''To support encoding images, please install \'Pillow\'.''' )

							if objs:
														__lowerCamelCase     ,    __lowerCamelCase   :   Union[str, Any]       =first_non_null_value(UpperCamelCase__ )
														if isinstance(UpperCamelCase__     ,    UpperCamelCase__ ):
																					return [{"path": obj, "bytes": None} if obj is not None else None for obj in objs]
														if isinstance(UpperCamelCase__     ,    np.ndarray ):
																					__lowerCamelCase   :   List[Any]       =no_op_if_value_is_null(UpperCamelCase__ )
																					return [obj_to_image_dict_func(UpperCamelCase__ ) for obj in objs]
														elif isinstance(UpperCamelCase__     ,    PIL.Image.Image ):
																					__lowerCamelCase   :   List[str]       =no_op_if_value_is_null(UpperCamelCase__ )
																					return [obj_to_image_dict_func(UpperCamelCase__ ) for obj in objs]
														else:
																					return objs
							else:
														return objs











def 					SCREAMING_SNAKE_CASE__				(							UpperCamelCase__:				float       , UpperCamelCase__:				float     ):
		if mass < 0:
				raise ValueError("""The mass of a body cannot be negative"""     )
		return 0.5 * mass * abs(UpperCamelCase__     ) * abs(UpperCamelCase__     )


if __name__ == "__main__":
	import doctest

	doctest.testmod(verbose=True)