Package github.com/matjam/bunyip/gfx/ktx2
gfx/ktx2
Package ktx2 reads and writes KTX2 texture files and encodes and decodes the block-compressed formats they carry. It is the offline half of the texture pipeline: bunyip-tex turns a PNG or JPEG into a KTX2 file holding BC1, BC3, BC4, BC5 or BC7 blocks and the whole mip chain, and gfx.NewCompressedTexture uploads that file straight into a compressed image with the levels as they are, so nothing is compressed or downsampled while a game runs.
What is written
A file holds one 2D image: a format, a size, and one byte slice per mip level, level 0 first. Array layers, cube faces, 3D textures and supercompression are neither written nor read, and a file that uses them is an error. The data format descriptor is written in its basic form so other KTX2 tools accept the file, and it is not read back: the format number is what the loader needs.
Colour
Encode premultiplies a colour image in linear light before compressing it, the same way gfx.NewTexture does, so a compressed texture blends like an uncompressed one. A format that is not sRGB holds data rather than colour, so its texels are encoded as they stand and its mip chain is averaged without a gamma step.
ASTC
ASTC blocks are carried but not encoded or decoded: a file that already holds ASTC parses, names its format and uploads on a device that samples it, and there is nothing to fall back on where a device does not.
Index
Functions
PSNR source
func PSNR(a, b *image.RGBA, channels int) float64
PSNR is the peak signal-to-noise ratio between two images of the same size, in decibels over the channels given: three for colour alone, four to include alpha. It is what bunyip-tex reports and what the tests hold an encoder to. Identical images have no noise, which it reports as positive infinity.
Types
type File source
type File struct {
Format Format
Width, Height int
Levels [][]byte
}
File is one 2D texture: a format, a size and its mip levels, level 0 first. Levels holds the blocks as the format packs them, ready to upload.
Encode source
func Encode(src image.Image, opts Options) (*File, error)
Encode compresses an image into a KTX2 file ready for gfx.NewCompressedTexture. A colour image, meaning one in an sRGB format, is premultiplied in linear light first, the same way gfx.NewTexture does it, so a compressed texture blends like an uncompressed one; a format that is not sRGB holds data rather than colour and its texels are encoded as they stand.
Parse source
func Parse(data []byte) (*File, error)
Parse reads a KTX2 file with one face, depth at most one, at most one layer and no supercompression. Dimensions must be 1..65536, every level must have its exact format-specific byte size, and the chain cannot extend beyond 1x1. A zero level count is read as one supplied base level. Levels alias data: keep the input unchanged while the File is in use.
Bytes source
func (f *File) Bytes() ([]byte, error)
Bytes encodes the file. The levels are written smallest first, which is the order the specification recommends, with the level index in level order as it requires.
Decodable source
func (f *File) Decodable() bool
Decodable reports whether DecodeLevel can expand the file's format, which is what gfx asks before falling back to software on a device that cannot sample it.
DecodeLevel source
func (f *File) DecodeLevel(level int) (*image.RGBA, error)
DecodeLevel expands one mip level back to RGBA, for a device that cannot sample the format and for checking what an encoder produced. BC4 puts its one channel in red and BC5 its two in red and green, in both cases with the rest of the texel left at zero and alpha opaque.
type Format source
type Format uint32
Format is the Vulkan format number a KTX2 file names for its texel data. Naming a format permits container parsing and GPU upload; it does not imply CPU codec support. Encode supports RGBA8, BC1, BC3, unsigned BC4/BC5 and BC7. DecodeLevel supports the same formats, with BC7 limited to modes 1 and 6. Other named formats, including ASTC, require a device that can sample them directly.
const (
Undefined Format = 0
R8G8B8A8Unorm Format = 37
R8G8B8A8SRGB Format = 43
// BC1 is four bits a texel: three colour channels and one bit of
// alpha in the RGBA forms. The encoder writes the opaque four-colour
// mode, so the RGBA forms decode with every texel opaque.
BC1RGBUnorm Format = 131
BC1RGBSRGB Format = 132
BC1RGBAUnorm Format = 133
BC1RGBASRGB Format = 134
BC2Unorm Format = 135
BC2SRGB Format = 136
// BC3 is eight bits a texel: a BC1 colour block and an eight-value
// alpha block, which is the format for sprites with soft edges.
BC3Unorm Format = 137
BC3SRGB Format = 138
// BC4 is one channel at four bits a texel and BC5 is two at eight,
// for masks, height fields and tangent-space normal maps.
BC4Unorm Format = 139
BC4SNorm Format = 140
BC5Unorm Format = 141
BC5SNorm Format = 142
BC6HUfloat Format = 143
BC6HSfloat Format = 144
// BC7 is eight bits a texel with alpha, and is the best of these for
// colour that has to hold up close.
BC7Unorm Format = 145
BC7SRGB Format = 146
// The ASTC formats, 4x4 through 12x12. The package passes these
// through: it neither encodes nor decodes them.
ASTC4x4Unorm Format = 157
ASTC4x4SRGB Format = 158
ASTC12x12Unorm Format = 183
ASTC12x12SRGB Format = 184
)
The formats this package names. The numbers are Vulkan's, which is what a KTX2 header carries, so gfx hands one straight to the driver.
Named source
func Named(name string, linear bool) (Format, error)
Named turns a name such as "bc7" or "bc1" into the format's sRGB or linear pair, for a command-line flag. The known names are bc1, bc3, bc4, bc5 and bc7; bc4 and bc5 hold no colour, so they are always linear.
ASTC source
func (f Format) ASTC() bool
ASTC reports whether the format is one of the ASTC block formats, which this package carries but does not encode or decode.
BlockSize source
func (f Format) BlockSize() (w, h int)
BlockSize is the texels one block covers, 4 by 4 for every BC format and 1 by 1 for the uncompressed ones.
Compressed source
func (f Format) Compressed() bool
Compressed reports whether the format stores blocks rather than texels.
LevelBytes source
func (f Format) LevelBytes(w, h int) int
LevelBytes is how many bytes a mip level of a size takes in the format, with the size rounded up to whole blocks.
type Options source
type Options struct {
// Format is the block format to write. Zero means BC7SRGB, which
// suits colour that has to hold up close; BC1 is a quarter of the
// size and drops alpha, BC3 keeps alpha at half of BC7's size, and
// BC4 and BC5 are for one and two channels of data.
Format Format
// NoMipmaps writes level 0 alone. The default is the whole chain
// down to one texel, averaged in linear light for an sRGB format, so
// a distant surface does not shimmer and nothing is downsampled while
// the game runs.
NoMipmaps bool
// Fast keeps the BC7 encoder to its single-subset mode instead of
// also searching the sixty-four two-subset partitions. It is several
// times quicker and a little worse on blocks that straddle an edge.
Fast bool
}
Options says how Encode compresses an image.
Source files
bc1.go bc4.go bc7.go bc7tables.go block.go encode.go format.go ktx2.go ktx2_test.go mip_validation_test.go