BLP format¶
Blizzard's texture format (wowdev.wiki/BLP). BLP2 is
version-stable — every client release from vanilla through The War Within reads
the same layout — so unlike the chunked formats there is one unversioned BLP
class and no for_version factory.
A file is a fixed header + 256-entry palette followed by up to 16 mipmap
payloads. read()/write() move the file whole and round-trip byte-perfectly
while the payloads are unmodified (unusual layouts — inter-mip gaps, trailing
bytes, shared placement — are recorded and replayed). decode(level) produces
an RGBA8 Image from any stored level — palettized,
DXT1/3/5, BC5 and raw BGRA all decode. encode(image, settings) rebuilds the
whole texture from one image: palette quantization (median cut), DXT compression
and box-filtered mip generation.
import numpy as np
import wowlib
from wowlib.formats import blp
with wowlib.fs.FileSystem.open(settings) as fs:
texture = blp.BLP()
texture.read(fs, wowlib.FileKey("Interface/Icons/INV_Misc_QuestionMark.blp"))
image = texture.decode() # level 0, RGBA8
pixels = np.asarray(image.pixels).reshape(image.height, image.width, 4)
pixels[..., 3] = 255 # edit in place (zero-copy view)
edited = blp.Image()
edited.width, edited.height = image.width, image.height
edited.pixels.extend(pixels.reshape(-1).tolist())
texture.encode(edited, blp.EncodeSettings(format=blp.PixelFormat.Dxt5))
texture.write(fs, wowlib.FileKey("Interface/Icons/INV_Misc_QuestionMark.blp"))
The BLP texture format: the version-stable BLP2 entity with byte-perfect round-trips, RGBA8 decode of every shipped encoding (palettized, DXT1/3/5, BC5, raw BGRA) and full re-encoding (palette quantization, DXT compression, mip-chain generation).
ColorEncoding
¶
Bases: IntEnum
How a BLP's pixel payload is encoded (the header's colorEncoding byte).
Attributes:
| Name | Description |
|---|---|
Jpeg |
JPEG-compressed content (Warcraft III heritage; never shipped in WoW clients — wowlib preserves but cannot decode it). |
Palettized |
256-color palette indices, one byte per pixel, followed by a separate alpha plane of alphaDepth bits per pixel. |
Dxt |
DXT/S3TC block compression; the variant (BC1/BC2/BC3/BC5) follows from preferred_format and alphaDepth. |
Bgra |
Raw 32-bit BGRA pixels (Cataclysm+; terrain cube maps). |
BgraAlt |
Raw 32-bit BGRA under a different client-side PIXEL_FORMAT; identical file content to Bgra. |
PixelFormat
¶
Bases: IntEnum
The client-side pixel format hint (the header's preferredFormat byte). For DXT-encoded files it selects the block format: Dxt1 -> BC1, Dxt3 -> BC2, Dxt5 -> BC3, Bc5 -> BC5.
Attributes:
| Name | Description |
|---|---|
Dxt1 |
BC1: 8-byte blocks, optional 1-bit punch-through alpha. |
Dxt3 |
BC2: 16-byte blocks, explicit 4-bit alpha. |
Argb8888 |
Raw 32-bit upload hint (used by Bgra-encoded files). |
Argb1555 |
16-bit 1555 upload hint; never a file content layout. |
Argb4444 |
16-bit 4444 upload hint; never a file content layout. |
Rgb565 |
16-bit 565 upload hint; never a file content layout. |
A8 |
Alpha-only upload hint; never a file content layout. |
Dxt5 |
BC3: 16-byte blocks, interpolated 8-bit alpha. |
Unspecified |
No preference recorded (typical for palettized files). |
Argb2565 |
Component-texture upload hint; never a file content layout. |
Bc5 |
BC5: two interpolated channels (normal maps, later clients). |
Image
¶
A decoded texture surface: 8-bit RGBA pixels in row-major order, row 0 at the top. pixels holds width * height * 4 bytes (r, g, b, a per pixel) and maps to NumPy zero-copy; reshape to (height, width, 4).
EncodeSettings
¶
EncodeSettings(encoding: ColorEncoding | None = ..., format: PixelFormat | None = ..., alpha_depth: int = 8, mipmaps: bool = True)
How encode() should build the file. The defaults produce what the client ships most: DXT compression with the block format chosen from the alpha depth (0 -> BC1, 1 -> BC1 punch-through, 4 -> BC2, 8 -> BC3), with a full generated mip chain.
encoding
property
writable
¶
encoding: ColorEncoding
The payload encoding to produce (Palettized, Dxt or Bgra; Jpeg is not supported).
format
property
writable
¶
format: PixelFormat
The DXT block format for Dxt encoding (Dxt1, Dxt3, Dxt5 or Bc5). Unspecified picks from alphaDepth: 0/1 -> Dxt1, 4 -> Dxt3, 8 -> Dxt5. Ignored for Palettized/Bgra.
alpha_depth
property
writable
¶
Alpha bits per pixel: 0, 1, 4 or 8. Selects the alpha plane depth for Palettized files and the block format for Dxt when format is Unspecified.
mipmaps
property
writable
¶
Whether to generate the full mip chain down to 1x1 (box-filtered). Off: the file holds only level 0.
BLP
¶
Bases: FileEntity
A BLP2 texture file — every WoW client release reads the same layout, so the class carries no client-version axis. read()/write() move the file whole with a byte-perfect round-trip while the mip payloads are unmodified; decode(level) produces an RGBA8 Image from a stored level (palettized, DXT1/3/5, BC5 and raw BGRA all decode); encode(image, settings) rebuilds the palette/compression/mip chain from one. Raw payload access goes through mip()/set_mip(). See https://wowdev.wiki/BLP.
alpha_depth
property
writable
¶
Alpha bits per pixel (0, 1, 4 or 8): the alpha plane depth for Palettized files, and a selection hint for DXT.
preferred_format
property
writable
¶
preferred_format: PixelFormat
The client-side pixel format hint; selects the DXT block format for Dxt-encoded files.
mip_flags
property
writable
¶
The header's mip byte: 0 = level 0 only, 1 = generated mips, 2 = handmade mips (plus rare high flag bits, preserved verbatim).
palette
property
writable
¶
palette: list[CImVector]
The 256-entry color table of Palettized files (b, g, r + a padding byte, preserved verbatim). Present but unused for Dxt/Bgra files.
read
¶
read(fs: FileSystem, key: FileKey) -> None
Parse a BLP2 file from memory, replacing this entity's contents.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
bytes
|
the complete file bytes |
required |
Load the BLP from a client filesystem, replacing this entity's contents.
Parameters:
| Name | Description | Default |
|---|---|---|
fs
|
the filesystem gateway |
required |
key
|
the file identity (path and/or FileDataID) |
required |
write
¶
write(fs: FileSystem, key: FileKey) -> None
Serialize this entity. While the mip payloads are unmodified the original file's exact layout is replayed, so an unmodified read rewrites byte-for-byte.
Returns:
| Type | Description |
|---|---|
bytes
|
the file bytes |
Serialize and store the BLP through the filesystem's project overlay.
Parameters:
| Name | Description | Default |
|---|---|---|
fs
|
the filesystem gateway |
required |
key
|
the file identity; must resolve to a path |
required |
decode
¶
encode
¶
encode(image: Image) -> None
encode(image: Image, settings: EncodeSettings) -> None
Rebuild the whole texture from an RGBA8 image with the default settings (DXT, alpha depth 8 -> BC3, full mip chain).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
Image
|
the level-0 image; width * height * 4 pixel bytes |
required |
Rebuild the whole texture from an RGBA8 image: sets the header fields, quantizes/compresses every level and generates the mip chain per the settings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
image
|
Image
|
the level-0 image; width * height * 4 pixel bytes |
required |
settings
|
encoding, block format, alpha depth and mip generation choices |
required |
mip
¶
One level's raw payload bytes (palette indices + alpha plane, DXT blocks, or BGRA pixels, per colorEncoding).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
the mip level |
required |
Returns:
| Type | Description |
|---|---|
bytes
|
a copy of the payload bytes |
set_mip
¶
Replace one level's raw payload bytes verbatim. The caller owns their consistency with the header fields; changing a payload's size switches write() to the canonical contiguous layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
the mip level |
required |
data
|
bytes
|
the payload bytes |
required |
mip_width
¶
The pixel width of a mip level (level 0 halves per step, floored at 1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
the mip level |
required |
mip_height
¶
The pixel height of a mip level (level 0 halves per step, floored at 1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
the mip level |
required |
validate
¶
Check the logical integrity contracts this texture must satisfy for the client to decode it — the base level's presence, the dimensions, and every stored level covering the pixels its size implies. write() never runs this; call it before writing when you want to know the result will load.
Returns:
| Type | Description |
|---|---|
ValidationReport
|
every violated contract, in level order |
ensure_valid
¶
Validate and raise on the first error instead of returning a report — the assert-style face of validate().
Returns:
| Type | Description |
|---|---|
None
|
nothing; raises when validate() finds any error |