diff --git a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
index f13481882..a5c9be547 100644
--- a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs
@@ -31,54 +31,11 @@ namespace ImageSharp.Formats
39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
};
- ///
- /// Counts the number of bits needed to hold an integer.
- ///
- private readonly byte[] bitCountLut =
- {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8,
- };
-
- ///
- /// The unscaled quantization tables in zig-zag order. Each
- /// encoder copies and scales the tables according to its quality parameter.
- /// The values are derived from section K.1 after converting from natural to
- /// zig-zag order.
- ///
- private readonly byte[,] unscaledQuant =
- {
- {
- // Luminance.
- 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
- 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51,
- 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81,
- 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92,
- 101, 103, 99,
- },
- {
- // Chrominance.
- 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- }
- };
-
///
/// The Huffman encoding specifications.
/// This encoder uses the same Huffman encoding for all images.
///
- private readonly HuffmanSpec[] huffmanSpec =
+ private static readonly HuffmanSpec[] TheHuffmanSpecs =
{
// Luminance DC.
new HuffmanSpec(
@@ -149,6 +106,54 @@ namespace ImageSharp.Formats
})
};
+ ///
+ /// The compiled representations of theHuffmanSpec.
+ ///
+ private static readonly HuffmanLut[] TheHuffmanLut = new HuffmanLut[4];
+
+ ///
+ /// Counts the number of bits needed to hold an integer.
+ ///
+ private readonly byte[] bitCountLut =
+ {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8,
+ };
+
+ ///
+ /// The unscaled quantization tables in zig-zag order. Each
+ /// encoder copies and scales the tables according to its quality parameter.
+ /// The values are derived from section K.1 after converting from natural to
+ /// zig-zag order.
+ ///
+ private readonly byte[,] unscaledQuant =
+ {
+ {
+ // Luminance.
+ 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40,
+ 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51,
+ 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81,
+ 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92,
+ 101, 103, 99,
+ },
+ {
+ // Chrominance.
+ 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
+ }
+ };
+
///
/// A scratch buffer to reduce allocations.
///
@@ -159,11 +164,6 @@ namespace ImageSharp.Formats
///
private readonly byte[][] quant = new byte[NQuantIndex][];
- ///
- /// The compiled representations of theHuffmanSpec.
- ///
- private readonly HuffmanLut[] theHuffmanLut = new HuffmanLut[4];
-
///
/// The SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes:
/// - the marker length "\x00\x0c",
@@ -211,6 +211,18 @@ namespace ImageSharp.Formats
///
private JpegSubsample subsample;
+ ///
+ /// Initializes static members of the class.
+ ///
+ static JpegEncoderCore()
+ {
+ // Initialize the Huffman tables
+ for (int i = 0; i < TheHuffmanSpecs.Length; i++)
+ {
+ TheHuffmanLut[i] = new HuffmanLut(TheHuffmanSpecs[i]);
+ }
+ }
+
///
/// Enumerates the Huffman tables
///
@@ -280,12 +292,6 @@ namespace ImageSharp.Formats
this.outputStream = stream;
this.subsample = sample;
- // TODO: This should be static should it not?
- for (int i = 0; i < this.huffmanSpec.Length; i++)
- {
- this.theHuffmanLut[i] = new HuffmanLut(this.huffmanSpec[i]);
- }
-
for (int i = 0; i < NQuantIndex; i++)
{
this.quant[i] = new byte[Block.BlockSize];
@@ -425,7 +431,7 @@ namespace ImageSharp.Formats
/// The value to encode.
private void EmitHuff(HuffIndex index, int value)
{
- uint x = this.theHuffmanLut[(int)index].Values[value];
+ uint x = TheHuffmanLut[(int)index].Values[value];
this.Emit(x & ((1 << 24) - 1), x >> 24);
}
@@ -730,12 +736,12 @@ namespace ImageSharp.Formats
{
byte[] headers = { 0x00, 0x10, 0x01, 0x11 };
int markerlen = 2;
- HuffmanSpec[] specs = this.huffmanSpec;
+ HuffmanSpec[] specs = TheHuffmanSpecs;
if (componentCount == 1)
{
// Drop the Chrominance tables.
- specs = new[] { this.huffmanSpec[0], this.huffmanSpec[1] };
+ specs = new[] { TheHuffmanSpecs[0], TheHuffmanSpecs[1] };
}
foreach (HuffmanSpec s in specs)
diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs
index 2d36e2da8..855c3a7af 100644
--- a/tests/ImageSharp.Tests/FileTestBase.cs
+++ b/tests/ImageSharp.Tests/FileTestBase.cs
@@ -22,11 +22,11 @@ namespace ImageSharp.Tests
//new TestFile(TestImages.Png.Pd),
new TestFile(TestImages.Jpeg.Floorplan), // Perf: Enable for local testing only
new TestFile(TestImages.Jpeg.Calliphora),
- //new TestFile(TestImages.Jpg.Cmyk), // Perf: Enable for local testing only
- //new TestFile(TestImages.Jpg.Turtle),
- //new TestFile(TestImages.Jpg.Fb), // Perf: Enable for local testing only
- //new TestFile(TestImages.Jpg.Progress), // Perf: Enable for local testing only
- //new TestFile(TestImages.Jpg.Gamma_dalai_lama_gray). // Perf: Enable for local testing only
+ //new TestFile(TestImages.Jpeg.Cmyk), // Perf: Enable for local testing only
+ new TestFile(TestImages.Jpeg.Turtle),
+ //new TestFile(TestImages.Jpeg.Fb), // Perf: Enable for local testing only
+ //new TestFile(TestImages.Jpeg.Progress), // Perf: Enable for local testing only
+ //new TestFile(TestImages.Jpeg.Gamma_dalai_lama_gray). // Perf: Enable for local testing only
new TestFile(TestImages.Bmp.Car),
//new TestFile(TestImages.Bmp.Neg_height), // Perf: Enable for local testing only
//new TestFile(TestImages.Png.Blur), // Perf: Enable for local testing only