.tim file format of Sony PlayStation (PSX) typical image format: Python parsing library

Application

Sony PlayStation (PSX) typical image format

File extension

tim

KS implementation details

License: CC0-1.0

This page hosts a formal specification of .tim file format of Sony PlayStation (PSX) typical image format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Parse a local file and get structure in memory:

data = PsxTim.from_file("path/to/local/file.tim")

Or parse structure from a bytes:

from kaitaistruct import KaitaiStream, BytesIO

raw = b"\x00\x01\x02..."
data = PsxTim(KaitaiStream(BytesIO(raw)))

After that, one can get various attributes from the structure by invoking getter methods like:

data.flags # => Encodes bits-per-pixel and whether CLUT is present in a file or not

Python source code to parse .tim file format of Sony PlayStation (PSX) typical image format

psx_tim.py

# This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

from pkg_resources import parse_version
from kaitaistruct import __version__ as ks_version, KaitaiStruct, KaitaiStream, BytesIO
from enum import Enum
import struct


if parse_version(ks_version) < parse_version('0.7'):
    raise Exception("Incompatible Kaitai Struct Python API: 0.7 or later is required, but you have %s" % (ks_version))

class PsxTim(KaitaiStruct):

    class BppType(Enum):
        bpp_4 = 0
        bpp_8 = 1
        bpp_16 = 2
        bpp_24 = 3
    def __init__(self, _io, _parent=None, _root=None):
        self._io = _io
        self._parent = _parent
        self._root = _root if _root else self
        self._read()

    def _read(self):
        self.magic = self._io.ensure_fixed_contents(struct.pack('4b', 16, 0, 0, 0))
        self.flags = self._io.read_u4le()
        if self.has_clut:
            self.clut = self._root.Bitmap(self._io, self, self._root)

        self.img = self._root.Bitmap(self._io, self, self._root)

    class Bitmap(KaitaiStruct):
        def __init__(self, _io, _parent=None, _root=None):
            self._io = _io
            self._parent = _parent
            self._root = _root if _root else self
            self._read()

        def _read(self):
            self.len = self._io.read_u4le()
            self.origin_x = self._io.read_u2le()
            self.origin_y = self._io.read_u2le()
            self.width = self._io.read_u2le()
            self.height = self._io.read_u2le()
            self.body = self._io.read_bytes((self.len - 12))


    @property
    def has_clut(self):
        if hasattr(self, '_m_has_clut'):
            return self._m_has_clut if hasattr(self, '_m_has_clut') else None

        self._m_has_clut = (self.flags & 8) != 0
        return self._m_has_clut if hasattr(self, '_m_has_clut') else None

    @property
    def bpp(self):
        if hasattr(self, '_m_bpp'):
            return self._m_bpp if hasattr(self, '_m_bpp') else None

        self._m_bpp = (self.flags & 3)
        return self._m_bpp if hasattr(self, '_m_bpp') else None