From f46cf82b07bf0a6cc652c4cf3ffb85a57c949c5e Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 5 Aug 2022 22:06:27 +0300 Subject: [PATCH 1/9] create_bootanimation: Update help --- create_bootanimation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index 98dcf5c..ad96788 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -12,11 +12,11 @@ def parse_arguments(): "of images") parser.add_argument("source", type=str, default="", - help="Absolute path to the GIF file or folder with images." - "Expected image name format: xxxx-001.png" - "Where:" - "xxx - some image name;" - "001 - image number.") + help="Absolute path to the GIF file or folder with images. " + "Expected image name format: xxxx-001.png " + "Where: " + "xxx - some image name; " + "001 - image number.") parser.add_argument("width", type=int, default=720, help="Width of result images in pixels. " From 442452eb21b9bcf1853324ecad8391de9bebc638 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 5 Aug 2022 22:06:59 +0300 Subject: [PATCH 2/9] create_bootanimation: Crop images and create trim.txt --- create_bootanimation.py | 69 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index ad96788..d8f6edf 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -151,7 +151,67 @@ def create_desc_file(t_folder, t_width, t_height, t_fps): return file_name +def compare_colors(color_a, color_b, tolerance=10): + return abs(color_a[0] - color_b[0]) < tolerance and \ + abs(color_a[1] - color_b[1]) < tolerance and \ + abs(color_a[2] - color_b[2]) < tolerance + + +def crop_image(image, steps=100): + """Crop image""" + + image_pixels = image.load() + + # Get background color + background_color = image_pixels[0, 0] + + # Get image crop coords + crop_start_x = image.width + crop_start_y = image.height + crop_end_x = 0 + crop_end_y = 0 + + for x in range(0, image.width - 1, int(image.width / steps)): + for y in range(0, image.height - 1, int(image.height / steps)): + if not compare_colors(image_pixels[x, y], background_color): + if x < crop_start_x: + crop_start_x = x + if y < crop_start_y: + crop_start_y = y + if x > crop_end_x: + crop_end_x = x + if y > crop_end_y: + crop_end_y = y + + crop_start_x = max(crop_start_x - int(image.width / steps), 0) + crop_start_y = max(crop_start_y - int(image.height / steps), 0) + crop_end_x = min(crop_end_x + int(image.width / steps), image.width - 1) + crop_end_y = min(crop_end_y + int(image.height / steps), image.height - 1) + + # Get only 1 pixel if start > end + if crop_start_x > crop_end_x: + crop_start_x = 0 + crop_end_x = 1 + if crop_start_y > crop_end_y: + crop_start_y = 0 + crop_end_y = 1 + + # Crop image + cropped_image = image.crop((crop_start_x, crop_start_y, + crop_end_x, crop_end_y)) + + print(f'trim: {cropped_image.width}x{cropped_image.height}+{crop_start_x}+{crop_start_y}') + + return { + 'image': cropped_image, + 'pos_x': crop_start_x, + 'pos_y': crop_start_y + } + + def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): + print(f'Process image {t_count}: {t_img_path}') + original_img = Image.open(t_img_path) # Scale image @@ -159,12 +219,19 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): height_size = int((float(original_img.height) * float(width_percent))) original_img = original_img.resize((t_width, height_size), Image.LANCZOS) - result_image = Image.new("RGB", (t_width, t_height), "white") + result_image = Image.new("RGB", (t_width, t_height), original_img.getpixel((0, 0))) width_pos = 0 height_pos = int(t_height / 2 - original_img.height / 2) result_image.paste(original_img, (width_pos, height_pos)) + crop_result = crop_image(result_image) + result_image = crop_result['image'] + + fd = open(t_save_to_path + '/' + 'trim.txt', mode="a+") + print(f'{result_image.width}x{result_image.height}' + f'+{crop_result["pos_x"]}+{crop_result["pos_y"]}', file=fd) + result_img_name = "{0:0{width}}.png".format(t_count, width=5) result_img_path = t_save_to_path + "/" + result_img_name result_image.save(result_img_path) From 961536453aaecb1b52eadebe9d138682d3aa9f61 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 5 Aug 2022 22:56:35 +0300 Subject: [PATCH 3/9] create_bootanimation: Use logging for logs output --- create_bootanimation.py | 55 +++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index d8f6edf..4cff16f 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -1,10 +1,17 @@ import argparse +import logging import os import tempfile +import time import zipfile + from PIL import Image + import gifextract +logging.basicConfig(level=logging.INFO) +_log = logging.getLogger(__name__) + def parse_arguments(): parser = argparse.ArgumentParser( @@ -43,52 +50,58 @@ def parse_arguments(): def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip): result = True if len(t_source) <= 0: - print("Error: source path is empty") + _log.error("source path is empty") result = False if os.path.exists(t_source) is False: - print("Error: path '{}' do not exist".format(t_source)) + _log.error("path '{}' do not exist".format(t_source)) result = False if t_width <= 0: - print("Error: width is too small: " + str(t_width)) + _log.error("width is too small: " + str(t_width)) result = False if t_height <= 0: - print("Error: height is too small: " + str(t_height)) + _log.error("height is too small: " + str(t_height)) result = False if t_fps <= 0: - print("Error: fps is too small: " + str(t_fps)) + _log.error("fps is too small: " + str(t_fps)) result = False if t_fps <= 0: - print("Error: fps is too small: " + str(t_fps)) + _log.error("fps is too small: " + str(t_fps)) result = False if len(t_save_to) <= 0: - print("Error: save_to path is empty") + _log.error("save_to path is empty") result = False return result def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip): + start = time.time() + + _log.info('start creating bootimage') + source_dir = "" temp_dir = None if os.path.isdir(t_source): source_dir = t_source elif os.path.isfile(t_source) and get_extension(t_source) == "gif": temp_dir = tempfile.TemporaryDirectory() + _log.info(f'extracting {t_source} to {temp_dir.name}') gifextract.processImage(t_source, temp_dir.name) source_dir = temp_dir.name + _log.debug(f'gif extracted to {source_dir}') else: - print("Error: invalid source path: " + t_source) + _log.error("invalid source path: " + t_source) return images = get_images_paths(source_dir) if len(images) <= 0: - print("Error: no images to process") + _log.error("no images to process") return if not os.path.exists(t_save_to): @@ -100,9 +113,9 @@ def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip): if not os.path.exists(dir_for_images): os.makedirs(dir_for_images) - count = 0 - for img in images: - count = transform_images(img, count, t_width, t_height, dir_for_images) + _log.info(f'{len(images)} images are ready to process') + for idx, img in enumerate(images): + transform_images(img, idx, t_width, t_height, dir_for_images) with open(path_to_desc_file, "a") as f: print("p 1 0 part0", file=f) @@ -117,7 +130,8 @@ def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip): zip_dir(dir_for_images, zip_file) zip_file.close() - print("Done") + end = time.time() + _log.info(f'done in {end - start} seconds') def get_extension(t_path): @@ -165,6 +179,8 @@ def crop_image(image, steps=100): # Get background color background_color = image_pixels[0, 0] + _log.debug(f'using background color {background_color}') + # Get image crop coords crop_start_x = image.width crop_start_y = image.height @@ -187,7 +203,7 @@ def crop_image(image, steps=100): crop_start_y = max(crop_start_y - int(image.height / steps), 0) crop_end_x = min(crop_end_x + int(image.width / steps), image.width - 1) crop_end_y = min(crop_end_y + int(image.height / steps), image.height - 1) - + # Get only 1 pixel if start > end if crop_start_x > crop_end_x: crop_start_x = 0 @@ -196,11 +212,14 @@ def crop_image(image, steps=100): crop_start_y = 0 crop_end_y = 1 + _log.debug(f'crop coords: ({crop_start_x},{crop_start_y}) - ' + f'({crop_end_x}, {crop_end_y})') + # Crop image cropped_image = image.crop((crop_start_x, crop_start_y, crop_end_x, crop_end_y)) - print(f'trim: {cropped_image.width}x{cropped_image.height}+{crop_start_x}+{crop_start_y}') + _log.debug(f'trim: {cropped_image.width}x{cropped_image.height}+{crop_start_x}+{crop_start_y}') return { 'image': cropped_image, @@ -210,7 +229,7 @@ def crop_image(image, steps=100): def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): - print(f'Process image {t_count}: {t_img_path}') + _log.info(f'processing image {t_count}: {t_img_path}') original_img = Image.open(t_img_path) @@ -225,8 +244,10 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): height_pos = int(t_height / 2 - original_img.height / 2) result_image.paste(original_img, (width_pos, height_pos)) + _log.debug(f'size before crop: {result_image.width}x{result_image.height}') crop_result = crop_image(result_image) result_image = crop_result['image'] + _log.debug(f'size after crop: {result_image.width}x{result_image.height}') fd = open(t_save_to_path + '/' + 'trim.txt', mode="a+") print(f'{result_image.width}x{result_image.height}' @@ -235,8 +256,6 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): result_img_name = "{0:0{width}}.png".format(t_count, width=5) result_img_path = t_save_to_path + "/" + result_img_name result_image.save(result_img_path) - t_count += 1 - return t_count def zip_dir(t_path, t_zip_file): From 4a65c8d3361516724db022ad2464d97c723be7df Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Sat, 6 Aug 2022 14:50:54 +0300 Subject: [PATCH 4/9] create_bootanimation: Pass color tolerance as parameter --- create_bootanimation.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index 4cff16f..18d7cb8 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -40,14 +40,19 @@ def parse_arguments(): help="path to the folder where result images should " "be saved") - parser.add_argument("-zip", action='store_true', + parser.add_argument("--zip", action='store_true', help="create bootanimation.zip with result images") + parser.add_argument("--tolerance", type=int, default=10, + help="set tolerance for detecting background color. " + "For background detection (0, 0) pixel used") + args = parser.parse_args() - return args.source, args.width, args.height, args.fps, args.save_to, args.zip + return args.source, args.width, args.height, args.fps, \ + args.save_to, args.zip, args.tolerance -def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip): +def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance): result = True if len(t_source) <= 0: _log.error("source path is empty") @@ -77,10 +82,14 @@ def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip): _log.error("save_to path is empty") result = False + if t_tolerance <= 0: + _log.error(f'background color tolerance is too small: {t_tolerance}') + result = False + return result -def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip): +def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance): start = time.time() _log.info('start creating bootimage') @@ -115,7 +124,7 @@ def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip): _log.info(f'{len(images)} images are ready to process') for idx, img in enumerate(images): - transform_images(img, idx, t_width, t_height, dir_for_images) + transform_images(img, idx, t_width, t_height, dir_for_images, t_tolerance) with open(path_to_desc_file, "a") as f: print("p 1 0 part0", file=f) @@ -171,7 +180,7 @@ def compare_colors(color_a, color_b, tolerance=10): abs(color_a[2] - color_b[2]) < tolerance -def crop_image(image, steps=100): +def crop_image(image, tolerance, steps=100): """Crop image""" image_pixels = image.load() @@ -189,7 +198,7 @@ def crop_image(image, steps=100): for x in range(0, image.width - 1, int(image.width / steps)): for y in range(0, image.height - 1, int(image.height / steps)): - if not compare_colors(image_pixels[x, y], background_color): + if not compare_colors(image_pixels[x, y], background_color, tolerance): if x < crop_start_x: crop_start_x = x if y < crop_start_y: @@ -203,7 +212,7 @@ def crop_image(image, steps=100): crop_start_y = max(crop_start_y - int(image.height / steps), 0) crop_end_x = min(crop_end_x + int(image.width / steps), image.width - 1) crop_end_y = min(crop_end_y + int(image.height / steps), image.height - 1) - + # Get only 1 pixel if start > end if crop_start_x > crop_end_x: crop_start_x = 0 @@ -228,7 +237,7 @@ def crop_image(image, steps=100): } -def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): +def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_tolerance): _log.info(f'processing image {t_count}: {t_img_path}') original_img = Image.open(t_img_path) @@ -245,7 +254,7 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path): result_image.paste(original_img, (width_pos, height_pos)) _log.debug(f'size before crop: {result_image.width}x{result_image.height}') - crop_result = crop_image(result_image) + crop_result = crop_image(result_image, t_tolerance) result_image = crop_result['image'] _log.debug(f'size after crop: {result_image.width}x{result_image.height}') From 1439321be8eb4056777c229e6be50e863a3d1062 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Sat, 6 Aug 2022 18:46:29 +0300 Subject: [PATCH 5/9] create_bootanimation: Specify colors count for output images --- create_bootanimation.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index 18d7cb8..d1d2ea9 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -47,12 +47,15 @@ def parse_arguments(): help="set tolerance for detecting background color. " "For background detection (0, 0) pixel used") + parser.add_argument("--colors", type=int, default=256, + help="set colors count for resulted images") + args = parser.parse_args() return args.source, args.width, args.height, args.fps, \ - args.save_to, args.zip, args.tolerance + args.save_to, args.zip, args.tolerance, args.colors -def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance): +def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_colors): result = True if len(t_source) <= 0: _log.error("source path is empty") @@ -86,10 +89,14 @@ def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance _log.error(f'background color tolerance is too small: {t_tolerance}') result = False + if t_colors <= 0: + _log.error(f'colors count is too small: {t_colors}') + result = False + return result -def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance): +def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_colors): start = time.time() _log.info('start creating bootimage') @@ -124,7 +131,7 @@ def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance): _log.info(f'{len(images)} images are ready to process') for idx, img in enumerate(images): - transform_images(img, idx, t_width, t_height, dir_for_images, t_tolerance) + transform_images(img, idx, t_width, t_height, dir_for_images, t_tolerance, t_colors) with open(path_to_desc_file, "a") as f: print("p 1 0 part0", file=f) @@ -237,7 +244,7 @@ def crop_image(image, tolerance, steps=100): } -def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_tolerance): +def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_tolerance, t_colors): _log.info(f'processing image {t_count}: {t_img_path}') original_img = Image.open(t_img_path) @@ -253,6 +260,7 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_t height_pos = int(t_height / 2 - original_img.height / 2) result_image.paste(original_img, (width_pos, height_pos)) + # Crop image _log.debug(f'size before crop: {result_image.width}x{result_image.height}') crop_result = crop_image(result_image, t_tolerance) result_image = crop_result['image'] @@ -262,6 +270,9 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_t print(f'{result_image.width}x{result_image.height}' f'+{crop_result["pos_x"]}+{crop_result["pos_y"]}', file=fd) + # Convert image to adaptive palette colors + result_image = result_image.convert('P', palette=Image.ADAPTIVE, colors=t_colors) + result_img_name = "{0:0{width}}.png".format(t_count, width=5) result_img_path = t_save_to_path + "/" + result_img_name result_image.save(result_img_path) From 4d090d7987181a6fe2df0d11c18566102b5f334a Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Mon, 8 Aug 2022 11:13:22 +0300 Subject: [PATCH 6/9] readme: Update usage --- README.md | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0ede5dd..2ebf3bf 100644 --- a/README.md +++ b/README.md @@ -6,15 +6,22 @@ Create Android bootanimation from .gif or .png images ## Usage - $python3 create_bootanimation.py SOURCE_FOLDER WIDTH HEIGHT FPS SAVE_TO_FOLDER -ZIP - -* SOURCE_FOLDER - absolute path to the folder with .gif image or .png -images. If you specify .gif image, it will be unpacked to .png images. -* WIDTH - width of the device screen -* HEIGHT - height of the device screen -* FPS - speed at which images will be displayed -* SAVE_TO_FOLDER - folder where result files will be saved -* -ZIP - (optional) create bootanimation.zip with result files +usage: `create_bootanimation.py [-h] [--zip] [--tolerance TOLERANCE] [--colors COLORS] source width height fps save_to` + +Create Android bootanimation.zip from .gif or bunch of images + +positional arguments: + * `source` - Absolute path to the GIF file or folder with images. Expected image name format: xxxx-001.png Where: xxx - some image name; 001 - image number. + * `width` - Width of result images in pixels. You should use width of the device screen + * `height` - Height of result images in pixels. You should use height of the device screen + * `fps` - FPS (Frames Per Second) for animation + * `save_to` - path to the folder where result images should be saved + +optional arguments: + * `-h, --help` - show this help message and exit + * `--zip` - create bootanimation.zip with result images + * `--tolerance TOLERANCE` - set tolerance for detecting background color. For background detection (0, 0) pixel used + * `--colors COLORS` - set colors count for resulted images ## Examples From 6a41c0d2ef42275e35ff7d79c10a6c7e48196d2c Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Wed, 10 Aug 2022 16:23:26 +0300 Subject: [PATCH 7/9] create_bootanimation: Add `steps` script parameter --- create_bootanimation.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index d1d2ea9..59898dd 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -50,12 +50,17 @@ def parse_arguments(): parser.add_argument("--colors", type=int, default=256, help="set colors count for resulted images") + parser.add_argument("--steps", type=int, default=100, + help="set steps count for scanning image") + args = parser.parse_args() return args.source, args.width, args.height, args.fps, \ - args.save_to, args.zip, args.tolerance, args.colors + args.save_to, args.zip, args.tolerance, args.colors, \ + args.steps -def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_colors): +def check_args(t_source, t_width, t_height, t_fps, t_save_to, + t_zip, t_tolerance, t_colors, t_steps): result = True if len(t_source) <= 0: _log.error("source path is empty") @@ -93,10 +98,14 @@ def check_args(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance _log.error(f'colors count is too small: {t_colors}') result = False + if t_steps <= 0: + _log.error(f'steps count is too small: {t_steps}') + result = False + return result -def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_colors): +def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_colors, t_steps): start = time.time() _log.info('start creating bootimage') @@ -131,7 +140,7 @@ def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_co _log.info(f'{len(images)} images are ready to process') for idx, img in enumerate(images): - transform_images(img, idx, t_width, t_height, dir_for_images, t_tolerance, t_colors) + transform_images(img, idx, t_width, t_height, dir_for_images, t_tolerance, t_colors, t_steps) with open(path_to_desc_file, "a") as f: print("p 1 0 part0", file=f) @@ -244,7 +253,8 @@ def crop_image(image, tolerance, steps=100): } -def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_tolerance, t_colors): +def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, + t_tolerance, t_colors, t_steps): _log.info(f'processing image {t_count}: {t_img_path}') original_img = Image.open(t_img_path) @@ -262,7 +272,7 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, t_t # Crop image _log.debug(f'size before crop: {result_image.width}x{result_image.height}') - crop_result = crop_image(result_image, t_tolerance) + crop_result = crop_image(result_image, tolerance=t_tolerance, steps=t_steps) result_image = crop_result['image'] _log.debug(f'size after crop: {result_image.width}x{result_image.height}') From 73ecd3961c0b2ced57ac4f7bea59c027e859517e Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 30 Dec 2022 16:00:29 +0300 Subject: [PATCH 8/9] create_bootanimation: Fix trim file writing --- create_bootanimation.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/create_bootanimation.py b/create_bootanimation.py index 59898dd..51600df 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -140,7 +140,8 @@ def main(t_source, t_width, t_height, t_fps, t_save_to, t_zip, t_tolerance, t_co _log.info(f'{len(images)} images are ready to process') for idx, img in enumerate(images): - transform_images(img, idx, t_width, t_height, dir_for_images, t_tolerance, t_colors, t_steps) + transform_images(img, idx, t_width, t_height, dir_for_images, + t_tolerance, t_colors, t_steps) with open(path_to_desc_file, "a") as f: print("p 1 0 part0", file=f) @@ -262,7 +263,7 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, # Scale image width_percent = (t_width / float(original_img.width)) height_size = int((float(original_img.height) * float(width_percent))) - original_img = original_img.resize((t_width, height_size), Image.LANCZOS) + original_img = original_img.resize((t_width, height_size), Image.Resampling.LANCZOS) result_image = Image.new("RGB", (t_width, t_height), original_img.getpixel((0, 0))) @@ -276,12 +277,12 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, result_image = crop_result['image'] _log.debug(f'size after crop: {result_image.width}x{result_image.height}') - fd = open(t_save_to_path + '/' + 'trim.txt', mode="a+") - print(f'{result_image.width}x{result_image.height}' - f'+{crop_result["pos_x"]}+{crop_result["pos_y"]}', file=fd) + with open(t_save_to_path + '/' + 'trim.txt', mode="a+") as trim_file: + trim_file.write(f'{result_image.width}x{result_image.height}' + f'+{crop_result["pos_x"]}+{crop_result["pos_y"]}\n') # Convert image to adaptive palette colors - result_image = result_image.convert('P', palette=Image.ADAPTIVE, colors=t_colors) + result_image = result_image.convert('P', palette=Image.Palette.ADAPTIVE, colors=t_colors) result_img_name = "{0:0{width}}.png".format(t_count, width=5) result_img_path = t_save_to_path + "/" + result_img_name From d2e6085f152216c2d8e91c4572a74353cdb9839c Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Fri, 13 Oct 2023 18:28:54 +0300 Subject: [PATCH 9/9] create_bootanimation: Update readme Signed-off-by: Dmitry Dmitriev --- README.md | 42 +++++++++++++++++++++++++---------------- create_bootanimation.py | 4 ++-- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 2ebf3bf..9c2a9f8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,15 @@ Create Android bootanimation from .gif or .png images +## Fast bash commands + +```bash +python create_bootanimation.py ../input/1 1440 3120 50 ../input/output/1 --steps 200 --colors 16 --tolerance 1 +python create_bootanimation.py ../input/2 1440 3120 50 ../input/output/2 --steps 200 --colors 16 --tolerance 1 + +zip -0qry -i \*.txt \*.png \*.wav @ ../bootanimation.zip *.txt part* +``` + ## Usage usage: `create_bootanimation.py [-h] [--zip] [--tolerance TOLERANCE] [--colors COLORS] source width height fps save_to` @@ -11,29 +20,30 @@ usage: `create_bootanimation.py [-h] [--zip] [--tolerance TOLERANCE] [--colors C Create Android bootanimation.zip from .gif or bunch of images positional arguments: - * `source` - Absolute path to the GIF file or folder with images. Expected image name format: xxxx-001.png Where: xxx - some image name; 001 - image number. - * `width` - Width of result images in pixels. You should use width of the device screen - * `height` - Height of result images in pixels. You should use height of the device screen - * `fps` - FPS (Frames Per Second) for animation - * `save_to` - path to the folder where result images should be saved + +- `source` - Absolute path to the GIF file or folder with images. Expected image name format: xxxx-001.png Where: xxx - + some image name; 001 - image number. +- `width` - Width of result images in pixels. You should use width of the device screen +- `height` - Height of result images in pixels. You should use height of the device screen +- `fps` - FPS (Frames Per Second) for animation +- `save_to` - path to the folder where result images should be saved optional arguments: - * `-h, --help` - show this help message and exit - * `--zip` - create bootanimation.zip with result images - * `--tolerance TOLERANCE` - set tolerance for detecting background color. For background detection (0, 0) pixel used - * `--colors COLORS` - set colors count for resulted images + +- `-h, --help` - show this help message and exit +- `--zip` - create bootanimation.zip with result images +- `--tolerance TOLERANCE` - set tolerance for detecting background color. For background detection (0, 0) pixel used +- `--colors COLORS` - set colors count for resulted images ## Examples -Create bootanimation.zip in '/path/to/result_folder' folder from images, that -was unpacked from example.gif, for device with HD screen resolution (1280x720) -and set FPS to 24: +Create bootanimation.zip in '/path/to/result_folder' folder from images, that was unpacked from example.gif, for device +with HD screen resolution (1280x720) and set FPS to 24: $ python3 create_bootanimation.py /path/to/example.gif 720 1280 24 /path/to/result_folder -zip -Create bootanimation.zip in '/path/to/result_folder' folder with images from -folder 'folder_with_images' for device with HD screen resolution (1920x1080) -and set FPS to 60: +Create bootanimation.zip in '/path/to/result_folder' folder with images from folder 'folder_with_images' for device with +HD screen resolution (1920x1080) and set FPS to 60: $ python3 create_bootanimation.py /path/to/folder_with_images 1080 1920 60 /path/to/result_folder @@ -43,4 +53,4 @@ Show help: ## Additional Info -* https://forum.xda-developers.com/showthread.php?t=2756198 +- https://forum.xda-developers.com/showthread.php?t=2756198 diff --git a/create_bootanimation.py b/create_bootanimation.py index 51600df..76647a7 100644 --- a/create_bootanimation.py +++ b/create_bootanimation.py @@ -263,7 +263,7 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, # Scale image width_percent = (t_width / float(original_img.width)) height_size = int((float(original_img.height) * float(width_percent))) - original_img = original_img.resize((t_width, height_size), Image.Resampling.LANCZOS) + original_img = original_img.resize((t_width, height_size), Image.LANCZOS) result_image = Image.new("RGB", (t_width, t_height), original_img.getpixel((0, 0))) @@ -282,7 +282,7 @@ def transform_images(t_img_path, t_count, t_width, t_height, t_save_to_path, f'+{crop_result["pos_x"]}+{crop_result["pos_y"]}\n') # Convert image to adaptive palette colors - result_image = result_image.convert('P', palette=Image.Palette.ADAPTIVE, colors=t_colors) + result_image = result_image.convert('P', palette=Image.ADAPTIVE, colors=t_colors) result_img_name = "{0:0{width}}.png".format(t_count, width=5) result_img_path = t_save_to_path + "/" + result_img_name