srctools.vtf

Reads VTF image data into a PIL object.

After this is imported, the imghdr module can recoginise VTF images (returning ‘source_vtf’).

class srctools.vtf.VTF(
width: int,
height: int,
version: Tuple[int, int] = (7, 5),
ref: Vec = Vec(0, 0, 0),
frames: int = 1,
bump_scale: float = 1.0,
sheet_info: Mapping[int, SheetSequence] = srctools.EmptyMapping,
flags: VTFFlags = VTFFlags.EMPTY,
fmt: ImageFormats = ImageFormats.RGBA8888,
thumb_fmt: ImageFormats = ImageFormats.DXT1,
depth: int = 1,
)

Valve Texture Format files, used in the Source Engine.

classmethod read(file: IO[bytes]) VTF

Read in a VTF file.

save(
file: IO[bytes],
version: Optional[Tuple[int, int]] = None,
sheet_seq_version: int = 1,
asw_or_later: bool = True,
) None

Write out the VTF file to this.

If a version is specified, this overrides the one in the object. The particle system version needs to be specified here. If ATI1N or ATI2N used, whether the engine is ASW or later needs to be specified.

load() None

Fully load all image frames from the VTF.

This allows closing the file stream.

clear_mipmaps(*, after: int = 0) None

Erase the contents of all mipmaps smaller than the given size.

When saved or compute_mipmaps() is called, these empty mipmaps will be recomputed from the largest mipmap. By default this clears all but the largest mipmap.

compute_mipmaps(
filter: FilterMode = FilterMode.BILINEAR,
) None

Regenerate all mipmaps that have previously been cleared.

get(
*,
frame: int = 0,
depth: int = 0,
side: Optional[CubeSide] = None,
mipmap: int = 0,
) Frame

Get a specific image frame.

If the texture is a cubemap, a side must be provided and depth must be 0.

class srctools.vtf.Frame(width: int, height: int)

A single frame of a VTF. This should not be constructed independently.

This is lazy, so it will only read from the file when actually used.

load() None

If the image has not been loaded, load it from the file stream.

clear() None

This clears the contents of the frame.

If the VTF is saved, this will be generated from the larger mipmaps.

copy_from(source: Frame) None
copy_from(
source: Union[bytes, bytearray, 'array[int]', memoryview],
format: ImageFormats = ImageFormats.RGBA8888,
) None

Overwrite this frame with other data.

The source can be another Frame, or any buffer with bytes-format data.

rescale_from(
larger: Frame,
filter: FilterMode = FilterMode.BILINEAR,
) None

Regenerate this image from the next mipmap.

The larger image must either have the same dimension, or exactly double.

to_PIL() PIL_Image

Convert the given frame into a PIL image.

Requires Pillow to be installed.

to_tkinter(
tk: tkinter.Misc | None = None,
*,
bg: Optional[Tuple[int, int, int]] = None,
) tkinter.PhotoImage

Convert the given frame into a Tkinter PhotoImage.

If bg is set, the image will be composited onto this background. Otherwise, alpha is ignored.

to_wx_image(
bg: Optional[Tuple[int, int, int]] = None,
) Any

Convert the given frame into a wxPython wx.Image.

This requires wxPython to be installed. If bg is set, the image will be composited onto this background. Otherwise, alpha is ignored.

to_wx_bitmap(
bg: Optional[Tuple[int, int, int]] = None,
) Any

Convert the given frame into a wxPython wx.Bitmap.

This requires wxPython to be installed. If bg is set, the image will be composited onto this background. Otherwise, alpha is ignored.

class srctools.vtf.FilterMode(value)

Bases: Enum

The algorithm to use for generating mipmaps.

NEAREST = 0

Alias: UPPER_LEFT

UPPER_RIGHT = 1
LOWER_LEFT = 2
LOWER_RIGHT = 3
BILINEAR = 4

Alias: AVERAGE

class srctools.vtf.ResourceID(value)

Bases: bytes, Enum

For VTF format 7.3+, there is an extensible resource system.

LOW_RES = b'\x01\x00\x00'
HIGH_RES = b'0\x00\x00'
PARTICLE_SHEET = b'\x10\x00\x00'
CRC = b'CRC'
LOD_SETTINGS = b'LOD'
EXTRA_FLAGS = b'TSO'
KEYVALUES = b'KVD'
class srctools.vtf.CubeSide(value)

Bases: Enum

The sides of a cubemap texture.

RIGHT = 0
LEFT = 1
BACK = 2
FRONT = 3
UP = 4
DOWN = 5
SPHERE = 6
class srctools.vtf.ImageFormats(value)

Bases: Enum

All VTF image formats, with their data sizes in the value.

RGBA8888 = (8, 8, 8, 8, 32, 0)
ABGR8888 = (8, 8, 8, 8, 32, 1)
RGB888 = (8, 8, 8, 0, 24, 2)
BGR888 = (8, 8, 8, 0, 24, 3)
RGB565 = (5, 6, 5, 0, 16, 4)
I8 = (8, 8, 8, 0, 8, 5)
IA88 = (8, 8, 8, 8, 16, 6)
P8 = (0, 0, 0, 0, 0, 7)
A8 = (0, 0, 0, 8, 8, 8)
RGB888_BLUESCREEN = (8, 8, 8, 0, 24, 9)
BGR888_BLUESCREEN = (8, 8, 8, 0, 24, 10)
ARGB8888 = (8, 8, 8, 8, 32, 11)
BGRA8888 = (8, 8, 8, 8, 32, 12)
DXT1 = (0, 0, 0, 0, 64, 13)
DXT3 = (0, 0, 0, 0, 128, 14)
DXT5 = (0, 0, 0, 0, 128, 15)
BGRX8888 = (8, 8, 8, 8, 32, 16)
BGR565 = (5, 6, 5, 0, 16, 17)
BGRX5551 = (5, 5, 5, 1, 16, 18)
BGRA4444 = (4, 4, 4, 4, 16, 19)
DXT1_ONEBITALPHA = (0, 0, 0, 0, 64, 20)
BGRA5551 = (5, 5, 5, 1, 16, 21)
UV88 = (0, 0, 0, 0, 16, 22)
UVWQ8888 = (0, 0, 0, 0, 32, 23)
RGBA16161616F = (16, 16, 16, 16, 64, 24)
RGBA16161616 = (16, 16, 16, 16, 64, 25)
UVLX8888 = (0, 0, 0, 0, 32, 26)
NONE = (0, 0, 0, 0, 0, 27)
ATI1N = (0, 0, 0, 0, 64, 28)
ATI2N = (0, 0, 0, 0, 128, 29)
is_compressed

Checks if the format is compressed in 4x4 blocks.

frame_size = <function ImageFormats.frame_size>
bin_value = <function ImageFormats.bin_value>
class srctools.vtf.VTFFlags(value)

Bases: Flag

The various image flags that may be set.

EMPTY = 0
POINT_SAMPLE = 1
TRILINEAR = 2
CLAMP_S = 4
CLAMP_T = 8
ANISOTROPIC = 16
HINT_DXT5 = 32
PWL_CORRECTED = 64
NORMAL = 128
NO_MIP = 256
NO_LOD = 512
ALL_MIPS = 1024
PROCEDURAL = 2048
ONEBITALPHA = 4096
EIGHTBITALPHA = 8192
ENVMAP = 16384
RENDER_TARGET = 32768
DEPTH_RENDER_TARGET = 65536
NO_DEBUG_OVERRIDE = 131072
SINGLE_COPY = 262144
PRE_SRGB = 524288
NO_DEPTH_BUFFER = 8388608
CLAMP_U = 33554432
VERTEX_TEXTURE = 67108864
SS_BUMP = 134217728
BORDER = 536870912