PyPVR is an unofficial, modern tool written in Python for encoding / decoding PowerVR2 images used by SEGA Dreamcast and SEGA Naomi.
Project description
PyPVR - Python PVR Image Tool
PyPVR is an unofficial, modern Python tool for encoding/decoding PowerVR2 images used by SEGA Dreamcast and SEGA Naomi systems.
Use it as a module in your Python scripts with:
from pypvr import Pypvr
✅ Supports decoding/encoding to PIL Image object buffers via
-bufferparameter.
📦 Installation
You can install PyPVR using pip:
pip install pypvr
Note: Ensure you have Python 3.9+ and that required dependencies (
numpy,Pillow,faiss) are installed. If not, pip will attempt to install them automatically.
🧾 Required Imports
numpyPillowfaiss
🫶 Support
🙏 Credits
Special thanks to:
- Rob2d - K-means idea for better VQ
- Egregiousguy - YUV420 decoding
- Kion - SmallVQ mipmaps
- tvspelsfreak - SR to normal map
- MetalliC - Hardware insights
- My daughter - Logo design! ❤️
Testers:
Esppiral, Alexvgz, PkR, Derek (ateam), dakrk, neSneSgB, woofmute, TVi, Sappharad
⚙️ Decode Options
| Option | Description |
|---|---|
-flip |
Flip image vertically |
-silent |
Suppress console output |
-nolog |
Don't create pvr_info.txt |
-dbg |
Enable debug mode |
-usepal |
Decode palettized image using a .pvp palette |
-act |
Convert .pvp to Adobe ACT format |
-nopvp |
Skip extracting .pvp file |
🧪 Encode Options
🎨 Color Formats
| Param | Color Type | Description |
|---|---|---|
-565 |
RGB | Ideal for gradients, no transparency |
-1555 |
ARGB 1-bit alpha | Opaque or fully transparent only |
-4444 |
ARGB 4-bit alpha | Lower quality, supports transparency |
-8888 |
ARGB 8-bit alpha | Full transparency support |
-yuv422 |
YUV422 | Lossy but vibrant color format |
-yuv420 |
YUV420 | For YUV converter or .SAN files (WARNING) |
-bump |
RGB Normal map | Converts height map to SR format |
-555 |
RGB PCX converter | Use -1555 instead |
-p4bpp |
4-bit palette | Placeholder only |
-p8bpp |
8-bit palette | Placeholder only |
🧵 Texture Formats
| Param | Type | Twiddled | Description | Mipmaps |
|---|---|---|---|---|
-tw |
Square | Yes | Square dims only | Yes |
-twre |
Rectangle | Yes | Rectangular multiples | No |
-re |
Rectangle | No | Rectangular multiples | No |
-st |
Stride | No | Width must be multiple of 32 | No |
-twal |
Alias | Yes | Square + mipmaps ≤ 8x8 | Yes |
-pal4 |
16-color palette | Yes | Square only | Yes |
-pal8 |
256-color palette | Yes | Square only | Yes |
-vq |
Vector Quantized | Yes | High compression + quality | Yes |
-svq |
Small VQ | Yes | Max dimensions 64x64 | Yes |
-bmp |
Bitmap | No | Square only | Yes |
🧰 Other Options
| Option | Description |
|---|---|
-mm |
Generate mipmaps |
-near |
Use nearest resampling (default is bilinear) |
-flip |
Flip image vertically |
-cla |
Clean RGB where alpha is 0 |
-gi <n> |
GBIX header value |
-gitrim |
Use short GBIX header |
-pvptrim |
Trim unused colors in palette |
-pvpbank <n> |
Set palette bank index (0–63) |
-nopvp |
Skip PVP output |
-vqa1 |
VQ Algo 1 - detail focused, slower on large images |
-vqa2 |
VQ Algo 2 - gradient focused, fast (FAISS) |
-vqi <n> |
VQ iterations (default: 10) |
| `-vqs | rand` |
🔍 Examples
🔹 Decode to PIL Image
from pypvr import Pypvr
from PIL import Image
with open('test.pvr', 'rb') as file:
pvr_data = file.read()
image_buffer = Pypvr.Decode('-buffer', buff_pvr=pvr_data).get_image_buffer()
🔹 Decode with Palette (PVR + PVP)
from pypvr import Pypvr
from PIL import Image
with open('test.pvr', 'rb') as file:
pvr_data = file.read()
with open('palette.pvp', 'rb') as file:
pvp_data = file.read()
image_buffer = Pypvr.Decode('-buffer', buff_pvr=pvr_data, buff_pvp=pvp_data).get_image_buffer()
🔹 Encode from PIL Image
from pypvr import Pypvr
from PIL import Image
image = Image.open("test.png")
pvr_buffer = Pypvr.Encode('-buffer -vq', image).get_pvr_buffer()
🔹 Other Encode Examples
-
pvr_buffer = Pypvr.Encode('-buffer -vq', image).get_pvr_buffer()
-
pvp_buffer = Pypvr.Encode('-buffer', image).get_pvp_buffer()
-
From file path (PNG) to
.PVRbuffer:pvr_buffer = Pypvr.Encode('c:\filename.png -buffer').get_pvr_buffer()
-
From file path (PNG) to
.PVPbuffer:pvp_buffer = Pypvr.Encode('c:\filename.png -buffer').get_pvp_buffer()
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pypvr-1.0.0.tar.gz.
File metadata
- Download URL: pypvr-1.0.0.tar.gz
- Upload date:
- Size: 32.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b362feb0aea68f29d864f77fcc3519522c2bdd0c250bc120f676ec980bb4e1c
|
|
| MD5 |
716c3fc4f03f78e4a925ccaa96237b57
|
|
| BLAKE2b-256 |
784aaab4dbbc07514e7c6280cc991b663731221d36a4f8b6688b8ad396a3b59a
|
File details
Details for the file pypvr-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pypvr-1.0.0-py3-none-any.whl
- Upload date:
- Size: 32.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af6f4a7b1e24ece75373138dd5bee56a54c0de7a6592cccd89bbff7a08fe2757
|
|
| MD5 |
86fe2b0a8bab0051bc6805e7c0b88fcb
|
|
| BLAKE2b-256 |
82c642ed1082a5df8fe75a5843c2cc182d1b09bd6d131c78c6f4ded20dad1e28
|