diff --git a/__pycache__/texture_checks.cpython-39.pyc b/__pycache__/texture_checks.cpython-39.pyc new file mode 100644 index 0000000..8892792 Binary files /dev/null and b/__pycache__/texture_checks.cpython-39.pyc differ diff --git a/__pycache__/texture_operations.cpython-39.pyc b/__pycache__/texture_operations.cpython-39.pyc new file mode 100644 index 0000000..c205ed7 Binary files /dev/null and b/__pycache__/texture_operations.cpython-39.pyc differ diff --git a/demo_images/example.png b/demo_images/example.png new file mode 100644 index 0000000..2e05ba4 Binary files /dev/null and b/demo_images/example.png differ diff --git a/generator.py b/generator.py new file mode 100644 index 0000000..7fa162c --- /dev/null +++ b/generator.py @@ -0,0 +1,62 @@ +import os +import cv2 +import sys +import argparse +from texture_operations import * +from texture_checks import * +from PIL import Image + + +def generate_pseudonormal(source_texture, normal_map, replace=False): + img = Image.open(normal_map).convert('L') + print("Generating ",normal_map[:len(normal_map)-4]+"_grayscaled.png") + grayscaled_name = normal_map[:len(normal_map)-4]+"_grayscaled.png" + try: + img.save(grayscaled_name) + except: + pass + print("Combining texture and normal map") + background = cv2.imread(source_texture) + overlay = cv2.imread(grayscaled_name) + added_image = cv2.addWeighted(background, 0.92, overlay, 1, 0) + cv2.imwrite('combined.png', added_image) + print("Time to fix brightness of result...") + value = delta_brightness(source_texture, 'combined.png') + result = change_brightness('combined.png', -1*value) + cv2.imwrite('combined_result.png', result) + print("Adjusting saturation...") + img_pil = adjust_saturation(Image.open('combined_result.png'), 3) + print("Removing intermediate files") + os.remove('combined.png') + os.remove('combined_result.png') + for i in os.listdir(): + if 'grayscaled' in i: + os.remove(i) + if replace: + img_pil.save(source_texture) + return True + print("Prepairing result: "+source_texture[: len(source_texture) - 4]+'_pseudonormal.png') + img_pil.save(source_texture[: len(source_texture) - 4]+'_pseudonormal.png') + print("Done!") + return True + +def parse_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument('-t', '--texture', required=True, type=str) + parser.add_argument('-n', '--nmap', required=True, type=str) + return parser + +def main(): + parser = parse_arguments() + parameters = parser.parse_args(sys.argv[1:]) + source_texture = format(parameters.texture) + normal_map = format(parameters.nmap) + texture_validation(source_texture=source_texture, normal_map=normal_map) + generate_pseudonormal(source_texture=source_texture, normal_map=normal_map, replace=False) + + + +if __name__=='__main__': + main() + + diff --git a/texture_checks.py b/texture_checks.py new file mode 100644 index 0000000..d62f371 --- /dev/null +++ b/texture_checks.py @@ -0,0 +1,54 @@ +import os +import cv2 +from PIL import Image + +SUPPORTED_TEXTURES = ['.png', '.jpg', '.bmp', '.jpeg'] + +def is_supportedtexture(filename): + filename = filename.lower() + if filename[filename.find("."):] in SUPPORTED_TEXTURES: + return True + return False + +def existence_check(texture, normalmap): + if os.path.exists(texture) and os.path.exists(normalmap): + return True + print("One or both texture files don't exist. Please check input paths.") + exit(-1) + +def check_sizes(source_texture, normal_map): + f_source_texture = cv2.imread(source_texture) + f_normal_map = cv2.imread(normal_map) + ws, hs, _ = f_source_texture.shape + wn, hn, _ = f_normal_map.shape + if ws==wn and hs == hn: + return True + print("Normal map and source texture sould have same widht and height") + print("Your texture resolution: ", ws,'x',hs) + print("Your normal map resolution: ", wn, 'x', hn) + exit(-1) + +def has_nss(path, alphabet=set('абвгдеёжзийклмнопрстуфхцчшщъыьэюяäößü')): + return not alphabet.isdisjoint(path.lower()) + +def texture_path_check(source_texture, normal_map): + if ' ' not in source_texture and ' ' not in normal_map and not has_nss(source_texture) and not has_nss(normal_map): + return True + print("Your texture/normal map path contains not supported symbols. Please change the path(s).") + exit(-1) + +def typo_check(source_texture, normal_map): + if is_supportedtexture(source_texture) and is_supportedtexture(normal_map): + return True + print("Input file types aren't supported by this utility. ") + print("Supported types: ", end=' ') + for i in SUPPORTED_TEXTURES: + print(i, end=" ") + exit(-1) + +def texture_validation(source_texture, normal_map): + existence_check(texture=source_texture, normalmap=normal_map) + texture_path_check(source_texture=source_texture, normal_map=normal_map) + typo_check(source_texture=source_texture, normal_map=normal_map) + check_sizes(source_texture=source_texture, normal_map=normal_map) + return True \ No newline at end of file diff --git a/texture_operations.py b/texture_operations.py new file mode 100644 index 0000000..74d7938 --- /dev/null +++ b/texture_operations.py @@ -0,0 +1,25 @@ +import cv2 +from PIL import Image +from PIL import ImageStat +from PIL import ImageEnhance + + +def delta_brightness(source_texture, overlayed_texture): + return ImageStat.Stat(Image.open(overlayed_texture).convert('L')).mean[0]-ImageStat.Stat(Image.open(source_texture).convert('L')).mean[0] + +def adjust_saturation(img, saturation_factor): + enhancer = ImageEnhance.Color(img) + img = enhancer.enhance(saturation_factor) + return img + +def change_brightness(imgpath, value=30): + img = cv2.imread(imgpath) + hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) + h, s, v = cv2.split(hsv) + v = cv2.add(v,value) + v[v > 255] = 255 + v[v < 0] = 0 + final_hsv = cv2.merge((h, s, v)) + img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR) + return img +