Browse Source

Read Rgba64 png + some tests

af/merge-core
James Jackson-South 8 years ago
parent
commit
6c5c2a5cd1
  1. 37
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  2. 71
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
  3. 45
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
  4. 33
      tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs
  5. 16
      tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs
  6. 20
      tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs
  7. 18
      tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs
  8. 18
      tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs
  9. 16
      tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs

37
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -784,12 +784,15 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16)
{
int length = this.header.Width * 4;
using (IBuffer<byte> compressed = this.configuration.MemoryManager.Allocate<byte>(length))
Rgba64 rgba64 = default;
for (int x = 0, o = 0; x < this.header.Width; x++, o += 8)
{
// TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressed.Span, length);
PixelOperations<TPixel>.Instance.PackFromRgba32Bytes(compressed.Span, rowSpan, this.header.Width);
rgba64.R = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o, 2));
rgba64.G = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o + 2, 2));
rgba64.B = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o + 4, 2));
rgba64.A = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o + 6, 2));
color.PackFromRgba64(rgba64);
rowSpan[x] = color;
}
}
else
@ -1053,23 +1056,15 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16)
{
int length = this.header.Width * 4;
using (IBuffer<byte> compressed = this.configuration.MemoryManager.Allocate<byte>(length))
Rgba64 rgba64 = default;
for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o += 8)
{
Span<byte> compressedSpan = compressed.Span;
// TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressedSpan, length);
for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o += 4)
{
rgba.R = compressedSpan[o];
rgba.G = compressedSpan[o + 1];
rgba.B = compressedSpan[o + 2];
rgba.A = compressedSpan[o + 3];
color.PackFromRgba32(rgba);
rowSpan[x] = color;
}
rgba64.R = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o, 2));
rgba64.G = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o + 2, 2));
rgba64.B = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o + 4, 2));
rgba64.A = BinaryPrimitives.ReadUInt16BigEndian(scanlineBuffer.Slice(o + 6, 2));
color.PackFromRgba64(rgba64);
rowSpan[x] = color;
}
}
else

71
src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs

@ -11,6 +11,77 @@ namespace SixLabors.ImageSharp.PixelFormats
public partial class PixelOperations<TPixel>
{
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgba64"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgba64"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromRgba64(ReadOnlySpan<Rgba64> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
var rgba = new Rgba64(0, 0, 0, 65535);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
rgba = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba64(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgba64(ReadOnlySpan{Rgba64}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgba64"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromRgba64Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgba64(MemoryMarshal.Cast<byte, Rgba64>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgba64"/>-s.
/// Bulk version of <see cref="IPixel.ToRgba64(ref Rgba64)"/>.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Rgba64"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgba64(ReadOnlySpan<TPixel> sourcePixels, Span<Rgba64> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destBaseRef = ref MemoryMarshal.GetReference(dest);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToRgba64(ref dp);
}
}
/// <summary>
/// A helper for <see cref="ToRgba64(ReadOnlySpan{TPixel}, Span{Rgba64}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgba64"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgba64Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
{
this.ToRgba64(sourceColors, MemoryMarshal.Cast<byte, Rgba64>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgba32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>

45
src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt

@ -51,6 +51,48 @@
<#
}
void GeneratePackFromMethodUsingPackFromRgba64(string pixelType, string rgbaOperationCode)
{
#>
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="<#=pixelType#>"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="<#=pixelType#>"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
var rgba = new Rgba64(0, 0, 0, 65535);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
<#=rgbaOperationCode#>
dp.PackFromRgba64(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFrom<#=pixelType#>(ReadOnlySpan{<#=pixelType#>}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="<#=pixelType#>"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFrom<#=pixelType#>Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFrom<#=pixelType#>(MemoryMarshal.Cast<byte, <#=pixelType#>>(sourceBytes), destPixels, count);
}
<#
}
void GeneratePackFromMethodUsingPackFromRgba32(string pixelType, string rgbaOperationCode)
{
#>
@ -192,6 +234,9 @@ namespace SixLabors.ImageSharp.PixelFormats
{
<#
GeneratePackFromMethodUsingPackFromRgba64("Rgba64", "rgba = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgba64");
GeneratePackFromMethodUsingPackFromRgba32("Rgba32", "rgba = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgba32");

33
tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs

@ -157,5 +157,38 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToRgba64()
{
// arrange
Alpha8 alpha = default;
Rgba64 actual = default;
var expected = new Rgba64(0, 0, 0, 65535);
Vector4 scaled = new Alpha8(1F).ToScaledVector4();
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromRgba64_ToRgba64()
{
// arrange
var alpha = default(Alpha8);
var actual = default(Rgba64);
var expected = new Rgba64(0, 0, 0, 65535);
// act
alpha.PackFromRgba64(expected);
alpha.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

16
tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs

@ -189,5 +189,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_PackFromRgba64_ToRgba64()
{
// arrange
var argb = default(Argb32);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
argb.PackFromRgba64(expected);
argb.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

20
tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs

@ -22,13 +22,13 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(g, p.G);
Assert.Equal(b, p.B);
}
[Fact]
public unsafe void ByteLayoutIsSequentialBgr()
{
var color = new Bgr24(1, 2, 3);
byte* ptr = (byte*)&color;
Assert.Equal(3, ptr[0]);
Assert.Equal(2, ptr[1]);
Assert.Equal(1, ptr[2]);
@ -139,5 +139,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(new Bgra32(1, 2, 3, 255), bgra);
}
[Fact]
public void Bgr24_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgr24);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 65535);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

18
tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs

@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.PixelFormats
{
{
public class Bgr565Tests
{
[Fact]
@ -144,5 +144,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgr565);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 65535);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

18
tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
public static readonly TheoryData<byte, byte, byte, byte> ColorData =
new TheoryData<byte, byte, byte, byte>()
{
{ 1, 2, 3, 4 }, { 4, 5, 6, 7 }, { 0, 255, 42, 0 }, { 1, 2, 3, 255 }
{ 1, 2, 3, 4 }, { 4, 5, 6, 7 }, { 0, 255, 42, 0 }, { 1, 2, 3, 255 }
};
[Theory]
@ -146,5 +146,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(new Bgra32(1, 2, 3, 4), bgra);
}
[Fact]
public void Bgra32_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgra32);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

16
tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs

@ -193,5 +193,21 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgra4444);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

Loading…
Cancel
Save