Created
April 13, 2020 23:32
-
-
Save ranguli/5885b4bdecf78cc6d7db39826d339826 to your computer and use it in GitHub Desktop.
This file contains 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
import os | |
from PIL import Image | |
def generate_palette_table(palette_file): | |
""" | |
The palette.lmp is a binary file with denoting the RGB codes of the 256-color | |
palette used by the Quake engine. It contains no header data. Each byte is one | |
component of an RGB value. | |
https://quakewiki.org/wiki/Quake_palette#palette.lmp | |
Think of the palette as a dictionary or lookup table. Values from 0-255 each | |
contain an RGB code. Images in the .lmp format do not contain RGB information, | |
instead for each pixel in the image there is a number from 0-255 that corresponds to | |
a value in the color palette. | |
""" | |
data = [] | |
with open(palette_file, "rb") as f: | |
for i in range(os.path.getsize(palette_file)): | |
data.append(int.from_bytes(f.read(1), byteorder='big')) | |
data = [data[x:x+3] for x in range(0, len(data), 3)] | |
palette_table = {k:v for k, v in enumerate(data)} | |
return palette_table | |
def main(lmp_file, palette_file): | |
# .lmp files in Quake are of a different structure than those from DOOM. | |
# They can be one of three types, an image, a palette, or a colormap. | |
lmp_data = [] | |
with open(lmp_file, "rb") as f: | |
size = os.path.getsize(lmp_file) | |
for i in range(size): | |
byte = int.from_bytes(f.read(1), byteorder='big') | |
lmp_data.append(byte) | |
""" | |
The first 8 bytes comprise the files header data, 4 bytes for the | |
width of the image and 4 bytes for its height. | |
TODO: Currently only reading the first byte (of potentially up to 4) | |
for the width and height values. We need to fix this as it literally | |
only works for images <= 255x255 in resolution. | |
""" | |
header = lmp_data[:8] | |
width = header[0] | |
height = header[4] | |
""" | |
TODO: Confirm the .lmp is valid by checking that given a width and height from the | |
header data, (width * height) equals the size of the rest of the file after | |
the header. | |
""" | |
lmp_data = lmp_data[8:] | |
palette_table = generate_palette_table(palette_file) | |
# TODO: If this does not divide evenly, the .lmp is bad | |
#rgb_values = group(data, len(data) // 3) | |
image_data = [] | |
for table_id in lmp_data: | |
image_data.extend(palette_table.get(table_id)) | |
image_data = bytes(image_data) | |
img = Image.frombytes('RGB', (width, height), image_data) | |
img.show() | |
img.save(f"{lmp_file}.png") | |
main("ranking.lmp", "palette.lmp") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment