Browse Source

docs

pull/322/head
Anton Firszov 9 years ago
parent
commit
99b0b1525e
  1. 55
      src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
  2. 3
      src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs
  3. 43
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.cs
  4. 32
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegComponentPostProcessor.cs
  5. 17
      src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs
  6. 0
      src/ImageSharp/Memory/Buffer2D{T}.cs
  7. 40
      src/ImageSharp/Memory/BufferArea{T}.cs
  8. 0
      src/ImageSharp/Memory/Buffer{T}.cs
  9. 0
      src/ImageSharp/Memory/IBuffer2D{T}.cs
  10. 2
      src/ImageSharp/Memory/IBuffer{T}.cs
  11. 2
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs
  12. 3
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.ComponentData.cs
  13. 3
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs
  14. 20
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.cs
  15. 3
      tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs
  16. 6
      tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.StandardIntegerDCT.cs

55
src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs

@ -16,8 +16,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// </summary> /// </summary>
public const int Size = 64; public const int Size = 64;
/// <summary>
/// A fixed size buffer holding the values.
/// See: <see>
/// <cref>https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/unsafe-code-pointers/fixed-size-buffers</cref>
/// </see>
/// </summary>
private fixed short data[Size]; private fixed short data[Size];
/// <summary>
/// Initializes a new instance of the <see cref="Block8x8"/> struct.
/// </summary>
/// <param name="coefficients">A <see cref="Span{T}"/> of coefficients</param>
public Block8x8(Span<short> coefficients) public Block8x8(Span<short> coefficients)
{ {
ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this); ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this);
@ -25,6 +35,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
Unsafe.CopyBlock(ref selfRef, ref sourceRef, Size * sizeof(short)); Unsafe.CopyBlock(ref selfRef, ref sourceRef, Size * sizeof(short));
} }
/// <summary>
/// Gets or sets a <see cref="short"/> value at the given index
/// </summary>
/// <param name="idx">The index</param>
/// <returns>The value</returns>
public short this[int idx] public short this[int idx]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -44,6 +59,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
} }
} }
/// <summary>
/// Gets or sets a value in a row+coulumn of the 8x8 block
/// </summary>
/// <param name="x">The x position index in the row</param>
/// <param name="y">The column index</param>
/// <returns>The value</returns>
public short this[int x, int y] public short this[int x, int y]
{ {
get => this[(y * 8) + x]; get => this[(y * 8) + x];
@ -60,6 +81,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return !left.Equals(right); return !left.Equals(right);
} }
/// <summary>
/// Multiply all elements by a given <see cref="int"/>
/// </summary>
public static Block8x8 operator *(Block8x8 block, int value) public static Block8x8 operator *(Block8x8 block, int value)
{ {
Block8x8 result = block; Block8x8 result = block;
@ -73,6 +97,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return result; return result;
} }
/// <summary>
/// Divide all elements by a given <see cref="int"/>
/// </summary>
public static Block8x8 operator /(Block8x8 block, int value) public static Block8x8 operator /(Block8x8 block, int value)
{ {
Block8x8 result = block; Block8x8 result = block;
@ -86,6 +113,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return result; return result;
} }
/// <summary>
/// Add an <see cref="int"/> to all elements
/// </summary>
public static Block8x8 operator +(Block8x8 block, int value) public static Block8x8 operator +(Block8x8 block, int value)
{ {
Block8x8 result = block; Block8x8 result = block;
@ -99,6 +129,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return result; return result;
} }
/// <summary>
/// Subtract an <see cref="int"/> from all elements
/// </summary>
public static Block8x8 operator -(Block8x8 block, int value) public static Block8x8 operator -(Block8x8 block, int value)
{ {
Block8x8 result = block; Block8x8 result = block;
@ -142,6 +175,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
fp[idx] = value; fp[idx] = value;
} }
/// <summary>
/// Convert into <see cref="Block8x8F"/>
/// </summary>
public Block8x8F AsFloatBlock() public Block8x8F AsFloatBlock()
{ {
// TODO: Optimize this // TODO: Optimize this
@ -154,6 +190,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return result; return result;
} }
/// <summary>
/// Copy all elements to an array of <see cref="short"/>.
/// </summary>
public short[] ToArray() public short[] ToArray()
{ {
short[] result = new short[Size]; short[] result = new short[Size];
@ -161,6 +200,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return result; return result;
} }
/// <summary>
/// Copy elements into 'destination' Span of <see cref="short"/> values
/// </summary>
public void CopyTo(Span<short> destination) public void CopyTo(Span<short> destination)
{ {
ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this); ref byte selfRef = ref Unsafe.As<Block8x8, byte>(ref this);
@ -168,6 +210,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
Unsafe.CopyBlock(ref destRef, ref selfRef, Size * sizeof(short)); Unsafe.CopyBlock(ref destRef, ref selfRef, Size * sizeof(short));
} }
/// <summary>
/// Copy elements into 'destination' Span of <see cref="int"/> values
/// </summary>
public void CopyTo(Span<int> destination) public void CopyTo(Span<int> destination)
{ {
for (int i = 0; i < Size; i++) for (int i = 0; i < Size; i++)
@ -176,6 +221,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
} }
} }
/// <summary>
/// Cast and copy <see cref="Size"/> <see cref="int"/>-s from the beginning of 'source' span.
/// </summary>
public void LoadFrom(Span<int> source) public void LoadFrom(Span<int> source)
{ {
for (int i = 0; i < Size; i++) for (int i = 0; i < Size; i++)
@ -191,6 +239,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
DebugGuard.MustBeGreaterThanOrEqualTo(idx, 0, nameof(idx)); DebugGuard.MustBeGreaterThanOrEqualTo(idx, 0, nameof(idx));
} }
/// <inheritdoc />
public override string ToString() public override string ToString()
{ {
var bld = new StringBuilder(); var bld = new StringBuilder();
@ -208,6 +257,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return bld.ToString(); return bld.ToString();
} }
/// <inheritdoc />
public bool Equals(Block8x8 other) public bool Equals(Block8x8 other)
{ {
for (int i = 0; i < Size; i++) for (int i = 0; i < Size; i++)
@ -221,6 +271,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return true; return true;
} }
/// <inheritdoc />
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (ReferenceEquals(null, obj)) if (ReferenceEquals(null, obj))
@ -231,11 +282,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return obj is Block8x8 && this.Equals((Block8x8)obj); return obj is Block8x8 && this.Equals((Block8x8)obj);
} }
/// <inheritdoc />
public override int GetHashCode() public override int GetHashCode()
{ {
return (this[0] * 31) + this[1]; return (this[0] * 31) + this[1];
} }
/// <summary>
/// Calculate the total sum of absoulute differences of elements in 'a' and 'b'.
/// </summary>
public static long TotalDifference(ref Block8x8 a, ref Block8x8 b) public static long TotalDifference(ref Block8x8 a, ref Block8x8 b)
{ {
long result = 0; long result = 0;

3
src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs

@ -5,6 +5,9 @@
/// </summary> /// </summary>
internal static class ComponentUtils internal static class ComponentUtils
{ {
/// <summary>
/// Gets a reference to the <see cref="Block8x8"/> at the given row and column index from <see cref="IJpegComponent.SpectralBlocks"/>
/// </summary>
public static ref Block8x8 GetBlockReference(this IJpegComponent component, int bx, int by) public static ref Block8x8 GetBlockReference(this IJpegComponent component, int bx, int by)
{ {
return ref component.SpectralBlocks[bx, by]; return ref component.SpectralBlocks[bx, by];

43
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.cs

@ -7,17 +7,32 @@ using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{ {
/// <summary>
/// Encapsulates the conversion of Jpeg channels to RGBA values packed in <see cref="Vector4"/> buffer.
/// </summary>
internal abstract partial class JpegColorConverter internal abstract partial class JpegColorConverter
{ {
/// <summary>
/// The avalilable converters
/// </summary>
private static readonly JpegColorConverter[] Converters = { new FromYCbCr(), new FromYccK(), new FromCmyk(), new FromGrayScale(), new FromRgb() }; private static readonly JpegColorConverter[] Converters = { new FromYCbCr(), new FromYccK(), new FromCmyk(), new FromGrayScale(), new FromRgb() };
/// <summary>
/// Initializes a new instance of the <see cref="JpegColorConverter"/> class.
/// </summary>
protected JpegColorConverter(JpegColorSpace colorSpace) protected JpegColorConverter(JpegColorSpace colorSpace)
{ {
this.ColorSpace = colorSpace; this.ColorSpace = colorSpace;
} }
/// <summary>
/// Gets the <see cref="JpegColorSpace"/> of this converter.
/// </summary>
public JpegColorSpace ColorSpace { get; } public JpegColorSpace ColorSpace { get; }
/// <summary>
/// Returns the <see cref="JpegColorConverter"/> corresponding to the given <see cref="JpegColorSpace"/>
/// </summary>
public static JpegColorConverter GetConverter(JpegColorSpace colorSpace) public static JpegColorConverter GetConverter(JpegColorSpace colorSpace)
{ {
JpegColorConverter converter = Converters.FirstOrDefault(c => c.ColorSpace == colorSpace); JpegColorConverter converter = Converters.FirstOrDefault(c => c.ColorSpace == colorSpace);
@ -29,20 +44,48 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
return converter; return converter;
} }
/// <summary>
/// He implementation of the conversion.
/// </summary>
/// <param name="values">The input as a stack-only <see cref="ComponentValues"/> struct</param>
/// <param name="result">The destination buffer of <see cref="Vector4"/> values</param>
public abstract void ConvertToRGBA(ComponentValues values, Span<Vector4> result); public abstract void ConvertToRGBA(ComponentValues values, Span<Vector4> result);
/// <summary>
/// A stack-only struct to reference the input buffers using <see cref="ReadOnlySpan{T}"/>-s.
/// </summary>
public struct ComponentValues public struct ComponentValues
{ {
/// <summary>
/// The component count
/// </summary>
public readonly int ComponentCount; public readonly int ComponentCount;
/// <summary>
/// The component 0 (eg. Y)
/// </summary>
public readonly ReadOnlySpan<float> Component0; public readonly ReadOnlySpan<float> Component0;
/// <summary>
/// The component 1 (eg. Cb)
/// </summary>
public readonly ReadOnlySpan<float> Component1; public readonly ReadOnlySpan<float> Component1;
/// <summary>
/// The component 2 (eg. Cr)
/// </summary>
public readonly ReadOnlySpan<float> Component2; public readonly ReadOnlySpan<float> Component2;
/// <summary>
/// The component 4
/// </summary>
public readonly ReadOnlySpan<float> Component3; public readonly ReadOnlySpan<float> Component3;
/// <summary>
/// Initializes a new instance of the <see cref="ComponentValues"/> struct.
/// </summary>
/// <param name="componentBuffers">The 1-4 sized list of component buffers.</param>
/// <param name="row">The row to convert</param>
public ComponentValues(IReadOnlyList<IBuffer2D<float>> componentBuffers, int row) public ComponentValues(IReadOnlyList<IBuffer2D<float>> componentBuffers, int row)
{ {
this.ComponentCount = componentBuffers.Count; this.ComponentCount = componentBuffers.Count;

32
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegComponentPostProcessor.cs

@ -1,16 +1,27 @@
using System; using System;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
using SixLabors.Primitives; using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{ {
/// <summary>
/// Encapsulates postprocessing data for one component for <see cref="JpegImagePostProcessor"/>.
/// </summary>
internal class JpegComponentPostProcessor : IDisposable internal class JpegComponentPostProcessor : IDisposable
{ {
/// <summary>
/// Points to the current row in <see cref="Component"/>.
/// </summary>
private int currentComponentRowInBlocks; private int currentComponentRowInBlocks;
/// <summary>
/// The size of the area in <see cref="ColorBuffer"/> corrsponding to one 8x8 Jpeg block
/// </summary>
private readonly Size blockAreaSize; private readonly Size blockAreaSize;
/// <summary>
/// Initializes a new instance of the <see cref="JpegComponentPostProcessor"/> class.
/// </summary>
public JpegComponentPostProcessor(JpegImagePostProcessor imagePostProcessor, IJpegComponent component) public JpegComponentPostProcessor(JpegImagePostProcessor imagePostProcessor, IJpegComponent component)
{ {
this.Component = component; this.Component = component;
@ -21,21 +32,40 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
this.blockAreaSize = this.Component.SubSamplingDivisors * 8; this.blockAreaSize = this.Component.SubSamplingDivisors * 8;
} }
/// <summary>
/// Gets the <see cref="JpegImagePostProcessor"/>
/// </summary>
public JpegImagePostProcessor ImagePostProcessor { get; } public JpegImagePostProcessor ImagePostProcessor { get; }
/// <summary>
/// Gets the <see cref="Component"/>
/// </summary>
public IJpegComponent Component { get; } public IJpegComponent Component { get; }
/// <summary>
/// Gets the temporal working buffer of color values.
/// </summary>
public Buffer2D<float> ColorBuffer { get; } public Buffer2D<float> ColorBuffer { get; }
/// <summary>
/// Gets <see cref="IJpegComponent.SizeInBlocks"/>
/// </summary>
public Size SizeInBlocks => this.Component.SizeInBlocks; public Size SizeInBlocks => this.Component.SizeInBlocks;
/// <summary>
/// Gets the maximal number of block rows being processed in one step.
/// </summary>
public int BlockRowsPerStep { get; } public int BlockRowsPerStep { get; }
/// <inheritdoc />
public void Dispose() public void Dispose()
{ {
this.ColorBuffer.Dispose(); this.ColorBuffer.Dispose();
} }
/// <summary>
/// Invoke <see cref="JpegBlockPostProcessor"/> for <see cref="BlockRowsPerStep"/> block rows, copy the result into <see cref="ColorBuffer"/>.
/// </summary>
public unsafe void CopyBlocksToColorBuffer() public unsafe void CopyBlocksToColorBuffer()
{ {
var blockPp = default(JpegBlockPostProcessor); var blockPp = default(JpegBlockPostProcessor);

17
src/ImageSharp/Formats/Jpeg/Common/SizeExtensions.cs

@ -8,10 +8,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// </summary> /// </summary>
internal static class SizeExtensions internal static class SizeExtensions
{ {
/// <summary>
/// Multiplies 'a.Width' with 'b.Width' and 'a.Height' with 'b.Height'.
/// TODO: Shouldn't we expose this as operator in SixLabors.Core?
/// </summary>
public static Size MultiplyBy(this Size a, Size b) => new Size(a.Width * b.Width, a.Height * b.Height); public static Size MultiplyBy(this Size a, Size b) => new Size(a.Width * b.Width, a.Height * b.Height);
/// <summary>
/// Divides 'a.Width' with 'b.Width' and 'a.Height' with 'b.Height'.
/// TODO: Shouldn't we expose this as operator in SixLabors.Core?
/// </summary>
public static Size DivideBy(this Size a, Size b) => new Size(a.Width / b.Width, a.Height / b.Height); public static Size DivideBy(this Size a, Size b) => new Size(a.Width / b.Width, a.Height / b.Height);
/// <summary>
/// Divide Width and Height as real numbers and return the Ceiling.
/// </summary>
public static Size DivideRoundUp(this Size originalSize, int divX, int divY) public static Size DivideRoundUp(this Size originalSize, int divX, int divY)
{ {
var sizeVect = (Vector2)(SizeF)originalSize; var sizeVect = (Vector2)(SizeF)originalSize;
@ -22,9 +33,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return new Size((int)sizeVect.X, (int)sizeVect.Y); return new Size((int)sizeVect.X, (int)sizeVect.Y);
} }
/// <summary>
/// Divide Width and Height as real numbers and return the Ceiling.
/// </summary>
public static Size DivideRoundUp(this Size originalSize, int divisor) => public static Size DivideRoundUp(this Size originalSize, int divisor) =>
DivideRoundUp(originalSize, divisor, divisor); DivideRoundUp(originalSize, divisor, divisor);
/// <summary>
/// Divide Width and Height as real numbers and return the Ceiling.
/// </summary>
public static Size DivideRoundUp(this Size originalSize, Size divisor) => public static Size DivideRoundUp(this Size originalSize, Size divisor) =>
DivideRoundUp(originalSize, divisor.Width, divisor.Height); DivideRoundUp(originalSize, divisor.Width, divisor.Height);
} }

0
src/ImageSharp/Memory/Buffer2D.cs → src/ImageSharp/Memory/Buffer2D{T}.cs

40
src/ImageSharp/Memory/BufferArea.cs → src/ImageSharp/Memory/BufferArea{T}.cs

@ -12,6 +12,9 @@ namespace SixLabors.ImageSharp.Memory
internal struct BufferArea<T> internal struct BufferArea<T>
where T : struct where T : struct
{ {
/// <summary>
/// The rectangle specifying the boundaries of the area in <see cref="DestinationBuffer"/>.
/// </summary>
public readonly Rectangle Rectangle; public readonly Rectangle Rectangle;
public BufferArea(IBuffer2D<T> destinationBuffer, Rectangle rectangle) public BufferArea(IBuffer2D<T> destinationBuffer, Rectangle rectangle)
@ -30,17 +33,41 @@ namespace SixLabors.ImageSharp.Memory
{ {
} }
/// <summary>
/// Gets the <see cref="IBuffer2D{T}"/> being pointed by this instance.
/// </summary>
public IBuffer2D<T> DestinationBuffer { get; } public IBuffer2D<T> DestinationBuffer { get; }
/// <summary>
/// Gets the size of the area.
/// </summary>
public Size Size => this.Rectangle.Size; public Size Size => this.Rectangle.Size;
/// <summary>
/// Gets the pixel stride which is equal to the width of <see cref="DestinationBuffer"/>.
/// </summary>
public int Stride => this.DestinationBuffer.Width; public int Stride => this.DestinationBuffer.Width;
/// <summary>
/// Gets or sets a value at the given index.
/// </summary>
/// <param name="x">The position inside a row</param>
/// <param name="y">The row index</param>
/// <returns>The reference to the value</returns>
public ref T this[int x, int y] => ref this.DestinationBuffer.Span[this.GetIndexOf(x, y)]; public ref T this[int x, int y] => ref this.DestinationBuffer.Span[this.GetIndexOf(x, y)];
/// <summary>
/// Gets a reference to the [0,0] element.
/// </summary>
/// <returns>The reference to the [0,0] element</returns>
public ref T GetReferenceToOrigo() => public ref T GetReferenceToOrigo() =>
ref this.DestinationBuffer.Span[(this.Rectangle.Y * this.DestinationBuffer.Width) + this.Rectangle.X]; ref this.DestinationBuffer.Span[(this.Rectangle.Y * this.DestinationBuffer.Width) + this.Rectangle.X];
/// <summary>
/// Gets a span to row 'y' inside this area.
/// </summary>
/// <param name="y">The row index</param>
/// <returns>The span</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<T> GetRowSpan(int y) public Span<T> GetRowSpan(int y)
{ {
@ -51,6 +78,14 @@ namespace SixLabors.ImageSharp.Memory
return this.DestinationBuffer.Span.Slice(yy + xx, width); return this.DestinationBuffer.Span.Slice(yy + xx, width);
} }
/// <summary>
/// Returns a sub-area as <see cref="BufferArea{T}"/>. (Similar to <see cref="Span{T}.Slice(int, int)"/>.)
/// </summary>
/// <param name="x">The x index at the subarea origo</param>
/// <param name="y">The y index at the subarea origo</param>
/// <param name="width">The desired width of the subarea</param>
/// <param name="height">The desired height of the subarea</param>
/// <returns>The subarea</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferArea<T> GetSubArea(int x, int y, int width, int height) public BufferArea<T> GetSubArea(int x, int y, int width, int height)
{ {
@ -58,6 +93,11 @@ namespace SixLabors.ImageSharp.Memory
return this.GetSubArea(rectangle); return this.GetSubArea(rectangle);
} }
/// <summary>
/// Returns a sub-area as <see cref="BufferArea{T}"/>. (Similar to <see cref="Span{T}.Slice(int, int)"/>.)
/// </summary>
/// <param name="rectangle">The <see cref="Rectangle"/> specifying the boundaries of the subarea</param>
/// <returns>The subarea</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public BufferArea<T> GetSubArea(Rectangle rectangle) public BufferArea<T> GetSubArea(Rectangle rectangle)
{ {

0
src/ImageSharp/Memory/Buffer.cs → src/ImageSharp/Memory/Buffer{T}.cs

0
src/ImageSharp/Memory/IBuffer2D.cs → src/ImageSharp/Memory/IBuffer2D{T}.cs

2
src/ImageSharp/Memory/IBuffer.cs → src/ImageSharp/Memory/IBuffer{T}.cs

@ -4,7 +4,7 @@ namespace SixLabors.ImageSharp.Memory
{ {
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
/// Represents a contigous memory buffer of value-type items "promising" a <see cref="T:System.Span`1" /> /// Represents a contigous memory buffer of value-type items "promising" a <see cref="Span{T}"/>
/// </summary> /// </summary>
/// <typeparam name="T">The value type</typeparam> /// <typeparam name="T">The value type</typeparam>
internal interface IBuffer<T> : IDisposable internal interface IBuffer<T> : IDisposable

2
tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs

@ -41,6 +41,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
} }
} }
// TODO: This test occasionally fails. Don't get the reason, BufferArea.CopyTo() is totally OK.
[Fact] [Fact]
public void Unscaled() public void Unscaled()
{ {
@ -61,6 +62,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
} }
} }
// TODO: This test occasionally fails. Don't get the reason, BufferArea.CopyTo() is totally OK.
[Theory] [Theory]
[InlineData(1, 1)] [InlineData(1, 1)]
[InlineData(1, 2)] [InlineData(1, 2)]

3
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.ComponentData.cs

@ -13,6 +13,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
internal static partial class LibJpegTools internal static partial class LibJpegTools
{ {
/// <summary>
/// Stores spectral blocks for jpeg components.
/// </summary>
public class ComponentData : IEquatable<ComponentData>, IJpegComponent public class ComponentData : IEquatable<ComponentData>, IJpegComponent
{ {
public ComponentData(int widthInBlocks, int heightInBlocks, int index) public ComponentData(int widthInBlocks, int heightInBlocks, int index)

3
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.SpectralData.cs

@ -12,6 +12,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
internal static partial class LibJpegTools internal static partial class LibJpegTools
{ {
/// <summary>
/// Stores spectral jpeg compoent data in libjpeg-compatible style.
/// </summary>
public class SpectralData : IEquatable<SpectralData> public class SpectralData : IEquatable<SpectralData>
{ {
public int ComponentCount { get; private set; } public int ComponentCount { get; private set; }

20
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.cs

@ -8,6 +8,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
using SixLabors.ImageSharp.Formats.Jpeg.Common; using SixLabors.ImageSharp.Formats.Jpeg.Common;
/// <summary>
/// Utilities to read raw libjpeg data for reference conversion.
/// </summary>
internal static partial class LibJpegTools internal static partial class LibJpegTools
{ {
public static (double total, double average) CalculateDifference(ComponentData expected, ComponentData actual) public static (double total, double average) CalculateDifference(ComponentData expected, ComponentData actual)
@ -47,13 +50,30 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
TestEnvironment.ToolsDirectoryFullPath, TestEnvironment.ToolsDirectoryFullPath,
@"jpeg\dump-jpeg-coeffs.exe"); @"jpeg\dump-jpeg-coeffs.exe");
/// <summary>
/// Executes 'dump-jpeg-coeffs.exe' for the given jpeg image file, saving the libjpeg spectral data into 'destFile'. Windows only!
/// See:
/// <see>
/// <cref>https://github.com/SixLabors/Imagesharp.Tests.Images/blob/master/tools/jpeg/README.md</cref>
/// </see>
/// </summary>
public static void RunDumpJpegCoeffsTool(string sourceFile, string destFile) public static void RunDumpJpegCoeffsTool(string sourceFile, string destFile)
{ {
if (!TestEnvironment.IsWindows)
{
throw new InvalidOperationException("Can't run dump-jpeg-coeffs.exe in non-Windows environment. Skip this test on Linux/Unix!");
}
string args = $@"""{sourceFile}"" ""{destFile}"""; string args = $@"""{sourceFile}"" ""{destFile}""";
var process = Process.Start(DumpToolFullPath, args); var process = Process.Start(DumpToolFullPath, args);
process.WaitForExit(); process.WaitForExit();
} }
/// <summary>
/// Extract libjpeg <see cref="SpectralData"/> from the given jpg file with 'dump-jpeg-coeffs.exe'. Windows only!
/// See:
/// https://github.com/SixLabors/Imagesharp.Tests.Images/blob/master/tools/jpeg/README.md
/// </summary>
public static SpectralData ExtractSpectralData(string inputFile) public static SpectralData ExtractSpectralData(string inputFile)
{ {
TestFile testFile = TestFile.Create(inputFile); TestFile testFile = TestFile.Create(inputFile);

3
tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs

@ -71,6 +71,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
return r; return r;
} }
#pragma warning disable 219
/// <summary> /// <summary>
/// https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L200 /// https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L200
/// </summary> /// </summary>
@ -82,6 +84,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
float z0, z1, z2, z3, z4; float z0, z1, z2, z3, z4;
// see: PrintConstants() // see: PrintConstants()
float r0 = 1.41421354f; float r0 = 1.41421354f;
float r1 = 1.3870399f; float r1 = 1.3870399f;
float r2 = 1.306563f; float r2 = 1.306563f;

6
tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.StandardIntegerDCT.cs

@ -8,6 +8,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
internal static partial class ReferenceImplementations internal static partial class ReferenceImplementations
{ {
/// <summary> /// <summary>
/// TODO: produces really bad results for bigger values!
///
/// Contains the "original" golang based DCT/IDCT implementations as reference implementations. /// Contains the "original" golang based DCT/IDCT implementations as reference implementations.
/// 1. ===== Forward DCT ===== /// 1. ===== Forward DCT =====
/// **** The original golang source claims: /// **** The original golang source claims:
@ -76,7 +78,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
return result; return result;
} }
[Obsolete("Looks like this method produces really bad results for bigger values!")] // [Obsolete("Looks like this method produces really bad results for bigger values!")]
public static Block8x8 TransformIDCT(ref Block8x8 block) public static Block8x8 TransformIDCT(ref Block8x8 block)
{ {
int[] temp = new int[Block8x8.Size]; int[] temp = new int[Block8x8.Size];
@ -233,7 +235,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
/// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984. /// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
/// </summary> /// </summary>
/// <param name="src">The source block of coefficients</param> /// <param name="src">The source block of coefficients</param>
[Obsolete("Looks like this method produces really bad results for bigger values!")] // [Obsolete("Looks like this method produces really bad results for bigger values!")]
public static void TransformIDCTInplace(Span<int> src) public static void TransformIDCTInplace(Span<int> src)
{ {
// Horizontal 1-D IDCT. // Horizontal 1-D IDCT.

Loading…
Cancel
Save