Created
October 25, 2025 04:41
-
-
Save uyjulian/e6e347ec5a1c0446811fbdd9fbbede46 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # SPDX-License-Identifier: MIT | |
| # Program to copy images referenced by glTF files. | |
| # Run the program with --help argument for arguments. | |
| import sys | |
| import shutil | |
| import os | |
| import json | |
| def gltf_copy_image(in_gltf_path, in_img_path, out_img_path): | |
| dic = None | |
| embedded_buffer = None | |
| with open(in_gltf_path, "rb") as f: | |
| h = f.read(12) | |
| if h[0:1] == b"\x7B": | |
| f.seek(0) | |
| dic = json.loads(f.read().decode("utf-8")) | |
| elif h[0:4] == b"glTF" and h[4:8] == b"\x02\x00\x00\x00": | |
| total_size = int.from_bytes(h[8:12], byteorder="little") | |
| while True: | |
| c = f.read(8) | |
| if len(c) != 8: | |
| break | |
| c_size = int.from_bytes(c[4:8], byteorder=little) | |
| if c == b"JSON": | |
| dic = json.loads(f.read(c_size).decode("utf-8")) | |
| elif c == b"BIN\x00": | |
| embedded_buffer = f.read(c_size) | |
| if dic == None: | |
| raise Exception("invalid glTF file") | |
| if "images" not in dic or not dic["images"]: | |
| print("Warning: no images are attached to the glTF file") | |
| return | |
| image_fn_list = [] | |
| images = dic["images"] | |
| for image in images: | |
| if "uri" not in image: | |
| print("Warning: detected image with no URI") | |
| continue | |
| uri = image["uri"] | |
| if uri[0:5] == "data:": | |
| print("Warning: detected image with data URI") | |
| continue | |
| image_fn_list.append(uri.rsplit("/", maxsplit=2)[-1]) | |
| image_fn_list = sorted(list(set(image_fn_list))) | |
| if image_fn_list: | |
| if not os.path.isdir(out_img_path): | |
| os.makedirs(name=out_img_path) | |
| for fn in image_fn_list: | |
| in_img_path_full = in_img_path + "/" + fn | |
| out_img_path_full = out_img_path + "/" + fn | |
| if not os.path.isfile(in_img_path_full): | |
| print("Warning: file " + in_img_path_full + " does not exist") | |
| continue | |
| if os.path.isfile(out_img_path_full): | |
| print("Warning: file " + out_img_path_full + " does exist") | |
| continue | |
| shutil.copy2(in_img_path_full, out_img_path_full, follow_symlinks=True) | |
| else: | |
| print("Warning: no images to copy") | |
| if __name__ == "__main__": | |
| import argparse | |
| import textwrap | |
| parser = argparse.ArgumentParser( | |
| description='Copies images referenced in glTF 2.0 files.', | |
| usage='Use "%(prog)s --help" for more information.', | |
| formatter_class=argparse.RawTextHelpFormatter) | |
| parser.add_argument("input_file", | |
| type=str, | |
| help="The input glTF 2.0 file.") | |
| parser.add_argument("--input-texture-path", | |
| type=str, | |
| default="", | |
| help=textwrap.dedent('''\ | |
| The path to the input directory containing texture files. | |
| If the path name is empty, it will default to the directory containing the input pathname. | |
| ''') | |
| ) | |
| parser.add_argument("--output-texture-path", | |
| type=str, | |
| default="", | |
| help=textwrap.dedent('''\ | |
| The path to the output directory containing texture files. | |
| If it does not already exist, it will be created. | |
| If the path name is empty, it will default to the input pathname with no extension with "__textures" appended to it. | |
| ''') | |
| ) | |
| args = parser.parse_args() | |
| input_file = args.input_file | |
| if not os.path.isfile(input_file): | |
| raise Exception("invalid input file") | |
| input_file_noext = input_file.rsplit(".", maxsplit=2)[0] | |
| input_texture_path = args.input_texture_path | |
| if input_texture_path == "": | |
| input_texture_path = os.path.dirname(input_file) | |
| if input_texture_path == "": | |
| input_texture_path = "." | |
| output_texture_path = args.output_texture_path | |
| if output_texture_path == "": | |
| output_texture_path = input_file_noext + "__textures" | |
| gltf_copy_image(input_file, input_texture_path, output_texture_path) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment