Skip to content

Commit

Permalink
Some more code style changes, more raw api's and duplicate encoder co…
Browse files Browse the repository at this point in the history
…de removed
  • Loading branch information
Nominom committed Jan 12, 2021
1 parent f9308e6 commit f4678fd
Show file tree
Hide file tree
Showing 35 changed files with 552 additions and 451 deletions.
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true


[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 4

[*.{diff,md}]
trim_trailing_whitespace = false
5 changes: 3 additions & 2 deletions BCnEnc.Net/Decoder/BcBlockDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BCnEncoder.Shared;

Expand All @@ -12,14 +13,14 @@ internal interface IBcBlockDecoder
}

internal abstract class BaseBcBlockDecoder<T> : IBcBlockDecoder
where T : struct
where T : unmanaged
{
public RawBlock4X4Rgba32[,] Decode(ReadOnlySpan<byte> data, int pixelWidth, int pixelHeight, out int blockWidth, out int blockHeight)
{
blockWidth = (int)MathF.Ceiling(pixelWidth / 4.0f);
blockHeight = (int)MathF.Ceiling(pixelHeight / 4.0f);

if (data.Length != blockWidth * blockHeight * Marshal.SizeOf<T>())
if (data.Length != blockWidth * blockHeight * Unsafe.SizeOf<T>())
{
throw new InvalidDataException("Given data does not match expected length.");
}
Expand Down
50 changes: 48 additions & 2 deletions BCnEnc.Net/Decoder/BcDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using BCnEncoder.Decoder.Options;
using BCnEncoder.Shared;
Expand Down Expand Up @@ -33,7 +34,7 @@ public class BcDecoder
/// <returns>The decoded Rgba32 image.</returns>
public Image<Rgba32> DecodeRaw(Stream inputStream, CompressionFormat format, int pixelWidth, int pixelHeight)
{
var dataArray = new byte[inputStream.Position];
var dataArray = new byte[GetBufferSize(format, pixelWidth, pixelHeight)];
inputStream.Read(dataArray, 0, dataArray.Length);

return DecodeRaw(dataArray, format, pixelWidth, pixelHeight);
Expand All @@ -47,8 +48,13 @@ public Image<Rgba32> DecodeRaw(Stream inputStream, CompressionFormat format, int
/// <param name="pixelWidth">The pixelWidth of the image.</param>
/// <param name="pixelHeight">The pixelHeight of the image.</param>
/// <returns>The decoded Rgba32 image.</returns>
public Image<Rgba32> DecodeRaw(byte[] input, CompressionFormat format, int pixelWidth, int pixelHeight)
public Image<Rgba32> DecodeRaw(ReadOnlySpan<byte> input, CompressionFormat format, int pixelWidth, int pixelHeight)
{
if (input.Length != GetBufferSize(format, pixelWidth, pixelHeight))
{
throw new ArgumentException("The size of the input buffer does not match the expected size");
}

var isCompressedFormat = format.IsCompressedFormat();
if (isCompressedFormat)
{
Expand Down Expand Up @@ -502,5 +508,45 @@ private IRawDecoder GetRawDecoder(CompressionFormat format)
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
}

private int GetBufferSize(CompressionFormat format, int pixelWidth, int pixelHeight)
{
switch (format)
{
case CompressionFormat.R:
return pixelWidth * pixelHeight;

case CompressionFormat.Rg:
return 2 * pixelWidth * pixelHeight;

case CompressionFormat.Rgb:
return 3 * pixelWidth * pixelHeight;

case CompressionFormat.Rgba:
return 4 * pixelWidth * pixelHeight;

case CompressionFormat.Bc1:
case CompressionFormat.Bc1WithAlpha:
return Unsafe.SizeOf<Bc1Block>() * ImageToBlocks.CalculateNumOfBlocks(pixelWidth, pixelHeight);

case CompressionFormat.Bc2:
return Unsafe.SizeOf<Bc2Block>() * ImageToBlocks.CalculateNumOfBlocks(pixelWidth, pixelHeight);

case CompressionFormat.Bc3:
return Unsafe.SizeOf<Bc3Block>() * ImageToBlocks.CalculateNumOfBlocks(pixelWidth, pixelHeight);

case CompressionFormat.Bc4:
return Unsafe.SizeOf<Bc4Block>() * ImageToBlocks.CalculateNumOfBlocks(pixelWidth, pixelHeight);

case CompressionFormat.Bc5:
return Unsafe.SizeOf<Bc5Block>() * ImageToBlocks.CalculateNumOfBlocks(pixelWidth, pixelHeight);

case CompressionFormat.Bc7:
return Unsafe.SizeOf<Bc7Block>() * ImageToBlocks.CalculateNumOfBlocks(pixelWidth, pixelHeight);

default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
}
}
}
43 changes: 43 additions & 0 deletions BCnEnc.Net/Encoder/BaseBcBlockEncoder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using BCnEncoder.Shared;

namespace BCnEncoder.Encoder
{
internal abstract class BaseBcBlockEncoder<T> : IBcBlockEncoder where T : unmanaged
{
public byte[] Encode(RawBlock4X4Rgba32[] blocks, int blockWidth, int blockHeight, CompressionQuality quality, bool parallel)
{
var outputData = new byte[blockWidth * blockHeight * Unsafe.SizeOf<T>()];
var outputBlocks = MemoryMarshal.Cast<byte, T>(outputData);

if (parallel)
{
Parallel.For(0, blocks.Length, i =>
{
var outputBlocks = MemoryMarshal.Cast<byte, T>(outputData);
outputBlocks[i] = EncodeBlock(blocks[i], quality);
});
}
else
{
for (var i = 0; i < blocks.Length; i++)
{
outputBlocks[i] = EncodeBlock(blocks[i], quality);
}
}

return outputData;
}

public abstract GlInternalFormat GetInternalFormat();
public abstract GlFormat GetBaseInternalFormat();
public abstract DxgiFormat GetDxgiFormat();

protected abstract T EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality);
}
}
102 changes: 26 additions & 76 deletions BCnEnc.Net/Encoder/Bc1BlockEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,9 @@

namespace BCnEncoder.Encoder
{
internal class Bc1BlockEncoder : IBcBlockEncoder
internal class Bc1BlockEncoder : BaseBcBlockEncoder<Bc1Block>
{

public byte[] Encode(RawBlock4X4Rgba32[] blocks, int blockWidth, int blockHeight, CompressionQuality quality, bool parallel)
{
var outputData = new byte[blockWidth * blockHeight * Marshal.SizeOf<Bc1Block>()];
var outputBlocks = MemoryMarshal.Cast<byte, Bc1Block>(outputData);

if (parallel)
{
Parallel.For(0, blocks.Length, i =>
{
var outputBlocks = MemoryMarshal.Cast<byte, Bc1Block>(outputData);
outputBlocks[i] = EncodeBlock(blocks[i], quality);
});
}
else
{
for (var i = 0; i < blocks.Length; i++)
{
outputBlocks[i] = EncodeBlock(blocks[i], quality);
}
}

return outputData;
}

private Bc1Block EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality)
protected override Bc1Block EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality)
{
switch (quality)
{
Expand All @@ -48,17 +23,17 @@ private Bc1Block EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality
}
}

public GlInternalFormat GetInternalFormat()
public override GlInternalFormat GetInternalFormat()
{
return GlInternalFormat.GlCompressedRgbS3TcDxt1Ext;
}

public GlFormat GetBaseInternalFormat()
public override GlFormat GetBaseInternalFormat()
{
return GlFormat.GlRgb;
}

public DxgiFormat GetDxgiFormat()
public override DxgiFormat GetDxgiFormat()
{
return DxgiFormat.DxgiFormatBc1Unorm;
}
Expand Down Expand Up @@ -127,8 +102,8 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
}

private static class Bc1BlockEncoderBalanced {
private const int MaxTries_ = 24 * 2;
private const float ErrorThreshold_ = 0.05f;
private const int MaxTries = 24 * 2;
private const float ErrorThreshold = 0.05f;

internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
{
Expand All @@ -149,7 +124,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)

var best = TryColors(rawBlock, c0, c1, out var bestError);

for (var i = 0; i < MaxTries_; i++) {
for (var i = 0; i < MaxTries; i++) {
var (newC0, newC1) = ColorVariationGenerator.Variate565(c0, c1, i);

if (newC0.data < newC1.data)
Expand All @@ -169,7 +144,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
c1 = newC1;
}

if (bestError < ErrorThreshold_) {
if (bestError < ErrorThreshold) {
break;
}
}
Expand All @@ -180,8 +155,8 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)

private static class Bc1BlockEncoderSlow
{
private const int MaxTries_ = 9999;
private const float ErrorThreshold_ = 0.01f;
private const int MaxTries = 9999;
private const float ErrorThreshold = 0.01f;

internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
{
Expand All @@ -204,7 +179,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)

var lastChanged = 0;

for (var i = 0; i < MaxTries_; i++) {
for (var i = 0; i < MaxTries; i++) {
var (newC0, newC1) = ColorVariationGenerator.Variate565(c0, c1, i);

if (newC0.data < newC1.data)
Expand All @@ -227,7 +202,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
lastChanged = 0;
}

if (bestError < ErrorThreshold_ || lastChanged > ColorVariationGenerator.VarPatternCount) {
if (bestError < ErrorThreshold || lastChanged > ColorVariationGenerator.VarPatternCount) {
break;
}
}
Expand All @@ -239,34 +214,9 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
#endregion
}

internal class Bc1AlphaBlockEncoder : IBcBlockEncoder
internal class Bc1AlphaBlockEncoder : BaseBcBlockEncoder<Bc1Block>
{

public byte[] Encode(RawBlock4X4Rgba32[] blocks, int blockWidth, int blockHeight, CompressionQuality quality, bool parallel)
{
var outputData = new byte[blockWidth * blockHeight * Marshal.SizeOf<Bc1Block>()];
var outputBlocks = MemoryMarshal.Cast<byte, Bc1Block>(outputData);

if (parallel)
{
Parallel.For(0, blocks.Length, i =>
{
var outputBlocks = MemoryMarshal.Cast<byte, Bc1Block>(outputData);
outputBlocks[i] = EncodeBlock(blocks[i], quality);
});
}
else
{
for (var i = 0; i < blocks.Length; i++)
{
outputBlocks[i] = EncodeBlock(blocks[i], quality);
}
}

return outputData;
}

private Bc1Block EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality)
protected override Bc1Block EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality)
{
switch (quality)
{
Expand All @@ -282,17 +232,17 @@ private Bc1Block EncodeBlock(RawBlock4X4Rgba32 block, CompressionQuality quality
}
}

public GlInternalFormat GetInternalFormat()
public override GlInternalFormat GetInternalFormat()
{
return GlInternalFormat.GlCompressedRgbaS3TcDxt1Ext;
}

public GlFormat GetBaseInternalFormat()
public override GlFormat GetBaseInternalFormat()
{
return GlFormat.GlRgba;
}

public DxgiFormat GetDxgiFormat()
public override DxgiFormat GetDxgiFormat()
{
return DxgiFormat.DxgiFormatBc1Unorm;
}
Expand Down Expand Up @@ -370,8 +320,8 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)

private static class Bc1AlphaBlockEncoderBalanced
{
private const int MaxTries_ = 24 * 2;
private const float ErrorThreshold_ = 0.05f;
private const int MaxTries = 24 * 2;
private const float ErrorThreshold = 0.05f;


internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
Expand Down Expand Up @@ -399,7 +349,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)

var best = TryColors(rawBlock, c0, c1, out var bestError);

for (var i = 0; i < MaxTries_; i++) {
for (var i = 0; i < MaxTries; i++) {
var (newC0, newC1) = ColorVariationGenerator.Variate565(c0, c1, i);

if (!hasAlpha && newC0.data < newC1.data)
Expand All @@ -423,7 +373,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
c1 = newC1;
}

if (bestError < ErrorThreshold_) {
if (bestError < ErrorThreshold) {
break;
}
}
Expand All @@ -434,8 +384,8 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)

private static class Bc1AlphaBlockEncoderSlow
{
private const int MaxTries_ = 9999;
private const float ErrorThreshold_ = 0.05f;
private const int MaxTries = 9999;
private const float ErrorThreshold = 0.05f;

internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
{
Expand Down Expand Up @@ -463,7 +413,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
var best = TryColors(rawBlock, c0, c1, out var bestError);

var lastChanged = 0;
for (var i = 0; i < MaxTries_; i++) {
for (var i = 0; i < MaxTries; i++) {
var (newC0, newC1) = ColorVariationGenerator.Variate565(c0, c1, i);

if (!hasAlpha && newC0.data < newC1.data)
Expand All @@ -490,7 +440,7 @@ internal static Bc1Block EncodeBlock(RawBlock4X4Rgba32 rawBlock)
lastChanged = 0;
}

if (bestError < ErrorThreshold_ || lastChanged > ColorVariationGenerator.VarPatternCount) {
if (bestError < ErrorThreshold || lastChanged > ColorVariationGenerator.VarPatternCount) {
break;
}
}
Expand Down
Loading

0 comments on commit f4678fd

Please sign in to comment.