Created
September 28, 2025 03:29
-
-
Save celsowm/30afee4e38772aa2651b95ee5e0d2258 to your computer and use it in GitHub Desktop.
tga_fix.py for Saturn Jo Engine
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 | |
| # tga_fix.py — Converte TGA para 8bpp (indexed) sem RLE e força origem TOP-LEFT. | |
| # Requisitos: pip install pillow | |
| # Uso: | |
| # python tga_fix.py FLR.TGA | |
| # python tga_fix.py FLR.TGA --out FLR_8.TGA | |
| # python tga_fix.py FLR.TGA --no-flip | |
| # python tga_fix.py FLR.TGA --rotate 90 --colors 128 | |
| import argparse | |
| from pathlib import Path | |
| from PIL import Image | |
| def force_tga_origin_top_left(path: Path): | |
| """ | |
| Força o bit 5 (0x20) do Image Descriptor (byte 18 = offset 17) para TOP-LEFT. | |
| Mantém os demais bits (incluindo alpha bits). | |
| """ | |
| with open(path, "r+b") as f: | |
| header = bytearray(f.read(18)) | |
| if len(header) != 18: | |
| raise ValueError("Arquivo muito curto para TGA.") | |
| img_desc = header[17] | |
| img_desc |= 0x20 # seta TOP (bit 5) | |
| img_desc &= 0xEF # garante left-to-right (limpa bit 4) por segurança | |
| header[17] = img_desc | |
| f.seek(0) | |
| f.write(header) | |
| def main(): | |
| ap = argparse.ArgumentParser(description="Converte TGA para 8bpp sem RLE e origem TOP-LEFT.") | |
| ap.add_argument("src", help="Arquivo de entrada .TGA") | |
| ap.add_argument("--out", "-o", help="Arquivo de saída .TGA (default: <nome>_8.TGA)") | |
| ap.add_argument("--colors", type=int, default=256, help="Número de cores (1..256). Default: 256") | |
| ap.add_argument("--rotate", type=int, choices=[0, 90, 180, 270], default=0, | |
| help="Rotação (graus, sentido horário). Default: 0") | |
| ap.add_argument("--no-flip", dest="no_flip", action="store_true", | |
| help="Não aplicar flip vertical (por padrão aplicamos FLIP_TOP_BOTTOM).") | |
| ap.add_argument("--overwrite", action="store_true", help="Sobrescrever arquivo de saída se existir.") | |
| args = ap.parse_args() | |
| src = Path(args.src) | |
| if not src.exists(): | |
| raise SystemExit(f"Arquivo não encontrado: {src}") | |
| dst = Path(args.out) if args.out else src.with_name(src.stem + "_8.TGA") | |
| if dst.exists() and not args.overwrite: | |
| raise SystemExit(f"Arquivo de saída já existe: {dst} (use --overwrite)") | |
| im = Image.open(src) | |
| # Garante que os pixels fiquem "para cima" | |
| if not args.no_flip: | |
| im = im.transpose(Image.FLIP_TOP_BOTTOM) | |
| # Rotação (horário) | |
| if args.rotate == 90: | |
| im = im.transpose(Image.ROTATE_270) | |
| elif args.rotate == 180: | |
| im = im.transpose(Image.ROTATE_180) | |
| elif args.rotate == 270: | |
| im = im.transpose(Image.ROTATE_90) | |
| colors = max(1, min(256, args.colors)) | |
| im = im.convert("P", palette=Image.ADAPTIVE, colors=colors) | |
| im.save(dst, format="TGA", compress=False) | |
| # >>> Patch no header para TOP-LEFT <<< | |
| force_tga_origin_top_left(dst) | |
| print("OK!") | |
| print(f" Entrada : {src}") | |
| print(f" Saída : {dst}") | |
| print(f" Cores : {colors}") | |
| print(f" Flip Y : {'NÃO' if args.no_flip else 'SIM (forçar TOP-LEFT)'}") | |
| print(f" Rotação : {args.rotate}°") | |
| print(" Origem : TOP-LEFT (header ajustado)") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment