Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #! python3
- #### Use python 3.7, required libs: PIL (pip install Pillow) and Numpy (pip install numpy)
- #### By AgentM
- #### https://pastebin.com/c9CNndT6
- #### Last update: Oct 21, 2019 @ 21:50 UTC+1:00
- #### Just run the file using python <this_file_name>
- #### Alternatively you can run it with ./<this_file_name>
- import numpy as np
- import shutil
- import os
- import sys
- import time
- import json
- from PIL import Image, ImageOps, ImageStat
- from os import walk
- from os import mkdir
- from os import listdir
- from os.path import exists
- from os.path import isfile
- from os.path import isdir
- from os.path import join as path_join
- from shutil import copyfile
- from threading import Thread
- IN = 'in'
- OUT = 'out'
- ################################## MAIN ##################################
- def main():
- args = sys.argv[1:]
- if (len(args) > 0):
- if (args[0] == 'help'):
- show_help()
- elif (args[0] == 'auto-contrast'):
- benchmark(auto_contrast_routine)
- elif (args[0] == 'colorize'):
- if (len(args) > 6):
- colors = ((float(args[1]), float(args[2]), float(args[3])), (float(args[4]), float(args[5]), float(args[6])))
- benchmark(colorize_routine, colors)
- else:
- print('Missing argument <colors>')
- elif (args[0] == 'color'):
- if (len(args) > 3):
- color = (float(args[1]), float(args[2]), float(args[3]))
- benchmark(color_routine, color)
- else:
- print('Missing argument <color>')
- elif (args[0] == 'grayscale'):
- benchmark(grayscale_routine)
- elif (args[0] == 'blend'):
- if (len(args) > 1):
- alpha = 0.5
- if (len(args) > 2):
- alpha = float(args[2])
- benchmark(blend_routine, (args[1], alpha))
- else:
- print('Missing argument <blend img>')
- elif (args[0] == 'shift-hue'):
- amount = 1
- if (len(args) > 1):
- amount = int(args[1])
- benchmark(hue_shift_routine, amount)
- elif(args[0] == 'posterize'):
- bits = 3
- if (len(args) > 1):
- bits = int(args[1])
- benchmark(posterize_routine, bits)
- elif(args[0] == 'solarize'):
- threshold = 0.5
- if (len(args) > 1):
- threshold = float(args[1])
- benchmark(solarize_routine, threshold)
- elif(args[0] == 'mean'):
- benchmark(mean_routine)
- elif (args[0] == 'invert'):
- if (len(args) > 1):
- benchmark(invert_routine, to_bool(args[1]))
- else:
- benchmark(invert_routine)
- elif (args[0] == 'threshold'):
- if (len(args) > 1):
- benchmark(threshold_routine, float(args[1]))
- else:
- benchmark(threshold_routine)
- elif (args[0] == 'rainbow'):
- if (len(args) > 1):
- interpolate = True
- speed = int(args[1])
- if (len(args) > 2):
- interpolate = args[2].lower() == 'true'
- benchmark(rainbow_routine, (speed, interpolate))
- else:
- benchmark(rainbow_routine)
- else:
- usage()
- else:
- usage()
- ############################## COMMAND INFO ##############################
- def usage():
- file_name = sys.argv[0]
- print(' Usage: python %s <mode> [mode arguments]' % file_name)
- def show_help():
- file_name = sys.argv[0]
- print(' Usage: %s <mode> [mode arguments]' % file_name)
- print(' or: %s help View this help page.' % file_name)
- print(' ')
- print(' Available modes:')
- print(' %s auto-contrast Amplify the contrast to the max!' % file_name)
- print(' %s blend <blend img> [alpha] Interpolate with blend img using alpha!' % file_name)
- print(' %s color <r> <g> <b> Convert to a color as r, g and b (between 0 and 1 inclusive)' % file_name)
- print(' %s colorize <black_rgb> <white_rgb> Colorize for white and black colors' % file_name)
- print(' %s grayscale Convert to grayscale' % file_name)
- print(' %s invert [invert-alpha] Invert all colors (and alpha, if passed "True")' % file_name)
- print(' %s mean Takes the mean color value and uses it to fill the image' % file_name)
- print(' %s posterize [bits] Change the bit-depth of the image' % file_name)
- print(' %s shift-hue [amount] Shifts hue r->g->b->r by "amount" times' % file_name)
- print(' %s solarize [threshold] Inverts any pixels above the threshold' % file_name)
- print(' %s rainbow [time] [interpolate] ???' % file_name)
- print(' %s threshold [cut-off] All values on or above the cut-off will be 255, all others: 0' % file_name)
- ################################ ROUTINES ################################
- def rainbow_routine(args=(20, True)):
- csi = rainbow_color_image()
- alpha = 0.25
- print('Applying "Rainbow (%s, %s)":' % (str(args[0]), str(args[1])))
- convert_all_file_locations_special(rainbow, blend_no_alpha, args, (csi, alpha))
- print('Done!')
- def solarize_routine(threshold = 0.5):
- print('Applying "Solarize (%s)":' % str(threshold))
- convert_all_file_locations(solarize, threshold)
- print('Done!')
- def posterize_routine(bits = 3):
- print('Applying "Posterize (%s)":' % str(bits))
- convert_all_file_locations(posterize, bits)
- print('Done!')
- def auto_contrast_routine():
- print('Applying "Auto Contrast":')
- convert_all_file_locations(auto_contrast)
- print('Done!')
- def blend_routine(args):
- csi = Image.open(args[0]).convert('RGBA')
- print('Applying "Colorize (%s, %s)":' % (args[0], str(args[1])))
- convert_all_file_locations(blend, (csi, args[1]))
- print('Done!')
- def colorize_routine(colors):
- print('Applying "Colorize (%s, %s)":' % (str(colors[0]), str(colors[1])))
- convert_all_file_locations(colorize, colors)
- print('Done!')
- def mean_routine():
- print('Applying "Mean":')
- convert_all_file_locations(single_color)
- print('Done!')
- # Every value on or above the threshold will be 255, everything below will be 0
- def threshold_routine(cut_off_point = 0.5):
- print('Applying "Threshold (%s)":' % str(cut_off_point))
- convert_all_file_locations(f_threshold, cut_off_point)
- print('Done!')
- def invert_routine(alpha = False):
- print('Applying "Invert%s":' % ' (including alpha)' if alpha else ' ')
- convert_all_file_locations(invert, alpha)
- print('Done!')
- def hue_shift_routine(amount):
- print('Applying "Shift Hue (%s)":' % str(amount))
- convert_all_file_locations(hue_shift, amount)
- print('Done!')
- def color_routine(color):
- print('Applying "Color (%s)":' % str(color))
- convert_all_file_locations(colorize_self, color)
- print('Done!')
- def grayscale_routine():
- print('Applying "Grayscale":')
- convert_all_file_locations(convert_image_grayscale)
- print('Done!')
- ############################### ACTUAL FUNCTIONS ###############################
- def blend_no_alpha(img_name, args):
- blend_img, alpha = args
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- r, g, b, a = rgba_img.split()
- if (blend_img.size != rgba_img.size):
- blend_img = blend_img.resize(rgba_img.size)
- r2, g2, b2, a2 = Image.blend(rgba_img, blend_img, alpha).split()
- img = Image.merge('RGBA', (r2, g2, b2, a))
- img.save(OUT + '/' + img_name)
- img.close()
- rgba_img.close()
- def rainbow(img_name, args):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- la_img = rgba_img.convert('LA')
- l, a = la_img.split()
- colors_size = 6
- colors_w = [(255, 0, 0), (255, 255, 0), (0, 255, 0), (0, 255, 255), (0, 0, 255), (255, 0, 255)]
- colors_b = [(0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0)]
- w, h = rgba_img.size
- aspect = 1
- if (w != 0):
- aspect = int(h / w)
- x = np.lcm(colors_size, aspect)
- l_split = [l.crop((0, w*i, w, w*(i + 1))) for i in range(0, aspect)]
- a_split = [a.crop((0, w*i, w, w*(i + 1))) for i in range(0, aspect)]
- colorset = [colors_b, colors_w]
- rgb_colorized = [ImageOps.colorize(l_split[i % aspect], colorset[0][i % colors_size], colorset[1][i % colors_size]) for i in range(0, x)]
- rgba_colorized = [Image.merge('RGBA', rgb_colorized[i].split() + (a_split[i % aspect],)) for i in range(0, len(rgb_colorized))]
- new_img = Image.new('RGBA', (w, w*x))
- [new_img.paste(rgba_colorized[i], (0, w*i, w, w*(i+1))) for i in range(0, x)]
- new_img.save(OUT + '/' + img_name)
- new_img.close()
- [img.close() for img in rgba_colorized]
- [img.close() for img in rgb_colorized]
- la_img.close()
- rgba_img.close()
- generate_mcmeta(img_name, args)
- def generate_mcmeta(filename, args):
- speed, inter = args
- interpolate = 'true' if inter else 'false'
- filepath = '%s/%s.mcmeta' % (OUT, filename)
- file_json = {}
- if isfile(filepath):
- with open(filepath, 'r') as file:
- file_json = json.load(file)
- mcmeta_json = {'animation':{'interpolate': interpolate, 'frametime': speed}}
- file_json.update(mcmeta_json)
- with open(filepath, 'w+') as file:
- json.dump(file_json, file, indent=2, sort_keys=True)
- def built_in_rgb(function, img_name, arg = None):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- r, g, b, a = rgba_img.split()
- rgb_img = Image.merge('RGB', (r,g,b))
- if (arg is None):
- edited_img = function(rgb_img)
- else:
- edited_img = function(Image.merge('RGB', (r,g,b)), arg)
- r2, g2, b2 = edited_img.split()
- img = Image.merge('RGBA', (r2, g2, b2, a))
- img.save(OUT + '/' + img_name)
- img.close()
- edited_img.close()
- rgb_img.close()
- rgba_img.close()
- def auto_contrast(img_name):
- built_in_rgb(ImageOps.autocontrast, img_name)
- def solarize(img_name, threshold = 0.5):
- built_in_rgb(ImageOps.solarize, img_name, (255 * threshold))
- def posterize(img_name, bits = 3):
- built_in_rgb(ImageOps.posterize, img_name, bits)
- def blend(img_name, args):
- blend_img, alpha = args
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- if (blend_img.size != rgba_img.size):
- blend_img = blend_img.resize(rgba_img.size)
- img = Image.blend(rgba_img, blend_img, alpha)
- img.save(OUT + '/' + img_name)
- img.close()
- rgba_img.close()
- def colorize(img_name, colors):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- la_img = rgba_img.convert('LA')
- l, a = la_img.split()
- black_color, white_color = colors
- c_black_color = [255 * x for x in black_color]
- c_white_color = [255 * x for x in white_color]
- colorized = ImageOps.colorize(l, c_black_color, c_white_color)
- r, g, b = colorized.split()
- img = Image.merge('RGBA', (r, g, b, a))
- img.save(OUT + '/' + img_name)
- img.close()
- colorized.close()
- la_img.close()
- rgba_img.close()
- def single_color(img_name):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- r, g, b, a = rgba_img.split()
- rgb_img = Image.merge('RGB', (r, g, b))
- m = mean(rgb_img, a)
- mean_int = [int(f) for f in m]
- sc_img = Image.new('RGB', rgba_img.size, tuple(mean_int))
- r2, g2, b2 = sc_img.split()
- img = Image.merge('RGBA', (r2, g2, b2, a))
- img.save(OUT + '/' + img_name)
- img.close()
- sc_img.close()
- rgb_img.close()
- rgba_img.close()
- # Calculate the mean of all pixels in an image ignoring completely transparent pixels
- def mean(rgb, a):
- a_arr = np.array(a)
- img_arr = np.array(rgb)
- mask = (a_arr > 0) # Create mask from all non-transparent pixels
- ntp = img_arr[mask] # Array containing all pixels that aren't transparent
- rows = len(ntp)
- if rows < 1:
- return (0, 0, 0)
- cols = len(ntp[0])
- data = np.zeros([cols, rows, 3], dtype = np.uint8)
- data[:] = ntp
- c_img = Image.fromarray(data, 'RGB')
- m = ImageStat.Stat(c_img).mean
- c_img.close()
- return m
- # Note, this function doesn't apply a threshold to alpha as it isn't used much in the game.
- def f_threshold(img_name, cut_off_point = 0.5):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- rgba_array = np.array(rgba_img)
- w, h = rgba_img.size
- data = np.zeros([h, w, 4], dtype = np.uint8)
- r, g, b, a = init_arrays4(w, h)
- r[:] = rgba_array[..., 0]
- g[:] = rgba_array[..., 1]
- b[:] = rgba_array[..., 2]
- a[:] = rgba_array[..., 3]
- c = 256 * cut_off_point
- r[r < c] = 0
- r[r >= c] = 255
- g[g < c] = 0
- g[g >= c] = 255
- b[b < c] = 0
- b[b >= c] = 255
- data[..., 0] = r
- data[..., 1] = g
- data[..., 2] = b
- data[..., 3] = a
- img = Image.fromarray(data, 'RGBA')
- img.save(OUT + '/' + img_name)
- img.close()
- rgba_img.close()
- # Colorize the image to a single color with respected luminosity
- def colorize_self(img_name, color):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- la_img = rgba_img.convert('LA')
- # Get the array representations
- rgba_array = np.array(rgba_img)
- gray_array = np.array(la_img)
- # Flatmap arrays on last value
- flat_orig_r = np.concatenate(rgba_array[..., 0], axis = 0);
- flat_orig_g = np.concatenate(rgba_array[..., 1], axis = 0);
- flat_orig_b = np.concatenate(rgba_array[..., 2], axis = 0);
- flat_gray = np.concatenate(gray_array[..., 0], axis = 0);
- x = max(flat_gray)
- if (x != 0):
- factor = max([max(flat_orig_g), max(flat_orig_b), max(flat_orig_r)]) / x
- else:
- factor = 0
- # Fill the data array
- w, h = rgba_img.size
- data = np.zeros([h, w, 4], dtype = np.uint8)
- r, g, b, a = init_arrays4(w, h)
- r[:] = gray_array[..., 0] * factor * color[0]
- g[:] = gray_array[..., 0] * factor * color[1]
- b[:] = gray_array[..., 0] * factor * color[2]
- a[:] = rgba_array[..., 3]
- data[..., 0] = r
- data[..., 1] = g
- data[..., 2] = b
- data[..., 3] = a
- img = Image.fromarray(data, 'RGBA')
- img.save(OUT + '/' + img_name)
- img.close()
- la_img.close()
- rgba_img.close()
- def invert(img_name, invert_alpha = False):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- r, g, b, a = rgba_img.split()
- inverted_img = ImageOps.invert(Image.merge('RGB', (r,g,b)))
- r2, g2, b2 = inverted_img.split()
- if invert_alpha:
- a = a.point(lambda p: 255 - p)
- img = Image.merge('RGBA', (r2,g2,b2,a))
- img.save(OUT + '/' + img_name)
- img.close()
- inverted_img.close()
- rgba_img.close()
- # Shift the hue from r to g, from g to b, from b to r
- def hue_shift(img_name, amount):
- rgba_img = Image.open(IN + '/' + img_name).convert('RGBA')
- rgba_array = np.array(rgba_img)
- w, h = rgba_img.size
- data = np.zeros([h, w, 4], dtype = np.uint8)
- r, g, b, a = init_arrays4(w, h)
- r[:] = rgba_array[..., 0]
- g[:] = rgba_array[..., 1]
- b[:] = rgba_array[..., 2]
- a[:] = rgba_array[..., 3]
- r, g, b = swap(r, g, b, amount)
- data[..., 0] = r
- data[..., 1] = g
- data[..., 2] = b
- data[..., 3] = a
- img = Image.fromarray(data, 'RGBA')
- img.save(OUT + '/' + img_name)
- img.close()
- rgba_img.close()
- # Grab original image and convert to gray
- def convert_image_grayscale(img_name):
- gray_img = Image.open(IN + '/' + img_name).convert('LA')
- gray_img.save(OUT + '/' + img_name)
- gray_img.close()
- ################################ AUXILARY ################################
- def benchmark(function, arg = None):
- start_time = time.time()
- if arg is None:
- function()
- else:
- function(arg)
- if (__debug__):
- elapsed_time = time.time() - start_time
- print_time(elapsed_time)
- def print_time(elapsed_time):
- millis = int(round((elapsed_time * 1000) % 1000))
- seconds = int(elapsed_time) % 60
- minutes = int(elapsed_time / 60) % 60
- hours = int(elapsed_time / 3600)
- print('Time passed: %02d:%02d:%02d.%03d' % (hours, minutes, seconds, millis))
- def to_bool(s):
- return (s.lower() == 'true')
- def init():
- if exists(OUT):
- shutil.rmtree(OUT)
- mdine()
- subfolders = get_subfolders_rootless(IN)
- [mdine(subfolder) for subfolder in subfolders]
- return subfolders
- def init_arrays4(w, h):
- return (np.zeros([h, w]), np.zeros([h, w]), np.zeros([h, w]), np.zeros([h, w]))
- def convert_all_file_locations(function, arg = None):
- locations = init()
- [convert_file_locations(location, function, arg) for location in locations]
- def convert_all_file_locations_special(function, function_else, arg, else_arg):
- locations = init()
- [convert_file_locations(location, special, (function, function_else, arg, else_arg)) for location in locations]
- def special(img, sp):
- function, function_else, args, else_args = sp
- if '/block' in img or '/item' in img:
- function(img, args)
- else:
- function_else(img, else_args)
- def print_percentage(operation_string, meta_files, meta_action, png_files, file_action, arg = None):
- pl = len(png_files)
- ml = len(meta_files)
- segment_count = pl + ml
- toolbar_width = 50
- max_len = 45
- str_size = len(operation_string)
- rem_size = 50 - min(str_size - 3, max_len)
- str_start = max(str_size - max_len, 0)
- # setup toolbar
- sys.stdout.write(' [%s]%s[%s]' % (('...' if str_start > 0 else '') + operation_string[str_start:], ' ' * rem_size, ' ' * toolbar_width))
- sys.stdout.flush()
- sys.stdout.write('\b' * (toolbar_width + 1)) # return to start of line, after '['
- last_write = -1
- segment_writes = 0
- total_segment_writes = 0
- threads = []
- for i in range(0, ml):
- process = Thread(target=meta_action, args=[IN + '/' + meta_files[i], OUT + '/' + meta_files[i]])
- process.start()
- threads.append(process)
- segment_writes += (toolbar_width / segment_count)
- if segment_writes >= 0.999:
- # update the bar
- sys.stdout.write('■' * int(segment_writes))
- sys.stdout.flush()
- total_segment_writes += int(segment_writes)
- segment_writes -= int(segment_writes)
- for i in range(0, pl):
- if (arg is None):
- process = Thread(target=file_action, args=[png_files[i]])
- else:
- process = Thread(target=file_action, args=[png_files[i], arg])
- process.start()
- threads.append(process)
- segment_writes += (toolbar_width / segment_count)
- if segment_writes >= 0.999:
- # update the bar
- sys.stdout.write('■' * int(segment_writes))
- sys.stdout.flush()
- total_segment_writes += int(segment_writes)
- segment_writes -= int(segment_writes)
- for process in threads:
- process.join()
- if segment_count == 0:
- sys.stdout.write('■' * toolbar_width)
- elif total_segment_writes < toolbar_width:
- sys.stdout.write('■' * int(toolbar_width - total_segment_writes))
- sys.stdout.write(']\n') # this ends the progress bar
- def convert_file_locations(location, function, arg = None):
- f, m = get_files(location)
- print_percentage(IN + '/' + location, m, copyfile, f, function, arg)
- def get_files(dirc):
- for (dirpath, dirnames, filenames) in walk(IN + '/' + dirc):
- file = [dirc + '/' + filename for filename in filenames if filename.endswith('.png')]
- meta = [dirc + '/' + filename for filename in filenames if not filename.endswith('.png')]
- return (file, meta)
- def get_subfolders_rootless(path):
- return [x[len(path) + 1::] for x in get_subfolders(path)]
- def get_subfolders(path):
- all_paths = []
- for dirname, dirnames, filenames in walk(path):
- for subdirname in dirnames:
- all_paths.append(path_join(dirname, subdirname))
- new_paths = [path.replace(os.sep, '/') for path in all_paths]
- return new_paths
- def mdine(dirc = None):
- if dirc is None:
- _mdine(OUT)
- else:
- _mdine(OUT + '/' + dirc)
- def _mdine(path):
- if not exists(path):
- mkdir(path)
- def rainbow_color_image():
- stepsize = 2
- data = np.zeros((32, 32, 4), dtype=np.uint8)
- colors = [(255, 0, 0, 255), (255, 255, 0, 255), (0, 255, 0, 255), (0, 255, 255, 255), (0, 0, 255, 255), (255, 0, 255, 255)]
- for y in range(0, 32):
- for x in range(0, 32):
- index = int((x + y) / stepsize) % len(colors)
- data[x, y] = colors[index]
- return Image.fromarray(data, 'RGBA')
- def swap(arg0, arg1, arg2, amount):
- if amount > 0:
- temp = arg2
- arg2 = arg1
- arg1 = arg0
- arg0 = temp
- return swap(arg0, arg1, arg2, amount - 1)
- else:
- return arg0, arg1, arg2
- ### CALL MAIN ###
- main()
Advertisement
Add Comment
Please, Sign In to add comment