# --- package --- # --- color --- import webcolors # --- image --- from pathlib import Path from PIL import Image, ImageSequence import cv2 import numpy as np from io import BytesIO # --- base64 --- import base64 # --- common --- import os from datetime import datetime import shutil import time import inspect def hex_to_rgb(hex_code): """Convert a hex code to RGB values.""" hex_code = hex_code.lstrip('#') return tuple(int(hex_code[i:i+2], 16) for i in (0, 2, 4)) def rgb_to_hex(rgb_values): """Convert RGB values to a hex code.""" r, g, b = rgb_values hex_code = "{:02x}{:02x}{:02x}".format(r, g, b) return hex_code def get_color_name(rgb_values): """Return the name of the closest matching color.""" min_colors = {} for key, name in webcolors.CSS3_HEX_TO_NAMES.items(): r_c, g_c, b_c = hex_to_rgb(key) rd = (r_c - rgb_values[0]) ** 2 gd = (g_c - rgb_values[1]) ** 2 bd = (b_c - rgb_values[2]) ** 2 min_colors[(rd + gd + bd)] = name return min_colors[min(min_colors.keys())] def image_resize(import_path, import_raw_path, export_path, img, resize_target, resize_resolution): image_ext = os.path.splitext(img)[1].split('.')[1] move_date = datetime.now().strftime('%y%m%d%H%M%S') img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(img, f"{import_path}{img_new_nm}") image = cv2.imread(f'{import_path}{img_new_nm}') img_width = image.shape[1] img_height = image.shape[0] if resize_target == 'W': resize_height = int(img_height * (resize_resolution / img_width)) dim = (resize_resolution, resize_height) elif resize_target == 'H': resize_width = int(img_width * (resize_resolution / img_height)) dim = (resize_width, resize_resolution) resized_img = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) cv2.imwrite(f"{export_path}export_{move_date}.{image_ext}", resized_img) move_date = datetime.now().strftime('%y%m%d%H%M%S') img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(f'{import_path}{img_new_nm}', f"{import_raw_path}{img_new_nm}") time.sleep(1) return 'Success Image Resize' def distribute_serveral_png(import_path, import_raw_path, export_path, img): image_ext = os.path.splitext(img)[1].split('.')[1] if image_ext == 'png': move_date = datetime.now().strftime('%y%m%d%H%M%S') img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(img, f"{import_path}{img_new_nm}") pc_sizes = [16, 24, 32, 48, 64, 72, 80, 96, 128, 256] and_sizes = [36, 48, 72, 96, 144] ios_sizes = [20, 29, 40, 40, 48, 50, 55, 57, 58, 60, 60, 72, 76, 80, 87, 88, 100, 114, 120, 144, 152, 167, 172, 180, 196, 1024] android_names = ['launcher_ldpi', 'launcher_mdpi', 'launcher_hdpi', 'launcher_xhdpi', 'launcher_xxhdpi'] ios_names = ['icon-20', 'icon-29', 'icon-20@2x', 'icon-40', 'icon-24@2x', 'icon-50', 'icon-27.5@2x', 'icon', 'icon-29@2x', 'icon-20@3x', 'icon-60', 'icon-72', 'icon-76', 'icon-40@2x', 'icon-83.5@2x', 'icon-44@2x', 'icon-50@2x', 'icon@2x', 'icon-60@2x', 'icon-72@2x', 'icon-76@2x', 'icon-29@3x', 'icon-86@2x', 'icon-60@3x', 'icon-98@2x', 'icon-1024'] pc_icon_sizes = [(x, x) for x in pc_sizes] and_icon_sizes = [(x, x) for x in and_sizes] ios_icon_sizes = [(x, x) for x in ios_sizes] image = Image.open(f'{import_path}{img_new_nm}') for size in pc_icon_sizes: exp_img_new_nm = f"{export_path}export_{move_date}_{str(size[0])}.{image_ext}" new_image = image.resize(size) new_image.save(exp_img_new_nm) new_logo_ico_filename = f"{export_path}export_{move_date}_main.ico" new_logo_ico = image.resize(size) new_logo_ico.save(new_logo_ico_filename, format="ICO", quality=100) for num, label in zip(and_icon_sizes, android_names): exp_img_new_nm = f"{export_path}export_{move_date}_{label}.{image_ext}" new_image = image.resize(num) new_image.save(exp_img_new_nm) for num, label in zip(ios_icon_sizes, ios_names): exp_img_new_nm = f"{export_path}export_{move_date}_{label}.{image_ext}" new_image = image.resize(num) new_image.save(exp_img_new_nm) time.sleep(1) shutil.move(f'{import_path}{img_new_nm}', f"{import_raw_path}{img_new_nm}") return 'Success Image to Icon' else: return 'Only Convert .PNG' def bake_one_big_png_to_ico(import_path, import_raw_path, export_path, img): """Converts one big PNG into one ICO file. args: sourcefile (str): Pathname of a PNG file. targetfile (str): Pathname of the resulting ICO file. sizes (list of int): Requested sizes of the resulting icon file, defaults to [16, 32, 48]. Use this function if you have one big, square PNG file and don’t care about fine-tuning individual icon sizes. Example:: sourcefile = "Path/to/high_resolution_logo_512x512.png" targetfile = "Path/to/logo.ico" sizes = [16, 24, 32, 48, 256] bake_one_big_png_to_ico(sourcefile, targetfile, sizes) """ # if sizes is None: # sizes = [16, 24, 32, 48, 256, 512] # icon_sizes = [(x, x) for x in sizes] # Image.open(sourcefile).save(targetfile, icon_sizes=icon_sizes) image_ext = os.path.splitext(img)[1].split('.')[1] if image_ext == 'png': move_date = datetime.now().strftime('%y%m%d%H%M%S') img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(img, f"{import_path}{img_new_nm}") sizes = [16, 24, 32, 48, 64, 72, 80, 96, 128, 256] icon_sizes = [(x, x) for x in sizes] print(icon_sizes) # img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') Image.open(f'{import_path}{img_new_nm}').save(f"{export_path}export_{move_date}.ico", icon_sizes=icon_sizes) # shutil.move(f'{import_path}{img_new_nm}', f"{import_raw_path}{img_new_nm}") time.sleep(1) return 'Success Image to Icon' else: return 'Only Convert .PNG' def bake_several_pngs_to_ico(sourcefiles, targetfile): """Converts several PNG files into one ICO file. args: sourcefiles (list of str): A list of pathnames of PNG files. targetfile (str): Pathname of the resulting ICO file. Use this function if you want to have fine-grained control over the resulting icon file, providing each possible icon resolution individually. Example:: sourcefiles = [ "Path/to/logo_16x16.png", "Path/to/logo_32x32.png", "Path/to/logo_48x48.png" ] targetfile = "Path/to/logo.ico" bake_several_pngs_to_ico(sourcefiles, targetfile) """ # Write the global header number_of_sources = len(sourcefiles) data = bytes((0, 0, 1, 0, number_of_sources, 0)) offset = 6 + number_of_sources * 16 # Write the header entries for each individual image for sourcefile in sourcefiles: img = Image.open(sourcefile) data += bytes((img.width, img.height, 0, 0, 1, 0, 32, 0, )) bytesize = Path(sourcefile).stat().st_size data += bytesize.to_bytes(4, byteorder="little") data += offset.to_bytes(4, byteorder="little") offset += bytesize # Write the individual image data for sourcefile in sourcefiles: data += Path(sourcefile).read_bytes() # Save the icon file Path(targetfile).write_bytes(data) # def image_to_icon(import_path, import_raw_path, export_path, img, resize_resolution): # image_ext = os.path.splitext(img)[1].split('.')[1] # # if image_ext == 'png': # move_date = datetime.now().strftime('%y%m%d%H%M%S') # # img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') # # shutil.move(img, f"{import_path}{img_new_nm}") # # image = cv2.imread(f'{import_path}{img_new_nm}') # # resized_img = cv2.resize(image, (resize_resolution, resize_resolution)) # # cv2.imwrite(f"{export_path}export_{image_ext}_{move_date}.ico", resized_img, [cv2.IMWRITE_PNG_COMPRESSION, 9]) # # move_date = datetime.now().strftime('%y%m%d%H%M%S') # # img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') # # shutil.move(f'{import_path}{img_new_nm}', f"{import_raw_path}{img_new_nm}") # # time.sleep(1) # # return 'Success Image to Icon' # # else: # return 'Only Convert .PNG' def image_to_extension(import_path, import_raw_path, export_path, img, extension): image_ext = os.path.splitext(img)[1].split('.')[1] move_date = datetime.now().strftime('%y%m%d%H%M%S') img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(img, f"{import_path}{img_new_nm}") if image_ext == 'gif': # Load the GIF into a PIL Image object image = Image.open(f"{import_path}{img_new_nm}") if extension == 'png': # Split the GIF into individual frames frames = [] for frame in ImageSequence.Iterator(image): frames.append(frame.copy()) # Save each frame as an individual image file for i, frame in enumerate(frames): move_date = datetime.now().strftime('%y%m%d%H%M%S') frame.save(f"{export_path}export_{move_date}_{i}.{extension}", format=extension) else: image = image.convert("RGB") image.save(f"{export_path}export_{move_date}.{extension}") elif image_ext == 'png': # Load the GIF into a PIL Image object image = Image.open(f"{import_path}{img_new_nm}") background = Image.new('RGB', image.size, (255, 255, 255)) background.paste(image, mask=image) background.save(f"{export_path}export_{move_date}.{extension}") else: image = cv2.imread(f'{import_path}{img_new_nm}') cv2.imwrite(f"{export_path}export_{move_date}.{extension}", image) shutil.move(f'{import_path}{img_new_nm}', f"{import_raw_path}{img_new_nm}") time.sleep(1) return 'Success Image Extension' def base64_to_image(import_raw_path, export_path, base64_str, txt_file, file): try: # ImageFile.LOAD_TRUNCATED_IMAGES = True # Remove the "data:image/png;base64," prefix from the string base64_string = base64_str.split(',')[1] # Determine the length of the input string length = len(base64_string) # Add padding characters if necessary if length % 4 != 0: base64_string += '=' * (4 - length % 4) # Decode the base64-encoded string into bytes image_bytes = base64.b64decode(base64_string) image = Image.open(BytesIO(image_bytes)) image_ext = base64_str.split('/')[1].split(';')[0] move_date = datetime.now().strftime('%y%m%d%H%M%S') if image_ext == 'gif': if image.mode == "RGBA": # If the image has an alpha channel, convert it to RGB mode image = image.convert("RGB") # Get the duration of each frame in the animation frame_durations = [] frames = [] for frame in ImageSequence.Iterator(image): frame_durations.append(frame.info.get("duration", 100)) # default duration is 100ms frames.append(frame.copy()) # Calculate the speed of the animation average_duration = sum(frame_durations) / len(frame_durations) # if not average_duration == 0.0: if average_duration != 0: speed = 1 / (average_duration / 1000) # speed in frames per second else: speed = 0 frames[0].save(f"{export_path}export_{move_date}.{image_ext}", format="GIF", save_all=True, append_images=frames[1:], duration=speed, loop=0) # Check if the image is a PNG with transparency elif image_ext == "png": # Convert the image to RGB mode to remove the alpha channel image = image.convert("RGBA") # Save the image to file image.save(f"{export_path}export_{move_date}.{image_ext}") else: # Convert the bytes to a numpy array image_array = np.frombuffer(image_bytes, dtype=np.uint8) # Decode the numpy array into an OpenCV image image = cv2.imdecode(image_array, cv2.IMREAD_UNCHANGED) # Save the image to a file cv2.imwrite(f"{export_path}export_{move_date}.{image_ext}", image) file.close() image_ext = os.path.splitext(txt_file)[1].split('.')[1] img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(txt_file, f"{import_raw_path}{img_new_nm}") time.sleep(1) return 'Success Image Convert' except Exception as e: return e def image_to_base64(import_path, import_raw_path, export_path, img): image_ext = os.path.splitext(img)[1].split('.')[1] move_date = datetime.now().strftime('%y%m%d%H%M%S') img_new_nm = '{}_{}{}'.format('import', move_date, f'.{image_ext}') shutil.move(img, f"{import_path}{img_new_nm}") if image_ext == 'gif': image_pil = Image.open(f"{import_path}{img_new_nm}") # Convert the image to a sequence of frames frames = [] try: while True: frames.append(image_pil.copy()) image_pil.seek(len(frames)) # skip to the next frame except EOFError: pass # end of sequence # Encode the frames as GIF bytes with BytesIO() as output: frames[0].save(output, format='GIF', save_all=True, append_images=frames[1:]) image_bytes = output.getvalue() elif image_ext == 'png': image = Image.open(f'{import_path}{img_new_nm}') if image.mode != 'RGBA': image = image.convert('RGBA') buffer = BytesIO() image.save(buffer, format='PNG') # Encode the image data as a base64 string image_bytes = buffer.getvalue() else: # Load the image file image = cv2.imread(f'{import_path}{img_new_nm}') # Convert the image to bytes success, image_bytes = cv2.imencode(f'.{image_ext}', image) image_bytes = image_bytes.tobytes() # Encode the bytes as a base64 string base64_str = base64.b64encode(image_bytes).decode() # Create the base64-encoded image string base64_str_dec = f"data:image/{image_ext};base64," + base64_str shutil.move(f'{import_path}{img_new_nm}', f"{import_raw_path}{img_new_nm}") time.sleep(1) # Print the base64-encoded image string return base64_str_dec, 'Success Base64 Convert', f"{export_path}export_{move_date}"