Documentation
¶
Overview ¶
Package gaf implements reading and writing of Total Annihilation and TA: Kingdoms GAF (Graphics Animation Format) files.
The on-disk binary layout is identical between both games; only palette resolution differs. See variant.go for how callers signal which game an asset belongs to.
Index ¶
- Constants
- func WriteGAF(w io.Writer, sequences []*Sequence) error
- type Frame
- func (f *Frame) EffectiveTransparencyIndex() uint8
- func (f *Frame) ToImage(palette *Palette) *image.Paletted
- func (f *Frame) ToImageWith(palette *Palette, opts RenderOptions) *image.Paletted
- func (f *Frame) ToPNG(palette *Palette, w io.Writer) error
- func (f *Frame) ToPNGWith(palette *Palette, opts RenderOptions, w io.Writer) error
- type FrameInfo
- type FrameListItem
- type Header
- type Palette
- type Reader
- type RenderOptions
- type Sequence
- func (s *Sequence) ToAPNG(palette *Palette, w io.Writer) error
- func (s *Sequence) ToAPNGWith(palette *Palette, opts RenderOptions, w io.Writer) error
- func (s *Sequence) ToGIF(palette *Palette) (*gif.GIF, error)
- func (s *Sequence) ToGIFWith(palette *Palette, opts RenderOptions) (*gif.GIF, error)
- func (s *Sequence) WriteGIF(w io.Writer, palette *Palette) error
- func (s *Sequence) WriteGIFWith(w io.Writer, palette *Palette, opts RenderOptions) error
- type SequenceHeader
- type TransparencyMode
- type Variant
Constants ¶
const ( // HeaderSize is the size of the GAF header in bytes HeaderSize = 8 // EntryHeaderSize is the size of a GAF entry header EntryHeaderSize = 32 // FrameDataHeaderSize is the size of frame data header FrameDataHeaderSize = 32 )
const VersionTA = 0x00010100
VersionTA is the standard GAF header version word.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Frame ¶
type Frame struct {
Width uint16
Height uint16
OriginX int16
OriginY int16
TransparencyIndex uint8
Duration uint32 // In game ticks (1/30th second)
Pixels []byte // Palette indices
}
Frame represents a single animation frame.
func (*Frame) EffectiveTransparencyIndex ¶
EffectiveTransparencyIndex returns the palette index that should be treated as transparent when this frame is rendered.
Most TA assets store an honest TransparencyIndex in the frame header — the artist used that exact palette index for transparent pixels and the renderer simply makes palette[TI] transparent. TA: Kingdoms texture-atlas GAFs frequently carry a TransparencyIndex that doesn't match the actual pixel value the artist used as the transparent fill (e.g. metadata claims 9, the on-disk pixels are 5). In that case TA-style rendering shows the background as an opaque dark teal rather than transparent.
The heuristic:
If TransparencyIndex appears anywhere in the pixel data, trust it. This is the common case — the decompressor's "transparent run" opcode fills with TI, and TA assets where TI is correctly authored also have TI-valued pixels in the data.
Otherwise sample the four corners; if they all agree on a value, use that. This rescues TAK uncompressed frames where TI is bogus but the artist painted a uniform border (the canonical "background" pixels).
Otherwise fall back to TransparencyIndex.
The on-disk TransparencyIndex value is never overwritten — round-trip writers still see the original byte.
func (*Frame) ToImage ¶
ToImage converts a frame to an image.Image using the given palette and the auto-resolved transparency index.
func (*Frame) ToImageWith ¶
func (f *Frame) ToImageWith(palette *Palette, opts RenderOptions) *image.Paletted
ToImageWith renders a frame with explicit transparency handling.
type FrameInfo ¶
type FrameInfo struct {
Width uint16 // Frame width
Height uint16 // Frame height
OriginX int16 // X origin offset
OriginY int16 // Y origin offset
TransparencyIndex uint8 // Transparent color index
Compressed uint8 // 0=uncompressed, 1=compressed
LayerCount uint16 // Number of subframes (0 for simple frames)
Unknown2 uint32 // Unknown
PtrFrameData uint32 // Pointer to pixel data
Unknown3 uint32 // Unknown
}
FrameInfo describes frame properties (24 bytes).
type FrameListItem ¶
type FrameListItem struct {
PtrFrameInfo uint32 // Pointer to frame info
Duration uint32 // Duration in game ticks (1/30th second)
}
FrameListItem describes a frame entry (8 bytes).
type Header ¶
type Header struct {
Version uint32 // Always 0x00010100
SequenceCount uint32 // Number of animation sequences
Unknown1 uint32 // Always 0
}
Header represents the GAF file header (12 bytes).
type Palette ¶
Palette represents a TA color palette
func FallbackPalette ¶
func FallbackPalette() *Palette
FallbackPalette returns a greyscale palette for when no real palette is available.
func LoadPalette ¶
LoadPalette loads a TA .PAL palette file
func LoadPaletteFromBytes ¶
LoadPaletteFromBytes loads a palette from a byte slice.
func ReadPalette ¶
ReadPalette reads a palette from an io.Reader
func (*Palette) ColorModel ¶
ColorModel returns a color.Palette for this palette
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader reads GAF files.
func LoadFromFile ¶
LoadFromFile opens and validates a GAF file at path.
func LoadFromReader ¶
func LoadFromReader(rs io.ReadSeeker) (*Reader, error)
LoadFromReader creates a new Reader from an io.ReadSeeker and validates the GAF header.
func (*Reader) ReadSequences ¶
ReadSequences reads all animation sequences from the file.
type RenderOptions ¶
type RenderOptions struct {
Mode TransparencyMode
Index uint8 // honored when Mode == TransparencyModeIndex
}
RenderOptions controls per-render transparency choices. A zero-valued RenderOptions resolves to TransparencyModeAuto.
type Sequence ¶
Sequence represents a complete animation sequence.
func (*Sequence) ToAPNG ¶
ToAPNG converts a sequence to an animated PNG (APNG) using auto transparency.
func (*Sequence) ToAPNGWith ¶
ToAPNGWith converts a sequence to an animated PNG (APNG) with explicit transparency options.
func (*Sequence) ToGIFWith ¶
ToGIFWith converts a sequence to an animated GIF using explicit transparency options.
func (*Sequence) WriteGIF ¶
WriteGIF writes an animated GIF to the given writer using auto transparency.
func (*Sequence) WriteGIFWith ¶
WriteGIFWith writes an animated GIF using explicit transparency options.
type SequenceHeader ¶
type SequenceHeader struct {
FrameCount uint16 // Number of frames
Unknown1 uint16 // Unknown
Unknown2 uint32 // Unknown
Name [32]byte // Sequence name (null-terminated)
}
SequenceHeader represents an animation sequence header (40 bytes).
type TransparencyMode ¶
type TransparencyMode int
TransparencyMode selects how a frame's transparency index is resolved at render time. The zero value is TransparencyModeAuto, which preserves the historical behavior callers got from Frame.TransparencyIndex.
const ( // TransparencyModeAuto uses EffectiveTransparencyIndex (corner-detect // heuristic for TAK uncompressed frames, metadata otherwise). TransparencyModeAuto TransparencyMode = iota // TransparencyModeMetadata forces use of Frame.TransparencyIndex // exactly as stored on disk, bypassing the heuristic. TransparencyModeMetadata // TransparencyModeNone disables transparency for the render — every // palette entry stays opaque. TransparencyModeNone // TransparencyModeIndex uses a caller-supplied palette index. TransparencyModeIndex )
type Variant ¶
type Variant int
Variant identifies which game's colouring rules apply to a GAF's indexed pixels.
The on-disk GAF binary format is identical between Total Annihilation and TA: Kingdoms: the same version word, the same sequence/frame layout, and the same row RLE encoding. The games differ only in how the palette indices are coloured:
- Total Annihilation uses a single shared 256-colour palette (palettes/PALETTE.PAL).
- TA: Kingdoms stores palettes externally. Interface GAFs pair with a sibling .pcx of the same base name; unit and feature GAFs use a side-specific palette (Aramon, Taros, Veruna, Zhon).
Because the bytes are identical, the variant cannot be detected from a GAF file alone — callers supply it from context (which game or directory the asset came from). This type exists to make that decision explicit at call sites rather than leaving it implicit in whichever palette happens to be passed to the renderer.
const ( // VariantUnknown is the zero value: the caller has not stated which game // the asset belongs to. Rendering still works; it simply uses whatever // palette is supplied. VariantUnknown Variant = iota // VariantTA is Total Annihilation (shared palette). VariantTA // VariantTAK is TA: Kingdoms (external / side-specific palette). VariantTAK )
func (Variant) DefaultRenderOptions ¶
func (v Variant) DefaultRenderOptions() RenderOptions
DefaultRenderOptions returns the transparency policy that best matches a variant's authored assets.
TA: Kingdoms texture-atlas GAFs frequently carry a TransparencyIndex that does not match the pixel value the artist used for the transparent fill, so the corner-detect heuristic (TransparencyModeAuto) gives the most faithful result. Total Annihilation assets store an honest TransparencyIndex, which the same Auto mode also handles, so both currently resolve to Auto; keeping the choice behind this helper lets the policies diverge later without touching call sites.