⭐ If this tool saved you time, consider starring the repo — it helps others find it too.
A complete TIM2 (.tm2) texture toolkit for the PlayStation 2. Convert standard images into PS2-native TIM2 textures, extract existing TIM2 files back into regular images, inspect their internal structure, verify their integrity, and diff two TIM2 files to check compatibility — all from a single command-line script.
Built for PS2 homebrew development, game modding, and texture pipeline work, with accurate handling of GS pixel formats, CLUT palettes, VRAM swizzling, and mipmap chains.
- Image → TIM2 conversion in five PS2 GS pixel formats: 32-bit, 24-bit, 16-bit, 8-bit indexed, and 4-bit indexed
- TIM2 → Image extraction, converting
.tm2files back into common image formats - CLUT (palette) generation for indexed formats, including proper 8-bit CLUT swizzling
- GS VRAM swizzle support for 32-bit and 16-bit formats
- Mipmap chain generation for all formats — 32-bit, 24-bit, 16-bit, 8-bit indexed, and 4-bit indexed
- Alpha premultiplication, matching PS2 GS rendering behavior (32-bit and 16-bit)
- Floyd–Steinberg dithering for 4-bit and 8-bit indexed output
- Power-of-2 dimension handling, with optional automatic resize up or down
- Batch conversion from wildcards or a text list file
.tm2file inspection (--info) showing header, format, CLUT, and GS Tex0 data.tm2integrity verification (--verify) with a 12-point structural check.tm2diff / compatibility check (--diff) comparing an original file against a modified one — format, dimensions, file size, transparency, and pixel-level changes, with a SAFE / WARNING / UNSAFE verdict
- Python 3
- Pillow (
PIL)
Install Pillow with:
pip install Pillow
.png .jpg .jpeg .bmp .tga .tiff .tif .webp .gif .ppm .pgm .pbm .ico .dds
.png .jpg .jpeg .bmp .tga .tiff .tif .webp .ppm
| Format | Description |
|---|---|
32bit |
RGBA8888 — full color + 8-bit alpha — best for textures |
24bit |
RGB888 — full color, no alpha — backgrounds and opaque textures |
16bit |
RGBA5551 — 32K colors + 1-bit alpha — smaller file size |
8bit |
Indexed8 — 256 colors + CLUT — characters, environments |
4bit |
Indexed4 — 16 colors + CLUT — icons, UI elements |
python3 ps2_tim2_tool.py (filename) --format 32bit
python3 ps2_tim2_tool.py (filename) --format 24bit
python3 ps2_tim2_tool.py (filename) --format 16bit
python3 ps2_tim2_tool.py (filename) --format 8bit
python3 ps2_tim2_tool.py (filename) --format 4bit
python3 ps2_tim2_tool.py (filename) (filename) (filename) --format 32bit
python3 ps2_tim2_tool.py (filename) --format 8bit --dither
python3 ps2_tim2_tool.py (filename) --format 32bit --no-premult
python3 ps2_tim2_tool.py (filename) --format 32bit --output (filename)
python3 ps2_tim2_tool.py (filename) --format 32bit --output-dir (directory)
python3 ps2_tim2_tool.py (filename) --format 32bit --resize up
python3 ps2_tim2_tool.py (filename) --format 32bit --resize down
python3 ps2_tim2_tool.py (filename) --format 32bit --swizzle
python3 ps2_tim2_tool.py (filename) --format 32bit --mipmaps
python3 ps2_tim2_tool.py (filename) --format 32bit --swizzle --mipmaps --resize up
python3 ps2_tim2_tool.py --list (filename)
python3 ps2_tim2_tool.py (filename) --info
python3 ps2_tim2_tool.py (filename) --verify
python3 ps2_tim2_tool.py --diff --original (filename) --modified (filename)
python3 ps2_tim2_tool.py --diff --original (filename) (filename) --modified (filename) (filename)
python3 ps2_tim2_tool.py --diff --original (directory) --modified (directory)
python3 ps2_tim2_tool.py --diff-list (filename)
python3 ps2_tim2_tool.py (filename) --extract png
python3 ps2_tim2_tool.py (filename) --extract jpg
python3 ps2_tim2_tool.py (filename) --extract bmp
python3 ps2_tim2_tool.py (filename) --extract tga
python3 ps2_tim2_tool.py (filename) --extract tiff
python3 ps2_tim2_tool.py (filename) --extract webp
python3 ps2_tim2_tool.py (filename) --extract ppm
python3 ps2_tim2_tool.py --list-formats
| Option | Description |
|---|---|
--format, -f |
Output format: 4bit | 8bit | 16bit | 24bit | 32bit |
--output, -o |
Output file path (single file only) |
--output-dir |
Output directory for all converted files |
--no-premult |
Disable alpha premultiplication |
--dither |
Enable Floyd–Steinberg dithering (4-bit and 8-bit) |
--resize up | down |
Resize non-power-of-2 images up or down to the nearest power of 2 |
--swizzle |
Apply GS VRAM swizzle to pixel data (32-bit and 16-bit only) |
--mipmaps |
Generate a full mipmap chain stored in the TIM2 file (all formats) |
--info |
Read and display info from an existing .tm2 file |
--verify |
Verify the integrity of a .tm2 file (12 checks) |
--diff |
Compare an original TIM2 file (or folder) against a modified one |
--original PATH ... |
One or more original TIM2 files, or one folder (used with --diff) |
--modified PATH ... |
One or more modified TIM2 files, or one folder (used with --diff) |
--diff-list FILE.TXT |
Text file listing original/modified pairs to compare, one pair per line |
--list |
Convert images listed in a text file (filename + format per line) |
--extract |
Extract TIM2 to an image format |
--list-formats, -l |
List available formats and options |
When using --list, provide a plain text file with one entry per line, containing the filename and target format:
(filename) 32bit
(filename) 24bit
(filename) 16bit
(filename) 8bit
When using --diff-list, provide a plain text file with a header line followed by one original/modified pair per line:
original modified
(filename) (filename)
(filename) (filename)
Blank lines and lines starting with # are ignored.
Running --diff prints a per-file report checking:
- Format — whether the pixel format changed
- Dimensions — whether width or height changed
- File size — before and after, with the difference
- Transparency — whether an alpha channel was lost, gained, or unchanged
- Pixel diff — percentage of pixels changed and the maximum color difference (only when format and dimensions match)
Each file gets a final verdict:
| Verdict | Meaning |
|---|---|
SAFE |
No issues or warnings — safe to inject back into the game |
WARNING |
No blocking issues, but review the warnings (e.g. file size or transparency changed) |
UNSAFE |
Format or dimensions changed — the game may crash or render incorrectly |
Comparing two folders also reports any files present in one folder but missing from the other, plus a summary count of SAFE / WARNING / UNSAFE results across all compared files.
- Non-power-of-2 images are still converted by default, with a warning. Use
--resize upor--resize downto force power-of-2 dimensions. - The
--swizzleoption applies only to32bitand16bitformats. - The
--mipmapsoption applies to all five formats (32bit,24bit,16bit,8bit,4bit). - The
--ditheroption applies only to4bitand8bitformats. - The
24bitformat stores no alpha channel — every pixel is fully opaque, so--no-premultand--swizzlehave no effect on it. - When extracting a TIM2 file to a format without alpha support (
.jpg,.bmp,.ppm), transparency is composited onto a white background. --diffrequires either--diff-list, or both--originaland--modifiedtogether.
Don't have Python installed, or just want to run the tool without setting up an environment? Check the Releases page for ready-to-use executable builds — no Python or dependencies required, just download and run.
This project is licensed under the MIT License — see the LICENSE file for details.

