Browse Source

Rgba32 <-> Argb32 <-> Bgra32

pull/751/head
Anton Firszov 8 years ago
parent
commit
96d0ae80b9
  1. 76
      src/ImageSharp/PixelFormats/PixelConverter.cs
  2. 22
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
  3. 4
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs
  4. 167
      tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs

76
src/ImageSharp/PixelFormats/PixelConverter.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.PixelFormats
@ -16,32 +17,91 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </remarks>
internal static class PixelConverter
{
public static class Rgba32
public static class FromRgba32
{
/// <summary>
/// Converts a packed <see cref="PixelFormats.Rgba32"/> to <see cref="Argb32"/>.
/// Converts a packed <see cref="Rgba32"/> to <see cref="Argb32"/>.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint ToArgb32(uint packedRgba)
{
// packedRgba = [aa bb gg rr]
// ROL(8, packedRgba):
// packedRgba = [aa bb gg rr]
// ROL(8, packedRgba) = [bb gg rr aa]
return (packedRgba << 8) | (packedRgba >> 24);
}
/// <summary>
/// Converts a packed <see cref="Rgba32"/> to <see cref="Bgra32"/>.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint ToBgra32(uint packedRgba)
{
// packedRgba = [aa bb gg rr]
// tmp1 = [aa 00 gg 00]
// tmp2 = [00 bb 00 rr]
// tmp3=ROL(16, tmp2) = [00 rr 00 bb]
// tmp1 + tmp3 = [aa rr gg bb]
uint tmp1 = packedRgba & 0xFF00FF00;
uint tmp2 = packedRgba & 0x00FF00FF;
uint tmp3 = (tmp2 << 16) | (tmp2 >> 16);
return tmp1 + tmp3;
}
}
public static class Argb32
public static class FromArgb32
{
/// <summary>
/// Converts a packed <see cref="Argb32"/> to <see cref="PixelFormats.Rgba32"/>.
/// Converts a packed <see cref="Argb32"/> to <see cref="Rgba32"/>.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint ToRgba32(uint packedArgb)
{
// packedArgb = [bb gg rr aa]
// ROR(8, packedArgb):
// packedArgb = [bb gg rr aa]
// ROR(8, packedArgb) = [aa bb gg rr]
return (packedArgb >> 8) | (packedArgb << 24);
}
/// <summary>
/// Converts a packed <see cref="Argb32"/> to <see cref="Bgra32"/>.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint ToBgra32(uint packedArgb)
{
// packedArgb = [bb gg rr aa]
// REVERSE(packedArgb) = [aa rr gg bb]
return BinaryPrimitives.ReverseEndianness(packedArgb);
}
}
public static class FromBgra32
{
/// <summary>
/// Converts a packed <see cref="Bgra32"/> to <see cref="Argb32"/>.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint ToArgb32(uint packedBgra)
{
// packedBgra = [aa rr gg bb]
// REVERSE(packedBgra) = [bb gg rr aa]
return BinaryPrimitives.ReverseEndianness(packedBgra);
}
/// <summary>
/// Converts a packed <see cref="Rgba32"/> to <see cref="Bgra32"/>.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static uint ToRgba32(uint packedBgra)
{
// packedRgba = [aa rr gg bb]
// tmp1 = [aa 00 gg 00]
// tmp2 = [00 rr 00 bb]
// tmp3=ROL(16, tmp2) = [00 bb 00 rr]
// tmp1 + tmp3 = [aa bb gg rr]
uint tmp1 = packedBgra & 0xFF00FF00;
uint tmp2 = packedBgra & 0x00FF00FF;
uint tmp3 = (tmp2 << 16) | (tmp2 >> 16);
return tmp1 + tmp3;
}
}
}
}

22
src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs

@ -178,27 +178,5 @@ namespace SixLabors.ImageSharp.PixelFormats
dp.FromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// Verifies that the given 'source' and 'destination' spans are at least of 'minLength' size.
/// Throwing an <see cref="ArgumentException"/> if the condition is not met.
/// </summary>
/// <typeparam name="TSource">The source element type</typeparam>
/// <typeparam name="TDest">The destination element type</typeparam>
/// <param name="source">The source span</param>
/// <param name="sourceParamName">The source parameter name</param>
/// <param name="destination">The destination span</param>
/// <param name="destinationParamName">The destination parameter name</param>
/// <param name="minLength">The minimum length</param>
protected internal static void GuardSpans<TSource, TDest>(
ReadOnlySpan<TSource> source,
string sourceParamName,
Span<TDest> destination,
string destinationParamName,
int minLength)
{
Guard.MustBeSizedAtLeast(source, minLength, sourceParamName);
Guard.MustBeSizedAtLeast(destination, minLength, destinationParamName);
}
}
}

4
tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs

@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
for (int i = 0; i < this.Count; i++)
{
uint s = Unsafe.Add(ref sBase, i);
Unsafe.Add(ref dBase, i) = PixelConverter.Rgba32.ToArgb32(s);
Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s);
}
}
@ -190,7 +190,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
for (int i = 0; i < this.Count; i++)
{
uint s = Unsafe.Add(ref dBase, i);
Unsafe.Add(ref dBase, i) = PixelConverter.Rgba32.ToArgb32(s);
Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s);
}
}

167
tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs

@ -4,7 +4,7 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.PixelFormats
{
public class PixelConverterTests
public abstract class PixelConverterTests
{
public static readonly TheoryData<byte, byte, byte, byte> RgbaData =
new TheoryData<byte, byte, byte, byte>
@ -23,34 +23,103 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
{ 67, 71, 101, 109 }
};
[Theory]
[MemberData(nameof(RgbaData))]
public void Rgba32ToArgb32(byte r, byte g, byte b, byte a)
public class FromRgba32 : PixelConverterTests
{
Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a);
[Theory]
[MemberData(nameof(RgbaData))]
public void ToArgb32(byte r, byte g, byte b, byte a)
{
Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a);
// Act:
uint actualPacked = PixelConverter.FromRgba32.ToArgb32(s.PackedValue);
// Assert:
uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue;
Assert.Equal(expectedPacked, actualPacked);
}
[Theory]
[MemberData(nameof(RgbaData))]
public void ToBgra32(byte r, byte g, byte b, byte a)
{
Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a);
// Act:
uint actualPacked = PixelConverter.FromRgba32.ToBgra32(s.PackedValue);
// Assert:
uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue;
Assert.Equal(expectedPacked, actualPacked);
}
}
public class FromArgb32 : PixelConverterTests
{
[Theory]
[MemberData(nameof(RgbaData))]
public void ToRgba32(byte r, byte g, byte b, byte a)
{
Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a);
// Act:
uint actualPacked = PixelConverter.Rgba32.ToArgb32(s.PackedValue);
// Act:
uint actualPacked = PixelConverter.FromArgb32.ToRgba32(s.PackedValue);
// Assert:
uint expectedPacked = ReferenceImplementations.ToArgb32(s).PackedValue;
// Assert:
uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue;
Assert.Equal(expectedPacked, actualPacked);
Assert.Equal(expectedPacked, actualPacked);
}
[Theory]
[MemberData(nameof(RgbaData))]
public void ToBgra32(byte r, byte g, byte b, byte a)
{
Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a);
// Act:
uint actualPacked = PixelConverter.FromArgb32.ToBgra32(s.PackedValue);
// Assert:
uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue;
Assert.Equal(expectedPacked, actualPacked);
}
}
[Theory]
[MemberData(nameof(RgbaData))]
public void Argb32ToRgba32(byte r, byte g, byte b, byte a)
public class FromBgra32 : PixelConverterTests
{
Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a);
[Theory]
[MemberData(nameof(RgbaData))]
public void ToArgb32(byte r, byte g, byte b, byte a)
{
Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a);
// Act:
uint actualPacked = PixelConverter.Argb32.ToRgba32(s.PackedValue);
// Act:
uint actualPacked = PixelConverter.FromBgra32.ToArgb32(s.PackedValue);
// Assert:
uint expectedPacked = ReferenceImplementations.ToRgba32(s).PackedValue;
// Assert:
uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue;
Assert.Equal(expectedPacked, actualPacked);
Assert.Equal(expectedPacked, actualPacked);
}
[Theory]
[MemberData(nameof(RgbaData))]
public void ToRgba32(byte r, byte g, byte b, byte a)
{
Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a);
// Act:
uint actualPacked = PixelConverter.FromBgra32.ToRgba32(s.PackedValue);
// Assert:
uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue;
Assert.Equal(expectedPacked, actualPacked);
}
}
@ -85,66 +154,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
d.A = a;
return d;
}
public static Argb32 ToArgb32(Rgba32 s)
{
Argb32 d = default;
d.R = s.R;
d.G = s.G;
d.B = s.B;
d.A = s.A;
return d;
}
public static Argb32 ToArgb32(Bgra32 s)
{
Argb32 d = default;
d.R = s.R;
d.G = s.G;
d.B = s.B;
d.A = s.A;
return d;
}
public static Rgba32 ToRgba32(Argb32 s)
{
Rgba32 d = default;
d.R = s.R;
d.G = s.G;
d.B = s.B;
d.A = s.A;
return d;
}
public static Rgba32 ToRgba32(Bgra32 s)
{
Rgba32 d = default;
d.R = s.R;
d.G = s.G;
d.B = s.B;
d.A = s.A;
return d;
}
public static Bgra32 ToBgra32(Rgba32 s)
{
Bgra32 d = default;
d.R = s.R;
d.G = s.G;
d.B = s.B;
d.A = s.A;
return d;
}
public static Bgra32 ToBgra32(Argb32 s)
{
Bgra32 d = default;
d.R = s.R;
d.G = s.G;
d.B = s.B;
d.A = s.A;
return d;
}
}
}
}
Loading…
Cancel
Save