From 961ee13ba1772c5a6bbe1f4e7cd0deb0ac7e76fa Mon Sep 17 00:00:00 2001 From: James David Clarke Date: Wed, 10 Jan 2024 11:48:41 +0000 Subject: [PATCH] Converted utils os.system commands to useing the more pythonic: wand, library. And partially converted armor os.system commands to wand too. --- .../special_convert_cases.py | 127 +++++++++--------- tools/libtextureconverter/utils.py | 78 +++++++---- tools/requirements.txt | 1 + 3 files changed, 117 insertions(+), 89 deletions(-) diff --git a/tools/libtextureconverter/special_convert_cases.py b/tools/libtextureconverter/special_convert_cases.py index 71af2b6f2..0ad05b3da 100644 --- a/tools/libtextureconverter/special_convert_cases.py +++ b/tools/libtextureconverter/special_convert_cases.py @@ -6,6 +6,11 @@ import tempfile import sys import argparse import glob +from wand.image import Image +from wand.color import Color +from wand.display import display +from wand.drawing import Drawing +import warnings # Conversion of map backgrounds def convert_map_textures( @@ -23,21 +28,18 @@ def convert_map_textures( # Convert map background map_background_file = tex_dir + "/map/map_background.png" if os.path.isfile(map_background_file): - os.system( - "convert " + - map_background_file + - " -interpolate Integer -filter point -resize \"140x140\" " + - target_dir( - "/mods/ITEMS/mcl_maps/textures", - make_texture_pack, - output_dir, - output_dir_name, - mineclone2_path) + - "/mcl_maps_map_background.png") + destination_path = target_dir("/mods/ITEMS/mcl_maps/textures", make_texture_pack, output_dir, output_dir_name, mineclone2_path) + "/mcl_maps_map_background.png" + + with Image(filename=map_background_file) as img: + # Resize the image with 'point' filter + img.resize(140, 140, filter='point') + + # Save the result + img.save(filename=destination_path) + # Convert armor textures - def convert_armor_textures( make_texture_pack, dry_run, @@ -126,6 +128,7 @@ def convert_armor_textures( helmet = adir + "/" + a[3] chestplate = adir + "/" + a[4] boots = adir + "/" + a[6] + # helmet os.system("convert -size " + str(APXSIZE * 4) + @@ -150,59 +153,53 @@ def convert_armor_textures( str(APXSIZE) + "+0+0 \\) -composite -channel A -fx \"(a > 0.0) ? 1.0 : 0.0\" " + helmet) - os.system("convert -size " + - str(APXSIZE * - 4) + - "x" + - str(APXSIZE * - 2) + - " xc:none \\( " + - layer_1 + - " -scale " + - str(APXSIZE * - 4) + - "x" + - str(APXSIZE * - 2) + - " -geometry +" + - str(APXSIZE) + - "+" + - str(APXSIZE) + - " -crop " + - str(APXSIZE * - 2.5) + - "x" + - str(APXSIZE) + - "+" + - str(APXSIZE) + - "+" + - str(APXSIZE) + - " \\) -composite -channel A -fx \"(a > 0.0) ? 1.0 : 0.0\" " + - chestplate) - os.system("convert -size " + - str(APXSIZE * - 4) + - "x" + - str(APXSIZE * - 2) + - " xc:none \\( " + - layer_1 + - " -scale " + - str(APXSIZE * - 4) + - "x" + - str(APXSIZE * - 2) + - " -geometry +0+" + - str(APXSIZE) + - " -crop " + - str(APXSIZE) + - "x" + - str(APXSIZE) + - "+0+" + - str(APXSIZE) + - " \\) -composite -channel A -fx \"(a > 0.0) ? 1.0 : 0.0\" " + - boots) + + + + # chestplate + with Image(width=APXSIZE * 4, height=APXSIZE * 2, background=Color('none')) as img: + # Load layer_1 and scale + with Image(filename=layer_1) as layer1: + layer1.resize(APXSIZE * 4, APXSIZE * 2) + + # Define the crop geometry + crop_width = int(APXSIZE * 2.5) + crop_height = APXSIZE + crop_x = APXSIZE + crop_y = APXSIZE + + # Crop the image + layer1.crop(crop_x, crop_y, width=crop_width, height=crop_height) + + # Composite layer1 over the transparent image + img.composite(layer1, APXSIZE, APXSIZE) + + # Apply channel operation + img.fx("a > 0.0 ? 1.0 : 0.0", channel='alpha') + + # Save the result + img.save(filename=chestplate) + with Image(width=APXSIZE * 4, height=APXSIZE * 2, background=Color('none')) as img: + with Image(filename=layer_1) as layer1: + # Scale the image + layer1.resize(APXSIZE * 4, APXSIZE * 2) + + # Crop the image + crop_x = 0 + crop_y = APXSIZE + crop_width = APXSIZE + crop_height = APXSIZE + layer1.crop(crop_x, crop_y, width=crop_width, height=crop_height) + + # Composite the cropped image over the transparent image + img.composite(layer1, 0, APXSIZE) + + # Apply the channel operation + img.fx("a > 0.0 ? 1.0 : 0.0", channel='alpha') + + # Save the result + img.save(filename=boots) + if os.path.isfile(layer_2): leggings = adir + "/" + a[5] os.system("convert -size " + diff --git a/tools/libtextureconverter/utils.py b/tools/libtextureconverter/utils.py index 7d9cce7f1..3756574f6 100644 --- a/tools/libtextureconverter/utils.py +++ b/tools/libtextureconverter/utils.py @@ -8,11 +8,15 @@ import glob import re import zipfile from .config import SUPPORTED_MINECRAFT_VERSION, home -from PIL import Image from collections import Counter import platform +from wand.image import Image +from wand.color import Color +from wand.display import display +import warnings def detect_pixel_size(directory): + from PIL import Image sizes = [] for filename in glob.glob(directory + '/**/*.png', recursive=True): with Image.open(filename) as img: @@ -24,7 +28,6 @@ def detect_pixel_size(directory): f"Autodetected pixel size: {most_common_size[0]}x{most_common_size[1]}") return most_common_size[0] - def target_dir( directory, make_texture_pack, @@ -37,26 +40,42 @@ def target_dir( return mineclone2_path + directory -def colorize( - colormap, - source, - colormap_pixel, - texture_size, - destination, - tempfile1_name): - os.system( - "convert " + - colormap + - " -crop 1x1+" + - colormap_pixel + - " -depth 8 -resize " + - texture_size + - "x" + - texture_size + - " " + - tempfile1_name) - os.system("composite -compose Multiply " + - tempfile1_name + " " + source + " " + destination) +def colorize(colormap, source, colormap_pixel, texture_size, destination, tempfile1_name): + try: + # Convert the colormap_pixel to integer coordinates + x, y = map(int, colormap_pixel.split('+')) + + # Define texture size as integer + texture_size = int(texture_size) + + with Image(filename=colormap) as img: + # Crop the image + img.crop(x, y, width=1, height=1) + + # Set depth (This might be ignored by Wand as it manages depth automatically) + img.depth = 8 + + # Resize the image + img.resize(texture_size, texture_size) + + # Save the result + img.save(filename=tempfile1_name) + + except Exception as e: + warnings.warn(f"An error occurred during the first image processing operation: {e}") + + try: + # Load the images + with Image(filename=tempfile1_name) as top_image: + with Image(filename=source) as bottom_image: + # Perform composite operation with Multiply blend mode + bottom_image.composite(top_image, 0, 0, operator='multiply') + + # Save the result + bottom_image.save(filename=destination) + + except Exception as e: + warnings.warn(f"An error occurred during the second image processing operation: {e}") def colorize_alpha( @@ -68,8 +87,19 @@ def colorize_alpha( tempfile2_name): colorize(colormap, source, colormap_pixel, texture_size, destination, tempfile2_name) - os.system("composite -compose Dst_In " + source + " " + - tempfile2_name + " -alpha Set " + destination) + try: + with Image(filename=source) as source_image: + with Image(filename=tempfile2_name) as tempfile2_image: + # Perform composite operation with Dst_In blend mode + tempfile2_image.composite(source_image, 0, 0, operator='dst_in') + + # Set alpha channel + tempfile2_image.alpha_channel = 'set' + + # Save the result + tempfile2_image.save(filename=destination) + except Exception as e: + warnings.warn(f"An error occurred during the second image processing operation: {e}") def find_highest_minecraft_version(home, supported_version): diff --git a/tools/requirements.txt b/tools/requirements.txt index 7e2fba5e6..f4c5a4016 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1 +1,2 @@ Pillow +Wand