95 lines
2.8 KiB
Python

import math
import sys
def print_usage():
print("Usage: colorconv.py <from> <to> <color_from>")
print("")
print(" <from>: The color format to convert from.")
print(" <to>: The color format to convert to.")
print(" <color_from>: The color to convert the format of.")
print("")
print(" Color formats are formatted as their individual channels.")
print(" Ex.")
print(" r8g8b8")
print(" r5g6b5")
print("")
print(" Color data is represented as a number. Must be hexadecimal.")
print(" The output is a single color value in hexadecimal.")
def total_format_bytes(format: tuple[int, int, int]):
bits = sum(format)
return math.ceil(bits / 8)
def determine_format(format: str) -> tuple[int, int, int]:
r_ind: int = format.index("r")
g_ind: int = format.index("g")
b_ind: int = format.index("b")
r_sub: str = format[(r_ind + 1):g_ind]
g_sub: str = format[(g_ind + 1):b_ind]
b_sub: str = format[(b_ind + 1):]
r_val = int(r_sub)
g_val = int(g_sub)
b_val = int(b_sub)
return (r_val, g_val, b_val)
def convert_color(format_in: tuple[int, int, int], format_out: tuple[int, int, int], color_in):
in_r_max = 2 ** format_in[0] - 1
in_g_max = 2 ** format_in[1] - 1
in_b_max = 2 ** format_in[2] - 1
out_r_max = 2 ** format_out[0] - 1
out_g_max = 2 ** format_out[1] - 1
out_b_max = 2 ** format_out[2] - 1
in_r: int
in_g: int
in_b: int
if isinstance(color_in, int):
in_b = color_in & in_b_max
in_g = (color_in >> format_in[2]) & in_g_max
in_r = (color_in >> (format_in[2] + format_in[1])) & in_r_max
else:
in_r = color_in[0]
in_g = color_in[1]
in_b = color_in[2]
r_float = in_r / float(in_r_max)
g_float = in_g / float(in_g_max)
b_float = in_b / float(in_b_max)
out_r = int(r_float * out_r_max)
out_g = int(g_float * out_g_max)
out_b = int(b_float * out_b_max)
color_out = out_b + (out_g << format_out[2]) + (out_r << (format_out[2] + format_out[1]))
return color_out
def main(argv: list[str]):
argc: int = len(argv)
if argc < 4:
print_usage()
return
elif argc > 4:
print("Too many arguments!\n")
print_usage()
return
# The first argument is this file. Happens when calling python.exe.
format_in_str: str = argv[1]
format_out_str: str = argv[2]
color_str: str = argv[3]
format_in: tuple[int, int, int] = determine_format(format_in_str)
format_out: tuple[int, int, int] = determine_format(format_out_str)
color = int(color_str, 16)
result: int = convert_color(format_in, format_out, color)
formatter: str = "0x{:0" + str(total_format_bytes(format_out) * 2) + "X}"
print(formatter.format(result))
if __name__ == "__main__": main(sys.argv)