Skip to content

Instantly share code, notes, and snippets.

@xyzz

xyzz/tool.py Secret

Created December 13, 2016 17:32
Show Gist options
  • Save xyzz/fbb344f4c2e9bba1ad12215a72db5035 to your computer and use it in GitHub Desktop.
Save xyzz/fbb344f4c2e9bba1ad12215a72db5035 to your computer and use it in GitHub Desktop.
# based on https://github.com/xdanieldzd/Scarlet/blob/master/Scarlet.IO.ImageFormats/SHTXFS.cs
import datetime
from sys import argv, exit
from PIL import Image
def log(s):
print("[{}] {}".format(datetime.datetime.now(), s))
def shtx_to_png(in_path, out_path):
fin = open(in_path, "rb")
tag = fin.read(6)
width = int.from_bytes(fin.read(2), byteorder="little")
height = int.from_bytes(fin.read(2), byteorder="little")
unk = fin.read(2)
log("Converting...")
palette = []
for x in range(256):
palette.append(int.from_bytes(fin.read(4), byteorder="little"))
im = Image.new("RGBA", (width, height))
pixels = im.load()
for y in range(height):
for x in range(width):
pixel = palette[ord(fin.read(1))]
pixels[(x, y)] = (pixel & 0xFF, (pixel & 0xFF00) >> 8, (pixel & 0xFF0000) >> 16, (pixel & 0xFF000000) >> 24)
fin.close()
im.save(out_path)
log("Saved {}".format(out_path))
def png_to_shtx(orig_path, in_path, out_path):
fin = open(orig_path, "rb")
fin.seek(0xA)
magic = fin.read(2)
log("Reusing magic 0x{:x}".format(int.from_bytes(magic, byteorder="little")))
fin.close()
im = Image.open(in_path)
width, height = im.size
pixels = im.load()
log("Building the palette...")
colors = set()
for y in range(height):
for x in range(width):
p = pixels[(x, y)]
color = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)
colors.add(color)
if len(colors) > 256:
log("Error: palette is too big. Make sure your image only contains 256 different colors. (Use pngquant)")
return -1
color_to_idx = dict()
palette = []
for color in colors:
color_to_idx[color] = len(palette)
palette.append(color)
log("Writing the image...")
fout = open(out_path, "wb")
fout.write(b"SHTXFS")
fout.write(width.to_bytes(2, byteorder="little"))
fout.write(height.to_bytes(2, byteorder="little"))
fout.write(magic)
for color in palette:
fout.write(color.to_bytes(4, byteorder="little"))
for y in range(height):
for x in range(width):
p = pixels[(x, y)]
color = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)
fout.write(color_to_idx[color].to_bytes(1, byteorder="little"))
fout.close()
log("Saved {}".format(out_path))
def main():
if len(argv) == 3:
return shtx_to_png(argv[1], argv[2])
elif len(argv) == 4:
return png_to_shtx(argv[1], argv[2], argv[3])
else:
print("Usage:")
print("\tConvert shtx to png:")
print("\t\tpython tool.py source.shtx output.png")
print("\tConvert png to shtx:")
print("\t\tpython tool.py original.shtx source.png output.shtx")
return -1
if __name__ == "__main__":
exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment