Browse Source

Merge pull request #49 from olivif/olivif/fixwarnings2

Adding missing documentation and fixing style issues - part 2
af/merge-core
James Jackson-South 10 years ago
committed by GitHub
parent
commit
b3f304e703
  1. 1
      src/ImageSharp/Common/Helpers/Guard.cs
  2. 2
      src/ImageSharp/Drawing/Brushes/Brushes{TColor,TPacked}.cs
  3. 2
      src/ImageSharp/Drawing/Brushes/ImageBrush{TColor,TPacked}.cs
  4. 2
      src/ImageSharp/Drawing/Brushes/PatternBrush{TColor,TPacked}.cs
  5. 2
      src/ImageSharp/Drawing/Brushes/SolidBrush{TColor,TPacked}.cs
  6. 2
      src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs
  7. 6
      src/ImageSharp/Formats/Jpg/Components/Bits.cs
  8. 54
      src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs
  9. 9
      src/ImageSharp/Formats/Jpg/Components/Bytes.cs
  10. 9
      src/ImageSharp/Formats/Jpg/Components/Huffman.cs
  11. 77
      src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs
  12. 81
      src/ImageSharp/Formats/Jpg/Components/MutableSpanExtensions.cs
  13. 18
      src/ImageSharp/Formats/Jpg/Components/YCbCrImage.cs
  14. 183
      src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
  15. 22
      src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
  16. 2
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs

1
src/ImageSharp/Common/Helpers/Guard.cs

@ -65,6 +65,7 @@ namespace ImageSharp
/// <summary> /// <summary>
/// Verifies, that the enumeration is not null and not empty. /// Verifies, that the enumeration is not null and not empty.
/// </summary> /// </summary>
/// <typeparam name="T">The type of objects in the <paramref name="target"/></typeparam>
/// <param name="target">The target enumeration, which should be checked against being null or empty.</param> /// <param name="target">The target enumeration, which should be checked against being null or empty.</param>
/// <param name="parameterName">Name of the parameter.</param> /// <param name="parameterName">Name of the parameter.</param>
/// <param name="message">The error message, if any to add to the exception.</param> /// <param name="message">The error message, if any to add to the exception.</param>

2
src/ImageSharp/Drawing/Brushes/Brushes`2.cs → src/ImageSharp/Drawing/Brushes/Brushes{TColor,TPacked}.cs

@ -1,4 +1,4 @@
// <copyright file="Brushes`2.cs" company="James Jackson-South"> // <copyright file="Brushes{TColor,TPacked}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>

2
src/ImageSharp/Drawing/Brushes/ImageBrush`2.cs → src/ImageSharp/Drawing/Brushes/ImageBrush{TColor,TPacked}.cs

@ -1,4 +1,4 @@
// <copyright file="ImageBrush`2.cs" company="James Jackson-South"> // <copyright file="ImageBrush{TColor,TPacked}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>

2
src/ImageSharp/Drawing/Brushes/PatternBrush`2.cs → src/ImageSharp/Drawing/Brushes/PatternBrush{TColor,TPacked}.cs

@ -1,4 +1,4 @@
// <copyright file="PatternBrush`2.cs" company="James Jackson-South"> // <copyright file="PatternBrush{TColor,TPacked}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>

2
src/ImageSharp/Drawing/Brushes/SolidBrush`2.cs → src/ImageSharp/Drawing/Brushes/SolidBrush{TColor,TPacked}.cs

@ -1,4 +1,4 @@
// <copyright file="SolidBrush`2.cs" company="James Jackson-South"> // <copyright file="SolidBrush{TColor,TPacked}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors. // Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
// </copyright> // </copyright>

2
src/ImageSharp/Drawing/Processors/FillShapeProcessor.cs

@ -88,7 +88,7 @@ namespace ImageSharp.Drawing.Processors
int offsetY = y - polyStartY; int offsetY = y - polyStartY;
Vector2 currentPoint = default(Vector2); Vector2 currentPoint = default(Vector2);
Vector2 currentPointOffset = default(Vector2);
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
int offsetX = x - startX; int offsetX = x - startX;

6
src/ImageSharp/Formats/Jpg/Components/Bits.cs

@ -45,7 +45,11 @@ namespace ImageSharp.Formats
{ {
JpegDecoderCore.ErrorCodes errorCode; JpegDecoderCore.ErrorCodes errorCode;
byte c = decoder.Bytes.ReadByteStuffedByte(decoder.InputStream, out errorCode); // Grab the decode bytes, use them and then set them
// back on the decoder.
var decoderBytes = decoder.Bytes;
byte c = decoderBytes.ReadByteStuffedByte(decoder.InputStream, out errorCode);
decoder.Bytes = decoderBytes;
if (errorCode != JpegDecoderCore.ErrorCodes.NoError) if (errorCode != JpegDecoderCore.ErrorCodes.NoError)
{ {

54
src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs

@ -15,9 +15,17 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
internal partial struct Block8x8F internal partial struct Block8x8F
{ {
/// <summary>
/// Vector count
/// </summary>
public const int VectorCount = 16; public const int VectorCount = 16;
/// <summary>
/// Scalar count
/// </summary>
public const int ScalarCount = VectorCount * 4; public const int ScalarCount = VectorCount * 4;
#pragma warning disable SA1600 // ElementsMustBeDocumented
public Vector4 V0L; public Vector4 V0L;
public Vector4 V0R; public Vector4 V0R;
@ -41,6 +49,7 @@ namespace ImageSharp.Formats
public Vector4 V7L; public Vector4 V7L;
public Vector4 V7R; public Vector4 V7R;
#pragma warning restore SA1600 // ElementsMustBeDocumented
#pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore #pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore
private static readonly Vector4 C_1_175876 = new Vector4(1.175876f); private static readonly Vector4 C_1_175876 = new Vector4(1.175876f);
@ -59,6 +68,11 @@ namespace ImageSharp.Formats
private static readonly Vector4 C_0_125 = new Vector4(0.1250f); private static readonly Vector4 C_0_125 = new Vector4(0.1250f);
#pragma warning restore SA1310 // FieldNamesMustNotContainUnderscore #pragma warning restore SA1310 // FieldNamesMustNotContainUnderscore
/// <summary>
/// Index into the block
/// </summary>
/// <param name="idx">The index</param>
/// <returns>The float value at the specified index</returns>
public unsafe float this[int idx] public unsafe float this[int idx]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -143,25 +157,29 @@ namespace ImageSharp.Formats
} }
} }
/// <summary>
/// Multiply in place
/// </summary>
/// <param name="scalar">Scalar to multiply by</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MultiplyAllInplace(Vector4 s) public void MultiplyAllInplace(Vector4 scalar)
{ {
this.V0L *= s; this.V0L *= scalar;
this.V0R *= s; this.V0R *= scalar;
this.V1L *= s; this.V1L *= scalar;
this.V1R *= s; this.V1R *= scalar;
this.V2L *= s; this.V2L *= scalar;
this.V2R *= s; this.V2R *= scalar;
this.V3L *= s; this.V3L *= scalar;
this.V3R *= s; this.V3R *= scalar;
this.V4L *= s; this.V4L *= scalar;
this.V4R *= s; this.V4R *= scalar;
this.V5L *= s; this.V5L *= scalar;
this.V5R *= s; this.V5R *= scalar;
this.V6L *= s; this.V6L *= scalar;
this.V6R *= s; this.V6R *= scalar;
this.V7L *= s; this.V7L *= scalar;
this.V7R *= s; this.V7R *= scalar;
} }
/// <summary> /// <summary>
@ -381,7 +399,7 @@ namespace ImageSharp.Formats
internal void Clear() internal void Clear()
{ {
// The cheapest way to do this in C#: // The cheapest way to do this in C#:
this = new Block8x8F(); this = default(Block8x8F);
} }
/// <summary> /// <summary>

9
src/ImageSharp/Formats/Jpg/Components/Bytes.cs

@ -23,8 +23,14 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
public byte[] Buffer; public byte[] Buffer;
/// <summary>
/// Start of bytes read
/// </summary>
public int I; public int I;
/// <summary>
/// End of bytes read
/// </summary>
public int J; public int J;
/// <summary> /// <summary>
@ -44,6 +50,9 @@ namespace ImageSharp.Formats
return new Bytes { Buffer = ArrayPool.Rent(4096) }; return new Bytes { Buffer = ArrayPool.Rent(4096) };
} }
/// <summary>
/// Disposes of the underlying buffer
/// </summary>
public void Dispose() public void Dispose()
{ {
if (this.Buffer != null) if (this.Buffer != null)

9
src/ImageSharp/Formats/Jpg/Components/Huffman.cs

@ -53,6 +53,12 @@ namespace ImageSharp.Formats
private static readonly ArrayPool<int> IntBuffer = ArrayPool<int>.Create(JpegDecoderCore.MaxCodeLength, 50); private static readonly ArrayPool<int> IntBuffer = ArrayPool<int>.Create(JpegDecoderCore.MaxCodeLength, 50);
/// <summary>
/// Initializes the Huffman tree
/// </summary>
/// <param name="lutSize">Lut size</param>
/// <param name="maxNCodes">Max N codes</param>
/// <param name="maxCodeLength">Max code length</param>
public void Init(int lutSize, int maxNCodes, int maxCodeLength) public void Init(int lutSize, int maxNCodes, int maxCodeLength)
{ {
this.Lut = UshortBuffer.Rent(1 << lutSize); this.Lut = UshortBuffer.Rent(1 << lutSize);
@ -62,6 +68,9 @@ namespace ImageSharp.Formats
this.Indices = IntBuffer.Rent(maxCodeLength); this.Indices = IntBuffer.Rent(maxCodeLength);
} }
/// <summary>
/// Disposes the underlying buffers
/// </summary>
public void Dispose() public void Dispose()
{ {
UshortBuffer.Return(this.Lut, true); UshortBuffer.Return(this.Lut, true);

77
src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs

@ -5,7 +5,6 @@
namespace ImageSharp.Formats namespace ImageSharp.Formats
{ {
using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
/// <summary> /// <summary>
@ -15,27 +14,51 @@ namespace ImageSharp.Formats
/// <see> /// <see>
/// <cref>https://github.com/dotnet/corefxlab/blob/master/src/System.Slices/System/Span.cs</cref> /// <cref>https://github.com/dotnet/corefxlab/blob/master/src/System.Slices/System/Span.cs</cref>
/// </see> /// </see>
/// <typeparam name="T"></typeparam> /// <typeparam name="T">The type of the data in the span</typeparam>
internal struct MutableSpan<T> internal struct MutableSpan<T>
{ {
/// <summary>
/// Data
/// </summary>
public T[] Data; public T[] Data;
/// <summary>
/// Offset
/// </summary>
public int Offset; public int Offset;
/// <summary>
/// Initializes a new instance of the <see cref="MutableSpan{T}"/> struct.
/// </summary>
/// <param name="size">The size of the span</param>
/// <param name="offset">The offset (defaults to 0)</param>
public MutableSpan(int size, int offset = 0) public MutableSpan(int size, int offset = 0)
{ {
this.Data = new T[size]; this.Data = new T[size];
this.Offset = offset; this.Offset = offset;
} }
/// <summary>
/// Initializes a new instance of the <see cref="MutableSpan{T}"/> struct.
/// </summary>
/// <param name="data">The data</param>
/// <param name="offset">The offset (defaults to 0)</param>
public MutableSpan(T[] data, int offset = 0) public MutableSpan(T[] data, int offset = 0)
{ {
this.Data = data; this.Data = data;
this.Offset = offset; this.Offset = offset;
} }
/// <summary>
/// Gets the total count of data
/// </summary>
public int TotalCount => this.Data.Length - this.Offset; public int TotalCount => this.Data.Length - this.Offset;
/// <summary>
/// Index into the data
/// </summary>
/// <param name="idx">The data</param>
/// <returns>The value at the specified index</returns>
public T this[int idx] public T this[int idx]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -53,57 +76,25 @@ namespace ImageSharp.Formats
public static implicit operator MutableSpan<T>(T[] data) => new MutableSpan<T>(data, 0); public static implicit operator MutableSpan<T>(T[] data) => new MutableSpan<T>(data, 0);
/// <summary>
/// Slice the data
/// </summary>
/// <param name="offset">The offset</param>
/// <returns>The new <see cref="MutableSpan{T}"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public MutableSpan<T> Slice(int offset) public MutableSpan<T> Slice(int offset)
{ {
return new MutableSpan<T>(this.Data, this.Offset + offset); return new MutableSpan<T>(this.Data, this.Offset + offset);
} }
/// <summary>
/// Add to the offset
/// </summary>
/// <param name="offset">The additional offset</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddOffset(int offset) public void AddOffset(int offset)
{ {
this.Offset += offset; this.Offset += offset;
} }
} }
internal static class MutableSpanExtensions
{
public static MutableSpan<T> Slice<T>(this T[] array, int offset) => new MutableSpan<T>(array, offset);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SaveTo(this MutableSpan<float> data, ref Vector4 v)
{
v.X = data[0];
v.Y = data[1];
v.Z = data[2];
v.W = data[3];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SaveTo(this MutableSpan<int> data, ref Vector4 v)
{
v.X = data[0];
v.Y = data[1];
v.Z = data[2];
v.W = data[3];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LoadFrom(this MutableSpan<float> data, ref Vector4 v)
{
data[0] = v.X;
data[1] = v.Y;
data[2] = v.Z;
data[3] = v.W;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LoadFrom(this MutableSpan<int> data, ref Vector4 v)
{
data[0] = (int)v.X;
data[1] = (int)v.Y;
data[2] = (int)v.Z;
data[3] = (int)v.W;
}
}
} }

81
src/ImageSharp/Formats/Jpg/Components/MutableSpanExtensions.cs

@ -0,0 +1,81 @@
// <copyright file="MutableSpanExtensions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Jpg.Components
{
using System.Numerics;
using System.Runtime.CompilerServices;
/// <summary>
/// MutableSpan Extensions
/// </summary>
internal static class MutableSpanExtensions
{
/// <summary>
/// Slice <see cref="MutableSpan{T}"/>
/// </summary>
/// <typeparam name="T">The type of the data in the span</typeparam>
/// <param name="array">The data array</param>
/// <param name="offset">The offset</param>
/// <returns>The new <see cref="MutableSpan{T}"/></returns>
public static MutableSpan<T> Slice<T>(this T[] array, int offset) => new MutableSpan<T>(array, offset);
/// <summary>
/// Save to a Vector4
/// </summary>
/// <param name="data">The data</param>
/// <param name="v">The vector to save to</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SaveTo(this MutableSpan<float> data, ref Vector4 v)
{
v.X = data[0];
v.Y = data[1];
v.Z = data[2];
v.W = data[3];
}
/// <summary>
/// Save to a Vector4
/// </summary>
/// <param name="data">The data</param>
/// <param name="v">The vector to save to</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SaveTo(this MutableSpan<int> data, ref Vector4 v)
{
v.X = data[0];
v.Y = data[1];
v.Z = data[2];
v.W = data[3];
}
/// <summary>
/// Load from Vector4
/// </summary>
/// <param name="data">The data</param>
/// <param name="v">The vector to load from</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LoadFrom(this MutableSpan<float> data, ref Vector4 v)
{
data[0] = v.X;
data[1] = v.Y;
data[2] = v.Z;
data[3] = v.W;
}
/// <summary>
/// Load from Vector4
/// </summary>
/// <param name="data">The data</param>
/// <param name="v">The vector to load from</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void LoadFrom(this MutableSpan<int> data, ref Vector4 v)
{
data[0] = (int)v.X;
data[1] = (int)v.Y;
data[2] = (int)v.Z;
data[3] = (int)v.W;
}
}
}

18
src/ImageSharp/Formats/Jpg/Components/YCbCrImage.cs

@ -44,16 +44,34 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
public enum YCbCrSubsampleRatio public enum YCbCrSubsampleRatio
{ {
/// <summary>
/// YCbCrSubsampleRatio444
/// </summary>
YCbCrSubsampleRatio444, YCbCrSubsampleRatio444,
/// <summary>
/// YCbCrSubsampleRatio422
/// </summary>
YCbCrSubsampleRatio422, YCbCrSubsampleRatio422,
/// <summary>
/// YCbCrSubsampleRatio420
/// </summary>
YCbCrSubsampleRatio420, YCbCrSubsampleRatio420,
/// <summary>
/// YCbCrSubsampleRatio440
/// </summary>
YCbCrSubsampleRatio440, YCbCrSubsampleRatio440,
/// <summary>
/// YCbCrSubsampleRatio411
/// </summary>
YCbCrSubsampleRatio411, YCbCrSubsampleRatio411,
/// <summary>
/// YCbCrSubsampleRatio410
/// </summary>
YCbCrSubsampleRatio410, YCbCrSubsampleRatio410,
} }

183
src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs

@ -31,21 +31,6 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
internal const int LutSize = 8; internal const int LutSize = 8;
/// <summary>
/// The byte buffer.
/// </summary>
internal Bytes Bytes;
/// <summary>
/// The input stream.
/// </summary>
internal Stream InputStream;
/// <summary>
/// Holds the unprocessed bits that have been taken from the byte-stream.
/// </summary>
internal Bits Bits;
/// <summary> /// <summary>
/// The maximum number of color components /// The maximum number of color components
/// </summary> /// </summary>
@ -116,6 +101,21 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
private readonly byte[] temp; private readonly byte[] temp;
/// <summary>
/// The byte buffer.
/// </summary>
private Bytes bytes;
/// <summary>
/// The byte buffer.
/// </summary>
private Stream inputStream;
/// <summary>
/// Holds the unprocessed bits that have been taken from the byte-stream.
/// </summary>
private Bits bits;
/// <summary> /// <summary>
/// The image width /// The image width
/// </summary> /// </summary>
@ -205,8 +205,8 @@ namespace ImageSharp.Formats
this.temp = new byte[2 * BlockF.BlockSize]; this.temp = new byte[2 * BlockF.BlockSize];
this.componentArray = new Component[MaxComponents]; this.componentArray = new Component[MaxComponents];
this.progCoeffs = new Block8x8F[MaxComponents][]; this.progCoeffs = new Block8x8F[MaxComponents][];
this.Bits = default(Bits); this.bits = default(Bits);
this.Bytes = Bytes.Create(); this.bytes = Bytes.Create();
// TODO: This looks like it could be static. // TODO: This looks like it could be static.
for (int i = 0; i < MaxTc + 1; i++) for (int i = 0; i < MaxTc + 1; i++)
@ -224,10 +224,44 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
internal enum ErrorCodes internal enum ErrorCodes
{ {
/// <summary>
/// NoError
/// </summary>
NoError, NoError,
/// <summary>
/// MissingFF00
/// </summary>
MissingFF00 MissingFF00
} }
/// <summary>
/// Gets or sets the byte buffer.
/// </summary>
public Bytes Bytes
{
get
{
return this.bytes;
}
set
{
this.bytes = value;
}
}
/// <summary>
/// Gets the input stream.
/// </summary>
public Stream InputStream
{
get
{
return this.inputStream;
}
}
/// <summary> /// <summary>
/// Decodes the image from the specified this._stream and sets /// Decodes the image from the specified this._stream and sets
/// the data to image. /// the data to image.
@ -241,7 +275,7 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel<TPacked> where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct, IEquatable<TPacked> where TPacked : struct, IEquatable<TPacked>
{ {
this.InputStream = stream; this.inputStream = stream;
// Check for the Start Of Image marker. // Check for the Start Of Image marker.
this.ReadFull(this.temp, 0, 2); this.ReadFull(this.temp, 0, 2);
@ -381,7 +415,7 @@ namespace ImageSharp.Formats
this.ProcessApp14Marker(remaining); this.ProcessApp14Marker(remaining);
break; break;
default: default:
if ((JpegConstants.Markers.APP0 <= marker && marker <= JpegConstants.Markers.APP15) if ((marker >= JpegConstants.Markers.APP0 && marker <= JpegConstants.Markers.APP15)
|| marker == JpegConstants.Markers.COM) || marker == JpegConstants.Markers.COM)
{ {
this.Skip(remaining); this.Skip(remaining);
@ -449,6 +483,9 @@ namespace ImageSharp.Formats
} }
} }
/// <summary>
/// Dispose
/// </summary>
public void Dispose() public void Dispose()
{ {
for (int i = 0; i < this.huffmanTrees.Length; i++) for (int i = 0; i < this.huffmanTrees.Length; i++)
@ -456,7 +493,7 @@ namespace ImageSharp.Formats
this.huffmanTrees[i].Dispose(); this.huffmanTrees[i].Dispose();
} }
this.Bytes.Dispose(); this.bytes.Dispose();
} }
/// <summary> /// <summary>
@ -466,7 +503,7 @@ namespace ImageSharp.Formats
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal byte ReadByte() internal byte ReadByte()
{ {
return this.Bytes.ReadByte(this.InputStream); return this.bytes.ReadByte(this.inputStream);
} }
/// <summary> /// <summary>
@ -627,19 +664,19 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Uninitialized Huffman table"); throw new ImageFormatException("Uninitialized Huffman table");
} }
if (this.Bits.UnreadBits < 8) if (this.bits.UnreadBits < 8)
{ {
var errorCode = this.Bits.EnsureNBits(8, this); var errorCode = this.bits.EnsureNBits(8, this);
if (errorCode == ErrorCodes.NoError) if (errorCode == ErrorCodes.NoError)
{ {
ushort v = huffman.Lut[(this.Bits.Accumulator >> (this.Bits.UnreadBits - LutSize)) & 0xff]; ushort v = huffman.Lut[(this.bits.Accumulator >> (this.bits.UnreadBits - LutSize)) & 0xff];
if (v != 0) if (v != 0)
{ {
byte n = (byte)((v & 0xff) - 1); byte n = (byte)((v & 0xff) - 1);
this.Bits.UnreadBits -= n; this.bits.UnreadBits -= n;
this.Bits.Mask >>= n; this.bits.Mask >>= n;
return (byte)(v >> 8); return (byte)(v >> 8);
} }
} }
@ -652,22 +689,22 @@ namespace ImageSharp.Formats
int code = 0; int code = 0;
for (int i = 0; i < MaxCodeLength; i++) for (int i = 0; i < MaxCodeLength; i++)
{ {
if (this.Bits.UnreadBits == 0) if (this.bits.UnreadBits == 0)
{ {
var errorCode = this.Bits.EnsureNBits(1, this); var errorCode = this.bits.EnsureNBits(1, this);
if (errorCode != ErrorCodes.NoError) if (errorCode != ErrorCodes.NoError)
{ {
throw new MissingFF00Exception(); throw new MissingFF00Exception();
} }
} }
if ((this.Bits.Accumulator & this.Bits.Mask) != 0) if ((this.bits.Accumulator & this.bits.Mask) != 0)
{ {
code |= 1; code |= 1;
} }
this.Bits.UnreadBits--; this.bits.UnreadBits--;
this.Bits.Mask >>= 1; this.bits.Mask >>= 1;
if (code <= huffman.MaxCodes[i]) if (code <= huffman.MaxCodes[i])
{ {
@ -686,18 +723,18 @@ namespace ImageSharp.Formats
/// <returns>The <see cref="bool"/></returns> /// <returns>The <see cref="bool"/></returns>
private bool DecodeBit() private bool DecodeBit()
{ {
if (this.Bits.UnreadBits == 0) if (this.bits.UnreadBits == 0)
{ {
var errorCode = this.Bits.EnsureNBits(1, this); var errorCode = this.bits.EnsureNBits(1, this);
if (errorCode != ErrorCodes.NoError) if (errorCode != ErrorCodes.NoError)
{ {
throw new MissingFF00Exception(); throw new MissingFF00Exception();
} }
} }
bool ret = (this.Bits.Accumulator & this.Bits.Mask) != 0; bool ret = (this.bits.Accumulator & this.bits.Mask) != 0;
this.Bits.UnreadBits--; this.bits.UnreadBits--;
this.Bits.Mask >>= 1; this.bits.Mask >>= 1;
return ret; return ret;
} }
@ -708,19 +745,19 @@ namespace ImageSharp.Formats
/// <returns>The <see cref="uint"/></returns> /// <returns>The <see cref="uint"/></returns>
private uint DecodeBits(int count) private uint DecodeBits(int count)
{ {
if (this.Bits.UnreadBits < count) if (this.bits.UnreadBits < count)
{ {
var errorCode = this.Bits.EnsureNBits(count, this); var errorCode = this.bits.EnsureNBits(count, this);
if (errorCode != ErrorCodes.NoError) if (errorCode != ErrorCodes.NoError)
{ {
throw new MissingFF00Exception(); throw new MissingFF00Exception();
} }
} }
uint ret = this.Bits.Accumulator >> (this.Bits.UnreadBits - count); uint ret = this.bits.Accumulator >> (this.bits.UnreadBits - count);
ret = (uint)(ret & ((1 << count) - 1)); ret = (uint)(ret & ((1 << count) - 1));
this.Bits.UnreadBits -= count; this.bits.UnreadBits -= count;
this.Bits.Mask >>= count; this.bits.Mask >>= count;
return ret; return ret;
} }
@ -733,13 +770,13 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
private void UnreadByteStuffedByte() private void UnreadByteStuffedByte()
{ {
this.Bytes.I -= this.Bytes.UnreadableBytes; this.bytes.I -= this.bytes.UnreadableBytes;
this.Bytes.UnreadableBytes = 0; this.bytes.UnreadableBytes = 0;
if (this.Bits.UnreadBits >= 8) if (this.bits.UnreadBits >= 8)
{ {
this.Bits.Accumulator >>= 8; this.bits.Accumulator >>= 8;
this.Bits.UnreadBits -= 8; this.bits.UnreadBits -= 8;
this.Bits.Mask >>= 8; this.bits.Mask >>= 8;
} }
} }
@ -752,32 +789,32 @@ namespace ImageSharp.Formats
private void ReadFull(byte[] data, int offset, int length) private void ReadFull(byte[] data, int offset, int length)
{ {
// Unread the overshot bytes, if any. // Unread the overshot bytes, if any.
if (this.Bytes.UnreadableBytes != 0) if (this.bytes.UnreadableBytes != 0)
{ {
if (this.Bits.UnreadBits >= 8) if (this.bits.UnreadBits >= 8)
{ {
this.UnreadByteStuffedByte(); this.UnreadByteStuffedByte();
} }
this.Bytes.UnreadableBytes = 0; this.bytes.UnreadableBytes = 0;
} }
while (length > 0) while (length > 0)
{ {
if (this.Bytes.J - this.Bytes.I >= length) if (this.bytes.J - this.bytes.I >= length)
{ {
Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, length); Array.Copy(this.bytes.Buffer, this.bytes.I, data, offset, length);
this.Bytes.I += length; this.bytes.I += length;
length -= length; length -= length;
} }
else else
{ {
Array.Copy(this.Bytes.Buffer, this.Bytes.I, data, offset, this.Bytes.J - this.Bytes.I); Array.Copy(this.bytes.Buffer, this.bytes.I, data, offset, this.bytes.J - this.bytes.I);
offset += this.Bytes.J - this.Bytes.I; offset += this.bytes.J - this.bytes.I;
length -= this.Bytes.J - this.Bytes.I; length -= this.bytes.J - this.bytes.I;
this.Bytes.I += this.Bytes.J - this.Bytes.I; this.bytes.I += this.bytes.J - this.bytes.I;
this.Bytes.Fill(this.InputStream); this.bytes.Fill(this.inputStream);
} }
} }
} }
@ -789,32 +826,32 @@ namespace ImageSharp.Formats
private void Skip(int count) private void Skip(int count)
{ {
// Unread the overshot bytes, if any. // Unread the overshot bytes, if any.
if (this.Bytes.UnreadableBytes != 0) if (this.bytes.UnreadableBytes != 0)
{ {
if (this.Bits.UnreadBits >= 8) if (this.bits.UnreadBits >= 8)
{ {
this.UnreadByteStuffedByte(); this.UnreadByteStuffedByte();
} }
this.Bytes.UnreadableBytes = 0; this.bytes.UnreadableBytes = 0;
} }
while (true) while (true)
{ {
int m = this.Bytes.J - this.Bytes.I; int m = this.bytes.J - this.bytes.I;
if (m > count) if (m > count)
{ {
m = count; m = count;
} }
this.Bytes.I += m; this.bytes.I += m;
count -= m; count -= m;
if (count == 0) if (count == 0)
{ {
break; break;
} }
this.Bytes.Fill(this.InputStream); this.bytes.Fill(this.inputStream);
} }
} }
@ -1478,7 +1515,7 @@ namespace ImageSharp.Formats
ah = this.temp[3 + scanComponentCountX2] >> 4; ah = this.temp[3 + scanComponentCountX2] >> 4;
al = this.temp[3 + scanComponentCountX2] & 0x0f; al = this.temp[3 + scanComponentCountX2] & 0x0f;
if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || BlockF.BlockSize <= zigEnd) if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || zigEnd >= BlockF.BlockSize)
{ {
throw new ImageFormatException("Bad spectral selection bounds"); throw new ImageFormatException("Bad spectral selection bounds");
} }
@ -1520,7 +1557,7 @@ namespace ImageSharp.Formats
} }
} }
this.Bits = default(Bits); this.bits = default(Bits);
int mcu = 0; int mcu = 0;
byte expectedRst = JpegConstants.Markers.RST0; byte expectedRst = JpegConstants.Markers.RST0;
@ -1533,12 +1570,12 @@ namespace ImageSharp.Formats
// blocks: the third block in the first row has (bx, by) = (2, 0). // blocks: the third block in the first row has (bx, by) = (2, 0).
int bx, by, blockCount = 0; int bx, by, blockCount = 0;
Block8x8F b = new Block8x8F(); Block8x8F b = default(Block8x8F);
Block8x8F temp1 = new Block8x8F(); Block8x8F temp1 = default(Block8x8F);
Block8x8F temp2 = new Block8x8F(); Block8x8F temp2 = default(Block8x8F);
// Tricky way to copy contents of the Unzig static variable to the stack: // Tricky way to copy contents of the Unzig static variable to the stack:
StackallocUnzigData unzigOnStack = new StackallocUnzigData(); StackallocUnzigData unzigOnStack = default(StackallocUnzigData);
int* unzigPtr = unzigOnStack.Data; int* unzigPtr = unzigOnStack.Data;
Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64); Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64);
@ -1673,7 +1710,7 @@ namespace ImageSharp.Formats
} }
// Reset the Huffman decoder. // Reset the Huffman decoder.
this.Bits = default(Bits); this.bits = default(Bits);
// Reset the DC components, as per section F.2.1.3.1. // Reset the DC components, as per section F.2.1.3.1.
dc = new int[MaxComponents]; dc = new int[MaxComponents];
@ -1728,7 +1765,7 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Excessive DC component"); throw new ImageFormatException("Excessive DC component");
} }
int deltaDC = this.Bits.ReceiveExtend(value, this); int deltaDC = this.bits.ReceiveExtend(value, this);
dc[compIndex] += deltaDC; dc[compIndex] += deltaDC;
// b[0] = dc[compIndex] << al; // b[0] = dc[compIndex] << al;
@ -1756,7 +1793,7 @@ namespace ImageSharp.Formats
break; break;
} }
int ac = this.Bits.ReceiveExtend(val1, this); int ac = this.bits.ReceiveExtend(val1, this);
// b[Unzig[zig]] = ac << al; // b[Unzig[zig]] = ac << al;
Block8x8F.SetScalarAt(b, unzigPtr[zig], ac << al); Block8x8F.SetScalarAt(b, unzigPtr[zig], ac << al);

22
src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs

@ -31,6 +31,7 @@ namespace ImageSharp.Formats
39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
}; };
#pragma warning disable SA1118 // ParameterMustNotSpanMultipleLines
/// <summary> /// <summary>
/// The Huffman encoding specifications. /// The Huffman encoding specifications.
/// This encoder uses the same Huffman encoding for all images. /// This encoder uses the same Huffman encoding for all images.
@ -43,7 +44,10 @@ namespace ImageSharp.Formats
{ {
0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
}, },
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }), new byte[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
}),
new HuffmanSpec( new HuffmanSpec(
new byte[] new byte[]
{ {
@ -75,7 +79,10 @@ namespace ImageSharp.Formats
{ {
0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
}, },
new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }), new byte[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
}),
// Chrominance AC. // Chrominance AC.
new HuffmanSpec( new HuffmanSpec(
@ -105,6 +112,7 @@ namespace ImageSharp.Formats
0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa
}) })
}; };
#pragma warning restore SA1118 // ParameterMustNotSpanMultipleLines
/// <summary> /// <summary>
/// The compiled representations of theHuffmanSpec. /// The compiled representations of theHuffmanSpec.
@ -960,11 +968,6 @@ namespace ImageSharp.Formats
/// </summary> /// </summary>
private class HuffmanLut private class HuffmanLut
{ {
/// <summary>
/// The collection of huffman values.
/// </summary>
public readonly uint[] Values;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HuffmanLut"/> class. /// Initializes a new instance of the <see cref="HuffmanLut"/> class.
/// </summary> /// </summary>
@ -999,6 +1002,11 @@ namespace ImageSharp.Formats
code <<= 1; code <<= 1;
} }
} }
/// <summary>
/// Gets the collection of huffman values.
/// </summary>
public uint[] Values { get; }
} }
} }
} }

2
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs

@ -56,11 +56,9 @@ namespace ImageSharp.Tests.Formats.Jpg
float a0, a1, a2, a3, b0, b1, b2, b3; float a0, a1, a2, a3, b0, b1, b2, b3;
float z0, z1, z2, z3, z4; float z0, z1, z2, z3, z4;
float r0 = 1.414214f;
float r1 = 1.387040f; float r1 = 1.387040f;
float r2 = 1.306563f; float r2 = 1.306563f;
float r3 = 1.175876f; float r3 = 1.175876f;
float r4 = 1.000000f;
float r5 = 0.785695f; float r5 = 0.785695f;
float r6 = 0.541196f; float r6 = 0.541196f;
float r7 = 0.275899f; float r7 = 0.275899f;

Loading…
Cancel
Save