TextureCompressor.Codecs.BasisUniversal 0.1.0

dotnet add package TextureCompressor.Codecs.BasisUniversal --version 0.1.0
                    
NuGet\Install-Package TextureCompressor.Codecs.BasisUniversal -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TextureCompressor.Codecs.BasisUniversal" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TextureCompressor.Codecs.BasisUniversal" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="TextureCompressor.Codecs.BasisUniversal" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TextureCompressor.Codecs.BasisUniversal --version 0.1.0
                    
#r "nuget: TextureCompressor.Codecs.BasisUniversal, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TextureCompressor.Codecs.BasisUniversal@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TextureCompressor.Codecs.BasisUniversal&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=TextureCompressor.Codecs.BasisUniversal&version=0.1.0
                    
Install as a Cake Tool

TextureCompressor

中文文档

TextureCompressor is a .NET texture codec library for converting bitmap data to common GPU texture formats and for reading or writing DDS, KTX, PVR, PNG, HDR, and ASTC containers.

The public API is still early and may change before the first stable release.

Features

  • Bitmap primitives: ArrayBitmap<TPixel>, BitmapView<TPixel>, and common RGBA pixel structs.
  • Texture metadata: TextureFormats definitions for uncompressed, packed, paletted, planar YUV, and block-compressed formats.
  • Built-in texture coders: representative coverage for S3TC/DXT, RGTC/LATC, BPTC, ETC/EAC, ASTC, ATC, PVRTC, FXT1, RGBM/RGBD, YUV, depth/stencil, and XR-style formats.
  • The core TextureCompressor package and built-in coders are fully managed and do not require external native libraries or texture-compression tools.
  • File-format packages: PNG, JPEG, GIF, HDR, DDS, KTX, PVR, and ASTC read/write helpers.
  • Unified file-format registration and non-CLI APIs for conversion, texture assembly, and subresource extraction.
  • Quality analysis: whole-image and per-channel MSE, RMSE, and PSNR.
  • Development CLI: format search, container metadata inspection, conversion, and quality metric output.
  • Source generator: automatically generates TextureFormatCatalog for format enumeration and name lookup.
  • Optional external encoder adapters: BCnEncoder, AstcEncoderCSharp, Basis Universal, DirectXTex, and PVRTexLib.

Texture Format Support

README only lists the major supported families. See docs/texture-format-support.en.md for the full support list.

  • Compressed textures: S3TC / DXT / BC1-BC3, RGTC / LATC / ATI, BPTC / BC6H / BC7, ETC / EAC, ASTC 2D, ATC, PVRTC, and FXT1.
  • Basis formats: raw Basis ETC1S payload encode/decode is implemented (I-frame only) through IBasisEtc1sTextureCoder because BasisLZ payloads are variable length, and Basis UASTC LDR 4x4 is available as a built-in managed format and is also readable/writable through KTX/PVR containers.
  • Uncompressed and non-block-compressed textures: sequential pixels, alpha/luminance/intensity, packed formats, paletted/indexed formats, YUV, depth/stencil, XR/RGBM/RGBD, and related layouts.

Project Layout

  • src/TextureCompressor: pixel structs, bitmap and view abstractions, texture format definitions, core coders, TextureCoderManager, file-format registration interfaces, and TextureConverter.
  • src/TextureCompressor.SourceGenerators: generates TextureFormatCatalog for format enumeration and name lookup.
  • src/TextureCompressor.Analysis: bitmap quality metrics.
  • src/TextureCompressor.Cli: development command-line tool.
  • src/TextureCompressor.FileFormats.Png: PNG decoder and encoder.
  • src/TextureCompressor.FileFormats.Jpeg: baseline JPEG decoder and encoder.
  • src/TextureCompressor.FileFormats.Gif: static GIF decoder and encoder.
  • src/TextureCompressor.FileFormats.Hdr: Radiance RGBE .hdr decoder and encoder.
  • src/TextureCompressor.FileFormats.Dds: DDS/DX10 and legacy DDS container I/O.
  • src/TextureCompressor.FileFormats.Ktx: KTX v1/v2 container I/O, including KTX2 Zstandard supercompression.
  • src/TextureCompressor.FileFormats.Pvr: PVR v1/v2/v3 container I/O.
  • src/TextureCompressor.FileFormats.Astc: .astc container I/O.
  • src/TextureCompressor.Codecs.*: optional third-party encoder adapters.
  • tests: core codec, file-format, and adapter tests.

Requirements

  • .NET SDK 10.0 or newer.
  • The core library does not require any external texture compressor or platform-native runtime. Optional third-party encoder adapters and some auxiliary tools bring their own NuGet dependencies.

Add It To Your Project

The repository currently ships as source projects. Add project references from your app or library:

dotnet add YourApp.csproj reference src/TextureCompressor/TextureCompressor.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Png/TextureCompressor.FileFormats.Png.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Jpeg/TextureCompressor.FileFormats.Jpeg.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Gif/TextureCompressor.FileFormats.Gif.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Hdr/TextureCompressor.FileFormats.Hdr.csproj

Reference the container packages you need:

dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Dds/TextureCompressor.FileFormats.Dds.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Ktx/TextureCompressor.FileFormats.Ktx.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Pvr/TextureCompressor.FileFormats.Pvr.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.FileFormats.Astc/TextureCompressor.FileFormats.Astc.csproj

Reference the analysis package when you need quality metrics:

dotnet add YourApp.csproj reference src/TextureCompressor.Analysis/TextureCompressor.Analysis.csproj

Run the development CLI directly from the source project:

dotnet run --project src/TextureCompressor.Cli -- --help

Quick Start: PNG To BC7 And Back

This example reads an RGBA8 PNG, encodes it to a BC7 texture payload, decodes it back, and writes a PNG preview:

using TextureCompressor.Bitmaps;
using TextureCompressor.Codecs;
using TextureCompressor.Colors;
using TextureCompressor.FileFormats.Png;
using TextureCompressor.Formats;
using TextureCompressor.Registry;

var source = PngCodec.DecodeRgba8("input.png");
var format = TextureFormats.Bc7UNorm;
var coder = TextureCoderManager.Global.GetCoder(format);

var encoded = new byte[coder.GetEncodedByteCount(source.Width, source.Height)];
coder.Encode(source.AsView(), encoded);

var decoded = new ArrayBitmap<Rgba8UNorm>(source.Width, source.Height);
coder.Decode(encoded, decoded.AsView());

PngCodec.Encode(decoded, "roundtrip.png");

TextureCoderManager.Global creates built-in coders by format. Built-in S3TC, FXT1, ETC/EAC, ASTC, ATC, RGTC/LATC, BPTC, and PVRTC coders also expose compression-mode options when you construct and register them yourself; see the next section. Register an external coder when you need a different implementation or higher production compression quality.

Non-CLI File Conversion API

TextureConverter provides a library-level conversion entry point similar to the CLI convert command. The core library does not directly depend on concrete PNG, DDS, or KTX packages; register the file formats you need with TextureFileFormatManager, then the converter selects an IImageFileFormat or ITextureFileFormat by input and output extension.

using TextureCompressor.Conversion;
using TextureCompressor.Bitmaps;
using TextureCompressor.FileFormats;
using TextureCompressor.FileFormats.Ktx;
using TextureCompressor.FileFormats.Png;
using TextureCompressor.Formats;

var fileFormats = new TextureFileFormatManager();
using var png = fileFormats.RegisterPngFileFormat();
using var ktx = fileFormats.RegisterKtxFileFormat();

var converter = new TextureConverter(fileFormats);

converter.Convert(
    "input.png",
    "output.ktx2",
    new TextureConversionOptions
    {
        TargetFormat = TextureFormats.Bc7Srgb,
        Mipmaps = TextureConversionMipmaps.Generate,
        MipmapOptions = new MipmapGenerationOptions
        {
            ColorSpace = MipmapColorSpace.Srgb,
            AlphaMode = MipmapAlphaMode.Premultiplied,
            Filter = MipmapFilter.Triangle,
            MaxLevelCount = 8
        },
        WriteOptions = new KtxEncodingOptions
        {
            Version = KtxVersion.Version2
        }
    });

When MipmapOptions is omitted in texture-aware APIs, the mip color space is inferred from the target format: Srgb and XRSrgb formats use sRGB-aware filtering, while other formats use linear filtering. Direct BitmapMipChain.Generate(...) calls keep the linear default unless options are supplied. The same options can be passed to TextureAssembler.CreateMipChain(...), TextureAssembler.CreateArrayMipChain(...), TextureAssembler.CreateCubeMipChain(...), and DDS/KTX/PVR encoding options when GenerateMipmaps is enabled.

The same API supports texture-to-image previews and texture-to-texture container conversion. Texture-to-texture conversion preserves the full mip level, array layer, and cube face topology when no source subresource is selected. Set SourceSubresource to decode one subresource and write it as a single image or single 2D texture.

using TextureCompressor.Conversion;
using TextureCompressor.FileFormats;
using TextureCompressor.FileFormats.Dds;
using TextureCompressor.FileFormats.Png;
using TextureCompressor.Formats;

var fileFormats = new TextureFileFormatManager();
using var png = fileFormats.RegisterPngFileFormat();
using var dds = fileFormats.RegisterDdsFileFormat();

var converter = new TextureConverter(fileFormats);

converter.Convert(
    "skybox.dds",
    "positive-x.png",
    new TextureConversionOptions
    {
        SourceSubresource = new TextureSubresourceSelection(
            MipLevel: 0,
            ArrayLayer: 0,
            Face: TextureCubeFace.PositiveX)
    });

Pass format-specific options through ReadOptions and WriteOptions. Option types implement IFileFormatOptions, including PngEncodingOptions, JpegEncodingOptions, HdrEncodingOptions, DdsEncodingOptions, KtxEncodingOptions, PvrEncodingOptions, AstcReadOptions, and AstcEncodingOptions. For non-file workflows, TextureConverter also exposes EncodeTexture(...), DecodeTexture(...), and TranscodeTexture(...).

TextureAssembler and TextureExtractor expose the CLI assemble and extract workflows as library APIs. They operate on TextureImage, so callers can pair them with any registered file format package or use them entirely in memory.

using TextureCompressor.Bitmaps;
using TextureCompressor.Colors;
using TextureCompressor.Conversion;
using TextureCompressor.FileFormats.Dds;
using TextureCompressor.FileFormats.Png;
using TextureCompressor.Formats;

IBitmap<Rgba8UNorm>[] faces =
[
    PngCodec.DecodeRgba8("positive-x.png"),
    PngCodec.DecodeRgba8("negative-x.png"),
    PngCodec.DecodeRgba8("positive-y.png"),
    PngCodec.DecodeRgba8("negative-y.png"),
    PngCodec.DecodeRgba8("positive-z.png"),
    PngCodec.DecodeRgba8("negative-z.png")
];

var assembler = new TextureAssembler();
var cube = assembler.CreateCubeMipChain(
    TextureFormats.Bc7Srgb,
    faces,
    mipmapOptions: new MipmapGenerationOptions { Filter = MipmapFilter.Triangle });
DdsCodec.Write(new DdsTexture(cube), "skybox.dds");

var extractor = new TextureExtractor();
var positiveZ = extractor.ExtractSubresource(
    cube,
    new TextureSubresourceSelection(0, 0, TextureCubeFace.PositiveZ));
PngCodec.Encode(positiveZ.Image, "positive-z-preview.png");

Use Built-In High-Quality Encoding Modes

The default built-in coders use TextureCompressionLevel.Normal for predictable baseline conversion. The built-in S3TC, FXT1, ETC/EAC, ASTC, ATC, RGTC/LATC, BPTC, and PVRTC implementations expose faster or higher-quality search modes through the shared TextureCompressionOptions type and TextureCompressionLevel enum. Register an optioned coder with TextureCoderManager, and later TextureCoderManager.Global.GetCoder(...), DdsCodec.Encode(...), KtxCodec.Encode(...), PvrCodec.Encode(...), or AstcCodec.Encode(...) calls will prefer your registered coder. The default behavior is restored when the using var registration is disposed.

using TextureCompressor.Codecs;
using TextureCompressor.Formats;
using TextureCompressor.Options;
using TextureCompressor.Registry;

var highQualityOptions = new TextureCompressionOptions
{
    CompressionMode = TextureCompressionLevel.High
};

var s3tcFormat = TextureFormats.Bc3Rgba;
using var highQualityS3tc = TextureCoderManager.Global.Register(
    s3tcFormat,
    new S3tcTextureCoder(
        s3tcFormat,
        highQualityOptions));

var fxt1Format = TextureFormats.RgbaFxt1UNorm;
using var highQualityFxt1 = TextureCoderManager.Global.Register(
    fxt1Format,
    new FxtcTextureCoder(
        fxt1Format,
        highQualityOptions));

var etcFormat = TextureFormats.RgbaEtc2EacUNorm;
using var highQualityEtc = TextureCoderManager.Global.Register(
    etcFormat,
    new EtcTextureCoder(
        etcFormat,
        highQualityOptions));

var atcFormat = TextureFormats.AtcRgbaInterpolatedAlpha;
using var highQualityAtc = TextureCoderManager.Global.Register(
    atcFormat,
    new AtcTextureCoder(
        atcFormat,
        highQualityOptions));

var rgtcFormat = TextureFormats.Bc5UNorm;
using var highQualityRgtc = TextureCoderManager.Global.Register(
    rgtcFormat,
    new RgtcLatcTextureCoder(
        rgtcFormat,
        highQualityOptions));

var bptcFormat = TextureFormats.Bc7UNorm;
using var highQualityBptc = TextureCoderManager.Global.Register(
    bptcFormat,
    new BptcTextureCoder(
        bptcFormat,
        highQualityOptions));

var astcFormat = TextureFormats.RgbaAstc8x8UNorm;
using var highQualityAstc = TextureCoderManager.Global.Register(
    astcFormat,
    new AstcTextureCoder(
        astcFormat,
        highQualityOptions));

var pvrtcFormat = TextureFormats.RgbaPvrtcI4BppUNorm;
using var exhaustivePvrtc = TextureCoderManager.Global.Register(
    pvrtcFormat,
    new PvrtcTextureCoder(
        pvrtcFormat,
        new TextureCompressionOptions { CompressionMode = TextureCompressionLevel.Exhaustive }));

var coder = TextureCoderManager.Global.GetCoder(s3tcFormat);

These built-in quality modes currently cover S3TC, FXT1, ETC/EAC, ASTC, ATC, RGTC/LATC, BPTC/BC6H/BC7, and PVRTC. For specialized production encoders and other formats, use the optional third-party encoder adapters below.

Read And Write PNG

using TextureCompressor.FileFormats.Png;

var bitmap = PngCodec.DecodeRgba8("input.png");
PngCodec.Encode(bitmap, "copy.png");

Decode into another pixel type when needed:

using TextureCompressor.Colors;
using TextureCompressor.FileFormats.Png;

var hdrReady = PngCodec.Decode<Rgba32Float>("input.png");

Read And Write JPEG And GIF

The JPEG codec supports 8-bit baseline JPEG. Use JpegEncodingOptions.Quality to select an output quality from 1 to 100:

using TextureCompressor.FileFormats.Jpeg;

var bitmap = JpegCodec.DecodeRgba8("photo.jpg");
JpegCodec.Encode(bitmap, "photo-copy.jpg", new JpegEncodingOptions
{
    Quality = 92
});

The GIF codec targets static GIF files. Encoding keeps an exact palette when the image has 256 or fewer colors; otherwise it falls back to an RGB332 palette and preserves transparency:

using TextureCompressor.FileFormats.Gif;

var icon = GifCodec.DecodeRgba8("icon.gif");
GifCodec.Encode(icon, "icon-copy.gif");

Read And Write HDR

The HDR codec supports Radiance RGBE .hdr files. Decode defaults to Rgba32Float so values above 1.0 are preserved:

using TextureCompressor.Colors;
using TextureCompressor.FileFormats.Hdr;

var hdr = HdrCodec.Decode("lighting.hdr");
var ldrPreview = HdrCodec.Decode<Rgba8UNorm>("lighting.hdr");
HdrCodec.Encode(hdr, "lighting-copy.hdr");

Query Texture Formats

TextureFormatCatalog is generated automatically by the source generator. Use it to enumerate all TextureFormats fields or resolve formats by field name or format name:

using TextureCompressor.Formats;

var bc7 = TextureFormatCatalog.Get("Bc7UNorm");
var found = TextureFormatCatalog.TryGet("BC7_UNORM", out var byFormatName);

foreach (var format in TextureFormatCatalog.All.Where(static item => item.IsCompressed))
{
    Console.WriteLine($"{TextureFormatCatalog.GetFieldName(format)}: {format.Name}");
}

Compare Compression Quality

TextureCompressor.Analysis compares two same-sized bitmaps and reports whole-image and per-channel MSE, RMSE, and PSNR:

using TextureCompressor.Analysis;
using TextureCompressor.FileFormats.Png;

var expected = PngCodec.DecodeRgba8("source.png");
var actual = PngCodec.DecodeRgba8("roundtrip.png");
var quality = BitmapQuality.Compare(expected, actual);

Console.WriteLine($"RMSE: {quality.RootMeanSquaredError:F4}");
Console.WriteLine($"PSNR: {quality.PeakSignalToNoiseRatio:F2} dB");
Console.WriteLine($"R channel PSNR: {quality.Red.PeakSignalToNoiseRatio:F2} dB");

Write DDS

DDS encoding writes a DX10 header by default. Use DdsEncodingOptions to select a DXGI format, a legacy header, or a legacy FourCC:

using TextureCompressor.FileFormats.Dds;
using TextureCompressor.FileFormats.Png;

var bitmap = PngCodec.DecodeRgba8("albedo.png");

DdsCodec.Encode(bitmap, "albedo-bc7.dds", new DdsEncodingOptions
{
    DxgiFormat = DdsDxgiFormat.BC7UNorm
});

DdsCodec.Encode(bitmap, "albedo-dxt5.dds", new DdsEncodingOptions
{
    HeaderKind = DdsHeaderKind.Legacy,
    LegacyPixelFormat = DdsLegacyPixelFormat.Dxt5
});

Read a DDS and export a PNG preview:

using TextureCompressor.FileFormats.Dds;
using TextureCompressor.FileFormats.Png;

var decoded = DdsCodec.Decode("albedo-bc7.dds");
PngCodec.Encode(decoded, "albedo-preview.png");

Write KTX / KTX2

using TextureCompressor.FileFormats.Ktx;
using TextureCompressor.FileFormats.Png;
using TextureCompressor.Formats;

var bitmap = PngCodec.DecodeRgba8("input.png");

KtxCodec.Encode(bitmap, "texture.ktx", new KtxEncodingOptions
{
    TextureFormat = TextureFormats.Rgba8Srgb
});

KtxCodec.Encode(bitmap, "texture.ktx2", new KtxEncodingOptions
{
    Version = KtxVersion.Version2,
    TextureFormat = TextureFormats.Bc7Srgb,
    SupercompressionScheme = KtxSupercompressionScheme.Zstandard
});

KTX APIs can either read container metadata or decode directly to a bitmap:

var texture = KtxCodec.Read("texture.ktx2");
var bitmap = KtxCodec.Decode("texture.ktx2");

Write PVR

using TextureCompressor.FileFormats.Png;
using TextureCompressor.FileFormats.Pvr;
using TextureCompressor.Formats;

var bitmap = PngCodec.DecodeRgba8("input.png");

PvrCodec.Encode(bitmap, "texture.pvr", new PvrEncodingOptions
{
    TextureFormat = TextureFormats.RgbaPvrtcI4BppUNorm
});

PVR v1/v2/v3 files can be read. When writing legacy PVR, use PvrEncodingOptions to select the version and legacy pixel type preference.

Write ASTC

using TextureCompressor.FileFormats.Astc;
using TextureCompressor.FileFormats.Png;

var bitmap = PngCodec.DecodeRgba8("input.png");

AstcCodec.Encode(bitmap, "texture.astc", new AstcEncodingOptions
{
    BlockWidth = 6,
    BlockHeight = 6,
    Profile = AstcProfile.UNorm
});

When reading ASTC, pass AstcReadOptions if you need to choose the UNorm, sRGB, or Float profile:

var bitmap = AstcCodec.Decode("texture.astc", new AstcReadOptions
{
    Profile = AstcProfile.UNorm
});

Register Optional External Encoders

Built-in coders are useful for basic conversion and tests. For production compression quality, reference the adapter project and register it with TextureCoderManager. Later registrations take precedence over built-in coders; when multiple adapters support the same format, register them in the priority order you want.

Available third-party encoder adapters:

  • TextureCompressor.Codecs.BCnEncoder: based on BCnEncoder.Net, targeting BC1/BC2/BC3/BC4/BC5/BC6H/BC7-related formats.
  • TextureCompressor.Codecs.AstcEnc: based on AstcEncoderCSharp, targeting ASTC 2D formats.
  • TextureCompressor.Codecs.BasisUniversal: based on BasisUniversal.NET, targeting Basis ETC1S/UASTC, ETC/EAC, BC/DXT, PVRTC, FXT1, ATC, and some ASTC LDR formats.
  • TextureCompressor.Codecs.DirectXTex: based on DirectXTex, targeting BC1-BC7, DXT, RGTC/ATI, and BPTC formats.
  • TextureCompressor.Codecs.PVRTexLib: based on PVRTexLib.NET, targeting ETC/EAC, PVRTC, BC/DXT, and ASTC formats.
dotnet add YourApp.csproj reference src/TextureCompressor.Codecs.BCnEncoder/TextureCompressor.Codecs.BCnEncoder.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.Codecs.AstcEnc/TextureCompressor.Codecs.AstcEnc.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.Codecs.BasisUniversal/TextureCompressor.Codecs.BasisUniversal.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.Codecs.DirectXTex/TextureCompressor.Codecs.DirectXTex.csproj
dotnet add YourApp.csproj reference src/TextureCompressor.Codecs.PVRTexLib/TextureCompressor.Codecs.PVRTexLib.csproj
using TextureCompressor.Codecs;
using TextureCompressor.Codecs.AstcEnc;
using TextureCompressor.Codecs.BasisUniversal;
using TextureCompressor.Codecs.BCnEncoder;
using TextureCompressor.Codecs.DirectXTex;
using TextureCompressor.Codecs.PVRTexLib;
using TextureCompressor.Registry;

using var bcn = TextureCoderManager.Global.RegisterBCnEncoderCoders();
using var astc = TextureCoderManager.Global.RegisterAstcEncCoders();
using var basis = TextureCoderManager.Global.RegisterBasisUniversalCoders();
using var directXTex = TextureCoderManager.Global.RegisterDirectXTexCoders();
using var pvrt = TextureCoderManager.Global.RegisterPVRTexLibCoders();

// Later DdsCodec/KtxCodec/AstcCodec/TextureCoderManager.Global.GetCoder(...)
// calls use the registered external coders.

You can also register one format:

using TextureCompressor.Codecs.BCnEncoder;
using TextureCompressor.Formats;
using TextureCompressor.Registry;

using var registration = TextureCoderManager.Global.RegisterBCnEncoderCoder(TextureFormats.Bc7UNorm);

CLI Tool

TextureCompressor.Cli is a development command-line tool for format search, container metadata inspection, conversion, and quality metric output:

dotnet run --project src/TextureCompressor.Cli -- --help
dotnet run --project src/TextureCompressor.Cli -- formats bc7 --compressed
dotnet run --project src/TextureCompressor.Cli -- formats bc7 --compressed --json
dotnet run --project src/TextureCompressor.Cli -- formats rgba --uncompressed
dotnet run --project src/TextureCompressor.Cli -- info input.ktx2
dotnet run --project src/TextureCompressor.Cli -- info input.ktx2 --json --subresources
dotnet run --project src/TextureCompressor.Cli -- convert input.png output.dds --format Bc7UNorm --mipmaps Generate --metrics
dotnet run --project src/TextureCompressor.Cli -- convert input.png output.ktx2 --format Bc7Srgb --mipmaps Generate --mipmap-color-space Auto --mipmap-alpha Premultiplied --mipmap-filter Triangle --mipmap-levels 8
dotnet run --project src/TextureCompressor.Cli -- convert input.png output.dds --format Bc7UNorm --metrics --json
dotnet run --project src/TextureCompressor.Cli -- convert input.png output.ktx2 --format Bc7Srgb --ktx-version 2 --quality High
dotnet run --project src/TextureCompressor.Cli -- assemble array.ktx2 --layers layer0.png layer1.png
dotnet run --project src/TextureCompressor.Cli -- assemble skybox.dds --cube px.png nx.png py.png ny.png pz.png nz.png --mipmaps Generate --mipmap-levels 8
dotnet run --project src/TextureCompressor.Cli -- extract array.ktx2 extracted --manifest
dotnet run --project src/TextureCompressor.Cli -- assemble rebuilt.ktx2 --manifest extracted/manifest.json
dotnet run --project src/TextureCompressor.Cli -- quality source.png output.dds
dotnet run --project src/TextureCompressor.Cli -- quality source.png output.dds --json

Common commands:

  • formats [query]: list or search texture formats accepted by --format; add --compressed or --uncompressed to filter, or --json for structured output.
  • info <input> / inspect <input>: print container metadata such as size, texture format, mip levels, payload size, and container-specific header fields; add --subresources to list mip/layer/face payloads, or --json for structured metadata output.
  • convert <input> <output>: convert between image and texture containers. The output container is inferred from the extension unless --container is passed explicitly. DDS/KTX/PVR to DDS/KTX/PVR conversions preserve mip levels, array layers, and cube faces by default; omit --format to keep the source texture format, or pass --format to re-encode every subresource. Texture inputs can select a single subresource with --mip, --layer, and --face; add --metrics --json for structured quality metrics after writing.
  • assemble <output>: build a DDS/KTX/PVR texture from PNG/JPEG/GIF/HDR images. Use exactly one of --layers, --cube, --mips, or --manifest; --cube expects PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ order. Add --mipmaps Generate with --layers or --cube to generate mip levels from each base image; --manifest rebuilds a complete extracted topology from manifest.json.
  • extract <input> <output-directory>: extract DDS/KTX/PVR subresources to PNG/JPEG/GIF/HDR images. Add --mip, --layer, or --face to filter, --container to choose the image type, --pattern to control file names, and --manifest to write JSON metadata.
  • quality <expected> <actual>: decode two image/texture files and print MSE, RMSE, and PSNR; add --ignore-alpha to ignore alpha or --json for structured output. Use --mip/--layer/--face for both inputs, or --expected-* and --actual-* options to select each input independently.

Image containers support PNG, JPEG, GIF, and HDR. convert, assemble, and extract provide --png-color-space, --jpg-color-space, and --gif-color-space conversions between Linear and Srgb for LDR image formats. JPEG output quality is controlled with --jpeg-quality; S3TC, FXT1, ETC/EAC, ASTC, ATC, RGTC/LATC, BPTC, and PVRTC built-in texture encoding quality can be selected with --quality. DDS, KTX, and PVR outputs can generate full mip-map chains with --mipmaps Generate during single-image conversion and assemble --layers / assemble --cube; use --mipmap-color-space Auto|Linear|Srgb, --mipmap-alpha Premultiplied|Straight, --mipmap-filter Box|Triangle, and --mipmap-levels <count> to tune generated mipmaps.

Common Workflows

PNG To DDS BC3

var bitmap = PngCodec.DecodeRgba8("input.png");
DdsCodec.Encode(bitmap, "output.dds", new DdsEncodingOptions
{
    HeaderKind = DdsHeaderKind.Legacy,
    LegacyPixelFormat = DdsLegacyPixelFormat.Dxt5
});

DDS To PNG Preview

var bitmap = DdsCodec.Decode("input.dds");
PngCodec.Encode(bitmap, "preview.png");

Work Directly With Container Payloads

If you already have a compressed payload, create the container object directly and write it:

using TextureCompressor.FileFormats.Dds;
using TextureCompressor.Formats;

var texture = new DdsTexture(
    TextureFormats.Bc1Rgba,
    width: 512,
    height: 512,
    payload: compressedBytes);

DdsCodec.Write(texture, "texture.dds");

Current Limitations

  • File-format helpers currently focus on 2D textures.
  • DDS, KTX v1/v2, and PVR v3 support explicit mip-map chains, texture arrays, complete cube maps, and single 3D textures. DDS legacy headers cannot write texture arrays. ASTC supports single 2D/3D texture files but not mip-map chains. Legacy PVR v1/v2 mip-map chains, cube maps, texture arrays, and 3D textures are not supported yet.
  • PNG supports common static PNG files. Animated PNG is not supported.
  • JPEG supports baseline JPEG. Progressive JPEG is not supported.
  • GIF reads the first image frame. Animation frame sequences are not emitted as animation.
  • HDR supports Radiance RGBE images without alpha.

Build And Test

dotnet restore TextureCompressor.slnx
dotnet build TextureCompressor.slnx --configuration Release --no-restore
dotnet test TextureCompressor.slnx --configuration Release --no-build
dotnet format TextureCompressor.slnx --verify-no-changes --verbosity minimal

The test suite includes generated PNG fixtures under tests/fixtures/images. Texture codec tests consume the source/*-source.png entries from assets-manifest.json.

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 43 6/6/2026