Sanket17's picture
added all files
5fbd25d
raw
history blame
6.28 kB
"""
Image process utils. Used to verify, convert and store Images.
@file: img_utils.py
@author: Konie
@update: 2024-03-23
"""
import base64
from io import BytesIO
from fastapi import UploadFile
from PIL import Image
import starlette
import requests
import numpy as np
async def convert_image(image_path: str, image_format: str = 'png') -> BytesIO:
"""
Convert image to another format
Args:
image_path (str): Image path
image_format (str): Image format
Returns:
BytesIO: Image bytes
"""
try:
img = Image.open(image_path)
image_bytes = BytesIO()
img.save(image_bytes, format=image_format.upper())
image_bytes.seek(0)
except Exception as e:
print(e)
return
return image_bytes.getvalue()
def upload2base64(image: UploadFile) -> str | None:
"""
Convert UploadFile obj to base64 string
Args:
image (UploadFile): UploadFile obj
Returns:
str: base64 string, None for None
"""
if image is None:
return None
image_bytes = image.file.read()
image_base64 = base64.b64encode(image_bytes).decode("utf-8")
return image_base64
def narray_to_base64img(narray: np.ndarray) -> str | None:
"""
Convert numpy array to base64 image string.
Args:
narray: numpy array
Returns:
base64 image string
"""
if narray is None:
return None
img = Image.fromarray(narray)
output_buffer = BytesIO()
img.save(output_buffer, format='PNG')
byte_data = output_buffer.getvalue()
base64_str = base64.b64encode(byte_data).decode('utf-8')
return base64_str
def narray_to_bytesimg(narray) -> bytes | None:
"""
Convert numpy array to bytes image.
Args:
narray: numpy array
Returns:
bytes image
"""
if narray is None:
return None
img = Image.fromarray(narray)
output_buffer = BytesIO()
img.save(output_buffer, format='PNG')
byte_data = output_buffer.getvalue()
return byte_data
def read_input_image(input_image: UploadFile | str | None) -> np.ndarray | None:
"""
Read input image from UploadFile or base64 string.
Args:
input_image: UploadFile, or base64 image string, or None
Returns:
numpy array of image
"""
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0'
}
if isinstance(input_image, str):
if input_image is None or input_image in ('', 'None', 'null', 'string', 'none'):
return None
if input_image.startswith("http"):
try:
response = requests.get(input_image, headers=headers, timeout=20)
input_image_bytes = response.content
except Exception:
return None
else:
if input_image.startswith('data:image'):
input_image = input_image.split(sep=',', maxsplit=1)[1]
input_image_bytes = base64.b64decode(input_image)
if isinstance(input_image, (UploadFile, starlette.datastructures.UploadFile)):
input_image_bytes = input_image.file.read()
pil_image = Image.open(BytesIO(input_image_bytes))
image = np.array(pil_image)
if image.ndim == 2:
image = np.stack((image, image, image), axis=-1)
return image
def base64_to_stream(image: str) -> UploadFile | None:
"""
Convert base64 image string to UploadFile.
Args:
image: base64 image string
Returns:
UploadFile or None
"""
if image in ['', None, 'None', 'none', 'string', 'null']:
return None
if image.startswith('http'):
return get_check_image(url=image)
if image.startswith('data:image'):
image = image.split(sep=',', maxsplit=1)[1]
image_bytes = base64.b64decode(image)
byte_stream = BytesIO()
byte_stream.write(image_bytes)
byte_stream.seek(0)
return UploadFile(file=byte_stream)
def get_check_image(url: str) -> UploadFile | None:
"""
Get image from url and check if it's valid.
Args:
url: image url
Returns:
UploadFile or None
"""
if url == '':
return None
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}
try:
response = requests.get(url, headers=headers, timeout=10)
binary_image = response.content
except Exception:
return None
try:
buffer = BytesIO(binary_image)
Image.open(buffer) # This validates the image
except Exception:
return None
byte_stream = BytesIO()
byte_stream.write(binary_image)
byte_stream.seek(0)
return UploadFile(file=byte_stream)
def bytes_image_to_io(binary_image: bytes) -> BytesIO | None:
"""
Convert bytes image to BytesIO.
Args:
binary_image: bytes image
Returns:
BytesIO or None
"""
try:
buffer = BytesIO(binary_image)
Image.open(buffer)
except Exception:
return None
byte_stream = BytesIO()
byte_stream.write(binary_image)
byte_stream.seek(0)
return byte_stream
def bytes_to_base64img(byte_data: bytes) -> str | None:
"""
Convert bytes image to base64 image string.
Args:
byte_data: bytes image
Returns:
base64 image string or None
"""
if byte_data is None:
return None
base64_str = base64.b64encode(byte_data).decode('utf-8')
return base64_str
def base64_to_bytesimg(base64_str: str) -> bytes | None:
"""
Convert base64 image string to bytes image.
Args:
base64_str: base64 image string
Returns:
bytes image or None
"""
if base64_str == '':
return None
bytes_image = base64.b64decode(base64_str)
return bytes_image
def base64_to_narray(base64_str: str) -> np.ndarray | None:
"""
Convert base64 image string to numpy array.
Args:
base64_str: base64 image string
Returns:
numpy array or None
"""
if base64_str == '':
return None
bytes_image = base64.b64decode(base64_str)
image = np.frombuffer(bytes_image, np.uint8)
return image