Browse Source

Merge branch 'master' into js/png-decode-to-type

pull/1861/head
James Jackson-South 4 years ago
parent
commit
c9f2c9e3f5
  1. 9
      src/ImageSharp/Color/Color.cs
  2. 11
      src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs
  3. 4
      src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs
  4. 51
      tests/ImageSharp.Tests/Color/ColorTests.CastTo.cs
  5. 18
      tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs

9
src/ImageSharp/Color/Color.cs

@ -270,8 +270,15 @@ namespace SixLabors.ImageSharp
return pixel;
}
if (this.boxedHighPrecisionPixel is null)
{
pixel = default;
pixel.FromRgba64(this.data);
return pixel;
}
pixel = default;
pixel.FromRgba64(this.data);
pixel.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
return pixel;
}

11
src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs

@ -650,6 +650,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
}
this.target.Write(this.streamWriteBuffer, 0, writeIdx);
this.emitWriteIndex = this.emitBuffer.Length;
}
/// <summary>
@ -660,11 +661,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// This must be called only if <see cref="IsStreamFlushNeeded"/> is true
/// only during the macroblocks encoding routine.
/// </remarks>
private void FlushToStream()
{
private void FlushToStream() =>
this.FlushToStream(this.emitWriteIndex * 4);
this.emitWriteIndex = this.emitBuffer.Length;
}
/// <summary>
/// Flushes final cached bits to the stream padding 1's to
@ -681,10 +679,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
// And writing only valuable count of bytes count we want to write to the output stream
int valuableBytesCount = (int)Numerics.DivideCeil((uint)this.bitCount, 8);
uint packedBytes = this.accumulatedBits | (uint.MaxValue >> this.bitCount);
this.emitBuffer[--this.emitWriteIndex] = packedBytes;
this.emitBuffer[this.emitWriteIndex - 1] = packedBytes;
// Flush cached bytes to the output stream with padding bits
this.FlushToStream((this.emitWriteIndex * 4) - 4 + valuableBytesCount);
int lastByteIndex = (this.emitWriteIndex * 4) - valuableBytesCount;
this.FlushToStream(lastByteIndex);
}
}
}

4
src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs

@ -192,7 +192,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
public bool UseCrossColorTransform { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to use the substract green transform.
/// Gets or sets a value indicating whether to use the subtract green transform.
/// </summary>
public bool UseSubtractGreenTransform { get; set; }
@ -1049,7 +1049,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
return EntropyIx.Palette;
}
using IMemoryOwner<uint> histoBuffer = this.memoryAllocator.Allocate<uint>((int)HistoIx.HistoTotal * 256);
using IMemoryOwner<uint> histoBuffer = this.memoryAllocator.Allocate<uint>((int)HistoIx.HistoTotal * 256, AllocationOptions.Clean);
Span<uint> histo = histoBuffer.Memory.Span;
uint pixPrev = bgra[0]; // Skip the first pixel.
ReadOnlySpan<uint> prevRow = null;

51
tests/ImageSharp.Tests/Color/ColorTests.CastTo.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
@ -90,17 +91,30 @@ namespace SixLabors.ImageSharp.Tests
}
[Fact]
public void GenericPixel()
public void Vector4Constructor()
{
AssertGenericPixel(new RgbaVector(float.Epsilon, 2 * float.Epsilon, float.MaxValue, float.MinValue));
AssertGenericPixel(new Rgba64(1, 2, ushort.MaxValue, ushort.MaxValue - 1));
AssertGenericPixel(new Rgb48(1, 2, ushort.MaxValue - 1));
AssertGenericPixel(new La32(1, ushort.MaxValue - 1));
AssertGenericPixel(new L16(ushort.MaxValue - 1));
AssertGenericPixel(new Rgba32(1, 2, 255, 254));
// Act:
Color color = new(Vector4.One);
// Assert:
Assert.Equal(new RgbaVector(1, 1, 1, 1), color.ToPixel<RgbaVector>());
Assert.Equal(new Rgba64(65535, 65535, 65535, 65535), color.ToPixel<Rgba64>());
Assert.Equal(new Rgba32(255, 255, 255, 255), color.ToPixel<Rgba32>());
Assert.Equal(new L8(255), color.ToPixel<L8>());
}
[Fact]
public void GenericPixelRoundTrip()
{
AssertGenericPixelRoundTrip(new RgbaVector(float.Epsilon, 2 * float.Epsilon, float.MaxValue, float.MinValue));
AssertGenericPixelRoundTrip(new Rgba64(1, 2, ushort.MaxValue, ushort.MaxValue - 1));
AssertGenericPixelRoundTrip(new Rgb48(1, 2, ushort.MaxValue - 1));
AssertGenericPixelRoundTrip(new La32(1, ushort.MaxValue - 1));
AssertGenericPixelRoundTrip(new L16(ushort.MaxValue - 1));
AssertGenericPixelRoundTrip(new Rgba32(1, 2, 255, 254));
}
private static void AssertGenericPixel<TPixel>(TPixel source)
private static void AssertGenericPixelRoundTrip<TPixel>(TPixel source)
where TPixel : unmanaged, IPixel<TPixel>
{
// Act:
@ -110,6 +124,27 @@ namespace SixLabors.ImageSharp.Tests
TPixel actual = color.ToPixel<TPixel>();
Assert.Equal(source, actual);
}
[Fact]
public void GenericPixelDifferentPrecision()
{
AssertGenericPixelDifferentPrecision(new RgbaVector(1, 1, 1, 1), new Rgba64(65535, 65535, 65535, 65535));
AssertGenericPixelDifferentPrecision(new RgbaVector(1, 1, 1, 1), new Rgba32(255, 255, 255, 255));
AssertGenericPixelDifferentPrecision(new Rgba64(65535, 65535, 65535, 65535), new Rgba32(255, 255, 255, 255));
AssertGenericPixelDifferentPrecision(new Rgba32(255, 255, 255, 255), new L8(255));
}
private static void AssertGenericPixelDifferentPrecision<TPixel, TPixel2>(TPixel source, TPixel2 expected)
where TPixel : unmanaged, IPixel<TPixel>
where TPixel2 : unmanaged, IPixel<TPixel2>
{
// Act:
var color = Color.FromPixel(source);
// Assert:
TPixel2 actual = color.ToPixel<TPixel2>();
Assert.Equal(expected, actual);
}
}
}
}

18
tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs

@ -101,6 +101,24 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder);
}
[Theory]
[WithFile(Lossy.NoFilter06, PixelTypes.Rgba32, 15114)]
public void Encode_Lossless_WithBestQuality_HasExpectedSize<TPixel>(TestImageProvider<TPixel> provider, int expectedBytes)
where TPixel : unmanaged, IPixel<TPixel>
{
var encoder = new WebpEncoder()
{
FileFormat = WebpFileFormatType.Lossless,
Method = WebpEncodingMethod.BestQuality
};
using Image<TPixel> image = provider.GetImage();
using var memoryStream = new MemoryStream();
image.Save(memoryStream, encoder);
Assert.Equal(memoryStream.Length, expectedBytes);
}
[Theory]
[WithFile(RgbTestPattern100x100, PixelTypes.Rgba32, 85)]
[WithFile(RgbTestPattern100x100, PixelTypes.Rgba32, 60)]

Loading…
Cancel
Save