From ee5d3ac38fca5263ca8c5d004aea5e61c2173b3c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 10 Nov 2016 02:27:55 +0100 Subject: [PATCH] minor cache optimiziation + benchmarks --- ImageSharp.46.sln | 6 + .../Formats/Jpg/Components/Block.cs | 21 +- .../Formats/Jpg/Components/Component.cs | 10 +- .../Formats/Jpg/Components/FDCT.cs | 2 +- .../Formats/Jpg/Components/Huffman.cs | 29 +- .../Formats/Jpg/Components/IDCT.cs | 6 +- .../Formats/Jpg/JpegDecoderCore.cs | 628 ++++++++++-------- .../Formats/Jpg/JpegEncoderCore.cs | 23 +- src/ImageSharp46/ImageSharp46.csproj | 5 +- src/ImageSharp46/packages.config | 1 + tests/ConsoleBenchmark/App.config | 22 + .../ConsoleBenchmark/ConsoleBenchmark.csproj | 89 +++ tests/ConsoleBenchmark/Program.cs | 36 + .../Properties/AssemblyInfo.cs | 36 + .../TestImages/Formats/Bmp/Car.bmp | 3 + .../TestImages/Formats/Bmp/F.bmp | 3 + .../TestImages/Formats/Bmp/neg_height.bmp | 3 + .../TestImages/Formats/Gif/giphy.gif | 3 + .../TestImages/Formats/Gif/rings.gif | 3 + .../TestImages/Formats/Jpg/Calliphora.jpg | 3 + .../TestImages/Formats/Jpg/Floorplan.jpeg | 3 + .../TestImages/Formats/Jpg/cmyk.jpg | 3 + .../TestImages/Formats/Jpg/exif.jpg | 3 + .../TestImages/Formats/Jpg/fb.jpg | 3 + .../Formats/Jpg/gamma_dalai_lama_gray.jpg | 3 + .../TestImages/Formats/Jpg/progress.jpg | 3 + .../TestImages/Formats/Jpg/turtle.jpg | 3 + .../TestImages/Formats/Png/blur.png | 3 + .../TestImages/Formats/Png/indexed.png | 3 + .../TestImages/Formats/Png/pd.png | 3 + .../TestImages/Formats/Png/pl.png | 3 + .../TestImages/Formats/Png/splash.png | 3 + tests/ConsoleBenchmark/packages.config | 8 + .../ImageSharp.Benchmarks/Image/DecodeJpeg.cs | 22 +- .../{DecodeJpeg.cs => DecodeJpegBenchmark.cs} | 6 +- .../ImageSharp.Tests46.csproj | 20 +- tests/ImageSharp.Tests46/JpegSandbox.cs | 38 +- tests/ImageSharp.Tests46/TestImages.cs | 23 +- tests/ImageSharp.Tests46/packages.config | 2 + 39 files changed, 735 insertions(+), 352 deletions(-) create mode 100644 tests/ConsoleBenchmark/App.config create mode 100644 tests/ConsoleBenchmark/ConsoleBenchmark.csproj create mode 100644 tests/ConsoleBenchmark/Program.cs create mode 100644 tests/ConsoleBenchmark/Properties/AssemblyInfo.cs create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Bmp/Car.bmp create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Bmp/F.bmp create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Bmp/neg_height.bmp create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Gif/giphy.gif create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Gif/rings.gif create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/Calliphora.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/Floorplan.jpeg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/cmyk.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/exif.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/fb.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/progress.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Jpg/turtle.jpg create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Png/blur.png create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Png/indexed.png create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Png/pd.png create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Png/pl.png create mode 100644 tests/ConsoleBenchmark/TestImages/Formats/Png/splash.png create mode 100644 tests/ConsoleBenchmark/packages.config rename tests/ImageSharp.Tests46/Benchmark/{DecodeJpeg.cs => DecodeJpegBenchmark.cs} (91%) diff --git a/ImageSharp.46.sln b/ImageSharp.46.sln index fe112b9ea..270d391cc 100644 --- a/ImageSharp.46.sln +++ b/ImageSharp.46.sln @@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp46", "src\ImageSh EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Tests46", "tests\ImageSharp.Tests46\ImageSharp.Tests46.csproj", "{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleBenchmark", "tests\ConsoleBenchmark\ConsoleBenchmark.csproj", "{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +23,10 @@ Global {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Debug|Any CPU.Build.0 = Debug|Any CPU {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Release|Any CPU.ActiveCfg = Release|Any CPU {635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Release|Any CPU.Build.0 = Release|Any CPU + {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ImageSharp46/Formats/Jpg/Components/Block.cs b/src/ImageSharp46/Formats/Jpg/Components/Block.cs index 8bc5a861c..168413292 100644 --- a/src/ImageSharp46/Formats/Jpg/Components/Block.cs +++ b/src/ImageSharp46/Formats/Jpg/Components/Block.cs @@ -3,12 +3,14 @@ // Licensed under the Apache License, Version 2.0. // +using System.Buffers; + namespace ImageSharp.Formats { /// /// Represents an 8x8 block of coefficients to transform and encode. /// - internal class Block + internal struct Block { /// /// Gets the size of the block. @@ -18,16 +20,23 @@ namespace ImageSharp.Formats /// /// The array of block data. /// - private readonly int[] data; + public int[] Data; /// /// Initializes a new instance of the class. /// - public Block() + //public Block() + //{ + // this.data = new int[BlockSize]; + //} + + public void Init() { - this.data = new int[BlockSize]; + this.Data = new int[BlockSize]; } + public bool IsInitialized => this.Data != null; + /// /// Gets the pixel data at the given block index. /// @@ -37,8 +46,8 @@ namespace ImageSharp.Formats /// public int this[int index] { - get { return this.data[index]; } - set { this.data[index] = value; } + get { return this.Data[index]; } + set { this.Data[index] = value; } } } } diff --git a/src/ImageSharp46/Formats/Jpg/Components/Component.cs b/src/ImageSharp46/Formats/Jpg/Components/Component.cs index f56b6d513..f70dbff3f 100644 --- a/src/ImageSharp46/Formats/Jpg/Components/Component.cs +++ b/src/ImageSharp46/Formats/Jpg/Components/Component.cs @@ -8,26 +8,26 @@ namespace ImageSharp.Formats /// /// Represents a single color component /// - internal class Component + internal struct Component { /// /// Gets or sets the horizontal sampling factor. /// - public int HorizontalFactor { get; set; } + public int HorizontalFactor; /// /// Gets or sets the vertical sampling factor. /// - public int VerticalFactor { get; set; } + public int VerticalFactor; /// /// Gets or sets the identifier /// - public byte Identifier { get; set; } + public byte Identifier; /// /// Gets or sets the quantization table destination selector. /// - public byte Selector { get; set; } + public byte Selector; } } diff --git a/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs index cd27b9e73..13ce80f55 100644 --- a/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs +++ b/src/ImageSharp46/Formats/Jpg/Components/FDCT.cs @@ -45,7 +45,7 @@ namespace ImageSharp.Formats /// Performs a forward DCT on an 8x8 block of coefficients, including a level shift. /// /// The block of coefficients. - public static void Transform(Block block) + public static void Transform(ref Block block) { // Pass 1: process rows. for (int y = 0; y < 8; y++) diff --git a/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs b/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs index 2c38cfd38..cef99ea1a 100644 --- a/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs +++ b/src/ImageSharp46/Formats/Jpg/Components/Huffman.cs @@ -8,7 +8,7 @@ namespace ImageSharp.Formats /// /// Represents a Huffman tree /// - internal class Huffman + internal struct Huffman { /// /// Initializes a new instance of the class. @@ -16,20 +16,29 @@ namespace ImageSharp.Formats /// The log-2 size of the Huffman decoder's look-up table. /// The maximum (inclusive) number of codes in a Huffman tree. /// The maximum (inclusive) number of bits in a Huffman code. - public Huffman(int lutSize, int maxNCodes, int maxCodeLength) + //public Huffman(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.Length = 0; + //} + + 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.Length = 0; } /// /// Gets or sets the number of codes in the tree. /// - public int Length { get; set; } + public int Length; /// /// Gets the look-up table for the next LutSize bits in the bit-stream. @@ -37,28 +46,30 @@ namespace ImageSharp.Formats /// are 1 plus the code length, or 0 if the value is too large to fit in /// lutSize bits. /// - public ushort[] Lut { get; } + public ushort[] Lut; /// /// Gets the the decoded values, sorted by their encoding. /// - public byte[] Values { get; } + public byte[] Values; /// /// Gets the array of minimum codes. /// MinCodes[i] is the minimum code of length i, or -1 if there are no codes of that length. /// - public int[] MinCodes { get; } + public int[] MinCodes; /// /// Gets the array of maximum codes. /// MaxCodes[i] is the maximum code of length i, or -1 if there are no codes of that length. /// - public int[] MaxCodes { get; } + public int[] MaxCodes; /// /// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i]. /// - public int[] Indices { get; } + public int[] Indices; } + + } \ No newline at end of file diff --git a/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs index bc145779a..8bbbae357 100644 --- a/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs +++ b/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs @@ -3,6 +3,8 @@ // Licensed under the Apache License, Version 2.0. // +using System.Numerics; + namespace ImageSharp.Formats { /// @@ -39,8 +41,10 @@ namespace ImageSharp.Formats /// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984. /// /// The source block of coefficients - public static void Transform(Block src) + public static void Transform(ref Block block) { + + var src = block.Data; // Horizontal 1-D IDCT. for (int y = 0; y < 8; y++) { diff --git a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs index a1e596649..d64803eb4 100644 --- a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs +++ b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs @@ -44,6 +44,8 @@ namespace ImageSharp.Formats /// private const int MaxTh = 3; + private const int ThRowSize = MaxTh + 1; + /// /// The maximum number of quantization tables /// @@ -85,7 +87,9 @@ namespace ImageSharp.Formats /// /// The huffman trees /// - private readonly Huffman[,] huffmanTrees; + //private readonly Huffman[,] huffmanTrees; + + private readonly Huffman[] huffmanTrees; /// /// Quantization tables, in zigzag order. @@ -187,12 +191,16 @@ namespace ImageSharp.Formats /// private short verticalResolution; + private int blockIndex; + /// /// Initializes a new instance of the class. /// public JpegDecoderCore() { - this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1]; + //this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1]; + this.huffmanTrees = new Huffman[(MaxTc + 1)*(MaxTh + 1)]; + this.quantizationTables = new Block[MaxTq + 1]; this.temp = new byte[2 * Block.BlockSize]; this.componentArray = new Component[MaxComponents]; @@ -201,23 +209,26 @@ namespace ImageSharp.Formats this.bytes = new Bytes(); // TODO: This looks like it could be static. + for (int i = 0; i < MaxTc + 1; i++) { for (int j = 0; j < MaxTh + 1; j++) { - this.huffmanTrees[i, j] = new Huffman(LutSize, MaxNCodes, MaxCodeLength); + //this.huffmanTrees[i, j].Init(LutSize, MaxNCodes, MaxCodeLength); + this.huffmanTrees[i* ThRowSize + j].Init(LutSize, MaxNCodes, MaxCodeLength); } } for (int i = 0; i < this.quantizationTables.Length; i++) { - this.quantizationTables[i] = new Block(); + //this.quantizationTables[i] = new Block(); + this.quantizationTables[i].Init(); } - for (int i = 0; i < this.componentArray.Length; i++) - { - this.componentArray[i] = new Component(); - } + //for (int i = 0; i < this.componentArray.Length; i++) + //{ + // this.componentArray[i] = new Component(); + //} } @@ -502,92 +513,96 @@ namespace ImageSharp.Formats throw new ImageFormatException("Bad Th value"); } - Huffman huffman = this.huffmanTrees[tc, th]; + ProcessDefineHuffmanTablesMarkerLoop(ref this.huffmanTrees[tc* ThRowSize + th], ref 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. - huffman.Length = 0; + private void ProcessDefineHuffmanTablesMarkerLoop(ref Huffman huffman, ref int remaining) + { - int[] ncodes = new int[MaxCodeLength]; - for (int i = 0; i < ncodes.Length; i++) - { - ncodes[i] = this.temp[i + 1]; - huffman.Length += ncodes[i]; - } + // 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. + huffman.Length = 0; - if (huffman.Length == 0) - { - throw new ImageFormatException("Huffman table has zero length"); - } + int[] ncodes = new int[MaxCodeLength]; + for (int i = 0; i < ncodes.Length; i++) + { + ncodes[i] = this.temp[i + 1]; + huffman.Length += ncodes[i]; + } - if (huffman.Length > MaxNCodes) - { - throw new ImageFormatException("Huffman table has excessive length"); - } + if (huffman.Length == 0) + { + throw new ImageFormatException("Huffman table has zero length"); + } - remaining -= huffman.Length + 17; - if (remaining < 0) - { - throw new ImageFormatException("DHT has wrong length"); - } + if (huffman.Length > MaxNCodes) + { + throw new ImageFormatException("Huffman table has excessive length"); + } - this.ReadFull(huffman.Values, 0, huffman.Length); + remaining -= huffman.Length + 17; + if (remaining < 0) + { + throw new ImageFormatException("DHT has wrong length"); + } - // Derive the look-up table. - for (int i = 0; i < huffman.Lut.Length; i++) - { - huffman.Lut[i] = 0; - } + this.ReadFull(huffman.Values, 0, huffman.Length); + + // Derive the look-up table. + for (int i = 0; i < huffman.Lut.Length; i++) + { + huffman.Lut[i] = 0; + } - uint x = 0, code = 0; + uint x = 0, code = 0; - for (int i = 0; i < LutSize; i++) + for (int i = 0; i < LutSize; i++) + { + code <<= 1; + + for (int j = 0; j < ncodes[i]; j++) { - code <<= 1; + // The codeLength is 1+i, so shift code by 8-(1+i) to + // calculate the high bits for every 8-bit sequence + // whose codeLength's high bits matches code. + // The high 8 bits of lutValue are the encoded value. + // The low 8 bits are 1 plus the codeLength. + byte base2 = (byte) (code << (7 - i)); + ushort lutValue = (ushort) ((huffman.Values[x] << 8) | (2 + i)); - for (int j = 0; j < ncodes[i]; j++) + for (int k = 0; k < 1 << (7 - i); k++) { - // The codeLength is 1+i, so shift code by 8-(1+i) to - // calculate the high bits for every 8-bit sequence - // whose codeLength's high bits matches code. - // The high 8 bits of lutValue are the encoded value. - // The low 8 bits are 1 plus the codeLength. - byte base2 = (byte)(code << (7 - i)); - ushort lutValue = (ushort)((huffman.Values[x] << 8) | (2 + i)); - - for (int k = 0; k < 1 << (7 - i); k++) - { - huffman.Lut[base2 | k] = lutValue; - } - - code++; - x++; + huffman.Lut[base2 | k] = lutValue; } + + code++; + x++; } + } - // Derive minCodes, maxCodes, and indices. - int c = 0, index = 0; - for (int i = 0; i < ncodes.Length; i++) + // Derive minCodes, maxCodes, and indices. + int c = 0, index = 0; + for (int i = 0; i < ncodes.Length; i++) + { + int nc = ncodes[i]; + if (nc == 0) { - int nc = ncodes[i]; - if (nc == 0) - { - huffman.MinCodes[i] = -1; - huffman.MaxCodes[i] = -1; - huffman.Indices[i] = -1; - } - else - { - huffman.MinCodes[i] = c; - huffman.MaxCodes[i] = c + nc - 1; - huffman.Indices[i] = index; - c += nc; - index += nc; - } - - c <<= 1; + huffman.MinCodes[i] = -1; + huffman.MaxCodes[i] = -1; + huffman.Indices[i] = -1; + } + else + { + huffman.MinCodes[i] = c; + huffman.MaxCodes[i] = c + nc - 1; + huffman.Indices[i] = index; + c += nc; + index += nc; } + + c <<= 1; } } @@ -596,7 +611,7 @@ namespace ImageSharp.Formats /// /// The huffman value /// The - private byte DecodeHuffman(Huffman huffman) + private byte DecodeHuffman(ref Huffman huffman) { if (huffman.Length == 0) { @@ -1480,7 +1495,8 @@ namespace ImageSharp.Formats this.ReadFull(this.temp, 0, remaining); byte scanComponentCount = this.temp[0]; - if (remaining != 4 + (2 * scanComponentCount)) + int scanComponentCountBy2 = 2 * scanComponentCount; + if (remaining != 4 + scanComponentCountBy2) { throw new ImageFormatException("SOS length inconsistent with number of components"); } @@ -1490,51 +1506,7 @@ namespace ImageSharp.Formats for (int i = 0; i < scanComponentCount; i++) { - // Component selector. - int cs = this.temp[1 + (2 * i)]; - int compIndex = -1; - for (int j = 0; j < this.componentCount; j++) - { - Component compv = this.componentArray[j]; - if (cs == compv.Identifier) - { - compIndex = j; - } - } - - if (compIndex < 0) - { - throw new ImageFormatException("Unknown component selector"); - } - - scan[i].Index = (byte)compIndex; - - // 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 - // verified that a frame's component identifiers (C_i values in section - // B.2.2) are unique, it suffices to check that the implicit indexes - // into comp are unique. - for (int j = 0; j < i; j++) - { - if (scan[i].Index == scan[j].Index) - { - throw new ImageFormatException("Repeated component selector"); - } - } - - totalHv += this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor; - - scan[i].DcTableSelector = (byte)(this.temp[2 + (2 * i)] >> 4); - if (scan[i].DcTableSelector > MaxTh) - { - throw new ImageFormatException("Bad DC table selector value"); - } - - scan[i].AcTableSelector = (byte)(this.temp[2 + (2 * i)] & 0x0f); - if (scan[i].AcTableSelector > MaxTh) - { - throw new ImageFormatException("Bad AC table selector value"); - } + ProcessScanImpl(i, ref scan[i], scan, ref totalHv); } // Section B.2.3 states that if there is more than one component then the @@ -1565,10 +1537,10 @@ namespace ImageSharp.Formats if (this.isProgressive) { - zigStart = this.temp[1 + (2 * scanComponentCount)]; - zigEnd = this.temp[2 + (2 * scanComponentCount)]; - ah = this.temp[3 + (2 * scanComponentCount)] >> 4; - al = this.temp[3 + (2 * scanComponentCount)] & 0x0f; + zigStart = this.temp[1 + scanComponentCountBy2]; + zigEnd = this.temp[2 + scanComponentCountBy2]; + ah = this.temp[3 + scanComponentCountBy2] >> 4; + al = this.temp[3 + scanComponentCountBy2] & 0x0f; if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || Block.BlockSize <= zigEnd) { @@ -1608,7 +1580,7 @@ namespace ImageSharp.Formats for (int j = 0; j < this.progCoeffs[compIndex].Length; j++) { - this.progCoeffs[compIndex][j] = new Block(); + this.progCoeffs[compIndex][j].Init(); } } } @@ -1620,7 +1592,7 @@ namespace ImageSharp.Formats byte expectedRst = JpegConstants.Markers.RST0; // b is the decoded coefficients block, in natural (not zig-zag) order. - Block b; + //Block b; int[] dc = new int[MaxComponents]; // bx and by are the location of the current block, in units of 8x8 @@ -1636,7 +1608,7 @@ namespace ImageSharp.Formats int compIndex = scan[i].Index; int hi = this.componentArray[compIndex].HorizontalFactor; int vi = this.componentArray[compIndex].VerticalFactor; - Block qt = this.quantizationTables[this.componentArray[compIndex].Selector]; + for (int j = 0; j < hi * vi; j++) { @@ -1679,168 +1651,28 @@ namespace ImageSharp.Formats } } + var qtIndex = this.componentArray[compIndex].Selector; + // Load the previous partially decoded coefficients, if applicable. - b = this.isProgressive ? this.progCoeffs[compIndex][((@by * mxx) * hi) + bx] : new Block(); - - if (ah != 0) - { - this.Refine(b, this.huffmanTrees[AcTable, scan[i].AcTableSelector], zigStart, zigEnd, 1 << al); - } - else - { - int zig = zigStart; - if (zig == 0) - { - zig++; - - // Decode the DC coefficient, as specified in section F.2.2.1. - byte value = this.DecodeHuffman(this.huffmanTrees[DcTable, scan[i].DcTableSelector]); - if (value > 16) - { - throw new ImageFormatException("Excessive DC component"); - } - - int deltaDC = this.ReceiveExtend(value); - dc[compIndex] += deltaDC; - b[0] = dc[compIndex] << al; - } - - if (zig <= zigEnd && this.eobRun > 0) - { - this.eobRun--; - } - else - { - // Decode the AC coefficients, as specified in section F.2.2.2. - Huffman huffv = this.huffmanTrees[AcTable, scan[i].AcTableSelector]; - for (; zig <= zigEnd; zig++) - { - byte value = this.DecodeHuffman(huffv); - byte val0 = (byte)(value >> 4); - byte val1 = (byte)(value & 0x0f); - if (val1 != 0) - { - zig += val0; - if (zig > zigEnd) - { - break; - } - - int ac = this.ReceiveExtend(val1); - b[Unzig[zig]] = ac << al; - } - else - { - if (val0 != 0x0f) - { - this.eobRun = (ushort)(1 << val0); - if (val0 != 0) - { - this.eobRun |= (ushort)this.DecodeBits(val0); - } - - this.eobRun--; - break; - } - - zig += 0x0f; - } - } - } - } + + //b = this.isProgressive ? this.progCoeffs[compIndex][blockIndex] : new Block(); if (this.isProgressive) { - if (zigEnd != Block.BlockSize - 1 || al != 0) - { - // We haven't completely decoded this 8x8 block. Save the coefficients. - this.progCoeffs[compIndex][((by * mxx) * hi) + bx] = b; - - // At this point, we could execute the rest of the loop body to dequantize and - // perform the inverse DCT, to save early stages of a progressive image to the - // *image.YCbCr buffers (the whole point of progressive encoding), but in Go, - // the jpeg.Decode function does not return until the entire image is decoded, - // so we "continue" here to avoid wasted computation. - continue; - } - } - - // Dequantize, perform the inverse DCT and store the block to the image. - for (int zig = 0; zig < Block.BlockSize; zig++) - { - b[Unzig[zig]] *= qt[zig]; - } - - IDCT.Transform(b); - - byte[] dst; - int offset; - int stride; - - if (this.componentCount == 1) - { - dst = this.grayImage.Pixels; - stride = this.grayImage.Stride; - offset = this.grayImage.Offset + (8 * ((by * this.grayImage.Stride) + bx)); + blockIndex = ((@by * mxx) * hi) + bx; + ProcessBlockImpl(ah, + ref this.progCoeffs[compIndex][blockIndex], + scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, bx, + ref this.quantizationTables[qtIndex] + ); } else { - switch (compIndex) - { - case 0: - dst = this.ycbcrImage.YChannel; - stride = this.ycbcrImage.YStride; - offset = this.ycbcrImage.YOffset + (8 * ((by * this.ycbcrImage.YStride) + bx)); - break; - - case 1: - dst = this.ycbcrImage.CbChannel; - stride = this.ycbcrImage.CStride; - offset = this.ycbcrImage.COffset + (8 * ((by * this.ycbcrImage.CStride) + bx)); - break; - - case 2: - dst = this.ycbcrImage.CrChannel; - stride = this.ycbcrImage.CStride; - offset = this.ycbcrImage.COffset + (8 * ((by * this.ycbcrImage.CStride) + bx)); - break; - - case 3: - - dst = this.blackPixels; - stride = this.blackStride; - offset = 8 * ((by * this.blackStride) + bx); - break; - - default: - throw new ImageFormatException("Too many components"); - } - } - - // Level shift by +128, clip to [0, 255], and write to dst. - for (int y = 0; y < 8; y++) - { - int y8 = y * 8; - int yStride = y * stride; - - for (int x = 0; x < 8; x++) - { - int c = b[y8 + x]; - if (c < -128) - { - c = 0; - } - else if (c > 127) - { - c = 255; - } - else - { - c += 128; - } - - dst[yStride + x + offset] = (byte)c; - } + var b = new Block(); + b.Init(); + ProcessBlockImpl(ah, ref b, scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, + bx, ref this.quantizationTables[qtIndex] + ); } } @@ -1883,6 +1715,226 @@ namespace ImageSharp.Formats // for my } + private void ProcessBlockImpl(int ah, ref Block b, Scan[] scan, int i, int zigStart, int zigEnd, int al, + int[] dc, int compIndex, int @by, int mxx, int hi, int bx, ref Block qt) + { + if (ah != 0) + { + this.Refine(ref b, ref this.huffmanTrees[AcTable * ThRowSize + scan[i].AcTableSelector], zigStart, zigEnd, 1 << al); + } + else + { + int zig = zigStart; + if (zig == 0) + { + 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]); + if (value > 16) + { + throw new ImageFormatException("Excessive DC component"); + } + + int deltaDC = this.ReceiveExtend(value); + dc[compIndex] += deltaDC; + b[0] = dc[compIndex] << al; + } + + if (zig <= zigEnd && this.eobRun > 0) + { + this.eobRun--; + } + else + { + // Decode the AC coefficients, as specified in section F.2.2.2. + //Huffman huffv = ; + for (; zig <= zigEnd; zig++) + { + byte value = this.DecodeHuffman(ref this.huffmanTrees[AcTable * ThRowSize + scan[i].AcTableSelector]); + byte val0 = (byte) (value >> 4); + byte val1 = (byte) (value & 0x0f); + if (val1 != 0) + { + zig += val0; + if (zig > zigEnd) + { + break; + } + + int ac = this.ReceiveExtend(val1); + b[Unzig[zig]] = ac << al; + } + else + { + if (val0 != 0x0f) + { + this.eobRun = (ushort) (1 << val0); + if (val0 != 0) + { + this.eobRun |= (ushort) this.DecodeBits(val0); + } + + this.eobRun--; + break; + } + + zig += 0x0f; + } + } + } + } + + if (this.isProgressive) + { + if (zigEnd != Block.BlockSize - 1 || al != 0) + { + // We haven't completely decoded this 8x8 block. Save the coefficients. + this.progCoeffs[compIndex][((@by*mxx)*hi) + bx] = b; + + // At this point, we could execute the rest of the loop body to dequantize and + // perform the inverse DCT, to save early stages of a progressive image to the + // *image.YCbCr buffers (the whole point of progressive encoding), but in Go, + // the jpeg.Decode function does not return until the entire image is decoded, + // so we "continue" here to avoid wasted computation. + return; + } + } + + // Dequantize, perform the inverse DCT and store the block to the image. + for (int zig = 0; zig < Block.BlockSize; zig++) + { + b[Unzig[zig]] *= qt[zig]; + } + + IDCT.Transform(ref b); + + byte[] dst; + int offset; + int stride; + + if (this.componentCount == 1) + { + dst = this.grayImage.Pixels; + stride = this.grayImage.Stride; + offset = this.grayImage.Offset + (8*((@by*this.grayImage.Stride) + bx)); + } + else + { + switch (compIndex) + { + case 0: + dst = this.ycbcrImage.YChannel; + stride = this.ycbcrImage.YStride; + offset = this.ycbcrImage.YOffset + (8*((@by*this.ycbcrImage.YStride) + bx)); + break; + + case 1: + dst = this.ycbcrImage.CbChannel; + stride = this.ycbcrImage.CStride; + offset = this.ycbcrImage.COffset + (8*((@by*this.ycbcrImage.CStride) + bx)); + break; + + case 2: + dst = this.ycbcrImage.CrChannel; + stride = this.ycbcrImage.CStride; + offset = this.ycbcrImage.COffset + (8*((@by*this.ycbcrImage.CStride) + bx)); + break; + + case 3: + + dst = this.blackPixels; + stride = this.blackStride; + offset = 8*((@by*this.blackStride) + bx); + break; + + default: + throw new ImageFormatException("Too many components"); + } + } + + // Level shift by +128, clip to [0, 255], and write to dst. + for (int y = 0; y < 8; y++) + { + int y8 = y*8; + int yStride = y*stride; + + for (int x = 0; x < 8; x++) + { + int c = b[y8 + x]; + if (c < -128) + { + c = 0; + } + else if (c > 127) + { + c = 255; + } + else + { + c += 128; + } + + dst[yStride + x + offset] = (byte) c; + } + } + } + + private void ProcessScanImpl(int i, ref Scan currentScan, Scan[] scan, ref int totalHv) + { + // Component selector. + int cs = this.temp[1 + (2 * i)]; + int compIndex = -1; + for (int j = 0; j < this.componentCount; j++) + { + //Component compv = ; + if (cs == this.componentArray[j].Identifier) + { + compIndex = j; + } + } + + if (compIndex < 0) + { + throw new ImageFormatException("Unknown component selector"); + } + + currentScan.Index = (byte)compIndex; + + 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) + { + // 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 + // verified that a frame's component identifiers (C_i values in section + // B.2.2) are unique, it suffices to check that the implicit indexes + // into comp are unique. + for (int j = 0; j < i; j++) + { + if (currentScan.Index == scan[j].Index) + { + throw new ImageFormatException("Repeated component selector"); + } + } + + + totalHv += currentComponent.HorizontalFactor*currentComponent.VerticalFactor; + + currentScan.DcTableSelector = (byte) (this.temp[2 + (2*i)] >> 4); + if (currentScan.DcTableSelector > MaxTh) + { + throw new ImageFormatException("Bad DC table selector value"); + } + + currentScan.AcTableSelector = (byte) (this.temp[2 + (2*i)] & 0x0f); + if (currentScan.AcTableSelector > MaxTh) + { + throw new ImageFormatException("Bad AC table selector value"); + } + } + /// /// Decodes a successive approximation refinement block, as specified in section G.1.2. /// @@ -1891,7 +1943,7 @@ namespace ImageSharp.Formats /// The zig-zag start index /// The zig-zag end index /// The low transform offset - private void Refine(Block b, Huffman h, int zigStart, int zigEnd, int delta) + private void Refine(ref Block b, ref Huffman h, int zigStart, int zigEnd, int delta) { // Refining a DC component is trivial. if (zigStart == 0) @@ -1918,7 +1970,7 @@ namespace ImageSharp.Formats { bool done = false; int z = 0; - byte val = this.DecodeHuffman(h); + byte val = this.DecodeHuffman(ref h); int val0 = val >> 4; int val1 = val & 0x0f; diff --git a/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs index 9cb4fce26..9a282a72b 100644 --- a/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs +++ b/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs @@ -488,9 +488,9 @@ namespace ImageSharp.Formats /// The quantization table index. /// The previous DC value. /// The - private int WriteBlock(Block block, QuantIndex index, int prevDC) + private int WriteBlock(ref Block block, QuantIndex index, int prevDC) { - FDCT.Transform(block); + FDCT.Transform(ref block); // Emit the DC delta. int dc = Round(block[0], 8 * this.quant[(int)index][0]); @@ -541,7 +541,8 @@ namespace ImageSharp.Formats /// The red chroma block. /// The blue chroma block. // ReSharper disable StyleCop.SA1305 - private void ToYCbCr(PixelAccessor pixels, int x, int y, Block yBlock, Block cbBlock, Block crBlock) + private void ToYCbCr(PixelAccessor pixels, int x, int y, + ref Block yBlock, ref Block cbBlock, ref Block crBlock) // ReSharper restore StyleCop.SA1305 where TColor : struct, IPackedPixel where TPacked : struct @@ -858,10 +859,10 @@ namespace ImageSharp.Formats { for (int x = 0; x < pixels.Width; x += 8) { - this.ToYCbCr(pixels, x, y, b, cb, cr); - prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY); - prevDCCb = this.WriteBlock(cb, QuantIndex.Chrominance, prevDCCb); - prevDCCr = this.WriteBlock(cr, QuantIndex.Chrominance, prevDCCr); + this.ToYCbCr(pixels, x, y, ref b, ref cb, ref cr); + prevDCY = this.WriteBlock(ref b, QuantIndex.Luminance, prevDCY); + prevDCCb = this.WriteBlock(ref cb, QuantIndex.Chrominance, prevDCCb); + prevDCCr = this.WriteBlock(ref cr, QuantIndex.Chrominance, prevDCCr); } } } @@ -902,14 +903,14 @@ namespace ImageSharp.Formats int xOff = (i & 1) * 8; int yOff = (i & 2) * 4; - this.ToYCbCr(pixels, x + xOff, y + yOff, b, cb[i], cr[i]); - prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY); + this.ToYCbCr(pixels, x + xOff, y + yOff, ref b, ref cb[i], ref cr[i]); + prevDCY = this.WriteBlock(ref b, QuantIndex.Luminance, prevDCY); } this.Scale16X16To8X8(b, cb); - prevDCCb = this.WriteBlock(b, QuantIndex.Chrominance, prevDCCb); + prevDCCb = this.WriteBlock(ref b, QuantIndex.Chrominance, prevDCCb); this.Scale16X16To8X8(b, cr); - prevDCCr = this.WriteBlock(b, QuantIndex.Chrominance, prevDCCr); + prevDCCr = this.WriteBlock(ref b, QuantIndex.Chrominance, prevDCCr); } } } diff --git a/src/ImageSharp46/ImageSharp46.csproj b/src/ImageSharp46/ImageSharp46.csproj index bf7829e22..e88dbb0e2 100644 --- a/src/ImageSharp46/ImageSharp46.csproj +++ b/src/ImageSharp46/ImageSharp46.csproj @@ -86,7 +86,10 @@ True - + + ..\..\packages\System.Numerics.Vectors.4.1.1\lib\net46\System.Numerics.Vectors.dll + True + ..\..\packages\System.Runtime.CompilerServices.Unsafe.4.0.0\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll True diff --git a/src/ImageSharp46/packages.config b/src/ImageSharp46/packages.config index b67050550..6ace6583b 100644 --- a/src/ImageSharp46/packages.config +++ b/src/ImageSharp46/packages.config @@ -23,6 +23,7 @@ + diff --git a/tests/ConsoleBenchmark/App.config b/tests/ConsoleBenchmark/App.config new file mode 100644 index 000000000..5bf749f82 --- /dev/null +++ b/tests/ConsoleBenchmark/App.config @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/ConsoleBenchmark/ConsoleBenchmark.csproj b/tests/ConsoleBenchmark/ConsoleBenchmark.csproj new file mode 100644 index 000000000..da38098fc --- /dev/null +++ b/tests/ConsoleBenchmark/ConsoleBenchmark.csproj @@ -0,0 +1,89 @@ + + + + + Debug + AnyCPU + {8783E3A1-79F1-4E37-AA79-F06C48BED5E7} + Exe + Properties + ConsoleBenchmark + ConsoleBenchmark + v4.6.1 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + ..\..\packages\System.Numerics.Vectors.4.1.1\lib\net46\System.Numerics.Vectors.dll + True + + + + + + + + + ..\..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll + True + + + ..\..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll + True + + + ..\..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll + True + + + + + + + + + + + + + {fba0b5f6-09c2-4317-8ef6-6adb9b20e6b1} + ImageSharp46 + + + {635e0a15-3893-4763-a7f6-fccff85bcca4} + ImageSharp.Tests46 + + + + + \ No newline at end of file diff --git a/tests/ConsoleBenchmark/Program.cs b/tests/ConsoleBenchmark/Program.cs new file mode 100644 index 000000000..52a53e316 --- /dev/null +++ b/tests/ConsoleBenchmark/Program.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using ImageSharp.Tests; +using ImageSharp.Tests46.Benchmark; +using Xunit.Abstractions; + +namespace ConsoleBenchmark +{ + class Program + { + private class Output : ITestOutputHelper + { + public void WriteLine(string message) + { + Console.WriteLine(message); + } + + public void WriteLine(string format, params object[] args) + { + Console.WriteLine(format, args); + } + } + + static void Main(string[] args) + { + DecodeJpegBenchmark benchmark = new DecodeJpegBenchmark(new Output()); + benchmark.JpegCore(100); + //JpegSandbox test = new JpegSandbox(null); + + //test.OpenJpeg_SaveBmp(TestImages.Jpeg.Calliphora); + } + } +} diff --git a/tests/ConsoleBenchmark/Properties/AssemblyInfo.cs b/tests/ConsoleBenchmark/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5d8efdb2e --- /dev/null +++ b/tests/ConsoleBenchmark/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ConsoleBenchmark")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Sapa")] +[assembly: AssemblyProduct("ConsoleBenchmark")] +[assembly: AssemblyCopyright("Copyright © Sapa 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8783e3a1-79f1-4e37-aa79-f06c48bed5e7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Bmp/Car.bmp b/tests/ConsoleBenchmark/TestImages/Formats/Bmp/Car.bmp new file mode 100644 index 000000000..edaf3a8e4 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Bmp/Car.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d3a4a30cd67db6ded1e57126c7ba275404703e64b3dfb1c9c711128c15b0124 +size 810054 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Bmp/F.bmp b/tests/ConsoleBenchmark/TestImages/Formats/Bmp/F.bmp new file mode 100644 index 000000000..d95598bef --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Bmp/F.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6da008d2b285b2db946e6d4ebf8569b0ddd4a05ef273b38304cb65afccac87b3 +size 65502 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Bmp/neg_height.bmp b/tests/ConsoleBenchmark/TestImages/Formats/Bmp/neg_height.bmp new file mode 100644 index 000000000..d0b99a902 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Bmp/neg_height.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81437b88a5d92fcb545fae4991643a0c73d95d0277dac0b79074971780008c8c +size 6220854 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Gif/giphy.gif b/tests/ConsoleBenchmark/TestImages/Formats/Gif/giphy.gif new file mode 100644 index 000000000..029afdec6 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Gif/giphy.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f42abd9f3e493a0acd5303ab0d37a6179835c5a14364a1f001abd9d9e906f96 +size 53655 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Gif/rings.gif b/tests/ConsoleBenchmark/TestImages/Formats/Gif/rings.gif new file mode 100644 index 000000000..acd5d6339 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Gif/rings.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:716448da88152225767c024aac498f5b7562b6e8391907cefc9d03dba40050fd +size 53435 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/Calliphora.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/Calliphora.jpg new file mode 100644 index 000000000..aa3fdef01 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/Calliphora.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67172fcab405f914587b88cd1106328e6b24ab59d622ba509dcc99509951ff5c +size 254766 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/Floorplan.jpeg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/Floorplan.jpeg new file mode 100644 index 000000000..6f439d220 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/Floorplan.jpeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de00b34b78dfa0886c93d8dd5cede27b4940d5c620e44631e77e6dc8838befc3 +size 161577 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/cmyk.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/cmyk.jpg new file mode 100644 index 000000000..2fe8f0a61 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/cmyk.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33e3546a64df7fa1d528441926421b193e399a83490a6307762fb7eee9640bf0 +size 611572 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/exif.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/exif.jpg new file mode 100644 index 000000000..cba862660 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/exif.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a9d04b92d0de5836c59ede8ae421235488e4031e893e07b1fe7e4b78f6a9901 +size 32764 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/fb.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/fb.jpg new file mode 100644 index 000000000..7241890e2 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/fb.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93bb4d6281dc1e845db57e836e0dca30b7a4062e81044efb27ad4d8b1a33130c +size 15787 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg new file mode 100644 index 000000000..c305caef4 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/gamma_dalai_lama_gray.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d92a88b04518e266b98d9d2f5b4eb88f3f91c332d3397ea859bab8cabc41185 +size 84887 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/progress.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/progress.jpg new file mode 100644 index 000000000..30b214c22 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/progress.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9a1f0da3c5b3a3e7e7f35abe9f5b458163b48ca56226227b3d3cffe06af1971 +size 44884 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Jpg/turtle.jpg b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/turtle.jpg new file mode 100644 index 000000000..07d96543b --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Jpg/turtle.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e5c576b0c5e743cfd498b110305268ecbae63c62061ba6c7eb8e060728191f1 +size 55126 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Png/blur.png b/tests/ConsoleBenchmark/TestImages/Formats/Png/blur.png new file mode 100644 index 000000000..2ac488b7c --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Png/blur.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:10df946d3d6a9832bacd9ac2587b890c348d17731412c8fd17c34f66f35d9c94 +size 183768 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Png/indexed.png b/tests/ConsoleBenchmark/TestImages/Formats/Png/indexed.png new file mode 100644 index 000000000..f06e1cbd6 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Png/indexed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65566cde707c02757a26fb5fb7702be9c53f55c17a1748d81c384559de2d1173 +size 33529 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Png/pd.png b/tests/ConsoleBenchmark/TestImages/Formats/Png/pd.png new file mode 100644 index 000000000..12fde3229 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Png/pd.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91dd938fb916d368738826741551aea694b340ba3362f56200c5d3c5e5510267 +size 1406 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Png/pl.png b/tests/ConsoleBenchmark/TestImages/Formats/Png/pl.png new file mode 100644 index 000000000..15e991284 --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Png/pl.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa550e61fe276d2ebee8666d0cbb811449433edb76e01bcd38cb00c1aafc417e +size 91 diff --git a/tests/ConsoleBenchmark/TestImages/Formats/Png/splash.png b/tests/ConsoleBenchmark/TestImages/Formats/Png/splash.png new file mode 100644 index 000000000..ca4f86bce --- /dev/null +++ b/tests/ConsoleBenchmark/TestImages/Formats/Png/splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4c13422913f1c1910f8dd607236e79b4a5c7053deb8ce1c8be8372eca7465fb +size 245033 diff --git a/tests/ConsoleBenchmark/packages.config b/tests/ConsoleBenchmark/packages.config new file mode 100644 index 000000000..50e8c3f1f --- /dev/null +++ b/tests/ConsoleBenchmark/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs b/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs index 6f2bd5e60..49af14763 100644 --- a/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Image/DecodeJpeg.cs @@ -26,17 +26,17 @@ namespace ImageSharp.Benchmarks.Image } } - [Benchmark(Baseline = true, Description = "System.Drawing Jpeg")] - public Size JpegSystemDrawing() - { - using (MemoryStream memoryStream = new MemoryStream(this.jpegBytes)) - { - using (Image image = Image.FromStream(memoryStream)) - { - return image.Size; - } - } - } + //[Benchmark(Baseline = true, Description = "System.Drawing Jpeg")] + //public Size JpegSystemDrawing() + //{ + // using (MemoryStream memoryStream = new MemoryStream(this.jpegBytes)) + // { + // using (Image image = Image.FromStream(memoryStream)) + // { + // return image.Size; + // } + // } + //} [Benchmark(Description = "ImageSharp Jpeg")] public CoreSize JpegCore() diff --git a/tests/ImageSharp.Tests46/Benchmark/DecodeJpeg.cs b/tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs similarity index 91% rename from tests/ImageSharp.Tests46/Benchmark/DecodeJpeg.cs rename to tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs index 968ca070f..6de820f8b 100644 --- a/tests/ImageSharp.Tests46/Benchmark/DecodeJpeg.cs +++ b/tests/ImageSharp.Tests46/Benchmark/DecodeJpegBenchmark.cs @@ -14,20 +14,20 @@ namespace ImageSharp.Tests46.Benchmark using CoreImage = ImageSharp.Image; using CoreSize = ImageSharp.Size; - public class DecodeJpeg + public class DecodeJpegBenchmark { private static byte[] jpegBytes = File.ReadAllBytes(TestImages.Jpeg.Calliphora); private ITestOutputHelper _output; - public DecodeJpeg(ITestOutputHelper output) + public DecodeJpegBenchmark(ITestOutputHelper output) { _output = output; } private void DoBenchmark(int times, Action action, [CallerMemberName]string method = null) { - _output.WriteLine($"Starting {method}.. "); + _output.WriteLine($"{method} x {times} ... "); Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < times; i++) { diff --git a/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj b/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj index 194d84be8..a1b4e990f 100644 --- a/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj +++ b/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj @@ -1,5 +1,6 @@  + Debug @@ -12,6 +13,8 @@ v4.6.1 512 + + true @@ -37,7 +40,10 @@ - + + ..\..\packages\System.Numerics.Vectors.4.1.1\lib\net46\System.Numerics.Vectors.dll + True + @@ -62,7 +68,7 @@ - + @@ -148,8 +154,16 @@ - + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + +