Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for BGR, BGR565, BGRA4444 and BGRA5551 #61

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
48 changes: 44 additions & 4 deletions BCnEnc.Net/Decoder/BcDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using BCnEncoder.Decoder.Options;
using BCnEncoder.Shared;
using BCnEncoder.Shared.ImageFiles;

using Microsoft.Toolkit.HighPerformance;

using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using BCnEncoder.Shared.ImageFiles;
using Microsoft.Toolkit.HighPerformance;

namespace BCnEncoder.Decoder
{
Expand Down Expand Up @@ -1160,7 +1162,7 @@ private ColorRgba32[][] DecodeInternal(KtxFile file, bool allMipMaps, Cancellati
/// <returns>An array of decoded Rgba32 images.</returns>
private ColorRgba32[][] DecodeInternal(DdsFile file, bool allMipMaps, CancellationToken token)
{
var mipMaps = allMipMaps ? file.header.dwMipMapCount : 1;
var mipMaps = allMipMaps ? file.header.MipMapCount : 1;
var colors = new ColorRgba32[mipMaps][];

var context = new OperationContext
Expand Down Expand Up @@ -1557,6 +1559,10 @@ private bool IsSupportedRawFormat(CompressionFormat format)
case CompressionFormat.Rgb:
case CompressionFormat.Rgba:
case CompressionFormat.Bgra:
case CompressionFormat.Bgr:
case CompressionFormat.B5G6R5:
case CompressionFormat.B5G5R5A1:
case CompressionFormat.B4G4R4A4:
return true;

default:
Expand Down Expand Up @@ -1670,6 +1676,18 @@ private IRawDecoder GetRawDecoder(CompressionFormat format)
case CompressionFormat.Rgba:
return new RawRgbaDecoder();

case CompressionFormat.B4G4R4A4:
return new RawB4G4R4A4Decoder();

case CompressionFormat.B5G5R5A1:
return new RawB5G5R5A1Decoder();

case CompressionFormat.B5G6R5:
return new RawB5G6R5Decoder();

case CompressionFormat.Bgr:
return new RawBgrDecoder();

case CompressionFormat.Bgra:
return new RawBgraDecoder();

Expand Down Expand Up @@ -1736,6 +1754,12 @@ public int GetBlockSize(CompressionFormat format)
case CompressionFormat.Rgba:
return 4;

case CompressionFormat.B4G4R4A4:
case CompressionFormat.B5G5R5A1:
case CompressionFormat.B5G6R5:
return 2;

case CompressionFormat.Bgr:
case CompressionFormat.Bgra:
return 4;

Expand Down Expand Up @@ -1773,7 +1797,7 @@ public int GetBlockSize(CompressionFormat format)

case CompressionFormat.Unknown:
return 0;

default:
throw new ArgumentOutOfRangeException(nameof(format), format, null);
}
Expand Down Expand Up @@ -1863,6 +1887,18 @@ private CompressionFormat GetCompressionFormat(DdsFile file)
case DxgiFormat.DxgiFormatR8G8B8A8Unorm:
return CompressionFormat.Rgba;

case DxgiFormat.DxgiFormatB4G4R4A4Unorm:
return CompressionFormat.B4G4R4A4;

case DxgiFormat.DxgiFormatB5G5R5A1Unorm:
return CompressionFormat.B5G5R5A1;

case DxgiFormat.DxgiFormatB5G6R5Unorm:
return CompressionFormat.B5G6R5;

case DxgiFormat.DxgiFormatB8G8R8X8Unorm:
return CompressionFormat.Bgr;

case DxgiFormat.DxgiFormatB8G8R8A8Unorm:
return CompressionFormat.Bgra;

Expand Down Expand Up @@ -1931,13 +1967,17 @@ private int GetBufferSize(CompressionFormat format, int pixelWidth, int pixelHei
return pixelWidth * pixelHeight;

case CompressionFormat.Rg:
case CompressionFormat.B5G6R5:
case CompressionFormat.B5G5R5A1:
case CompressionFormat.B4G4R4A4:
return 2 * pixelWidth * pixelHeight;

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

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

case CompressionFormat.Bc1:
Expand Down
125 changes: 124 additions & 1 deletion BCnEnc.Net/Decoder/RawDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using BCnEncoder.Shared;

using System;
using System.Runtime.InteropServices;

namespace BCnEncoder.Decoder
{
internal interface IRawDecoder
Expand Down Expand Up @@ -188,4 +190,125 @@ public ColorRgba32[] Decode(ReadOnlyMemory<byte> data, OperationContext context)
return output;
}
}

/// <summary>
/// A class to decode data to BGRX components.
/// </summary>
public class RawBgrDecoder : IRawDecoder
{
/// <summary>
/// Decode the data to color components.
/// </summary>
/// <param name="data">The data to decode.</param>
/// <param name="context">The context of the current operation.</param>
/// <returns>The decoded color components.</returns>
public ColorRgba32[] Decode(ReadOnlyMemory<byte> data, OperationContext context)
{
var output = new ColorRgba32[data.Length / 4];

// HINT: Ignoring parallel execution since we wouldn't gain performance from it.

var span = data.Span;
for (var i = 0; i < output.Length; i++)
{
context.CancellationToken.ThrowIfCancellationRequested();

output[i].b = span[i * 4];
output[i].g = span[i * 4 + 1];
output[i].r = span[i * 4 + 2];
output[i].a = 255;
}

return output;
}
}

/// <summary>
/// A class to decode data to B4G4R4A4 components.
/// </summary>
public class RawB4G4R4A4Decoder : IRawDecoder
{
/// <summary>
/// Decode the data to color components.
/// </summary>
/// <param name="data">The data to decode.</param>
/// <param name="context">The context of the current operation.</param>
/// <returns>The decoded color components.</returns>
public ColorRgba32[] Decode(ReadOnlyMemory<byte> data, OperationContext context)
{
var output = new ColorRgba32[data.Length / 2];

// HINT: Ignoring parallel execution since we wouldn't gain performance from it.

var span = MemoryMarshal.Cast<byte, ushort>(data.Span);
for (var i = 0; i < output.Length; i++)
{
context.CancellationToken.ThrowIfCancellationRequested();

var color4444 = new ColorRgb4444(span[i]);
output[i] = new ColorRgba32(color4444.R, color4444.G, color4444.B, color4444.A);
}
return output;
}
}

/// <summary>
/// A class to decode data to B5G5R5A1 components.
/// </summary>
public class RawB5G5R5A1Decoder : IRawDecoder
{
/// <summary>
/// Decode the data to color components.
/// </summary>
/// <param name="data">The data to decode.</param>
/// <param name="context">The context of the current operation.</param>
/// <returns>The decoded color components.</returns>
public ColorRgba32[] Decode(ReadOnlyMemory<byte> data, OperationContext context)
{
var output = new ColorRgba32[data.Length / 2];

// HINT: Ignoring parallel execution since we wouldn't gain performance from it.

var span = MemoryMarshal.Cast<byte, ushort>(data.Span);
for (var i = 0; i < output.Length; i++)
{
context.CancellationToken.ThrowIfCancellationRequested();

var color5551 = new ColorRgb555(span[i]);
output[i] = new ColorRgba32(color5551.R, color5551.G, color5551.B, color5551.Mode == 0 ? (byte)0 : (byte)255);
}
return output;
}
}

/// <summary>
/// A class to decode data to B5G6R5 components.
/// </summary>
public class RawB5G6R5Decoder : IRawDecoder
{
/// <summary>
/// Decode the data to color components.
/// </summary>
/// <param name="data">The data to decode.</param>
/// <param name="context">The context of the current operation.</param>
/// <returns>The decoded color components.</returns>
public ColorRgba32[] Decode(ReadOnlyMemory<byte> data, OperationContext context)
{
var output = new ColorRgba32[data.Length / 2];

// HINT: Ignoring parallel execution since we wouldn't gain performance from it.

var span = MemoryMarshal.Cast<byte, ushort>(data.Span);
for (var i = 0; i < output.Length; i++)
{
context.CancellationToken.ThrowIfCancellationRequested();

var color56 = new ColorRgb565(span[i]);
output[i] = color56.ToColorRgba32();
}
return output;
}
}


}
33 changes: 24 additions & 9 deletions BCnEnc.Net/Encoder/BcEncoder.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
using BCnEncoder.Encoder.Bptc;
using BCnEncoder.Encoder.Options;
using BCnEncoder.Shared;
using BCnEncoder.Shared.ImageFiles;

using Microsoft.Toolkit.HighPerformance;

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BCnEncoder.Encoder.Bptc;
using BCnEncoder.Encoder.Options;
using BCnEncoder.Shared;
using BCnEncoder.Shared.ImageFiles;
using Microsoft.Toolkit.HighPerformance;

namespace BCnEncoder.Encoder
{
Expand Down Expand Up @@ -610,7 +612,7 @@ public int GetBlockSize()
if (compressedEncoder == null)
{
var hdrEncoder = GetFloatBlockEncoder(OutputOptions.Format);

if (hdrEncoder == null)
{
throw new NotSupportedException($"This format is either not supported or does not use block compression: {OutputOptions.Format}");
Expand Down Expand Up @@ -1319,7 +1321,7 @@ private DdsFile EncodeCubeMapToDdsInternalHdr(ReadOnlyMemory2D<ColorRgbFloat> ri
{
DdsFile output;
IBcBlockEncoder<RawBlock4X4RgbFloat> compressedEncoder = null;

var faces = new[] { right, left, top, down, back, front };

var width = right.Width;
Expand All @@ -1337,7 +1339,7 @@ private DdsFile EncodeCubeMapToDdsInternalHdr(ReadOnlyMemory2D<ColorRgbFloat> ri
output = new DdsFile(ddsHeader, dxt10Header);

if (OutputOptions.DdsBc1WriteAlphaFlag &&
OutputOptions.Format == CompressionFormat.Bc1WithAlpha)
OutputOptions.Format == CompressionFormat.Bc1WithAlpha)
{
output.header.ddsPixelFormat.dwFlags |= PixelFormatFlags.DdpfAlphaPixels;
}
Expand Down Expand Up @@ -1373,7 +1375,7 @@ private DdsFile EncodeCubeMapToDdsInternalHdr(ReadOnlyMemory2D<ColorRgbFloat> ri
for (var mip = 0; mip < numMipMaps; mip++)
{
byte[] encoded;

var blocks = ImageToBlocks.ImageTo4X4(mipChain[mip], out var blocksWidth, out var blocksHeight);
encoded = compressedEncoder.Encode(blocks, blocksWidth, blocksHeight, OutputOptions.Quality, context);

Expand Down Expand Up @@ -2173,6 +2175,19 @@ private IRawEncoder GetRawEncoder(CompressionFormat format)
case CompressionFormat.Rgba:
return new RawRgbaEncoder();


case CompressionFormat.Bgr:
return new RawBgrEncoder();

case CompressionFormat.B5G6R5:
return new RawBgr565Encoder();

case CompressionFormat.B4G4R4A4:
return new RawBgr4444Encoder();

case CompressionFormat.B5G5R5A1:
return new RawBgr5551Encoder();

case CompressionFormat.Bgra:
return new RawBgraEncoder();

Expand Down
Loading