Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
*.dds filter=lfs diff=lfs merge=lfs -text
*.ktx filter=lfs diff=lfs merge=lfs -text
*.ktx2 filter=lfs diff=lfs merge=lfs -text
*.astc filter=lfs diff=lfs merge=lfs -text
*.pam filter=lfs diff=lfs merge=lfs -text
*.pbm filter=lfs diff=lfs merge=lfs -text
*.pgm filter=lfs diff=lfs merge=lfs -text
Expand Down
18 changes: 9 additions & 9 deletions ImageSharp.Textures.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29613.14
# Visual Studio Version 18
VisualStudioVersion = 18.5.11716.220
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Textures", "src\ImageSharp.Textures\ImageSharp.Textures.csproj", "{1588F6C4-2186-4A35-9693-E9F296791393}"
EndProject
Expand Down Expand Up @@ -50,13 +50,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
EndProjectSection
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems*{1588f6c4-2186-4a35-9693-e9f296791393}*SharedItemsImports = 5
tests\Images\Images.projitems*{17fcbd4d-d232-45e8-876f-dfbc2fad52cf}*SharedItemsImports = 5
tests\Images\Images.projitems*{18be79b6-6b95-4ed7-a963-ad75f6cb9f3c}*SharedItemsImports = 5
tests\Images\Images.projitems*{68a8cc40-6aed-4e96-b524-31b1158fdeea}*SharedItemsImports = 13
tests\Images\Images.projitems*{b159ffd1-e646-42d0-892c-4abf69103712}*SharedItemsImports = 5
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Expand Down Expand Up @@ -94,4 +87,11 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F1762A0D-74C4-454A-BCB7-C010BB067E58}
EndGlobalSection
GlobalSection(SharedMSBuildProjectFiles) = preSolution
shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems*{1588f6c4-2186-4a35-9693-e9f296791393}*SharedItemsImports = 5
tests\Images\Images.projitems*{17fcbd4d-d232-45e8-876f-dfbc2fad52cf}*SharedItemsImports = 5
tests\Images\Images.projitems*{18be79b6-6b95-4ed7-a963-ad75f6cb9f3c}*SharedItemsImports = 5
tests\Images\Images.projitems*{68a8cc40-6aed-4e96-b524-31b1158fdeea}*SharedItemsImports = 13
tests\Images\Images.projitems*{b159ffd1-e646-42d0-892c-4abf69103712}*SharedItemsImports = 5
EndGlobalSection
EndGlobal
4 changes: 2 additions & 2 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
-->

<!-- Import the shared src .props file -->
<Import Project="$(MSBuildThisFileDirectory)..\shared-infrastructure\msbuild\props\SixLabors.Src.props" />
<Import Project="$(MSBuildThisFileDirectory)../shared-infrastructure/msbuild/props/SixLabors.Src.props" />

<!-- Import the solution .props file. -->
<Import Project="$(MSBuildThisFileDirectory)..\Directory.Build.props" />
Expand All @@ -22,7 +22,7 @@
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="SixLabors.ImageSharp.Textures.Benchmarks" Key="$(SixLaborsPublicKey)" />
<InternalsVisibleTo Include="ImageSharp.Textures.Benchmarks" Key="$(SixLaborsPublicKey)" />
<InternalsVisibleTo Include="SixLabors.ImageSharp.Textures.InteractiveTest" Key="$(SixLaborsPublicKey)" />
<InternalsVisibleTo Include="SixLabors.ImageSharp.Textures.Tests" Key="$(SixLaborsPublicKey)" />
</ItemGroup>
Expand Down
541 changes: 541 additions & 0 deletions src/ImageSharp.Textures/Compression/Astc/AstcDecoder.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

namespace SixLabors.ImageSharp.Textures.Compression.Astc.BiseEncoding;

/// <summary>
/// The encoding modes supported by BISE.
/// </summary>
/// <remarks>
/// Note that the values correspond to the number of symbols in each alphabet.
/// </remarks>
internal enum BiseEncodingMode
{
Unknown = 0,
BitEncoding = 1,
TritEncoding = 3,
QuintEncoding = 5,
}
168 changes: 168 additions & 0 deletions src/ImageSharp.Textures/Compression/Astc/BiseEncoding/BitStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

using SixLabors.ImageSharp.Textures.Compression.Astc.Core;

namespace SixLabors.ImageSharp.Textures.Compression.Astc.BiseEncoding;

/// <summary>
/// A simple bit stream used for reading/writing arbitrary-sized chunks.
/// </summary>
internal struct BitStream
{
private ulong low;
private ulong high;
private uint dataSize; // number of valid bits in the 128-bit buffer

public BitStream(ulong data = 0, uint dataSize = 0)
{
this.low = data;
this.high = 0;
this.dataSize = dataSize;
}

public BitStream(UInt128 data, uint dataSize)
{
this.low = data.Low();
this.high = data.High();
this.dataSize = dataSize;
}

public readonly uint Bits => this.dataSize;

public void PutBits(ulong value, int size)
{
if (this.dataSize + (uint)size > 128)
{
throw new InvalidOperationException("Not enough space in BitStream");
}

if (this.dataSize < 64)
{
int lowFree = (int)(64 - this.dataSize);
if (size <= lowFree)
{
this.low |= (value & MaskFor(size)) << (int)this.dataSize;
}
else
{
this.low |= (value & MaskFor(lowFree)) << (int)this.dataSize;
this.high |= (value >> lowFree) & MaskFor(size - lowFree);
}
}
else
{
int shift = (int)(this.dataSize - 64);
this.high |= (value & MaskFor(size)) << shift;
}

this.dataSize += (uint)size;
}

/// <summary>
/// Attempt to retrieve the specified number of bits from the buffer as a <see cref="UInt128"/>.
/// The buffer is shifted accordingly if successful.
/// </summary>
public bool TryGetBits(int count, out UInt128 bits)
{
UInt128? result = this.GetBitsUInt128(count);
bits = result ?? default;
return result is not null;
}

public bool TryGetBits(int count, out ulong bits)
{
if (count > this.dataSize)
{
bits = 0;
return false;
}

bits = count switch
{
0 => 0,
<= 64 => this.low & MaskFor(count),
_ => this.low
};
this.ShiftBuffer(count);
return true;
}

public bool TryGetBits(int count, out uint bits)
{
if (count > this.dataSize)
{
bits = 0;
return false;
}

bits = (uint)(count switch
{
0 => 0UL,
<= 64 => this.low & MaskFor(count),
_ => this.low
});
this.ShiftBuffer(count);
return true;
}

private static ulong MaskFor(int bits)
=> bits == 64
? ~0UL
: ((1UL << bits) - 1UL);

private UInt128? GetBitsUInt128(int count)
{
if (count > this.dataSize)
{
return null;
}

UInt128 result = count switch
{
0 => UInt128.Zero,
<= 64 => (UInt128)(this.low & MaskFor(count)),
128 => new UInt128(this.high, this.low),
_ => new UInt128(
(count - 64 == 64) ? this.high : (this.high & MaskFor(count - 64)),
this.low)
};

this.ShiftBuffer(count);

return result;
}

private void ShiftBuffer(int count)
{
// C# masks shift amounts to the width of the operand, so `ulong << 64` and `ulong >> 64`
// are identity, not zero. Special-case count == 0 and count >= 128 to avoid polluting
// the low/high halves on boundary shifts.
if (count == 0)
{
// Reading zero bits is a no-op.
}
else if (count < 64)
{
this.low = (this.low >> count) | (this.high << (64 - count));
this.high >>= count;
}
else if (count == 64)
{
this.low = this.high;
this.high = 0;
}
else if (count < 128)
{
this.low = this.high >> (count - 64);
this.high = 0;
}
else
{
this.low = 0;
this.high = 0;
}

this.dataSize -= (uint)count;
}
}
Loading
Loading