public static void WritePAA(BinaryWriterEx writer, ReadOnlyMemory2D <ColorRgba32> image, ColorRgba32 max, ColorRgba32 avg, PAAType type = PAAType.DXT5, PAAFlags flags = PAAFlags.InterpolatedAlpha) { if (type != PAAType.DXT5 && type != PAAType.DXT1) { throw new NotSupportedException(); } var enc = new BCnEncoder.Encoder.BcEncoder(type == PAAType.DXT5 ? CompressionFormat.Bc3 : CompressionFormat.Bc1); var mipmaps = new List <MipmapEncoder>(); var width = image.Width; var height = image.Width; var offset = type == PAAType.DXT5 ? 128 : 112; foreach (var mipmap in enc.EncodeToRawBytes(image)) { if (width > 2 || height > 2) { var menc = new MipmapEncoder(mipmap, width, height, offset); offset += menc.MipmapEntrySize; mipmaps.Add(menc); width = width / 2; height = height / 2; } } writer.Write(type == PAAType.DXT5 ? (ushort)0xff05 : (ushort)0xff01); writer.WriteAscii("GGATCGVA", 8); writer.Write((uint)4); writer.Write(avg.r); writer.Write(avg.g); writer.Write(avg.b); writer.Write(avg.a); writer.WriteAscii("GGATCXAM", 8); writer.Write((uint)4); writer.Write(max.r); writer.Write(max.g); writer.Write(max.b); writer.Write(max.a); if (type == PAAType.DXT5) { writer.WriteAscii("GGATGALF", 8); writer.Write((uint)4); writer.Write((uint)flags); } writer.WriteAscii("GGATSFFO", 8); writer.Write(16 * 4); for (int i = 0; i < 16; ++i) { if (i < mipmaps.Count) { writer.Write((uint)mipmaps[i].Offset); } else { writer.Write((uint)0); } } writer.Write((ushort)0x0000); int index = 0; foreach (var mipmap in mipmaps) { if (writer.Position != mipmap.Offset) { throw new Exception($"Wrong offset @{mipmap.Width} : {writer.Position} != { mipmap.Offset}"); } writer.Write(mipmap.WidthEncoded); writer.Write(mipmap.Height); writer.WriteUInt24((uint)mipmap.PaaData.Length); writer.Write(mipmap.PaaData); index++; width = width / 2; height = height / 2; } writer.Write((uint)0x0000); writer.Write((ushort)0x0000); }