diff --git a/src/ImageSharp/Formats/Jpg/Components/Bits.cs b/src/ImageSharp/Formats/Jpg/Components/Bits.cs
index 9bec6cd167..975c92aee0 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Bits.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/Bits.cs
@@ -3,10 +3,10 @@
// Licensed under the Apache License, Version 2.0.
//
-using System.Runtime.CompilerServices;
-
namespace ImageSharp.Formats
{
+ using System.Runtime.CompilerServices;
+
///
/// Holds the unprocessed bits that have been taken from the byte-stream.
/// The n least significant bits of a form the unread bits, to be read in MSB to
@@ -30,20 +30,20 @@ namespace ImageSharp.Formats
///
public int UnreadBits;
-
///
/// Reads bytes from the byte buffer to ensure that bits.UnreadBits is at
/// least n. For best performance (avoiding function calls inside hot loops),
/// the caller is the one responsible for first checking that bits.UnreadBits < n.
///
/// The number of bits to ensure.
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal JpegDecoderCore.ErrorCodes EnsureNBits(int n, JpegDecoderCore decoder)
{
while (true)
{
JpegDecoderCore.ErrorCodes errorCode;
-
+
byte c = decoder.bytes.ReadByteStuffedByte(decoder.inputStream, out errorCode);
if (errorCode != JpegDecoderCore.ErrorCodes.NoError)
@@ -51,40 +51,39 @@ namespace ImageSharp.Formats
return errorCode;
}
- Accumulator = (Accumulator << 8) | c;
- UnreadBits += 8;
- if (Mask == 0)
+ this.Accumulator = (this.Accumulator << 8) | c;
+ this.UnreadBits += 8;
+ if (this.Mask == 0)
{
- Mask = 1 << 7;
+ this.Mask = 1 << 7;
}
else
{
- Mask <<= 8;
+ this.Mask <<= 8;
}
- if (UnreadBits >= n)
+ if (this.UnreadBits >= n)
{
return JpegDecoderCore.ErrorCodes.NoError;
- //break;
}
}
}
-
+
internal int ReceiveExtend(byte t, JpegDecoderCore decoder)
{
- if (UnreadBits < t)
+ if (this.UnreadBits < t)
{
- var errorCode = EnsureNBits(t, decoder);
+ var errorCode = this.EnsureNBits(t, decoder);
if (errorCode != JpegDecoderCore.ErrorCodes.NoError)
{
throw new JpegDecoderCore.MissingFF00Exception();
}
}
- UnreadBits -= t;
- Mask >>= t;
+ this.UnreadBits -= t;
+ this.Mask >>= t;
int s = 1 << t;
- int x = (int)((Accumulator >> UnreadBits) & (s - 1));
+ int x = (int)((this.Accumulator >> this.UnreadBits) & (s - 1));
if (x < (s >> 1))
{
@@ -93,7 +92,5 @@ namespace ImageSharp.Formats
return x;
}
-
-
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpg/Components/Block.cs b/src/ImageSharp/Formats/Jpg/Components/Block.cs
index 111a1cac57..4d4ad4d81e 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Block.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/Block.cs
@@ -2,13 +2,12 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
-using System;
-using System.Buffers;
-using System.Runtime.CompilerServices;
-
namespace ImageSharp.Formats
{
+ using System;
+ using System.Buffers;
+ using System.Runtime.CompilerServices;
+
///
/// Represents an 8x8 block of coefficients to transform and encode.
///
@@ -26,17 +25,9 @@ namespace ImageSharp.Formats
///
public int[] Data;
- ///
- /// Initializes a new instance of the class.
- ///
- //public Block()
- //{
- // this.data = new int[BlockSize];
- //}
-
public void Init()
{
- //this.Data = new int[BlockSize];
+ // this.Data = new int[BlockSize];
this.Data = ArrayPool.Rent(BlockSize);
}
@@ -54,6 +45,7 @@ namespace ImageSharp.Formats
{
result[i].Init();
}
+
return result;
}
@@ -69,18 +61,25 @@ namespace ImageSharp.Formats
public int this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get { return this.Data[index]; }
+ get
+ {
+ return this.Data[index];
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set { this.Data[index] = value; }
+ set
+ {
+ this.Data[index] = value;
+ }
}
// TODO: Refactor Block.Dispose() callers to always use 'using' or 'finally' statement!
public void Dispose()
{
- if (Data != null)
+ if (this.Data != null)
{
- ArrayPool.Return(Data, true);
- Data = null;
+ ArrayPool.Return(this.Data, true);
+ this.Data = null;
}
}
@@ -92,24 +91,24 @@ namespace ImageSharp.Formats
}
}
-
public void Clear()
{
- for (int i = 0; i < Data.Length; i++)
+ for (int i = 0; i < this.Data.Length; i++)
{
- Data[i] = 0;
+ this.Data[i] = 0;
}
}
public Block Clone()
{
Block clone = Create();
- Array.Copy(Data, clone.Data, BlockSize);
+ Array.Copy(this.Data, clone.Data, BlockSize);
return clone;
}
}
///
+ /// TODO: Should be removed, when JpegEncoderCore is refactored to use Block8x8F
/// Temporal class to make refactoring easier.
/// 1. Refactor Block -> BlockF
/// 2. Test
@@ -120,7 +119,7 @@ namespace ImageSharp.Formats
private static readonly ArrayPool ArrayPool = ArrayPool.Create(BlockSize, 50);
///
- /// Gets the size of the block.
+ /// Size of the block.
///
public const int BlockSize = 64;
@@ -129,17 +128,9 @@ namespace ImageSharp.Formats
///
public float[] Data;
- ///
- /// Initializes a new instance of the class.
- ///
- //public Block()
- //{
- // this.data = new int[BlockSize];
- //}
-
public void Init()
{
- //this.Data = new int[BlockSize];
+ // this.Data = new int[BlockSize];
this.Data = ArrayPool.Rent(BlockSize);
}
@@ -157,6 +148,7 @@ namespace ImageSharp.Formats
{
result[i].Init();
}
+
return result;
}
@@ -172,18 +164,25 @@ namespace ImageSharp.Formats
public float this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get { return this.Data[index]; }
+ get
+ {
+ return this.Data[index];
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set { this.Data[index] = value; }
+ set
+ {
+ this.Data[index] = value;
+ }
}
// TODO: Refactor Block.Dispose() callers to always use 'using' or 'finally' statement!
public void Dispose()
{
- if (Data != null)
+ if (this.Data != null)
{
- ArrayPool.Return(Data, true);
- Data = null;
+ ArrayPool.Return(this.Data, true);
+ this.Data = null;
}
}
@@ -195,22 +194,19 @@ namespace ImageSharp.Formats
}
}
-
public void Clear()
{
- for (int i = 0; i < Data.Length; i++)
+ for (int i = 0; i < this.Data.Length; i++)
{
- Data[i] = 0;
+ this.Data[i] = 0;
}
}
public BlockF Clone()
{
BlockF clone = Create();
- Array.Copy(Data, clone.Data, BlockSize);
+ Array.Copy(this.Data, clone.Data, BlockSize);
return clone;
}
}
-
-
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.cs
index 2fec402d62..3b48dc572d 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.cs
@@ -1,4 +1,5 @@
-
+//
+
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@@ -8,6 +9,14 @@ namespace ImageSharp.Formats
{
internal partial struct Block8x8F
{
+ private static readonly Vector4 CMin4 = new Vector4(-128f);
+ private static readonly Vector4 CMax4 = new Vector4(127f);
+ private static readonly Vector4 COff4 = new Vector4(128f);
+
+ ///
+ /// Transpose the block into d
+ ///
+ /// Destination
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TransposeInto(ref Block8x8F d)
{
@@ -21,24 +30,12 @@ namespace ImageSharp.Formats
d.V0R.W = V7L.X; d.V1R.W = V7L.Y; d.V2R.W = V7L.Z; d.V3R.W = V7L.W; d.V4R.W = V7R.X; d.V5R.W = V7R.Y; d.V6R.W = V7R.Z; d.V7R.W = V7R.W;
}
-
- public void CropInto(float min, float max, ref Block8x8F d)
- {
- Vector4 minVec = new Vector4(min);
- Vector4 maxVec = new Vector4(max);
-
- d.V0L = Vector4.Max(Vector4.Min(V0L, maxVec), minVec);d.V0R = Vector4.Max(Vector4.Min(V0R, maxVec), minVec);
- d.V1L = Vector4.Max(Vector4.Min(V1L, maxVec), minVec);d.V1R = Vector4.Max(Vector4.Min(V1R, maxVec), minVec);
- d.V2L = Vector4.Max(Vector4.Min(V2L, maxVec), minVec);d.V2R = Vector4.Max(Vector4.Min(V2R, maxVec), minVec);
- d.V3L = Vector4.Max(Vector4.Min(V3L, maxVec), minVec);d.V3R = Vector4.Max(Vector4.Min(V3R, maxVec), minVec);
- d.V4L = Vector4.Max(Vector4.Min(V4L, maxVec), minVec);d.V4R = Vector4.Max(Vector4.Min(V4R, maxVec), minVec);
- d.V5L = Vector4.Max(Vector4.Min(V5L, maxVec), minVec);d.V5R = Vector4.Max(Vector4.Min(V5R, maxVec), minVec);
- d.V6L = Vector4.Max(Vector4.Min(V6L, maxVec), minVec);d.V6R = Vector4.Max(Vector4.Min(V6R, maxVec), minVec);
- d.V7L = Vector4.Max(Vector4.Min(V7L, maxVec), minVec);d.V7R = Vector4.Max(Vector4.Min(V7R, maxVec), minVec);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ColorifyInto(ref Block8x8F d)
+ ///
+ /// Level shift by +128, clip to [0, 255]
+ ///
+ /// Destination
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void TransformByteConvetibleColorValuesInto(ref Block8x8F d)
{
d.V0L = Vector4.Max(Vector4.Min(V0L, CMax4), CMin4) + COff4;d.V0R = Vector4.Max(Vector4.Min(V0R, CMax4), CMin4) + COff4;
d.V1L = Vector4.Max(Vector4.Min(V1L, CMax4), CMin4) + COff4;d.V1R = Vector4.Max(Vector4.Min(V1R, CMax4), CMin4) + COff4;
diff --git a/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.tt
index 810c4e9047..951d62d914 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.tt
+++ b/src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.tt
@@ -4,19 +4,28 @@
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
+//
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
<#
-char[] coordz = new[] {'X', 'Y', 'Z', 'W'};
+char[] coordz = {'X', 'Y', 'Z', 'W'};
#>
namespace ImageSharp.Formats
{
internal partial struct Block8x8F
{
+ private static readonly Vector4 CMin4 = new Vector4(-128f);
+ private static readonly Vector4 CMax4 = new Vector4(127f);
+ private static readonly Vector4 COff4 = new Vector4(128f);
+
+ ///
+ /// Transpose the block into d
+ ///
+ /// Destination
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void TransposeInto(ref Block8x8F d)
{
@@ -34,33 +43,7 @@ namespace ImageSharp.Formats
char srcSide = (j / 4) % 2 == 0 ? 'L' : 'R';
string expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord}; ";
- //bld.Append(expression);
Write(expression);
- }
- //bld.AppendLine();
- WriteLine("");
- }
- PopIndent();
- //Write(bld.ToString());
- #>
- }
-
-
- public void CropInto(float min, float max, ref Block8x8F d)
- {
- Vector4 minVec = new Vector4(min);
- Vector4 maxVec = new Vector4(max);
-
- <#
-
- PushIndent(" ");
-
- for (int i = 0; i < 8; i++)
- {
- for (int j = 0; j < 2; j++)
- {
- char side = j == 0 ? 'L' : 'R';
- Write($"d.V{i}{side} = Vector4.Max(Vector4.Min(V{i}{side}, maxVec), minVec);");
}
WriteLine("");
}
@@ -68,8 +51,12 @@ namespace ImageSharp.Formats
#>
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void ColorifyInto(ref Block8x8F d)
+ ///
+ /// Level shift by +128, clip to [0, 255]
+ ///
+ /// Destination
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void TransformByteConvetibleColorValuesInto(ref Block8x8F d)
{
<#
diff --git a/src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs
index 4b9830aa73..6fefb86965 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs
@@ -1,13 +1,15 @@
-using System;
-using System.Buffers;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
// ReSharper disable InconsistentNaming
-
namespace ImageSharp.Formats
{
+ using System;
+ using System.Numerics;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
///
/// DCT code Ported from https://github.com/norishigefukushima/dct_simd
///
@@ -37,251 +39,193 @@ namespace ImageSharp.Formats
public Vector4 V7L;
public Vector4 V7R;
-
public const int VectorCount = 16;
public const int ScalarCount = VectorCount*4;
- private static readonly ArrayPool ScalarArrayPool = ArrayPool.Create(ScalarCount, 50);
-
+ ///
+ /// Load raw 32bit floating point data from source
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void LoadFrom(MutableSpan source)
{
- fixed (Vector4* ptr = &V0L)
+ fixed (void* ptr = &this.V0L)
{
- Marshal.Copy(source.Data, source.Offset, (IntPtr) ptr, ScalarCount);
- //float* fp = (float*)ptr;
- //for (int i = 0; i < ScalarCount; i++)
- //{
- // fp[i] = source[i];
- //}
+ Marshal.Copy(source.Data, source.Offset, (IntPtr)ptr, ScalarCount);
}
}
+ ///
+ /// Load raw 32bit floating point data from source
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe void CopyTo(MutableSpan dest)
+ public static unsafe void LoadFrom(Block8x8F* blockPtr, MutableSpan source)
{
- fixed (Vector4* ptr = &V0L)
+ Marshal.Copy(source.Data, source.Offset, (IntPtr)blockPtr, ScalarCount);
+ }
+
+ ///
+ /// Load raw 32bit floating point data from source
+ ///
+ internal unsafe void LoadFrom(MutableSpan source)
+ {
+ fixed (Vector4* ptr = &this.V0L)
{
- Marshal.Copy((IntPtr) ptr, dest.Data, dest.Offset, ScalarCount);
+ float* fp = (float*)ptr;
+ for (int i = 0; i < ScalarCount; i++)
+ {
+ fp[i] = source[i];
+ }
}
}
-
+ ///
+ /// Copy raw 32bit floating point data to dest
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe void CopyTo(float[] dest)
+ public unsafe void CopyTo(MutableSpan dest)
{
- fixed (Vector4* ptr = &V0L)
+ fixed (void* ptr = &this.V0L)
{
- Marshal.Copy((IntPtr) ptr, dest, 0, ScalarCount);
+ Marshal.Copy((IntPtr)ptr, dest.Data, dest.Offset, ScalarCount);
}
}
-
+ ///
+ /// Copy raw 32bit floating point data to dest
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe void LoadFrom(Block8x8F* blockPtr, MutableSpan source)
+ public unsafe void CopyTo(float[] dest)
{
- Marshal.Copy(source.Data, source.Offset, (IntPtr) blockPtr, ScalarCount);
+ fixed (void* ptr = &this.V0L)
+ {
+ Marshal.Copy((IntPtr)ptr, dest, 0, ScalarCount);
+ }
}
+ ///
+ /// Copy raw 32bit floating point data to dest
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void CopyTo(Block8x8F* blockPtr, MutableSpan dest)
{
- Marshal.Copy((IntPtr) blockPtr, dest.Data, dest.Offset, ScalarCount);
- }
-
-
- internal unsafe void LoadFrom(MutableSpan source)
- {
- fixed (Vector4* ptr = &V0L)
- {
- float* fp = (float*) ptr;
- for (int i = 0; i < ScalarCount; i++)
- {
- fp[i] = source[i];
- }
- }
+ Marshal.Copy((IntPtr)blockPtr, dest.Data, dest.Offset, ScalarCount);
}
+ ///
+ /// Copy raw 32bit floating point data to dest
+ ///
internal unsafe void CopyTo(MutableSpan dest)
{
- fixed (Vector4* ptr = &V0L)
+ fixed (Vector4* ptr = &this.V0L)
{
- float* fp = (float*) ptr;
+ float* fp = (float*)ptr;
for (int i = 0; i < ScalarCount; i++)
{
- dest[i] = (int) fp[i];
+ dest[i] = (int)fp[i];
}
}
}
- public unsafe void TransposeInplace()
- {
- fixed (Vector4* ptr = &V0L)
- {
- float* data = (float*) ptr;
-
- for (int i = 1; i < 8; i++)
- {
- int i8 = i*8;
- for (int j = 0; j < i; j++)
- {
- float tmp = data[i8 + j];
- data[i8 + j] = data[j*8 + i];
- data[j*8 + i] = tmp;
- }
- }
- }
-
- }
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MultiplyAllInplace(Vector4 s)
{
- V0L *= s;
- V0R *= s;
- V1L *= s;
- V1R *= s;
- V2L *= s;
- V2R *= s;
- V3L *= s;
- V3R *= s;
- V4L *= s;
- V4R *= s;
- V5L *= s;
- V5R *= s;
- V6L *= s;
- V6R *= s;
- V7L *= s;
- V7R *= s;
+ this.V0L *= s;
+ this.V0R *= s;
+ this.V1L *= s;
+ this.V1R *= s;
+ this.V2L *= s;
+ this.V2R *= s;
+ this.V3L *= s;
+ this.V3R *= s;
+ this.V4L *= s;
+ this.V4R *= s;
+ this.V5L *= s;
+ this.V5R *= s;
+ this.V6L *= s;
+ this.V6R *= s;
+ this.V7L *= s;
+ this.V7R *= s;
}
- // ReSharper disable once InconsistentNaming
- public void IDCTInto(ref Block8x8F dest, ref Block8x8F temp)
+ ///
+ /// Apply floating point IDCT transformation into dest, using a temporary block 'temp' provided by the caller (optimization)
+ ///
+ /// Destination
+ /// Temporary block provided by the caller
+ public void TransformIDCTInto(ref Block8x8F dest, ref Block8x8F temp)
{
- TransposeInto(ref temp);
- temp.iDCT2D8x4_LeftPart(ref dest);
- temp.iDCT2D8x4_RightPart(ref dest);
+ this.TransposeInto(ref temp);
+ temp.IDCT8x4_LeftPart(ref dest);
+ temp.IDCT8x4_RightPart(ref dest);
dest.TransposeInto(ref temp);
- temp.iDCT2D8x4_LeftPart(ref dest);
- temp.iDCT2D8x4_RightPart(ref dest);
-
- dest.MultiplyAllInplace(_0_125);
- }
+ temp.IDCT8x4_LeftPart(ref dest);
+ temp.IDCT8x4_RightPart(ref dest);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void IDCTInplace()
- {
- Block8x8F result = new Block8x8F();
- Block8x8F temp = new Block8x8F();
- IDCTInto(ref result, ref temp);
- this = result;
+ dest.MultiplyAllInplace(c_0_125);
}
- private static readonly Vector4 _1_175876 = new Vector4(1.175876f);
- private static readonly Vector4 _1_961571 = new Vector4(-1.961571f);
- private static readonly Vector4 _0_390181 = new Vector4(-0.390181f);
- private static readonly Vector4 _0_899976 = new Vector4(-0.899976f);
- private static readonly Vector4 _2_562915 = new Vector4(-2.562915f);
- private static readonly Vector4 _0_298631 = new Vector4(0.298631f);
- private static readonly Vector4 _2_053120 = new Vector4(2.053120f);
- private static readonly Vector4 _3_072711 = new Vector4(3.072711f);
- private static readonly Vector4 _1_501321 = new Vector4(1.501321f);
- private static readonly Vector4 _0_541196 = new Vector4(0.541196f);
- private static readonly Vector4 _1_847759 = new Vector4(-1.847759f);
- private static readonly Vector4 _0_765367 = new Vector4(0.765367f);
- private static readonly Vector4 _0_125 = new Vector4(0.1250f);
+ private static readonly Vector4 c_1_175876 = new Vector4(1.175876f);
+ private static readonly Vector4 c_1_961571 = new Vector4(-1.961571f);
+ private static readonly Vector4 c_0_390181 = new Vector4(-0.390181f);
+ private static readonly Vector4 c_0_899976 = new Vector4(-0.899976f);
+ private static readonly Vector4 c_2_562915 = new Vector4(-2.562915f);
+ private static readonly Vector4 c_0_298631 = new Vector4(0.298631f);
+ private static readonly Vector4 c_2_053120 = new Vector4(2.053120f);
+ private static readonly Vector4 c_3_072711 = new Vector4(3.072711f);
+ private static readonly Vector4 c_1_501321 = new Vector4(1.501321f);
+ private static readonly Vector4 c_0_541196 = new Vector4(0.541196f);
+ private static readonly Vector4 c_1_847759 = new Vector4(-1.847759f);
+ private static readonly Vector4 c_0_765367 = new Vector4(0.765367f);
+
+ private static readonly Vector4 c_0_125 = new Vector4(0.1250f);
+ ///
+ /// Do IDCT internal operations on the left part of the block. Original source:
+ /// https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L261
+ ///
+ /// Destination block
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void iDCT2D8x4_LeftPart(ref Block8x8F d)
+ internal void IDCT8x4_LeftPart(ref Block8x8F d)
{
- /*
- float a0,a1,a2,a3,b0,b1,b2,b3; float z0,z1,z2,z3,z4; float r[8]; int i;
- for(i = 0;i < 8;i++){ r[i] = (float)(cos((double)i / 16.0 * M_PI) * M_SQRT2); }
- */
- /*
- 0: 1.414214
- 1: 1.387040
- 2: 1.306563
- 3:
- 4: 1.000000
- 5: 0.785695
- 6:
- 7: 0.275899
- */
-
- Vector4 my1 = V1L;
- Vector4 my7 = V7L;
+ Vector4 my1 = this.V1L;
+ Vector4 my7 = this.V7L;
Vector4 mz0 = my1 + my7;
- Vector4 my3 = V3L;
+ Vector4 my3 = this.V3L;
Vector4 mz2 = my3 + my7;
- Vector4 my5 = V5L;
+ Vector4 my5 = this.V5L;
Vector4 mz1 = my3 + my5;
Vector4 mz3 = my1 + my5;
- Vector4 mz4 = ((mz0 + mz1)*_1_175876);
- //z0 = y[1] + y[7]; z1 = y[3] + y[5]; z2 = y[3] + y[7]; z3 = y[1] + y[5];
- //z4 = (z0 + z1) * r[3];
-
- mz2 = mz2*_1_961571 + mz4;
- mz3 = mz3*_0_390181 + mz4;
- mz0 = mz0*_0_899976;
- mz1 = mz1*_2_562915;
-
- /*
- -0.899976
- -2.562915
- -1.961571
- -0.390181
- z0 = z0 * (-r[3] + r[7]);
- z1 = z1 * (-r[3] - r[1]);
- z2 = z2 * (-r[3] - r[5]) + z4;
- z3 = z3 * (-r[3] + r[5]) + z4;*/
-
-
- Vector4 mb3 = my7*_0_298631 + mz0 + mz2;
- Vector4 mb2 = my5*_2_053120 + mz1 + mz3;
- Vector4 mb1 = my3*_3_072711 + mz1 + mz2;
- Vector4 mb0 = my1*_1_501321 + mz0 + mz3;
-
- /*
- 0.298631
- 2.053120
- 3.072711
- 1.501321
- b3 = y[7] * (-r[1] + r[3] + r[5] - r[7]) + z0 + z2;
- b2 = y[5] * ( r[1] + r[3] - r[5] + r[7]) + z1 + z3;
- b1 = y[3] * ( r[1] + r[3] + r[5] - r[7]) + z1 + z2;
- b0 = y[1] * ( r[1] + r[3] - r[5] - r[7]) + z0 + z3;
- */
-
- Vector4 my2 = V2L;
- Vector4 my6 = V6L;
- mz4 = (my2 + my6)*_0_541196;
- Vector4 my0 = V0L;
- Vector4 my4 = V4L;
+ Vector4 mz4 = ((mz0 + mz1) * c_1_175876);
+
+ mz2 = (mz2 * c_1_961571) + mz4;
+ mz3 = (mz3 * c_0_390181) + mz4;
+ mz0 = mz0 * c_0_899976;
+ mz1 = mz1 * c_2_562915;
+
+ Vector4 mb3 = (my7 * c_0_298631) + mz0 + mz2;
+ Vector4 mb2 = (my5 * c_2_053120) + mz1 + mz3;
+ Vector4 mb1 = (my3 * c_3_072711) + mz1 + mz2;
+ Vector4 mb0 = (my1 * c_1_501321) + mz0 + mz3;
+
+ Vector4 my2 = this.V2L;
+ Vector4 my6 = this.V6L;
+ mz4 = (my2 + my6) * c_0_541196;
+ Vector4 my0 = this.V0L;
+ Vector4 my4 = this.V4L;
mz0 = my0 + my4;
mz1 = my0 - my4;
- mz2 = mz4 + my6*_1_847759;
- mz3 = mz4 + my2*_0_765367;
+ mz2 = mz4 + (my6 * c_1_847759);
+ mz3 = mz4 + (my2 * c_0_765367);
my0 = mz0 + mz3;
my3 = mz0 - mz3;
my1 = mz1 + mz2;
my2 = mz1 - mz2;
- /*
- 1.847759
- 0.765367
- z4 = (y[2] + y[6]) * r[6];
- z0 = y[0] + y[4]; z1 = y[0] - y[4];
- z2 = z4 - y[6] * (r[2] + r[6]);
- z3 = z4 + y[2] * (r[2] - r[6]);
- a0 = z0 + z3; a3 = z0 - z3;
- a1 = z1 + z2; a2 = z1 - z2;
- */
d.V0L = my0 + mb0;
d.V7L = my0 - mb0;
@@ -291,104 +235,53 @@ namespace ImageSharp.Formats
d.V5L = my2 - mb2;
d.V3L = my3 + mb3;
d.V4L = my3 - mb3;
- /*
- x[0] = a0 + b0; x[7] = a0 - b0;
- x[1] = a1 + b1; x[6] = a1 - b1;
- x[2] = a2 + b2; x[5] = a2 - b2;
- x[3] = a3 + b3; x[4] = a3 - b3;
- for(i = 0;i < 8;i++){ x[i] *= 0.353554f; }
- */
}
+ ///
+ /// Do IDCT internal operations on the right part of the block.
+ /// Original source:
+ /// https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L261
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void iDCT2D8x4_RightPart(ref Block8x8F d)
+ internal void IDCT8x4_RightPart(ref Block8x8F d)
{
- /*
- float a0,a1,a2,a3,b0,b1,b2,b3; float z0,z1,z2,z3,z4; float r[8]; int i;
- for(i = 0;i < 8;i++){ r[i] = (float)(cos((double)i / 16.0 * M_PI) * M_SQRT2); }
- */
- /*
- 0: 1.414214
- 1: 1.387040
- 2: 1.306563
- 3:
- 4: 1.000000
- 5: 0.785695
- 6:
- 7: 0.275899
- */
-
- Vector4 my1 = V1R;
- Vector4 my7 = V7R;
+ Vector4 my1 = this.V1R;
+ Vector4 my7 = this.V7R;
Vector4 mz0 = my1 + my7;
- Vector4 my3 = V3R;
+ Vector4 my3 = this.V3R;
Vector4 mz2 = my3 + my7;
- Vector4 my5 = V5R;
+ Vector4 my5 = this.V5R;
Vector4 mz1 = my3 + my5;
Vector4 mz3 = my1 + my5;
- Vector4 mz4 = ((mz0 + mz1)*_1_175876);
- //z0 = y[1] + y[7]; z1 = y[3] + y[5]; z2 = y[3] + y[7]; z3 = y[1] + y[5];
- //z4 = (z0 + z1) * r[3];
-
- mz2 = mz2*_1_961571 + mz4;
- mz3 = mz3*_0_390181 + mz4;
- mz0 = mz0*_0_899976;
- mz1 = mz1*_2_562915;
-
- /*
- -0.899976
- -2.562915
- -1.961571
- -0.390181
- z0 = z0 * (-r[3] + r[7]);
- z1 = z1 * (-r[3] - r[1]);
- z2 = z2 * (-r[3] - r[5]) + z4;
- z3 = z3 * (-r[3] + r[5]) + z4;*/
-
-
- Vector4 mb3 = my7*_0_298631 + mz0 + mz2;
- Vector4 mb2 = my5*_2_053120 + mz1 + mz3;
- Vector4 mb1 = my3*_3_072711 + mz1 + mz2;
- Vector4 mb0 = my1*_1_501321 + mz0 + mz3;
-
- /*
- 0.298631
- 2.053120
- 3.072711
- 1.501321
- b3 = y[7] * (-r[1] + r[3] + r[5] - r[7]) + z0 + z2;
- b2 = y[5] * ( r[1] + r[3] - r[5] + r[7]) + z1 + z3;
- b1 = y[3] * ( r[1] + r[3] + r[5] - r[7]) + z1 + z2;
- b0 = y[1] * ( r[1] + r[3] - r[5] - r[7]) + z0 + z3;
- */
-
- Vector4 my2 = V2R;
- Vector4 my6 = V6R;
- mz4 = (my2 + my6)*_0_541196;
- Vector4 my0 = V0R;
- Vector4 my4 = V4R;
+ Vector4 mz4 = (mz0 + mz1) * c_1_175876;
+
+ mz2 = (mz2 * c_1_961571) + mz4;
+ mz3 = (mz3 * c_0_390181) + mz4;
+ mz0 = mz0 * c_0_899976;
+ mz1 = mz1 * c_2_562915;
+
+ Vector4 mb3 = (my7 * c_0_298631) + mz0 + mz2;
+ Vector4 mb2 = (my5 * c_2_053120) + mz1 + mz3;
+ Vector4 mb1 = (my3 * c_3_072711) + mz1 + mz2;
+ Vector4 mb0 = (my1 * c_1_501321) + mz0 + mz3;
+
+ Vector4 my2 = this.V2R;
+ Vector4 my6 = this.V6R;
+ mz4 = (my2 + my6) * c_0_541196;
+ Vector4 my0 = this.V0R;
+ Vector4 my4 = this.V4R;
mz0 = my0 + my4;
mz1 = my0 - my4;
- mz2 = mz4 + my6*_1_847759;
- mz3 = mz4 + my2*_0_765367;
+ mz2 = mz4 + (my6 * c_1_847759);
+ mz3 = mz4 + (my2 * c_0_765367);
my0 = mz0 + mz3;
my3 = mz0 - mz3;
my1 = mz1 + mz2;
my2 = mz1 - mz2;
- /*
- 1.847759
- 0.765367
- z4 = (y[2] + y[6]) * r[6];
- z0 = y[0] + y[4]; z1 = y[0] - y[4];
- z2 = z4 - y[6] * (r[2] + r[6]);
- z3 = z4 + y[2] * (r[2] - r[6]);
- a0 = z0 + z3; a3 = z0 - z3;
- a1 = z1 + z2; a2 = z1 - z2;
- */
d.V0R = my0 + mb0;
d.V7R = my0 - mb0;
@@ -398,15 +291,7 @@ namespace ImageSharp.Formats
d.V5R = my2 - mb2;
d.V3R = my3 + mb3;
d.V4R = my3 - mb3;
- /*
- x[0] = a0 + b0; x[7] = a0 - b0;
- x[1] = a1 + b1; x[6] = a1 - b1;
- x[2] = a2 + b2; x[5] = a2 - b2;
- x[3] = a3 + b3; x[4] = a3 - b3;
- for(i = 0;i < 8;i++){ x[i] *= 0.353554f; }
- */
}
-
public unsafe float this[int idx]
{
@@ -415,83 +300,94 @@ namespace ImageSharp.Formats
{
fixed (Block8x8F* p = &this)
{
- float* fp = (float*) p;
+ float* fp = (float*)p;
return fp[idx];
}
}
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
fixed (Block8x8F* p = &this)
{
- float* fp = (float*) p;
+ float* fp = (float*)p;
fp[idx] = value;
}
}
}
+ ///
+ /// Pointer-based "Indexer" (getter part)
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe float GetScalarAt(Block8x8F* blockPtr, int idx)
{
- float* fp = (float*) blockPtr;
+ float* fp = (float*)blockPtr;
return fp[idx];
}
+ ///
+ /// Pointer-based "Indexer" (setter part)
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void SetScalarAt(Block8x8F* blockPtr, int idx, float value)
{
- float* fp = (float*) blockPtr;
+ float* fp = (float*)blockPtr;
fp[idx] = value;
}
+ ///
+ /// Fill the block with defaults (zeroes)
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Clear()
{
- this = new Block8x8F(); // LOL C# Plz!
+ // The cheapest way to do this in C#:
+ this = new Block8x8F();
}
+ ///
+ /// TODO: Should be removed when BlockF goes away
+ ///
+ ///
internal void LoadFrom(ref BlockF legacyBlock)
{
- LoadFrom(legacyBlock.Data);
+ this.LoadFrom(legacyBlock.Data);
}
+ ///
+ /// TODO: Should be removed when BlockF goes away
+ ///
+ ///
internal void CopyTo(ref BlockF legacyBlock)
{
- CopyTo(legacyBlock.Data);
+ this.CopyTo(legacyBlock.Data);
}
-
- private static readonly Vector4 CMin4 = new Vector4(-128f);
- private static readonly Vector4 CMax4 = new Vector4(127f);
- private static readonly Vector4 COff4 = new Vector4(128f);
-
+
///
- /// Level shift by +128, clip to [0, 255], and write to buffer.
+ /// Level shift by +128, clip to [0, 255], and write to buffer.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal unsafe void CopyColorsTo(
- MutableSpan buffer,
- int stride,
- Block8x8F* temp)
+ internal unsafe void CopyColorsTo(MutableSpan buffer, int stride, Block8x8F* temp)
{
- ColorifyInto(ref *temp);
+ this.TransformByteConvetibleColorValuesInto(ref *temp);
- float* src = (float*) temp;
+ float* src = (float*)temp;
for (int i = 0; i < 8; i++)
{
- buffer[0] = (byte) src[0];
- buffer[1] = (byte) src[1];
- buffer[2] = (byte) src[2];
- buffer[3] = (byte) src[3];
- buffer[4] = (byte) src[4];
- buffer[5] = (byte) src[5];
- buffer[6] = (byte) src[6];
- buffer[7] = (byte) src[7];
+ buffer[0] = (byte)src[0];
+ buffer[1] = (byte)src[1];
+ buffer[2] = (byte)src[2];
+ buffer[3] = (byte)src[3];
+ buffer[4] = (byte)src[4];
+ buffer[5] = (byte)src[5];
+ buffer[6] = (byte)src[6];
+ buffer[7] = (byte)src[7];
buffer.AddOffset(stride);
src += 8;
}
}
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void UnZig(Block8x8F* block, Block8x8F* qt, int* unzigPtr)
{
diff --git a/src/ImageSharp/Formats/Jpg/Components/Bytes.cs b/src/ImageSharp/Formats/Jpg/Components/Bytes.cs
index 3377b61558..32a767d586 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Bytes.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/Bytes.cs
@@ -2,14 +2,13 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
-using System;
-using System.Buffers;
-using System.IO;
-using System.Runtime.CompilerServices;
-
namespace ImageSharp.Formats
{
+ using System;
+ using System.Buffers;
+ using System.IO;
+ using System.Runtime.CompilerServices;
+
///
/// Bytes is a byte buffer, similar to a stream, except that it
/// has to be able to unread more than 1 byte, due to byte stuffing.
@@ -17,25 +16,14 @@ namespace ImageSharp.Formats
///
internal struct Bytes : IDisposable
{
- ///
- /// Initializes a new instance of the class.
- ///
- //public Bytes()
- //{
- // this.Buffer = new byte[4096];
- // this.I = 0;
- // this.J = 0;
- // this.UnreadableBytes = 0;
- //}
-
private static readonly ArrayPool ArrayPool = ArrayPool.Create(4096, 50);
+ ///
+ /// Creates a new instance of the , and initializes it's buffer.
+ ///
public static Bytes Create()
{
- return new Bytes
- {
- Buffer = ArrayPool.Rent(4096)
- };
+ return new Bytes { Buffer = ArrayPool.Rent(4096) };
}
///
@@ -57,15 +45,14 @@ namespace ImageSharp.Formats
public void Dispose()
{
- if (Buffer!= null) ArrayPool.Return(Buffer);
- Buffer = null;
+ if (this.Buffer != null) ArrayPool.Return(this.Buffer);
+ this.Buffer = null;
}
///
/// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data.
///
/// The
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal byte ReadByteStuffedByte(Stream inputStream, out JpegDecoderCore.ErrorCodes errorCode)
{
byte x;
@@ -87,7 +74,8 @@ namespace ImageSharp.Formats
{
errorCode = JpegDecoderCore.ErrorCodes.MissingFF00;
return 0;
- //throw new MissingFF00Exception();
+
+ // throw new MissingFF00Exception();
}
this.I++;
@@ -110,7 +98,8 @@ namespace ImageSharp.Formats
{
errorCode = JpegDecoderCore.ErrorCodes.MissingFF00;
return 0;
- //throw new MissingFF00Exception();
+
+ // throw new MissingFF00Exception();
}
return JpegConstants.Markers.XFF;
@@ -165,6 +154,5 @@ namespace ImageSharp.Formats
this.J += n;
}
-
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpg/Components/Huffman.cs b/src/ImageSharp/Formats/Jpg/Components/Huffman.cs
index 345b45e0e0..7a6f031e86 100644
--- a/src/ImageSharp/Formats/Jpg/Components/Huffman.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/Huffman.cs
@@ -2,42 +2,30 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
-using System;
-using System.Buffers;
-
namespace ImageSharp.Formats
{
+ using System;
+ using System.Buffers;
+
///
/// Represents a Huffman tree
///
internal struct Huffman : IDisposable
{
- private static ArrayPool UshortBuffer =
- //ArrayPool.Shared;
- ArrayPool.Create(1 << JpegDecoderCore.LutSize, 50);
+ private static ArrayPool UshortBuffer = ArrayPool.Create(1 << JpegDecoderCore.LutSize, 50);
- private static ArrayPool ByteBuffer =
- //ArrayPool.Shared;
- ArrayPool.Create(JpegDecoderCore.MaxNCodes, 50);
+ private static ArrayPool ByteBuffer = ArrayPool.Create(JpegDecoderCore.MaxNCodes, 50);
- private static readonly ArrayPool IntBuffer =
- //ArrayPool.Shared;
- ArrayPool.Create(JpegDecoderCore.MaxCodeLength, 50);
+ private static readonly ArrayPool IntBuffer = ArrayPool.Create(JpegDecoderCore.MaxCodeLength, 50);
public void Init(int lutSize, int maxNCodes, int maxCodeLength)
{
- //this.Lut = new ushort[1 << lutSize];
- //this.Values = new byte[maxNCodes];
- //this.MinCodes = new int[maxCodeLength];
- //this.MaxCodes = new int[maxCodeLength];
- //this.Indices = new int[maxCodeLength];
-
this.Lut = UshortBuffer.Rent(1 << lutSize);
this.Values = ByteBuffer.Rent(maxNCodes);
this.MinCodes = IntBuffer.Rent(maxCodeLength);
- this.MaxCodes = IntBuffer.Rent(maxCodeLength); ;
- this.Indices = IntBuffer.Rent(maxCodeLength); ;
+ this.MaxCodes = IntBuffer.Rent(maxCodeLength);
+ this.Indices = IntBuffer.Rent(maxCodeLength);
+
}
///
@@ -77,13 +65,11 @@ namespace ImageSharp.Formats
public void Dispose()
{
- UshortBuffer.Return(Lut, true);
- ByteBuffer.Return(Values, true);
- IntBuffer.Return(MinCodes, true);
- IntBuffer.Return(MaxCodes, true);
- IntBuffer.Return(Indices, true);
+ UshortBuffer.Return(this.Lut, true);
+ ByteBuffer.Return(this.Values, true);
+ IntBuffer.Return(this.MinCodes, true);
+ IntBuffer.Return(this.MaxCodes, true);
+ IntBuffer.Return(this.Indices, true);
}
}
-
-
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpg/Components/IDCT.cs b/src/ImageSharp/Formats/Jpg/Components/IDCT.cs
index 88b493c4b4..b3277e0278 100644
--- a/src/ImageSharp/Formats/Jpg/Components/IDCT.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/IDCT.cs
@@ -3,8 +3,6 @@
// Licensed under the Apache License, Version 2.0.
//
-using System.Numerics;
-
namespace ImageSharp.Formats
{
///
diff --git a/src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs b/src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs
index 0cb11690b0..492f28f5b4 100644
--- a/src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs
+++ b/src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs
@@ -1,52 +1,67 @@
-using System.Buffers;
-using System.Numerics;
-using System.Runtime.CompilerServices;
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
namespace ImageSharp.Formats
{
+ using System.Numerics;
+ using System.Runtime.CompilerServices;
+
///
/// Like corefxlab Span, but with an AddOffset() method for efficiency.
/// TODO: When Span will be official, consider replacing this class!
///
- ///
+ ///
+ /// https://github.com/dotnet/corefxlab/blob/master/src/System.Slices/System/Span.cs
+ ///
///
internal struct MutableSpan
{
public T[] Data;
+
public int Offset;
- public int TotalCount => Data.Length - Offset;
+ public int TotalCount => this.Data.Length - this.Offset;
public MutableSpan(int size, int offset = 0)
{
- Data = new T[size];
- Offset = offset;
+ this.Data = new T[size];
+ this.Offset = offset;
}
public MutableSpan(T[] data, int offset = 0)
{
- Data = data;
- Offset = offset;
+ this.Data = data;
+ this.Offset = offset;
}
public T this[int idx]
{
- [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Data[idx + Offset]; }
- [MethodImpl(MethodImplOptions.AggressiveInlining)] set { Data[idx + Offset] = value; }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return this.Data[idx + this.Offset];
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ set
+ {
+ this.Data[idx + this.Offset] = value;
+ }
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public MutableSpan Slice(int offset)
{
- return new MutableSpan(Data, Offset + offset);
+ return new MutableSpan(this.Data, this.Offset + offset);
}
public static implicit operator MutableSpan(T[] data) => new MutableSpan(data, 0);
-
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddOffset(int offset)
{
- Offset += offset;
+ this.Offset += offset;
}
}
@@ -89,7 +104,5 @@ namespace ImageSharp.Formats
data[2] = (int)v.Z;
data[3] = (int)v.W;
}
-
-
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
index e66d3ca219..446da29dbd 100644
--- a/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs
@@ -3,14 +3,12 @@
// Licensed under the Apache License, Version 2.0.
//
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
namespace ImageSharp.Formats
{
using System;
using System.IO;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
using System.Threading.Tasks;
///
@@ -71,12 +69,12 @@ namespace ImageSharp.Formats
/// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
///
private static readonly int[] Unzig =
- {
- 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26,
- 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57,
- 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31,
- 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
- };
+ {
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33,
+ 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50,
+ 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63,
+ };
///
/// The component array
@@ -92,7 +90,6 @@ namespace ImageSharp.Formats
/// The huffman trees
///
//private readonly Huffman[,] huffmanTrees;
-
private readonly Huffman[] huffmanTrees;
///
@@ -223,7 +220,6 @@ namespace ImageSharp.Formats
}
}
-
///
/// Decodes the image from the specified this._stream and sets
/// the data to image.
@@ -234,8 +230,7 @@ namespace ImageSharp.Formats
/// The stream, where the image should be.
/// Whether to decode metadata only.
public void Decode(Image image, Stream stream, bool configOnly)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
this.inputStream = stream;
@@ -373,7 +368,8 @@ namespace ImageSharp.Formats
this.ProcessApp14Marker(remaining);
break;
default:
- if ((JpegConstants.Markers.APP0 <= marker && marker <= JpegConstants.Markers.APP15) || marker == JpegConstants.Markers.COM)
+ if ((JpegConstants.Markers.APP0 <= marker && marker <= JpegConstants.Markers.APP15)
+ || marker == JpegConstants.Markers.COM)
{
this.Skip(remaining);
}
@@ -422,7 +418,7 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Missing SOS marker.");
}
}
-
+
///
/// Processes a Define Huffman Table marker, and initializes a huffman
/// struct from its contents. Specified in section B.2.4.2.
@@ -451,13 +447,12 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Bad Th value");
}
- ProcessDefineHuffmanTablesMarkerLoop(ref this.huffmanTrees[tc * ThRowSize + th], ref remaining);
+ this.ProcessDefineHuffmanTablesMarkerLoop(ref this.huffmanTrees[tc * ThRowSize + th], ref remaining);
}
}
private void ProcessDefineHuffmanTablesMarkerLoop(ref Huffman huffman, ref int remaining)
{
-
// Read nCodes and huffman.Valuess (and derive h.Length).
// nCodes[i] is the number of codes with code length i.
// h.Length is the total number of codes.
@@ -552,7 +547,7 @@ namespace ImageSharp.Formats
private byte DecodeHuffman(ref Huffman huffman)
{
// Copy stuff to the stack:
-
+
if (huffman.Length == 0)
{
throw new ImageFormatException("Uninitialized Huffman table");
@@ -560,35 +555,24 @@ namespace ImageSharp.Formats
if (this.bits.UnreadBits < 8)
{
- //try
- //{
- var errorCode = bits.EnsureNBits(8, this);
+ var errorCode = this.bits.EnsureNBits(8, this);
- if (errorCode == ErrorCodes.NoError)
- {
- ushort v = huffman.Lut[(this.bits.Accumulator >> (this.bits.UnreadBits - LutSize)) & 0xff];
+ if (errorCode == ErrorCodes.NoError)
+ {
+ ushort v = huffman.Lut[(this.bits.Accumulator >> (this.bits.UnreadBits - LutSize)) & 0xff];
- if (v != 0)
- {
- byte n = (byte)((v & 0xff) - 1);
- this.bits.UnreadBits -= n;
- this.bits.Mask >>= n;
- return (byte)(v >> 8);
- }
- }
- else
+ if (v != 0)
{
- this.UnreadByteStuffedByte();
+ byte n = (byte)((v & 0xff) - 1);
+ this.bits.UnreadBits -= n;
+ this.bits.Mask >>= n;
+ return (byte)(v >> 8);
}
-
- //}
- //catch (ShortHuffmanDataException) // TODO: This is actually never thrown!
- //{
- // if (this.bytes.UnreadableBytes != 0)
- // {
- // this.UnreadByteStuffedByte();
- // }
- //}
+ }
+ else
+ {
+ this.UnreadByteStuffedByte();
+ }
}
int code = 0;
@@ -666,37 +650,6 @@ namespace ImageSharp.Formats
return ret;
}
- ///
- /// Fills up the bytes buffer from the underlying stream.
- /// It should only be called when there are no unread bytes in bytes.
- ///
- //private void Fill()
- //{
- // if (this.bytes.I != this.bytes.J)
- // {
- // throw new ImageFormatException("Fill called when unread bytes exist.");
- // }
-
- // // Move the last 2 bytes to the start of the buffer, in case we need
- // // to call UnreadByteStuffedByte.
- // if (this.bytes.J > 2)
- // {
- // this.bytes.Buffer[0] = this.bytes.Buffer[this.bytes.J - 2];
- // this.bytes.Buffer[1] = this.bytes.Buffer[this.bytes.J - 1];
- // this.bytes.I = 2;
- // this.bytes.J = 2;
- // }
-
- // // Fill in the rest of the buffer.
- // int n = this.inputStream.Read(this.bytes.Buffer, this.bytes.J, this.bytes.Buffer.Length - this.bytes.J);
- // if (n == 0)
- // {
- // throw new EOFException();
- // }
-
- // this.bytes.J += n;
- //}
-
///
/// Undoes the most recent ReadByteStuffedByte call,
/// giving a byte of data back from bits to bytes. The Huffman look-up table
@@ -716,7 +669,6 @@ namespace ImageSharp.Formats
}
}
-
///
/// Returns the next byte, whether buffered or not buffered. It does not care about byte stuffing.
///
@@ -724,74 +676,9 @@ namespace ImageSharp.Formats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal byte ReadByte()
{
- return bytes.ReadByte(inputStream);
- //while (this.bytes.I == this.bytes.J)
- //{
- // this.Fill();
- //}
-
- //byte x = this.bytes.Buffer[this.bytes.I];
- //this.bytes.I++;
- //this.bytes.UnreadableBytes = 0;
- //return x;
+ return this.bytes.ReadByte(this.inputStream);
}
-
-
- ///
- /// ReadByteStuffedByte is like ReadByte but is for byte-stuffed Huffman data.
- ///
- /// The
- //internal byte ReadByteStuffedByte(out ErrorCodes errorCode)
- //{
- // byte x;
-
- // errorCode = ErrorCodes.NoError;
-
- // // Take the fast path if bytes.buf contains at least two bytes.
- // if (this.bytes.I + 2 <= this.bytes.J)
- // {
- // x = this.bytes.Buffer[this.bytes.I];
- // this.bytes.I++;
- // this.bytes.UnreadableBytes = 1;
- // if (x != JpegConstants.Markers.XFF)
- // {
- // return x;
- // }
-
- // if (this.bytes.Buffer[this.bytes.I] != 0x00)
- // {
- // errorCode = ErrorCodes.MissingFF00;
- // return 0;
- // //throw new MissingFF00Exception();
- // }
-
- // this.bytes.I++;
- // this.bytes.UnreadableBytes = 2;
- // return JpegConstants.Markers.XFF;
- // }
-
- // this.bytes.UnreadableBytes = 0;
-
- // x = this.ReadByte();
- // this.bytes.UnreadableBytes = 1;
- // if (x != JpegConstants.Markers.XFF)
- // {
- // return x;
- // }
-
- // x = this.ReadByte();
- // this.bytes.UnreadableBytes = 2;
- // if (x != 0x00)
- // {
- // errorCode = ErrorCodes.MissingFF00;
- // return 0;
- // //throw new MissingFF00Exception();
- // }
-
- // return JpegConstants.Markers.XFF;
- //}
-
///
/// Reads exactly length bytes into data. It does not care about byte stuffing.
///
@@ -805,7 +692,7 @@ namespace ImageSharp.Formats
{
if (this.bits.UnreadBits >= 8)
{
- UnreadByteStuffedByte();
+ this.UnreadByteStuffedByte();
}
this.bytes.UnreadableBytes = 0;
@@ -826,7 +713,7 @@ namespace ImageSharp.Formats
length -= this.bytes.J - this.bytes.I;
this.bytes.I += this.bytes.J - this.bytes.I;
- this.bytes.Fill(inputStream);
+ this.bytes.Fill(this.inputStream);
}
}
}
@@ -863,7 +750,7 @@ namespace ImageSharp.Formats
break;
}
- this.bytes.Fill(inputStream);
+ this.bytes.Fill(this.inputStream);
}
}
@@ -988,7 +875,8 @@ namespace ImageSharp.Formats
case 1:
{
// Cb.
- if (this.componentArray[0].HorizontalFactor % h != 0 || this.componentArray[0].VerticalFactor % v != 0)
+ if (this.componentArray[0].HorizontalFactor % h != 0
+ || this.componentArray[0].VerticalFactor % v != 0)
{
throw new ImageFormatException("Unsupported subsampling ratio");
}
@@ -999,7 +887,8 @@ namespace ImageSharp.Formats
case 2:
{
// Cr.
- if (this.componentArray[1].HorizontalFactor != h || this.componentArray[1].VerticalFactor != v)
+ if (this.componentArray[1].HorizontalFactor != h
+ || this.componentArray[1].VerticalFactor != v)
{
throw new ImageFormatException("Unsupported subsampling ratio");
}
@@ -1039,7 +928,8 @@ namespace ImageSharp.Formats
break;
case 3:
- if (this.componentArray[0].HorizontalFactor != h || this.componentArray[0].VerticalFactor != v)
+ if (this.componentArray[0].HorizontalFactor != h
+ || this.componentArray[0].VerticalFactor != v)
{
throw new ImageFormatException("Unsupported subsampling ratio");
}
@@ -1157,11 +1047,8 @@ namespace ImageSharp.Formats
remaining -= 13;
// TODO: We should be using constants for this.
- this.isJfif = this.temp[0] == 'J' &&
- this.temp[1] == 'F' &&
- this.temp[2] == 'I' &&
- this.temp[3] == 'F' &&
- this.temp[4] == '\x00';
+ this.isJfif = this.temp[0] == 'J' && this.temp[1] == 'F' && this.temp[2] == 'I' && this.temp[3] == 'F'
+ && this.temp[4] == '\x00';
if (this.isJfif)
{
@@ -1183,8 +1070,7 @@ namespace ImageSharp.Formats
/// The remaining bytes in the segment block.
/// The image.
private void ProcessApp1Marker(int remaining, Image image)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
if (remaining < 6)
{
@@ -1195,12 +1081,8 @@ namespace ImageSharp.Formats
byte[] profile = new byte[remaining];
this.ReadFull(profile, 0, remaining);
- if (profile[0] == 'E' &&
- profile[1] == 'x' &&
- profile[2] == 'i' &&
- profile[3] == 'f' &&
- profile[4] == '\0' &&
- profile[5] == '\0')
+ if (profile[0] == 'E' && profile[1] == 'x' && profile[2] == 'i' && profile[3] == 'f' && profile[4] == '\0'
+ && profile[5] == '\0')
{
image.ExifProfile = new ExifProfile(profile);
}
@@ -1223,11 +1105,8 @@ namespace ImageSharp.Formats
this.ReadFull(this.temp, 0, 12);
remaining -= 12;
- if (this.temp[0] == 'A' &&
- this.temp[1] == 'd' &&
- this.temp[2] == 'o' &&
- this.temp[3] == 'b' &&
- this.temp[4] == 'e')
+ if (this.temp[0] == 'A' && this.temp[1] == 'd' && this.temp[2] == 'o' && this.temp[3] == 'b'
+ && this.temp[4] == 'e')
{
this.adobeTransformValid = true;
this.adobeTransform = this.temp[11];
@@ -1248,12 +1127,12 @@ namespace ImageSharp.Formats
/// The image height.
/// The image.
private void ConvertFromCmyk(int width, int height, Image image)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
if (!this.adobeTransformValid)
{
- throw new ImageFormatException("Unknown color model: 4-component JPEG doesn't have Adobe APP14 metadata");
+ throw new ImageFormatException(
+ "Unknown color model: 4-component JPEG doesn't have Adobe APP14 metadata");
}
// If the 4-component JPEG image isn't explicitly marked as "Unknown (RGB
@@ -1274,21 +1153,21 @@ namespace ImageSharp.Formats
0,
height,
y =>
- {
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
-
- for (int x = 0; x < width; x++)
{
- byte yy = this.ycbcrImage.YChannel[yo + x];
- byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
- byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
+ int yo = this.ycbcrImage.GetRowYOffset(y);
+ int co = this.ycbcrImage.GetRowCOffset(y);
- TColor packed = default(TColor);
- this.PackCmyk(ref packed, yy, cb, cr, x, y);
- pixels[x, y] = packed;
- }
- });
+ for (int x = 0; x < width; x++)
+ {
+ byte yy = this.ycbcrImage.YChannel[yo + x];
+ byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
+ byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
+
+ TColor packed = default(TColor);
+ this.PackCmyk(ref packed, yy, cb, cr, x, y);
+ pixels[x, y] = packed;
+ }
+ });
}
this.AssignResolution(image);
@@ -1304,8 +1183,7 @@ namespace ImageSharp.Formats
/// The image height.
/// The image.
private void ConvertFromGrayScale(int width, int height, Image image)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
image.InitPixels(width, height);
@@ -1316,17 +1194,17 @@ namespace ImageSharp.Formats
height,
Bootstrapper.Instance.ParallelOptions,
y =>
- {
- int yoff = this.grayImage.GetRowOffset(y);
- for (int x = 0; x < width; x++)
{
- byte rgb = this.grayImage.Pixels[yoff + x];
+ int yoff = this.grayImage.GetRowOffset(y);
+ for (int x = 0; x < width; x++)
+ {
+ byte rgb = this.grayImage.Pixels[yoff + x];
- TColor packed = default(TColor);
- packed.PackFromBytes(rgb, rgb, rgb, 255);
- pixels[x, y] = packed;
- }
- });
+ TColor packed = default(TColor);
+ packed.PackFromBytes(rgb, rgb, rgb, 255);
+ pixels[x, y] = packed;
+ }
+ });
}
this.AssignResolution(image);
@@ -1341,8 +1219,7 @@ namespace ImageSharp.Formats
/// The image height.
/// The image.
private void ConvertFromYCbCr(int width, int height, Image image)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor;
image.InitPixels(width, height);
@@ -1354,27 +1231,26 @@ namespace ImageSharp.Formats
height,
Bootstrapper.Instance.ParallelOptions,
y =>
- {
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
-
- for (int x = 0; x < width; x++)
{
- byte yy = this.ycbcrImage.YChannel[yo + x];
- byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
- byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
+ int yo = this.ycbcrImage.GetRowYOffset(y);
+ int co = this.ycbcrImage.GetRowCOffset(y);
- TColor packed = default(TColor);
- PackYcbCr(ref packed, yy, cb, cr);
- pixels[x, y] = packed;
- }
- });
+ for (int x = 0; x < width; x++)
+ {
+ byte yy = this.ycbcrImage.YChannel[yo + x];
+ byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
+ byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
+
+ TColor packed = default(TColor);
+ PackYcbCr(ref packed, yy, cb, cr);
+ pixels[x, y] = packed;
+ }
+ });
}
this.AssignResolution(image);
}
-
///
/// Converts the image from the original RBG image pixels.
///
@@ -1384,8 +1260,7 @@ namespace ImageSharp.Formats
/// The height.
/// The image.
private void ConvertFromRGB(int width, int height, Image image)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
int scale = this.componentArray[0].HorizontalFactor / this.componentArray[1].HorizontalFactor;
image.InitPixels(width, height);
@@ -1397,21 +1272,21 @@ namespace ImageSharp.Formats
height,
Bootstrapper.Instance.ParallelOptions,
y =>
- {
- int yo = this.ycbcrImage.GetRowYOffset(y);
- int co = this.ycbcrImage.GetRowCOffset(y);
-
- for (int x = 0; x < width; x++)
{
- byte red = this.ycbcrImage.YChannel[yo + x];
- byte green = this.ycbcrImage.CbChannel[co + (x / scale)];
- byte blue = this.ycbcrImage.CrChannel[co + (x / scale)];
+ int yo = this.ycbcrImage.GetRowYOffset(y);
+ int co = this.ycbcrImage.GetRowCOffset(y);
- TColor packed = default(TColor);
- packed.PackFromBytes(red, green, blue, 255);
- pixels[x, y] = packed;
- }
- });
+ for (int x = 0; x < width; x++)
+ {
+ byte red = this.ycbcrImage.YChannel[yo + x];
+ byte green = this.ycbcrImage.CbChannel[co + (x / scale)];
+ byte blue = this.ycbcrImage.CrChannel[co + (x / scale)];
+
+ TColor packed = default(TColor);
+ packed.PackFromBytes(red, green, blue, 255);
+ pixels[x, y] = packed;
+ }
+ });
}
this.AssignResolution(image);
@@ -1424,8 +1299,7 @@ namespace ImageSharp.Formats
/// The packed format. uint, long, float.
/// The image to assign the resolution to.
private void AssignResolution(Image image)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
if (this.isJfif && this.horizontalResolution > 0 && this.verticalResolution > 0)
{
@@ -1476,7 +1350,7 @@ namespace ImageSharp.Formats
for (int i = 0; i < scanComponentCount; i++)
{
- ProcessScanImpl(i, ref scan[i], scan, ref totalHv);
+ this.ProcessScanImpl(i, ref scan[i], scan, ref totalHv);
}
// Section B.2.3 states that if there is more than one component then the
@@ -1546,7 +1420,8 @@ namespace ImageSharp.Formats
int compIndex = scan[i].Index;
if (this.progCoeffs[compIndex] == null)
{
- var size = mxx * myy * this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor;
+ var size = mxx * myy * this.componentArray[compIndex].HorizontalFactor
+ * this.componentArray[compIndex].VerticalFactor;
this.progCoeffs[compIndex] = new Block8x8F[size];
}
@@ -1573,7 +1448,7 @@ namespace ImageSharp.Formats
// Tricky way to copy contents of the Unzig static variable to the stack:
StackallocUnzigData unzigOnStack = new StackallocUnzigData();
int* unzigPtr = unzigOnStack.Data;
- Marshal.Copy(Unzig, 0, (IntPtr) unzigPtr, 64);
+ Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64);
for (int my = 0; my < myy; my++)
{
@@ -1585,7 +1460,6 @@ namespace ImageSharp.Formats
int hi = this.componentArray[compIndex].HorizontalFactor;
int vi = this.componentArray[compIndex].VerticalFactor;
-
for (int j = 0; j < hi * vi; j++)
{
// The blocks are traversed one MCU at a time. For 4:2:0 chroma
@@ -1630,43 +1504,59 @@ namespace ImageSharp.Formats
var qtIndex = this.componentArray[compIndex].Selector;
// TODO: Find a way to clean up this mess
-
+
fixed (Block8x8F* qtp = &this.quantizationTables[qtIndex])
{
if (this.isProgressive)
// Load the previous partially decoded coefficients, if applicable.
{
- blockIndex = ((@by*mxx)*hi) + bx;
+ this.blockIndex = ((@by * mxx) * hi) + bx;
- fixed (Block8x8F* bp = &this.progCoeffs[compIndex][blockIndex])
+ fixed (Block8x8F* bp = &this.progCoeffs[compIndex][this.blockIndex])
{
- ProcessBlockImpl(ah,
+ this.ProcessBlockImpl(
+ ah,
bp,
&temp1,
&temp2,
unzigPtr,
- scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, bx,
- qtp
- );
+ scan,
+ i,
+ zigStart,
+ zigEnd,
+ al,
+ dc,
+ compIndex,
+ @by,
+ mxx,
+ hi,
+ bx,
+ qtp);
}
}
else
{
b.Clear();
- ProcessBlockImpl(ah,
+ this.ProcessBlockImpl(
+ ah,
&b,
&temp1,
&temp2,
unzigPtr,
- scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi,
- bx, qtp
- );
+ scan,
+ i,
+ zigStart,
+ zigEnd,
+ al,
+ dc,
+ compIndex,
+ @by,
+ mxx,
+ hi,
+ bx,
+ qtp);
}
}
-
-
-
-
}
// for j
@@ -1709,14 +1599,22 @@ namespace ImageSharp.Formats
}
private void ProcessBlockImpl(
- int ah,
- Block8x8F* b,
+ int ah,
+ Block8x8F* b,
Block8x8F* temp1,
Block8x8F* temp2,
int* unzigPtr,
- Scan[] scan,
- int i, int zigStart, int zigEnd, int al,
- int[] dc, int compIndex, int @by, int mxx, int hi, int bx,
+ Scan[] scan,
+ int i,
+ int zigStart,
+ int zigEnd,
+ int al,
+ int[] dc,
+ int compIndex,
+ int @by,
+ int mxx,
+ int hi,
+ int bx,
Block8x8F* qt)
{
var huffmannIdx = AcTable * ThRowSize + scan[i].AcTableSelector;
@@ -1732,7 +1630,8 @@ namespace ImageSharp.Formats
zig++;
// Decode the DC coefficient, as specified in section F.2.2.1.
- byte value = this.DecodeHuffman(ref this.huffmanTrees[DcTable * ThRowSize + scan[i].DcTableSelector]);
+ byte value = this.DecodeHuffman(
+ ref this.huffmanTrees[DcTable * ThRowSize + scan[i].DcTableSelector]);
if (value > 16)
{
throw new ImageFormatException("Excessive DC component");
@@ -1741,7 +1640,7 @@ namespace ImageSharp.Formats
int deltaDC = this.bits.ReceiveExtend(value, this);
dc[compIndex] += deltaDC;
- //b[0] = dc[compIndex] << al;
+ // b[0] = dc[compIndex] << al;
Block8x8F.SetScalarAt(b, 0, dc[compIndex] << al);
}
@@ -1752,7 +1651,7 @@ namespace ImageSharp.Formats
else
{
// Decode the AC coefficients, as specified in section F.2.2.2.
- //Huffman huffv = ;
+ // Huffman huffv = ;
for (; zig <= zigEnd; zig++)
{
byte value = this.DecodeHuffman(ref this.huffmanTrees[huffmannIdx]);
@@ -1768,7 +1667,7 @@ namespace ImageSharp.Formats
int ac = this.bits.ReceiveExtend(val1, this);
- //b[Unzig[zig]] = ac << al;
+ // b[Unzig[zig]] = ac << al;
Block8x8F.SetScalarAt(b, unzigPtr[zig], ac << al);
}
else
@@ -1813,8 +1712,8 @@ namespace ImageSharp.Formats
// Dequantize, perform the inverse DCT and store the block to the image.
Block8x8F.UnZig(b, qt, unzigPtr);
-
- b->IDCTInto(ref *temp1, ref *temp2);
+
+ b->TransformIDCTInto(ref *temp1, ref *temp2);
byte[] dst;
int offset;
@@ -1861,10 +1760,10 @@ namespace ImageSharp.Formats
}
// Level shift by +128, clip to [0, 255], and write to dst.
-
+
temp1->CopyColorsTo(new MutableSpan(dst, offset), stride, temp2);
}
-
+
private void ProcessScanImpl(int i, ref Scan currentScan, Scan[] scan, ref int totalHv)
{
// Component selector.
@@ -1886,10 +1785,15 @@ namespace ImageSharp.Formats
currentScan.Index = (byte)compIndex;
- ProcessComponentImpl(i, ref currentScan, scan, ref totalHv, ref this.componentArray[compIndex]);
+ this.ProcessComponentImpl(i, ref currentScan, scan, ref totalHv, ref this.componentArray[compIndex]);
}
- private void ProcessComponentImpl(int i, ref Scan currentScan, Scan[] scan, ref int totalHv, ref Component currentComponent)
+ private void ProcessComponentImpl(
+ int i,
+ ref Scan currentScan,
+ Scan[] scan,
+ ref int totalHv,
+ ref Component currentComponent)
{
// Section B.2.3 states that "the value of Cs_j shall be different from
// the values of Cs_1 through Cs_(j-1)". Since we have previously
@@ -1904,7 +1808,6 @@ namespace ImageSharp.Formats
}
}
-
totalHv += currentComponent.HorizontalFactor * currentComponent.VerticalFactor;
currentScan.DcTableSelector = (byte)(this.temp[2 + (2 * i)] >> 4);
@@ -1925,6 +1828,7 @@ namespace ImageSharp.Formats
///
/// The block of coefficients
/// The Huffman tree
+ ///
/// The zig-zag start index
/// The zig-zag end index
/// The low transform offset
@@ -1941,11 +1845,11 @@ namespace ImageSharp.Formats
bool bit = this.DecodeBit();
if (bit)
{
- int stuff = (int) Block8x8F.GetScalarAt(b, 0);
+ int stuff = (int)Block8x8F.GetScalarAt(b, 0);
- //int stuff = (int)b[0];
+ // int stuff = (int)b[0];
stuff |= delta;
- //b[0] = stuff;
+ // b[0] = stuff;
Block8x8F.SetScalarAt(b, 0, stuff);
}
@@ -2145,7 +2049,8 @@ namespace ImageSharp.Formats
return true;
}
- return this.componentArray[0].Identifier == 'R' && this.componentArray[1].Identifier == 'G' && this.componentArray[2].Identifier == 'B';
+ return this.componentArray[0].Identifier == 'R' && this.componentArray[1].Identifier == 'G'
+ && this.componentArray[2].Identifier == 'B';
}
///
@@ -2160,8 +2065,7 @@ namespace ImageSharp.Formats
/// The cr chroma component.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void PackYcbCr(ref TColor packed, byte y, byte cb, byte cr)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
int ccb = cb - 128;
int ccr = cr - 128;
@@ -2186,8 +2090,7 @@ namespace ImageSharp.Formats
/// The x-position within the image.
/// The y-position within the image.
private void PackCmyk(ref TColor packed, byte y, byte cb, byte cr, int xx, int yy)
- where TColor : struct, IPackedPixel
- where TPacked : struct
+ where TColor : struct, IPackedPixel where TPacked : struct
{
// TODO: We can speed this up further with Vector4
int ccb = cb - 128;
@@ -2265,11 +2168,11 @@ namespace ImageSharp.Formats
public void Dispose()
{
- for (int i = 0; i < huffmanTrees.Length; i++)
+ for (int i = 0; i < this.huffmanTrees.Length; i++)
{
- huffmanTrees[i].Dispose();
+ this.huffmanTrees[i].Dispose();
}
- bytes.Dispose();
+ this.bytes.Dispose();
}
}
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
index 25d7af8284..524b84082e 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
@@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Formats.Jpg
public void Indexer()
{
float sum = 0;
- Measure(Times, () =>
+ this.Measure(Times, () =>
{
Block8x8F block = new Block8x8F();
@@ -44,8 +44,8 @@ namespace ImageSharp.Tests.Formats.Jpg
{
sum += block[i];
}
- });
- Assert.Equal(sum, 64f*63f*0.5f);
+ });
+ Assert.Equal(sum, 64f * 63f * 0.5f);
}
[Fact]
@@ -151,28 +151,12 @@ namespace ImageSharp.Tests.Formats.Jpg
v.CopyTo(mirror);
});
+
Assert.Equal(data, mirror);
//PrintLinearData((MutableSpan)mirror);
}
-
- [Fact]
- public void TransposeInplace()
- {
- float[] expected = Create8x8FloatData();
- ReferenceImplementations.Transpose8x8(expected);
-
- Block8x8F buffer = new Block8x8F();
- buffer.LoadFrom(Create8x8FloatData());
-
- buffer.TransposeInplace();
-
- float[] actual = new float[64];
- buffer.CopyTo(actual);
-
- Assert.Equal(expected, actual);
- }
-
+
[Fact]
public void TransposeInto()
{
@@ -231,7 +215,7 @@ namespace ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F();
- source.iDCT2D8x4_LeftPart(ref dest);
+ source.IDCT8x4_LeftPart(ref dest);
float[] actualDestArray = new float[64];
dest.CopyTo(actualDestArray);
@@ -256,7 +240,7 @@ namespace ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F();
- source.iDCT2D8x4_RightPart(ref dest);
+ source.IDCT8x4_RightPart(ref dest);
float[] actualDestArray = new float[64];
dest.CopyTo(actualDestArray);
@@ -302,7 +286,7 @@ namespace ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F();
Block8x8F tempBuffer = new Block8x8F();
- source.IDCTInto(ref dest, ref tempBuffer);
+ source.TransformIDCTInto(ref dest, ref tempBuffer);
float[] actualDestArray = new float[64];
dest.CopyTo(actualDestArray);
@@ -342,26 +326,7 @@ namespace ImageSharp.Tests.Formats.Jpg
Assert.Equal(colorsExpected, colorsActual);
}
-
- [Fact]
- public void CropInto()
- {
- Block8x8F block = new Block8x8F();
- block.LoadFrom(Create8x8FloatData());
-
- Block8x8F dest = new Block8x8F();
- block.CropInto(10, 20, ref dest);
-
- float[] array = new float[64];
- dest.CopyTo(array);
- PrintLinearData(array);
- foreach (float val in array)
- {
- Assert.InRange(val, 10, 20);
- }
-
- }
-
+
private static float[] Create8x8ColorCropTestData()
{
float[] result = new float[64];
@@ -376,7 +341,7 @@ namespace ImageSharp.Tests.Formats.Jpg
}
[Fact]
- public void ColorifyInto()
+ public void TransformByteConvetibleColorValuesInto()
{
Block8x8F block = new Block8x8F();
var input = Create8x8ColorCropTestData();
@@ -386,7 +351,7 @@ namespace ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F();
- block.ColorifyInto(ref dest);
+ block.TransformByteConvetibleColorValuesInto(ref dest);
float[] array = new float[64];
dest.CopyTo(array);
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs
index cf965e1ba0..b620c1d19f 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs
@@ -1,46 +1,57 @@
-using System;
-using System.Buffers;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using ImageSharp.Formats;
-
-// ReSharper disable InconsistentNaming
+// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests.Formats.Jpg
{
+ using System.Numerics;
+ using System.Runtime.CompilerServices;
+
+ using ImageSharp.Formats;
+
///
/// This class contains simplified (unefficient) reference implementations to produce verification data for unit tests
/// DCT code Ported from https://github.com/norishigefukushima/dct_simd
///
internal static class ReferenceImplementations
{
+ ///
+ /// Transpose 8x8 block stored linearly in a span (inplace)
+ ///
+ ///
internal static void Transpose8x8(MutableSpan data)
{
for (int i = 1; i < 8; i++)
{
- int i8 = i*8;
+ int i8 = i * 8;
for (int j = 0; j < i; j++)
{
float tmp = data[i8 + j];
- data[i8 + j] = data[j*8 + i];
- data[j*8 + i] = tmp;
+ data[i8 + j] = data[j * 8 + i];
+ data[j * 8 + i] = tmp;
}
}
}
+ ///
+ /// Transpose 8x8 block stored linearly in a span
+ ///
internal static void Transpose8x8(MutableSpan src, MutableSpan dest)
{
for (int i = 0; i < 8; i++)
{
- int i8 = i*8;
+ int i8 = i * 8;
for (int j = 0; j < 8; j++)
{
- dest[j*8 + i] = src[i8 + j];
+ dest[j * 8 + i] = src[i8 + j];
}
}
}
- internal static void iDCT1Dllm_32f(MutableSpan y, MutableSpan x)
+ ///
+ /// https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L200
+ ///
+ ///
+ ///
+ private static void iDCT1Dllm_32f(MutableSpan y, MutableSpan x)
{
float a0, a1, a2, a3, b0, b1, b2, b3;
float z0, z1, z2, z3, z4;
@@ -58,23 +69,23 @@ namespace ImageSharp.Tests.Formats.Jpg
z1 = y[3] + y[5];
z2 = y[3] + y[7];
z3 = y[1] + y[5];
- z4 = (z0 + z1)*r3;
+ z4 = (z0 + z1) * r3;
- z0 = z0*(-r3 + r7);
- z1 = z1*(-r3 - r1);
- z2 = z2*(-r3 - r5) + z4;
- z3 = z3*(-r3 + r5) + z4;
+ z0 = z0 * (-r3 + r7);
+ z1 = z1 * (-r3 - r1);
+ z2 = z2 * (-r3 - r5) + z4;
+ z3 = z3 * (-r3 + r5) + z4;
- b3 = y[7]*(-r1 + r3 + r5 - r7) + z0 + z2;
- b2 = y[5]*(r1 + r3 - r5 + r7) + z1 + z3;
- b1 = y[3]*(r1 + r3 + r5 - r7) + z1 + z2;
- b0 = y[1]*(r1 + r3 - r5 - r7) + z0 + z3;
+ b3 = y[7] * (-r1 + r3 + r5 - r7) + z0 + z2;
+ b2 = y[5] * (r1 + r3 - r5 + r7) + z1 + z3;
+ b1 = y[3] * (r1 + r3 + r5 - r7) + z1 + z2;
+ b0 = y[1] * (r1 + r3 - r5 - r7) + z0 + z3;
- z4 = (y[2] + y[6])*r6;
+ z4 = (y[2] + y[6]) * r6;
z0 = y[0] + y[4];
z1 = y[0] - y[4];
- z2 = z4 - y[6]*(r2 + r6);
- z3 = z4 + y[2]*(r2 - r6);
+ z2 = z4 - y[6] * (r2 + r6);
+ z3 = z4 + y[2] * (r2 - r6);
a0 = z0 + z3;
a3 = z0 - z3;
a1 = z1 + z2;
@@ -90,20 +101,27 @@ namespace ImageSharp.Tests.Formats.Jpg
x[4] = a3 - b3;
}
+ ///
+ /// Original: https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L239
+ /// Applyies IDCT transformation on "s" copying transformed values to "d", using temporal block "temp"
+ ///
+ ///
+ ///
+ ///
internal static void iDCT2D_llm(MutableSpan s, MutableSpan d, MutableSpan temp)
{
int j;
for (j = 0; j < 8; j++)
{
- iDCT1Dllm_32f(s.Slice(j*8), temp.Slice(j*8));
+ iDCT1Dllm_32f(s.Slice(j * 8), temp.Slice(j * 8));
}
Transpose8x8(temp, d);
for (j = 0; j < 8; j++)
{
- iDCT1Dllm_32f(d.Slice(j*8), temp.Slice(j*8));
+ iDCT1Dllm_32f(d.Slice(j * 8), temp.Slice(j * 8));
}
Transpose8x8(temp, d);
@@ -113,8 +131,6 @@ namespace ImageSharp.Tests.Formats.Jpg
d[j] *= 0.125f;
}
}
-
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector4 _mm_load_ps(MutableSpan src, int offset)
@@ -123,12 +139,6 @@ namespace ImageSharp.Tests.Formats.Jpg
return new Vector4(src[0], src[1], src[2], src[3]);
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Vector4 _mm_load_ps(MutableSpan src)
- {
- return new Vector4(src[0], src[1], src[2], src[3]);
- }
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void _mm_store_ps(MutableSpan dest, int offset, Vector4 src)
{
@@ -139,29 +149,37 @@ namespace ImageSharp.Tests.Formats.Jpg
dest[3] = src.W;
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void _mm_store_ps(MutableSpan dest, Vector4 src)
- {
- dest[0] = src.X;
- dest[1] = src.Y;
- dest[2] = src.Z;
- dest[3] = src.W;
- }
-
-
private static readonly Vector4 _1_175876 = new Vector4(1.175876f);
+
private static readonly Vector4 _1_961571 = new Vector4(-1.961571f);
+
private static readonly Vector4 _0_390181 = new Vector4(-0.390181f);
+
private static readonly Vector4 _0_899976 = new Vector4(-0.899976f);
+
private static readonly Vector4 _2_562915 = new Vector4(-2.562915f);
+
private static readonly Vector4 _0_298631 = new Vector4(0.298631f);
+
private static readonly Vector4 _2_053120 = new Vector4(2.053120f);
+
private static readonly Vector4 _3_072711 = new Vector4(3.072711f);
+
private static readonly Vector4 _1_501321 = new Vector4(1.501321f);
+
private static readonly Vector4 _0_541196 = new Vector4(0.541196f);
+
private static readonly Vector4 _1_847759 = new Vector4(-1.847759f);
+
private static readonly Vector4 _0_765367 = new Vector4(0.765367f);
+ ///
+ /// Original:
+ /// https://github.com/norishigefukushima/dct_simd/blob/master/dct/dct8x8_simd.cpp#L261
+ /// Does a part of the IDCT job on the given parts of the blocks
+ ///
+ ///
+ ///
internal static void iDCT2D8x4_32f(MutableSpan y, MutableSpan x)
{
/*
@@ -178,7 +196,7 @@ namespace ImageSharp.Tests.Formats.Jpg
6:
7: 0.275899
*/
-
+
Vector4 my1 = _mm_load_ps(y, 8);
Vector4 my7 = _mm_load_ps(y, 56);
Vector4 mz0 = my1 + my7;
@@ -188,16 +206,16 @@ namespace ImageSharp.Tests.Formats.Jpg
Vector4 my5 = _mm_load_ps(y, 40);
Vector4 mz1 = my3 + my5;
Vector4 mz3 = my1 + my5;
-
- Vector4 mz4 = ((mz0 + mz1)* _1_175876);
+
+ Vector4 mz4 = ((mz0 + mz1) * _1_175876);
//z0 = y[1] + y[7]; z1 = y[3] + y[5]; z2 = y[3] + y[7]; z3 = y[1] + y[5];
//z4 = (z0 + z1) * r[3];
-
- mz2 = mz2* _1_961571 + mz4;
- mz3 = mz3* _0_390181 + mz4;
- mz0 = mz0* _0_899976;
- mz1 = mz1* _2_562915;
-
+
+ mz2 = mz2 * _1_961571 + mz4;
+ mz3 = mz3 * _0_390181 + mz4;
+ mz0 = mz0 * _0_899976;
+ mz1 = mz1 * _2_562915;
+
/*
-0.899976
-2.562915
@@ -208,11 +226,10 @@ namespace ImageSharp.Tests.Formats.Jpg
z2 = z2 * (-r[3] - r[5]) + z4;
z3 = z3 * (-r[3] + r[5]) + z4;*/
-
- Vector4 mb3 = my7* _0_298631 + mz0 + mz2;
- Vector4 mb2 = my5* _2_053120 + mz1 + mz3;
- Vector4 mb1 = my3* _3_072711 + mz1 + mz2;
- Vector4 mb0 = my1* _1_501321 + mz0 + mz3;
+ Vector4 mb3 = my7 * _0_298631 + mz0 + mz2;
+ Vector4 mb2 = my5 * _2_053120 + mz1 + mz3;
+ Vector4 mb1 = my3 * _3_072711 + mz1 + mz2;
+ Vector4 mb0 = my1 * _1_501321 + mz0 + mz3;
/*
0.298631
@@ -227,14 +244,14 @@ namespace ImageSharp.Tests.Formats.Jpg
Vector4 my2 = _mm_load_ps(y, 16);
Vector4 my6 = _mm_load_ps(y, 48);
- mz4 = (my2 + my6)* _0_541196;
+ mz4 = (my2 + my6) * _0_541196;
Vector4 my0 = _mm_load_ps(y, 0);
Vector4 my4 = _mm_load_ps(y, 32);
mz0 = my0 + my4;
mz1 = my0 - my4;
- mz2 = mz4 + my6* _1_847759;
- mz3 = mz4 + my2* _0_765367;
+ mz2 = mz4 + my6 * _1_847759;
+ mz3 = mz4 + my2 * _0_765367;
my0 = mz0 + mz3;
my3 = mz0 - mz3;
@@ -275,55 +292,12 @@ namespace ImageSharp.Tests.Formats.Jpg
*/
}
- internal static void iDCT8x8_llm_sse(MutableSpan s, MutableSpan d, MutableSpan temp)
- {
- Transpose8x8(s, temp);
- iDCT2D8x4_32f(temp, d);
-
- iDCT2D8x4_32f(temp.Slice(4), d.Slice(4));
-
- Transpose8x8(d, temp);
-
- iDCT2D8x4_32f(temp, d);
-
- iDCT2D8x4_32f(temp.Slice(4), d.Slice(4));
-
- Vector4 c = new Vector4(0.1250f);
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//0
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//1
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//2
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//3
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//4
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//5
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//6
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//7
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//8
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//9
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//10
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//11
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//12
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//13
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//14
-
- _mm_store_ps(d, (_mm_load_ps(d)*c));d.AddOffset(4);//15
- }
-
-
+ ///
+ /// Copies color values from block to the destination image buffer.
+ ///
+ ///
+ ///
+ ///
internal static unsafe void CopyColorsTo(ref Block8x8F block, MutableSpan buffer, int stride)
{
fixed (Block8x8F* p = &block)
@@ -356,9 +330,6 @@ namespace ImageSharp.Tests.Formats.Jpg
}
}
}
-
-
}
-
}
}
\ No newline at end of file