bcn

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 11 Imported by: 2

README

bcn

bcn is a native Go codec for BCn GPU texture compression (S3TC and BPTC). It encodes and decodes texture blocks, works directly with Go images, and reads and writes DDS and KTX v1 containers.

Use it to turn image.Image values into GPU-ready textures, inspect or decode existing DDS/KTX assets, and build 2D or cubemap textures with mipmaps. The hot paths use AVX2/SSE2 kernels on amd64 when available; -tags purego builds the same API without assembly or cgo.

Features

  • BC1 / DXT1, BC2 / DXT3, BC3 / DXT5, BC4 / BC5 (UNORM and SNORM), BC6H / BPTC-HDR, BC7 / BPTC encode/decode
  • DDS read/write (2D + cubemap, mipmaps, uncompressed RGBA8 / BGRA8 / BGRX8 / A8 / R8 / RG8/ R8S / RG8S / RGB10A2 / RGB565 / RGBA5551 / RGBA4444 / RGB8 / BGR8)
  • KTX v1 read/write (2D + cubemap, mipmaps, uncompressed RGBA8 / BGRA8 / A8 / R8 / RG8 / R8S / RG8S / RGB10A2 / RGB565 / RGBA5551 / RGBA4444 / RGB8 / BGR8)
  • Mipmap generation with optional sRGB-aware downscale
  • Quality levels (1..10) with least-squares endpoint refit and refinement overrides (Refinement)
  • Parallel encoding control via EncodeOptions.Workers (0=auto, 1=off)
  • Parallel decoding control via DecodeOptions.Workers (0=auto, 1=off)

BC4/BC5 signed normalized variants use FormatBC4S / FormatBC5S. Their NRGBA input and output map 0..255 to -1..1.

[!NOTE]
For large images or one‑by‑one encoding, use internal parallelism (default).
For batch/many small files, parallelize across images in your own code and keep Workers=1 here.
Workers=0 uses GOMAXPROCS (Go scheduler's CPU limit).

Usage

Encode image to DDS
img, _, _ := image.Decode(in)
opts := &bcn.EncodeOptions{
  QualityLevel: bcn.QualityLevelBalanced,
  GenerateMipmaps: true,
  UseSRGB: true,
}

dds, err := bcn.EncodeDDSWithOptions([]image.Image{img}, bcn.FormatBC3, opts)
if err != nil {
  /* handle */
}
_ = dds.Write(out)
Decode DDS to image
dds, err := bcn.ReadDDS(in)
if err != nil {
  /* handle */
}
img, err := bcn.DecodeImage(dds.Faces[0].Mipmaps[0], dds.Width, dds.Height, dds.Format)
if err != nil {
  /* handle */
}
_ = png.Encode(out, img)
Read DDS header only
hdr, dx10, err := bcn.ReadDDSHeader(in)
if err != nil {
  /* handle */
}
_ = hdr
_ = dx10
Encode to KTX
ktx, err := bcn.EncodeKTXWithOptions([]image.Image{img}, bcn.FormatBC5, &bcn.EncodeOptions{QualityLevel: bcn.QualityLevelFast})
if err != nil {
  /* handle */
}
_ = ktx.Write(out)
Use with standard image.Decode

Import the subpackages to register DDS and KTX with the image package; then image.Decode and image.DecodeConfig work as usual:

import (
  _ "github.com/woozymasta/bcn/dds"
  _ "github.com/woozymasta/bcn/ktx"
)

// ...
img, _, _ := image.Decode(f)       // decodes first face/mip to NRGBA
cfg, _, _ := image.DecodeConfig(f) // width, height only

Notes

  • KTX v1 arrays and 3D textures are not supported.
  • DDS DX10 supports BC1–BC7, RGBA/BGRA/BGRX, A8, R8/RG8 (UNORM and SNORM), RGB10A2, RGB565, RGBA5551, RGBA4444, RGB8, and BGR8; writing uses legacy FourCC where available.
  • BC4 uses red channel; BC5 uses red/green.
  • DDS BGRA is converted to RGBA on decode; BGRX always decodes with alpha 255. R8 decodes as R,R,R,255; RG8 as R,G,0,255. Signed R8S/RG8S use the same 0..255 to -1..1 mapping as BC4S/BC5S. A8 decodes as 0,0,0,A.
  • RGB10A2 is packed R:10,G:10,B:10,A:2 UNORM; conversion to/from NRGBA uses nearest rounding.
  • RGB565, RGBA5551, and RGBA4444 use nearest rounding when converting to/from NRGBA.
  • Refinement overrides QualityLevel when set.
  • Quality levels above 1 polish endpoints with an iterated least-squares refit on top of the grid search (higher quality, some extra encode cost; decode is unaffected).
    Disable or tune it via Refinement.LSQIters (0 = off, nil = quality default, N = iterations); set ColorTries: 0 with LSQIters > 0 for a cheap LSQ-only refine.

Acceleration

On amd64 the hot encode/decode paths use AVX2/SSE2 assembly kernels (in the internal/simd package, generated with avo) selected at runtime via golang.org/x/sys/cpu; a portable pure-Go fallback handles every other platform and any block the kernels do not cover (e.g. edge blocks when width or height is not a multiple of 4). The two paths are byte-exact - validated by exhaustive, randomized and fuzz equivalence tests.

  • AVX2 kernels need AVX2 (decode of BC1 needs AVX2; BC2/BC3/BC4/BC5 decode needs AVX2+BMI2). Without them the pure-Go path runs.
  • BCN_PUREGO=1 in the environment forces the pure-Go path at runtime; building with -tags purego excludes the assembly entirely.
  • The avo generator lives in its own build-time-only module (internal/simd/asmgen), so consumers never pull avo into their module graph; the only runtime dependency is golang.org/x/sys.
  • Regenerate kernels after editing internal/simd/asmgen with make generate; make generate-check (part of CI) verifies the committed .s is up to date.
  • Set GOAMD64=v2/v3 to let the Go compiler also vectorize the fallback and container helpers; it does not affect the hand-written kernels.

Performance

Single-thread, Ryzen 9 5950X, Go 1.26, 512x512, throughput over input bytes (RGBA for LDR formats, RGB float16 for BC6H; higher is better):

Format fast, MB/s balanced, MB/s best, MB/s decode, MB/s
BC1 ~830 ~35 ~12 ~920
BC2 ~635 ~33 ~12 ~1715
BC3 ~370 ~31 ~11 ~1670
BC4 ~480 ~74 ~23 ~1530
BC5 ~255 ~38 ~12 ~2490
BC6H ~150 ~8 ~2 ~150
BC7 ~55 ~0.9 ~0.5 ~66

Multi-thread, Workers=auto (GOMAXPROCS=32), 512x512, encode throughput over input bytes (higher is better):

Format fast, MB/s balanced, MB/s best, MB/s
BC1 ~5,000 ~380 ~144
BC3 ~2,620 ~370 ~130
BC6H ~1,350 ~90 ~30
BC7 ~540 ~13 ~7

Fast/Balanced/Best correspond to QualityLevelFast, QualityLevelBalanced, QualityLevelBest.
For batch/many small files, parallelize across images in your own code and keep Workers=1; see EncodeOptions.Workers.

Documentation

Overview

Package bcn provides BCn/DXT block compression encode/decode and container I/O.

The package focuses on practical texture workflows:

  • Encode/decode BC1/DXT1, BC2/DXT3, BC3/DXT5, BC4/BC5 (UNORM and SNORM), BC6H/BPTC-HDR, BC7/BPTC
  • Read/write DDS and KTX v1 containers
  • Optional mipmap generation with sRGB-aware downscaling

The core encode/decode APIs operate on NRGBA byte layout (R,G,B,A per pixel). BC6H is the exception: its API uses []uint16 (or []float32) RGB half-float input, via EncodeBC6H / DecodeBC6H and their variants. For best results, ensure inputs are in the expected color space (typically sRGB) and pick an appropriate QualityLevel in EncodeOptions.

DDS BGRA pixels are converted to RGBA on decode. Uncompressed DDS and KTX support RGBA, BGRA, alpha-only A8, R8/RG8 (UNORM and SNORM), RGB10A2, RGB565, RGBA5551, RGBA4444, RGB8, and BGR8; DDS additionally supports BGRX8.

Index

Examples

Constants

View Source
const (
	// DDSMagic is the file signature "DDS ".
	DDSMagic = 0x20534444

	// DDSHeaderSize is the size of DDS_HEADER.
	DDSHeaderSize = 124
	// DDSPixelFormatSize is the size of DDS_PIXELFORMAT.
	DDSPixelFormatSize = 32

	// DDSFlagCaps marks caps field as valid.
	DDSFlagCaps = 0x1
	// DDSFlagHeight marks height field as valid.
	DDSFlagHeight = 0x2
	// DDSFlagWidth marks width field as valid.
	DDSFlagWidth = 0x4
	// DDSFlagPitch marks pitch field as valid.
	DDSFlagPitch = 0x8
	// DDSFlagPixelFormat marks pixel format as valid.
	DDSFlagPixelFormat = 0x1000
	// DDSFlagMipmapCount marks mipmap count as valid.
	DDSFlagMipmapCount = 0x20000
	// DDSFlagLinearSize marks linear size as valid.
	DDSFlagLinearSize = 0x80000
	// DDSFlagDepth marks depth as valid.
	DDSFlagDepth = 0x800000

	// DDSPFAlphaPixels indicates alpha data is present.
	DDSPFAlphaPixels = 0x1
	// DDSPFAlpha indicates alpha-only data.
	DDSPFAlpha = 0x2
	// DDSPFFourCC indicates a FourCC format.
	DDSPFFourCC = 0x4
	// DDSPFRGB indicates uncompressed RGB data.
	DDSPFRGB = 0x40
	// DDSPFYUV indicates uncompressed YUV data.
	DDSPFYUV = 0x200
	// DDSPFLuminance indicates uncompressed luminance data.
	DDSPFLuminance = 0x20000

	// DDSCapsComplex indicates more than one surface (mips/cubemap/volume).
	DDSCapsComplex = 0x8
	// DDSCapsTexture indicates a texture.
	DDSCapsTexture = 0x1000
	// DDSCapsMipmap indicates mipmaps are present.
	DDSCapsMipmap = 0x400000

	// DDSCaps2Cubemap indicates cubemap faces are present.
	DDSCaps2Cubemap = 0x200

	// DDSFourCCDX10 is the DX10 FourCC ("DX10").
	DDSFourCCDX10 = 0x30315844
)
View Source
const (
	// FormatDXT1 is a compatibility alias for FormatBC1.
	FormatDXT1 = FormatBC1
	// FormatDXT3 is a compatibility alias for FormatBC2.
	FormatDXT3 = FormatBC2
	// FormatDXT5 is a compatibility alias for FormatBC3.
	FormatDXT5 = FormatBC3
)
View Source
const (
	// KTXEndianness is the canonical little-endian marker.
	KTXEndianness = 0x04030201

	// KTXGLUnsignedByte is GL_UNSIGNED_BYTE.
	KTXGLUnsignedByte = 0x1401
	// KTXGLByte is GL_BYTE.
	KTXGLByte = 0x1400
	// KTXGLUnsignedInt2101010Rev is GL_UNSIGNED_INT_2_10_10_10_REV.
	KTXGLUnsignedInt2101010Rev = 0x8368
	// KTXGLUnsignedShort565 is GL_UNSIGNED_SHORT_5_6_5.
	KTXGLUnsignedShort565 = 0x8363
	// KTXGLUnsignedShort1555Rev is GL_UNSIGNED_SHORT_1_5_5_5_REV.
	KTXGLUnsignedShort1555Rev = 0x8366
	// KTXGLUnsignedShort4444Rev is GL_UNSIGNED_SHORT_4_4_4_4_REV.
	KTXGLUnsignedShort4444Rev = 0x8365
	// KTXGLRGB is GL_RGB.
	KTXGLRGB = 0x1907
	// KTXGLRGBA is GL_RGBA.
	KTXGLRGBA = 0x1908
	// KTXGLAlpha is GL_ALPHA.
	KTXGLAlpha = 0x1906
	// KTXGLBGRA is GL_BGRA (extension).
	KTXGLBGRA = 0x80E1
	// KTXGLBGR is GL_BGR (extension).
	KTXGLBGR = 0x80E0
	// KTXGLRed is GL_RED.
	KTXGLRed = 0x1903
	// KTXGLRG is GL_RG.
	KTXGLRG = 0x8227
	// KTXGLRGBA8 is GL_RGBA8 (sized internal format).
	KTXGLRGBA8 = 0x8058
	// KTXGLAlpha8 is GL_ALPHA8 (sized internal format).
	KTXGLAlpha8 = 0x803C
	// KTXGLRGB565 is GL_RGB565 (sized internal format).
	KTXGLRGB565 = 0x8D62
	// KTXGLRGB8 is GL_RGB8 (sized internal format).
	KTXGLRGB8 = 0x8051
	// KTXGLRGB5A1 is GL_RGB5_A1 (sized internal format).
	KTXGLRGB5A1 = 0x8057
	// KTXGLRGBA4 is GL_RGBA4 (sized internal format).
	KTXGLRGBA4 = 0x8056
	// KTXGLRGB10A2 is GL_RGB10_A2 (sized internal format).
	KTXGLRGB10A2 = 0x8059
	// KTXGLR8 is GL_R8 (sized internal format).
	KTXGLR8 = 0x8229
	// KTXGLRG8 is GL_RG8 (sized internal format).
	KTXGLRG8 = 0x822B
	// KTXGLR8SNORM is GL_R8_SNORM (sized internal format).
	KTXGLR8SNORM = 0x8F94
	// KTXGLRG8SNORM is GL_RG8_SNORM (sized internal format).
	KTXGLRG8SNORM = 0x8F95

	// KTXGLCompressedRGBS3TCBC1 is GL_COMPRESSED_RGB_S3TC_DXT1_EXT.
	KTXGLCompressedRGBS3TCBC1 = 0x83F0
	// KTXGLCompressedRGBAS3TCBC1 is GL_COMPRESSED_RGBA_S3TC_DXT1_EXT.
	KTXGLCompressedRGBAS3TCBC1 = 0x83F1
	// KTXGLCompressedRGBAS3TCBC2 is GL_COMPRESSED_RGBA_S3TC_DXT3_EXT.
	KTXGLCompressedRGBAS3TCBC2 = 0x83F2
	// KTXGLCompressedRGBAS3TCBC3 is GL_COMPRESSED_RGBA_S3TC_DXT5_EXT.
	KTXGLCompressedRGBAS3TCBC3 = 0x83F3
	// KTXGLCompressedRedRGTC1 is GL_COMPRESSED_RED_RGTC1.
	KTXGLCompressedRedRGTC1 = 0x8DBB
	// KTXGLCompressedSignedRedRGTC1 is GL_COMPRESSED_SIGNED_RED_RGTC1.
	KTXGLCompressedSignedRedRGTC1 = 0x8DBC
	// KTXGLCompressedRGRGTC2 is GL_COMPRESSED_RG_RGTC2.
	KTXGLCompressedRGRGTC2 = 0x8DBD
	// KTXGLCompressedSignedRGRGTC2 is GL_COMPRESSED_SIGNED_RG_RGTC2.
	KTXGLCompressedSignedRGRGTC2 = 0x8DBE
	// KTXGLCompressedRGBABPTCUnorm is GL_COMPRESSED_RGBA_BPTC_UNORM (BC7).
	KTXGLCompressedRGBABPTCUnorm = 0x8E8C
	// KTXGLCompressedSRGBAlphaBPTCUnorm is GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM (BC7 sRGB).
	KTXGLCompressedSRGBAlphaBPTCUnorm = 0x8E8D
	// KTXGLCompressedRGBBPTCUnsignedFloat is GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT (BC6H UF16).
	KTXGLCompressedRGBBPTCUnsignedFloat = 0x8E8E
	// KTXGLCompressedRGBBPTCSignedFloat is GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT (BC6H SF16).
	KTXGLCompressedRGBBPTCSignedFloat = 0x8E8F
)
View Source
const (
	// KTXGLCompressedRGBS3TCDXT1 is a compatibility alias for KTXGLCompressedRGBS3TCBC1.
	KTXGLCompressedRGBS3TCDXT1 = KTXGLCompressedRGBS3TCBC1
	// KTXGLCompressedRGBAS3TCDXT1 is a compatibility alias for KTXGLCompressedRGBAS3TCBC1.
	KTXGLCompressedRGBAS3TCDXT1 = KTXGLCompressedRGBAS3TCBC1
	// KTXGLCompressedRGBAS3TCDXT3 is a compatibility alias for KTXGLCompressedRGBAS3TCBC2.
	KTXGLCompressedRGBAS3TCDXT3 = KTXGLCompressedRGBAS3TCBC2
	// KTXGLCompressedRGBAS3TCDXT5 is a compatibility alias for KTXGLCompressedRGBAS3TCBC3.
	KTXGLCompressedRGBAS3TCDXT5 = KTXGLCompressedRGBAS3TCBC3
)
View Source
const (
	// QualityLevelFast prioritizes speed over quality.
	QualityLevelFast = 1
	// QualityLevelBalanced is the default, balancing speed and quality.
	QualityLevelBalanced = 6
	// QualityLevelBest prioritizes quality and can be slower.
	QualityLevelBest = 8
)

Variables

View Source
var (
	// ErrInvalidDimensions indicates a width/height <= 0.
	ErrInvalidDimensions = errors.New("invalid dimensions")
	// ErrInvalidRGBALength indicates RGBA slice length mismatch.
	ErrInvalidRGBALength = errors.New("invalid rgba length")
	// ErrBufferTooSmall indicates a caller-provided destination buffer is too small.
	ErrBufferTooSmall = errors.New("destination buffer too small")
	// ErrInsufficientData indicates compressed/uncompressed data is too short.
	ErrInsufficientData = errors.New("insufficient data")
	// ErrUnsupportedFormat indicates an unsupported pixel format.
	ErrUnsupportedFormat = errors.New("unsupported format")
	// ErrUnsupportedUncompressedFormat indicates an unsupported uncompressed format.
	ErrUnsupportedUncompressedFormat = errors.New("unsupported uncompressed format")
	// ErrBC6HUsesHDRAPI is returned when a BC6H format is passed to the NRGBA byte API.
	// Use DecodeBC6H / EncodeBC6H instead.
	ErrBC6HUsesHDRAPI = errors.New("BC6H requires the HDR API (DecodeBC6H / EncodeBC6H)")
	// ErrInvalidHDRSliceLength indicates the HDR pixel slice length does not match width*height*3.
	ErrInvalidHDRSliceLength = errors.New("invalid HDR slice length: must be width*height*3")

	// ErrNilDDS indicates a nil DDS container.
	ErrNilDDS = errors.New("nil DDS")
	// ErrNilDDSHeader indicates a nil DDS header.
	ErrNilDDSHeader = errors.New("nil DDS header")
	// ErrInvalidDDSMagic indicates an invalid DDS magic.
	ErrInvalidDDSMagic = errors.New("invalid DDS magic")
	// ErrInvalidDDSHeaderSize indicates a DDS header size mismatch.
	ErrInvalidDDSHeaderSize = errors.New("invalid DDS header size")
	// ErrInvalidDDSPixelFormatSize indicates a DDS pixel format size mismatch.
	ErrInvalidDDSPixelFormatSize = errors.New("invalid DDS pixel format size")
	// ErrUnsupportedDDSPixelFormat indicates an unsupported DDS pixel format.
	ErrUnsupportedDDSPixelFormat = errors.New("unsupported DDS pixel format")
	// ErrUnsupportedDDSFourCC indicates an unsupported DDS FourCC.
	ErrUnsupportedDDSFourCC = errors.New("unsupported DDS FourCC")
	// ErrUnsupportedDDSFormat indicates an unsupported DDS format.
	ErrUnsupportedDDSFormat = errors.New("unsupported DDS format")
	// ErrUnsupportedDX10Format indicates an unsupported DX10 format.
	ErrUnsupportedDX10Format = errors.New("unsupported DX10 format")
	// ErrUnsupportedDDSResourceDimension indicates an unsupported DDS resource dimension.
	ErrUnsupportedDDSResourceDimension = errors.New("unsupported DDS resource dimension")
	// ErrDDSArrayNotSupported indicates DDS array textures are not supported.
	ErrDDSArrayNotSupported = errors.New("DDS array textures not supported")
	// ErrInvalidFaceCount indicates invalid face count (must be 1 or 6).
	ErrInvalidFaceCount = errors.New("invalid face count")
	// ErrNoFaces indicates no faces present.
	ErrNoFaces = errors.New("no faces")
	// ErrNoMipmaps indicates no mipmaps present.
	ErrNoMipmaps = errors.New("no mipmaps")
	// ErrEmptyMipmaps indicates a face has no mipmaps.
	ErrEmptyMipmaps = errors.New("empty mipmaps")
	// ErrExpectedOneOrSixImages indicates the encoder expected 1 or 6 images.
	ErrExpectedOneOrSixImages = errors.New("expected 1 or 6 images")
	// ErrFacesDifferentDimensions indicates cubemap faces mismatch dimensions.
	ErrFacesDifferentDimensions = errors.New("all faces must have same dimensions")
	// ErrMipmapCountMismatch indicates inconsistent mipmap count across faces.
	ErrMipmapCountMismatch = errors.New("mipmap count mismatch")
	// ErrMipmapSizeMismatch indicates inconsistent mipmap size across faces.
	ErrMipmapSizeMismatch = errors.New("mipmap size mismatch")

	// ErrNilKTX indicates a nil KTX container.
	ErrNilKTX = errors.New("nil KTX")
	// ErrNilKTXHeader indicates a nil KTX header.
	ErrNilKTXHeader = errors.New("nil KTX header")
	// ErrInvalidKTXIdentifier indicates an invalid KTX identifier.
	ErrInvalidKTXIdentifier = errors.New("invalid KTX identifier")
	// ErrUnsupportedKTXEndianness indicates unsupported KTX endianness.
	ErrUnsupportedKTXEndianness = errors.New("unsupported KTX endianness")
	// ErrKTXArraysNotSupported indicates KTX arrays are not supported.
	ErrKTXArraysNotSupported = errors.New("KTX arrays not supported")
	// ErrKTX3DNotSupported indicates KTX 3D textures are not supported.
	ErrKTX3DNotSupported = errors.New("KTX 3D textures not supported")
	// ErrUnsupportedKTXFormat indicates an unsupported KTX format.
	ErrUnsupportedKTXFormat = errors.New("unsupported KTX format")
	// ErrUnsupportedKTXInternalFormat indicates an unsupported KTX internal format.
	ErrUnsupportedKTXInternalFormat = errors.New("unsupported KTX internal format")
	// ErrUnsupportedKTXUncompressed indicates an unsupported uncompressed KTX format (only RGBA8/BGRA8 are supported).
	ErrUnsupportedKTXUncompressed = errors.New("unsupported KTX uncompressed format")
)

Package-level errors for consumers to match with errors.Is.

View Source
var (
	// DefaultRGBWeights is luminance-oriented (green dominant). Use for typical photos/UI.
	DefaultRGBWeights = RGBWeights{R: 0.3, G: 0.6, B: 0.1}
	// BalancedRGBWeights treats R, G, B equally. Use when all channels matter (e.g. normal maps).
	BalancedRGBWeights = RGBWeights{R: 1.0 / 3.0, G: 1.0 / 3.0, B: 1.0 / 3.0}
)

Presets for RGBWeights when encoding BC1/BC3 RGB block.

View Source
var KTXIdentifier = [12]byte{0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A}

KTXIdentifier is the 12-byte KTX v1 file signature.

Functions

func AsNRGBA

func AsNRGBA(rgba []byte, width, height int) *image.NRGBA

AsNRGBA converts a slice of RGBA bytes into an image.NRGBA without copying. The caller must ensure the slice length is width*height*4.

func DecodeBC1 added in v0.6.0

func DecodeBC1(data []byte, width, height int) ([]byte, error)

DecodeBC1 decodes BC1 blocks into an RGBA image (NRGBA layout).

func DecodeBC1WithOptions added in v0.6.0

func DecodeBC1WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC1WithOptions decodes BC1 blocks with explicit options.

func DecodeBC2 added in v0.6.0

func DecodeBC2(data []byte, width, height int) ([]byte, error)

DecodeBC2 decodes BC2 blocks into an RGBA image (NRGBA layout).

func DecodeBC2WithOptions added in v0.6.0

func DecodeBC2WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC2WithOptions decodes BC2 blocks with explicit options.

func DecodeBC3 added in v0.6.0

func DecodeBC3(data []byte, width, height int) ([]byte, error)

DecodeBC3 decodes BC3 blocks into an RGBA image (NRGBA layout).

func DecodeBC3WithOptions added in v0.6.0

func DecodeBC3WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC3WithOptions decodes BC3 blocks with explicit options.

func DecodeBC4

func DecodeBC4(data []byte, width, height int) ([]byte, error)

DecodeBC4 decodes BC4 blocks into an RGBA image (R replicated, A=255).

func DecodeBC4S added in v0.7.0

func DecodeBC4S(data []byte, width, height int) ([]byte, error)

DecodeBC4S decodes signed BC4 blocks into normalized RGBA (R replicated, A=255). Output values map the signed normalized range -1..1 to 0..255.

func DecodeBC4SWithOptions added in v0.7.0

func DecodeBC4SWithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC4SWithOptions decodes signed BC4 blocks with explicit options.

func DecodeBC4WithOptions added in v0.1.3

func DecodeBC4WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC4WithOptions decodes BC4 blocks with explicit options.

func DecodeBC5

func DecodeBC5(data []byte, width, height int) ([]byte, error)

DecodeBC5 decodes BC5 blocks into an RGBA image (R/G from block, B=0, A=255).

func DecodeBC5S added in v0.7.0

func DecodeBC5S(data []byte, width, height int) ([]byte, error)

DecodeBC5S decodes signed BC5 blocks into normalized RGBA. Output R/G map the signed normalized range -1..1 to 0..255; B=0 and A=255.

func DecodeBC5SWithOptions added in v0.7.0

func DecodeBC5SWithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC5SWithOptions decodes signed BC5 blocks with explicit options.

func DecodeBC5WithOptions added in v0.1.3

func DecodeBC5WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC5WithOptions decodes BC5 blocks with explicit options.

func DecodeBC6H added in v0.6.0

func DecodeBC6H(data []byte, width, height int, signed bool) ([]uint16, error)

DecodeBC6H decodes BC6H-compressed data into a flat []uint16 of RGB half-float pixels. Layout: width*height*3 uint16 values in row-major order (R, G, B per texel). signed selects BC6H_SF16 (true) or BC6H_UF16 (false).

func DecodeBC6HFloat32 added in v0.6.0

func DecodeBC6HFloat32(data []byte, width, height int, signed bool) ([]float32, error)

DecodeBC6HFloat32 decodes BC6H data into a flat []float32 of RGB pixels.

func DecodeBC6HFloat32WithOptions added in v0.6.0

func DecodeBC6HFloat32WithOptions(data []byte, width, height int, signed bool, opts *DecodeOptions) ([]float32, error)

DecodeBC6HFloat32WithOptions is DecodeBC6HFloat32 with explicit decode options.

func DecodeBC6HWithOptions added in v0.6.0

func DecodeBC6HWithOptions(data []byte, width, height int, signed bool, opts *DecodeOptions) ([]uint16, error)

DecodeBC6HWithOptions is DecodeBC6H with explicit decode options.

func DecodeBC7 added in v0.6.0

func DecodeBC7(data []byte, width, height int) ([]byte, error)

DecodeBC7 decodes BC7 blocks into an RGBA image (NRGBA layout).

func DecodeBC7WithOptions added in v0.6.0

func DecodeBC7WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeBC7WithOptions decodes BC7 blocks with explicit options.

func DecodeDXT1

func DecodeDXT1(data []byte, width, height int) ([]byte, error)

DecodeDXT1 is a compatibility alias for DecodeBC1.

func DecodeDXT1WithOptions added in v0.1.3

func DecodeDXT1WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeDXT1WithOptions is a compatibility alias for DecodeBC1WithOptions.

func DecodeDXT3

func DecodeDXT3(data []byte, width, height int) ([]byte, error)

DecodeDXT3 is a compatibility alias for DecodeBC2.

func DecodeDXT3WithOptions added in v0.1.3

func DecodeDXT3WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeDXT3WithOptions is a compatibility alias for DecodeBC2WithOptions.

func DecodeDXT5

func DecodeDXT5(data []byte, width, height int) ([]byte, error)

DecodeDXT5 is a compatibility alias for DecodeBC3.

func DecodeDXT5WithOptions added in v0.1.3

func DecodeDXT5WithOptions(data []byte, width, height int, opts *DecodeOptions) ([]byte, error)

DecodeDXT5WithOptions is a compatibility alias for DecodeBC3WithOptions.

func DecodeImage

func DecodeImage(data []byte, width, height int, format Format) (*image.NRGBA, error)

DecodeImage decodes BCn blocks into a new image.NRGBA.

func DecodeImageInto added in v0.5.0

func DecodeImageInto(dst *image.NRGBA, data []byte, width, height int, format Format, opts *DecodeOptions) (*image.NRGBA, error)

DecodeImageInto decodes BCn blocks into a reusable destination image and returns it. When dst is non-nil and its Pix capacity is large enough, the existing buffer is reused (no allocation); otherwise a new image is allocated. Pass the returned image back on the next call to reuse its buffer across decodes of varying sizes.

func DecodeImageWithOptions added in v0.1.3

func DecodeImageWithOptions(data []byte, width, height int, format Format, opts *DecodeOptions) (*image.NRGBA, error)

DecodeImageWithOptions decodes BCn blocks into a new image.NRGBA with options.

func EncodeBC1 added in v0.6.0

func EncodeBC1(rgba []byte, width, height int) ([]byte, error)

EncodeBC1 encodes an RGBA image (NRGBA layout) into BC1 blocks. The input length must be width*height*4.

func EncodeBC1WithOptions added in v0.6.0

func EncodeBC1WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeBC1WithOptions encodes with explicit options. QualityLevel and AlphaThreshold influence endpoint selection and 1-bit alpha mode.

func EncodeBC2 added in v0.6.0

func EncodeBC2(rgba []byte, width, height int) ([]byte, error)

EncodeBC2 encodes an RGBA image (NRGBA layout) into BC2 blocks.

func EncodeBC2WithOptions added in v0.6.0

func EncodeBC2WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeBC2WithOptions encodes with explicit options. QualityLevel affects color endpoint selection; alpha is explicit 4-bit.

func EncodeBC3 added in v0.6.0

func EncodeBC3(rgba []byte, width, height int) ([]byte, error)

EncodeBC3 encodes an RGBA image (NRGBA layout) into BC3 blocks.

func EncodeBC3WithOptions added in v0.6.0

func EncodeBC3WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeBC3WithOptions encodes with explicit options. QualityLevel affects color endpoint selection; alpha is interpolated (BC3).

func EncodeBC4

func EncodeBC4(rgba []byte, width, height int) ([]byte, error)

EncodeBC4 encodes an RGBA image into BC4 blocks using the red channel. Other channels are ignored.

func EncodeBC4S added in v0.7.0

func EncodeBC4S(rgba []byte, width, height int) ([]byte, error)

EncodeBC4S encodes normalized RGBA into signed BC4 blocks using the red channel. Input values map from 0..255 to the signed normalized range -1..1.

func EncodeBC5

func EncodeBC5(rgba []byte, width, height int) ([]byte, error)

EncodeBC5 encodes an RGBA image into BC5 blocks using red/green channels. Blue/alpha are ignored.

func EncodeBC5S added in v0.7.0

func EncodeBC5S(rgba []byte, width, height int) ([]byte, error)

EncodeBC5S encodes normalized RGBA into signed BC5 blocks using red/green channels. Input values map from 0..255 to the signed normalized range -1..1.

func EncodeBC6H added in v0.6.0

func EncodeBC6H(src []uint16, width, height int, signed bool) ([]byte, error)

EncodeBC6H encodes a flat []uint16 RGB half-float image into BC6H-compressed data. src must have length width*height*3. signed selects BC6H_SF16 (true) or BC6H_UF16 (false).

Example
package main

import (
	"fmt"

	"github.com/woozymasta/bcn"
)

func main() {
	const width, height = 4, 4

	// 0x3c00 is float16 1.0.
	src := make([]uint16, width*height*3)
	for i := range src {
		src[i] = 0x3c00
	}

	blocks, err := bcn.EncodeBC6H(src, width, height, false)
	if err != nil {
		panic(err)
	}
	decoded, err := bcn.DecodeBC6H(blocks, width, height, false)
	if err != nil {
		panic(err)
	}

	fmt.Println(len(blocks), len(decoded))
}
Output:
16 48

func EncodeBC6HFloat32 added in v0.6.0

func EncodeBC6HFloat32(src []float32, width, height int, signed bool) ([]byte, error)

EncodeBC6HFloat32 encodes a flat []float32 RGB image into BC6H-compressed data. src must have length width*height*3.

func EncodeBC6HFloat32WithOptions added in v0.6.0

func EncodeBC6HFloat32WithOptions(src []float32, width, height int, signed bool, opts *EncodeOptions) ([]byte, error)

EncodeBC6HFloat32WithOptions is EncodeBC6HFloat32 with explicit encode options.

func EncodeBC6HWithOptions added in v0.6.0

func EncodeBC6HWithOptions(src []uint16, width, height int, signed bool, opts *EncodeOptions) ([]byte, error)

EncodeBC6HWithOptions is EncodeBC6H with explicit encode options.

func EncodeBC7 added in v0.6.0

func EncodeBC7(rgba []byte, width, height int) ([]byte, error)

EncodeBC7 encodes an RGBA image (NRGBA layout) into BC7 blocks.

func EncodeBC7WithOptions added in v0.6.0

func EncodeBC7WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeBC7WithOptions encodes with explicit options. QualityLevel controls the endpoint refinement budget.

func EncodeDXT1

func EncodeDXT1(rgba []byte, width, height int) ([]byte, error)

EncodeDXT1 is a compatibility alias for EncodeBC1.

func EncodeDXT1WithOptions

func EncodeDXT1WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeDXT1WithOptions is a compatibility alias for EncodeBC1WithOptions.

func EncodeDXT3

func EncodeDXT3(rgba []byte, width, height int) ([]byte, error)

EncodeDXT3 is a compatibility alias for EncodeBC2.

func EncodeDXT3WithOptions

func EncodeDXT3WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeDXT3WithOptions is a compatibility alias for EncodeBC2WithOptions.

func EncodeDXT5

func EncodeDXT5(rgba []byte, width, height int) ([]byte, error)

EncodeDXT5 is a compatibility alias for EncodeBC3.

func EncodeDXT5WithOptions

func EncodeDXT5WithOptions(rgba []byte, width, height int, opts *EncodeOptions) ([]byte, error)

EncodeDXT5WithOptions is a compatibility alias for EncodeBC3WithOptions.

func EncodeImage

func EncodeImage(img image.Image, format Format) ([]byte, int, int, error)

EncodeImage encodes an image.Image into BCn blocks using default options.

The input is sampled as NRGBA (8-bit per channel).

Example
package main

import (
	"fmt"
	"image"

	"github.com/woozymasta/bcn"
)

func main() {
	img := image.NewNRGBA(image.Rect(0, 0, 4, 4))

	blocks, width, height, err := bcn.EncodeImage(img, bcn.FormatBC1)
	if err != nil {
		panic(err)
	}
	decoded, err := bcn.DecodeImage(blocks, width, height, bcn.FormatBC1)
	if err != nil {
		panic(err)
	}

	fmt.Println(len(blocks), decoded.Bounds())
}
Output:
8 (0,0)-(4,4)

func EncodeImageInto added in v0.5.0

func EncodeImageInto(dst []byte, img image.Image, format Format, opts *EncodeOptions) ([]byte, int, int, error)

EncodeImageInto encodes img into dst, a caller-owned buffer reused across calls, and returns the encoded slice plus the image dimensions. dst is reallocated only when its capacity is too small; pass the returned slice back on the next call to reuse it. The output is identical to EncodeImageWithOptions.

func EncodeImageWithOptions

func EncodeImageWithOptions(img image.Image, format Format, opts *EncodeOptions) ([]byte, int, int, error)

EncodeImageWithOptions encodes an image.Image into BCn blocks with options.

This is the main entry point for quality level and mipmap behavior.

func GenerateMipmaps

func GenerateMipmaps(img image.Image, useSRGB bool) []*image.NRGBA

GenerateMipmaps builds a full mip chain from the input image. If useSRGB is true, RGB is averaged in linear space and converted back to sRGB.

func GenerateMipmapsInto added in v0.5.0

func GenerateMipmapsInto(dst []*image.NRGBA, img image.Image, maxMipmaps int, useSRGB bool) []*image.NRGBA

GenerateMipmapsInto builds a mip chain reusing the buffers in dst across calls. Level 0 is the input image itself (not copied); levels 1..N-1 reuse the matching dst[i] Pix buffer when large enough, otherwise allocate. Pass the returned slice back on the next call to reuse buffers across images of varying sizes. The chain is identical to GenerateMipmapsN.

func GenerateMipmapsN added in v0.4.0

func GenerateMipmapsN(img image.Image, maxMipmaps int, useSRGB bool) []*image.NRGBA

GenerateMipmapsN builds a mip chain from the input image with an optional level limit. maxMipmaps <= 0 builds a full chain, maxMipmaps == 1 returns only the base level. If useSRGB is true, RGB is averaged in linear space and converted back to sRGB.

func SolidImage

func SolidImage(width, height int, c color.NRGBA) *image.NRGBA

SolidImage returns a solid-color NRGBA image for tests and examples.

func WriteDDSHeader

func WriteDDSHeader(w io.Writer, h *DDSHeader) error

WriteDDSHeader writes DDS header (without magic).

func WriteDDSMagic

func WriteDDSMagic(w io.Writer) error

WriteDDSMagic writes DDS magic.

func WriteKTXHeader

func WriteKTXHeader(w io.Writer, h *KTXHeader) error

WriteKTXHeader writes a KTX v1 header (no payload).

Types

type CubeFace

type CubeFace int

CubeFace identifies cubemap face order used by EncodeDDS/KTX.

const (
	// CubeFacePosX is +X.
	CubeFacePosX CubeFace = iota
	// CubeFaceNegX is -X.
	CubeFaceNegX
	// CubeFacePosY is +Y.
	CubeFacePosY
	// CubeFaceNegY is -Y.
	CubeFaceNegY
	// CubeFacePosZ is +Z.
	CubeFacePosZ
	// CubeFaceNegZ is -Z.
	CubeFaceNegZ
)

type DDS

type DDS struct {
	Faces  []Face // Faces of the texture.
	Format Format // Format of the texture.
	Width  int    // Width of the texture.
	Height int    // Height of the texture.
}

DDS represents a DDS texture with BCn payload.

Faces is 1 for 2D textures or 6 for cubemaps.

func DecodeDDS

func DecodeDDS(r io.Reader) (*DDS, *image.NRGBA, error)

DecodeDDS decodes the first face/mip level of a DDS into an image. This is a convenience wrapper around ReadDDS + DecodeImageWithOptions with nil options.

func DecodeDDSWithOptions added in v0.1.4

func DecodeDDSWithOptions(r io.Reader, opts *DecodeOptions) (*DDS, *image.NRGBA, error)

DecodeDDSWithOptions decodes the first face/mip level of a DDS into an image with options. This is a convenience wrapper around ReadDDS + DecodeImageWithOptions.

func EncodeDDS

func EncodeDDS(img image.Image, format Format) (*DDS, error)

EncodeDDS encodes an image into a DDS with a single mip level.

func EncodeDDSWithOptions

func EncodeDDSWithOptions(images []image.Image, format Format, opts *EncodeOptions) (*DDS, error)

EncodeDDSWithOptions encodes 1 image (2D) or 6 images (cubemap) into a DDS. Mipmaps are generated when EncodeOptions.GenerateMipmaps is true.

Example
package main

import (
	"bytes"
	"fmt"
	"image"

	"github.com/woozymasta/bcn"
)

func main() {
	img := image.NewNRGBA(image.Rect(0, 0, 4, 4))
	dds, err := bcn.EncodeDDSWithOptions([]image.Image{img}, bcn.FormatBC3, &bcn.EncodeOptions{
		GenerateMipmaps: true,
	})
	if err != nil {
		panic(err)
	}

	var dst bytes.Buffer
	if err := dds.Write(&dst); err != nil {
		panic(err)
	}

	fmt.Println(dds.Format, len(dds.Faces), len(dds.Faces[0].Mipmaps), dst.Len() > 0)
}
Output:
BC3 1 3 true

func ReadDDS

func ReadDDS(r io.Reader) (*DDS, error)

ReadDDS parses a DDS stream with BCn payload. Cubemaps and mipmaps are supported; arrays are not.

func (*DDS) IsCubemap

func (d *DDS) IsCubemap() bool

IsCubemap reports whether the DDS contains six faces.

func (*DDS) Write

func (d *DDS) Write(w io.Writer) error

Write serializes the DDS to a stream. The caller must populate Faces and Mipmaps consistently.

type DDSHeader

type DDSHeader struct {
	Size              uint32         // Size of the structure.
	Flags             uint32         // Flags.
	Height            uint32         // Height of the texture.
	Width             uint32         // Width of the texture.
	PitchOrLinearSize uint32         // Pitch or linear size.
	Depth             uint32         // Depth of the texture.
	MipMapCount       uint32         // Number of mipmaps.
	Reserved1         [11]uint32     // Reserved1.
	PixelFormat       DDSPixelFormat // Pixel format.
	Caps              uint32         // Caps.
	Caps2             uint32         // Caps2.
	Caps3             uint32         // Caps3.
	Caps4             uint32         // Caps4.
	Reserved2         uint32         // Reserved2.
}

DDSHeader represents DDS_HEADER.

func CreateDDSHeaderRGBA8

func CreateDDSHeaderRGBA8(width, height, mipMapCount uint32) *DDSHeader

CreateDDSHeaderRGBA8 creates a DDS header for RGBA8 (byte order R,G,B,A).

func ReadDDSHeader

func ReadDDSHeader(r io.Reader) (*DDSHeader, error)

ReadDDSHeader reads DDS magic + header.

type DDSHeaderDX10

type DDSHeaderDX10 struct {
	DXGIFormat        uint32 // DXGI format (DXGI_FORMAT).
	ResourceDimension uint32 // Resource dimension (D3D10_RESOURCE_DIMENSION).
	MiscFlag          uint32 // Misc flag (D3D10_MISC_FLAGS).
	ArraySize         uint32 // Array size (D3D10_ARRAY_SIZE).
	MiscFlags2        uint32 // Misc flags2 (D3D10_MISC_FLAGS2).
}

DDSHeaderDX10 represents DDS_HEADER_DXT10 (DXGI_FORMAT_UNKNOWN).

func ReadDDSHeaderDX10

func ReadDDSHeaderDX10(r io.Reader, h *DDSHeader) (*DDSHeaderDX10, error)

ReadDDSHeaderDX10 reads the optional DX10 header.

type DDSPixelFormat

type DDSPixelFormat struct {
	Size        uint32 // Size of the structure.
	Flags       uint32 // Flags.
	FourCC      uint32 // FourCC code.
	RGBBitCount uint32 // RGB bit count.
	RBitMask    uint32 // R bit mask.
	GBitMask    uint32 // G bit mask.
	BBitMask    uint32 // B bit mask.
	ABitMask    uint32 // A bit mask.
}

DDSPixelFormat represents DDS_PIXELFORMAT.

type DecodeOptions added in v0.1.3

type DecodeOptions struct {
	// Workers controls parallel block decoding. 0 = auto (GOMAXPROCS), 1 = disable parallelism,
	// N > 1 = use N workers. Defaults to 0 (auto) when options are omitted.
	Workers int
}

DecodeOptions configures block decoding.

type EncodeOptions

type EncodeOptions struct {
	// RGBWeights overrides weights for BC1 palette index selection (R, G, B). Nil = default;
	// for BC3, if nil and block has constant R (e.g. nohq), Balanced is used automatically.
	RGBWeights *RGBWeights
	// Refinement overrides quality behavior when non-nil (applied on top of QualityLevel).
	Refinement *RefinementOptions

	// QualityLevel provides a 1..10 quality scale. 0 = default (Balanced).
	// Recommended: 1=fast, 6=balanced, 8=best, 9-10=extreme.
	//
	// Beyond level 1, endpoint selection adds a PCA seed, a grid search,
	// and a least-squares endpoint refit (see RefinementOptions.LSQIters).
	// The refit trades some encode speed for higher quality.
	QualityLevel int
	// Workers controls parallel block encoding. 0 = auto (GOMAXPROCS), 1 = disable parallelism,
	// N > 1 = use N workers. Defaults to 0.
	Workers int
	// GenerateMipmaps enables mipmap generation from the input image.
	GenerateMipmaps bool
	// UseSRGB enables sRGB-aware downscale for mip generation.
	UseSRGB bool
	// AlphaThreshold controls BC1 1-bit alpha cutout (0..255). Default 128.
	AlphaThreshold uint8
	// contains filtered or unexported fields
}

EncodeOptions configures block encoding and mipmap generation.

type Face

type Face struct {
	Mipmaps [][]byte // Mipmaps of the face.
}

Face contains all mip levels for a single face.

type Format

type Format int

Format identifies a BCn compression format.

The format controls block size and how channels are interpreted: - BC1: RGB (optionally 1-bit alpha via 3-color mode) - BC2: RGBA with explicit 4-bit alpha - BC3: RGBA with interpolated alpha - BC4: single channel (stored in red, replicated on decode) - BC5: two channels (stored in red/green, blue=0 on decode)

const (
	// FormatUnknown is a sentinel for unsupported/unknown formats.
	FormatUnknown Format = iota
	// FormatBC1 is BC1 (formerly DXT1; 8 bytes per 4x4 block).
	FormatBC1
	// FormatBC2 is BC2 (formerly DXT3; 16 bytes per 4x4 block).
	FormatBC2
	// FormatBC3 is BC3 (formerly DXT5; 16 bytes per 4x4 block).
	FormatBC3
	// FormatBC4 is BC4/ATI1 (8 bytes per 4x4 block, single channel).
	FormatBC4
	// FormatBC5 is BC5/ATI2 (16 bytes per 4x4 block, two channels).
	FormatBC5
	// FormatRGBA8 is uncompressed RGBA (4 bytes per pixel).
	FormatRGBA8
	// FormatBGRA8 is uncompressed BGRA (4 bytes per pixel).
	FormatBGRA8
	// FormatBC7 is BC7/BPTC unorm RGBA (16 bytes per 4x4 block).
	FormatBC7
	// FormatBC6HU is BC6H unsigned float RGB HDR (16 bytes per 4x4 block).
	// Use DecodeBC6H / EncodeBC6H; the NRGBA byte API returns ErrBC6HUsesHDRAPI.
	FormatBC6HU
	// FormatBC6HS is BC6H signed float RGB HDR (16 bytes per 4x4 block).
	// Use DecodeBC6H / EncodeBC6H; the NRGBA byte API returns ErrBC6HUsesHDRAPI.
	FormatBC6HS
	// FormatBC4S is BC4 signed normalized (8 bytes per 4x4 block, single channel).
	// NRGBA input/output maps 0..255 to -1..1; the decoded value is replicated to RGB.
	FormatBC4S
	// FormatBC5S is BC5 signed normalized (16 bytes per 4x4 block, two channels).
	// NRGBA input/output maps R/G from 0..255 to -1..1; decoded B=0 and A=255.
	FormatBC5S
	// FormatBGRX8 is uncompressed BGR with an unused byte (4 bytes per pixel).
	// Encoding and decoding always set the unused byte/alpha to 255.
	FormatBGRX8
	// FormatR8 is uncompressed single-channel UNORM (1 byte per pixel).
	// Decoding replicates R to RGB and sets A to 255.
	FormatR8
	// FormatRG8 is uncompressed two-channel UNORM (2 bytes per pixel).
	// Decoding writes R and G, with B=0 and A=255.
	FormatRG8
	// FormatRGB10A2 is packed 10-bit RGB plus 2-bit alpha UNORM (4 bytes per pixel).
	FormatRGB10A2
	// FormatR8S is uncompressed single-channel SNORM (1 byte per pixel).
	// NRGBA input/output maps 0..255 to -1..1; decoding replicates R to RGB.
	FormatR8S
	// FormatRG8S is uncompressed two-channel SNORM (2 bytes per pixel).
	// NRGBA input/output maps R/G from 0..255 to -1..1; decoded B=0 and A=255.
	FormatRG8S
	// FormatA8 is uncompressed alpha-only UNORM (1 byte per pixel).
	// Decoding writes RGB=0 and preserves alpha.
	FormatA8
	// FormatRGB565 is packed 5-bit R, 6-bit G, 5-bit B UNORM (2 bytes per pixel).
	FormatRGB565
	// FormatRGBA5551 is packed 5-bit RGB plus 1-bit alpha UNORM (2 bytes per pixel).
	// The little-endian word layout is A1:R5:G5:B5.
	FormatRGBA5551
	// FormatRGBA4444 is packed 4-bit RGBA UNORM (2 bytes per pixel).
	// The little-endian word layout is A4:R4:G4:B4.
	FormatRGBA4444
	// FormatRGB8 is uncompressed RGB UNORM (3 bytes per pixel).
	FormatRGB8
	// FormatBGR8 is uncompressed BGR UNORM (3 bytes per pixel).
	FormatBGR8
)

func (Format) String

func (f Format) String() string

type KTX

type KTX struct {
	Faces  []Face // Faces of the texture.
	Format Format // Format of the texture.
	Width  int    // Width of the texture.
	Height int    // Height of the texture.
}

KTX represents a KTX v1 texture with BCn payload.

Faces is 1 for 2D textures or 6 for cubemaps.

func DecodeKTX

func DecodeKTX(r io.Reader) (*KTX, *image.NRGBA, error)

DecodeKTX decodes the first face/mip level of a KTX into an image. This is a convenience wrapper around ReadKTX + DecodeImageWithOptions with nil options.

func DecodeKTXWithOptions added in v0.1.4

func DecodeKTXWithOptions(r io.Reader, opts *DecodeOptions) (*KTX, *image.NRGBA, error)

DecodeKTXWithOptions decodes the first face/mip level of a KTX into an image with options. This is a convenience wrapper around ReadKTX + DecodeImageWithOptions.

func EncodeKTX

func EncodeKTX(img image.Image, format Format) (*KTX, error)

EncodeKTX encodes an image into a KTX with a single mip level.

func EncodeKTXWithOptions

func EncodeKTXWithOptions(images []image.Image, format Format, opts *EncodeOptions) (*KTX, error)

EncodeKTXWithOptions encodes 1 image (2D) or 6 images (cubemap) into a KTX. Mipmaps are generated when EncodeOptions.GenerateMipmaps is true.

func ReadKTX

func ReadKTX(r io.Reader) (*KTX, error)

ReadKTX parses a KTX v1 stream with BCn or supported uncompressed payload. Arrays and 3D textures are rejected.

func (*KTX) IsCubemap

func (k *KTX) IsCubemap() bool

IsCubemap reports whether the KTX contains six faces.

func (*KTX) Write

func (k *KTX) Write(w io.Writer) error

Write serializes the KTX to a stream. The caller must populate Faces and Mipmaps consistently.

type KTXHeader

type KTXHeader struct {
	Identifier            [12]byte
	Endianness            uint32
	GlType                uint32
	GlTypeSize            uint32
	GlFormat              uint32
	GlInternalFormat      uint32
	GlBaseInternalFormat  uint32
	PixelWidth            uint32
	PixelHeight           uint32
	PixelDepth            uint32
	NumberOfArrayElements uint32
	NumberOfFaces         uint32
	NumberOfMipmapLevels  uint32
	BytesOfKeyValueData   uint32
}

KTXHeader represents a KTX v1 header.

func ReadKTXHeader

func ReadKTXHeader(r io.Reader) (*KTXHeader, error)

ReadKTXHeader reads a KTX v1 header (no payload).

type RGBWeights added in v0.1.2

type RGBWeights struct {
	R, G, B float64
}

RGBWeights are used when choosing BC1 palette indices (and in refinement). R, G, B are relative weights; they are normalized when used. Used to preserve channels that matter (e.g. blue in normal maps).

type RefinementOptions added in v0.1.3

type RefinementOptions struct {
	UsePCA     *bool // UsePCA overrides quality behavior derived from QualityLevel.
	ColorTries *int  // ColorTries overrides quality behavior derived from QualityLevel.
	AlphaTries *int  // AlphaTries overrides quality behavior derived from QualityLevel.
	ColorStep  *int  // ColorStep overrides quality behavior derived from QualityLevel.

	// LSQIters overrides the least-squares endpoint polish iterations applied after the grid search.
	// 0 disables LSQ (grid search still runs); nil uses the quality-derived default.
	LSQIters *int
}

RefinementOptions allows overriding quality behavior derived from QualityLevel. Nil fields mean "use defaults".

Directories

Path Synopsis
Package dds registers the DDS image format with the standard image package.
Package dds registers the DDS image format with the standard image package.
internal
simd
Package simd provides the amd64 SIMD (AVX2/SSE2, BMI2) assembly kernels used by the bcn encoder/decoder, together with runtime CPU feature flags.
Package simd provides the amd64 SIMD (AVX2/SSE2, BMI2) assembly kernels used by the bcn encoder/decoder, together with runtime CPU feature flags.
Package ktx registers the KTX image format with the standard image package.
Package ktx registers the KTX image format with the standard image package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL