From c3c29586febd88dd25c1595dba8a76a8dc98f15b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Wed, 23 Aug 2017 01:19:49 +0200 Subject: [PATCH] open up OldJpegDecoderCore API for testing --- .../Formats/Jpeg/Common/Block8x8.cs | 42 ++++++++++- .../Jpeg/GolangPort/OldJpegDecoderCore.cs | 38 +++++----- .../Formats/Jpg/Block8x8Tests.cs | 38 ++++++++++ .../Formats/Jpg/LibJpegTools.cs | 69 ++++--------------- .../Formats/Jpg/SpectralJpegTests.cs | 6 +- 5 files changed, 114 insertions(+), 79 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs index c04ba1f83..d686a5e25 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common /// Represents a Jpeg block with coefficiens. /// // ReSharper disable once InconsistentNaming - internal unsafe struct Block8x8 + internal unsafe struct Block8x8 : IEquatable { /// /// A number of scalar coefficients in a @@ -44,6 +44,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common } } + public static bool operator ==(Block8x8 left, Block8x8 right) + { + return left.Equals(right); + } + + public static bool operator !=(Block8x8 left, Block8x8 right) + { + return !left.Equals(right); + } + /// /// Pointer-based "Indexer" (getter part) /// @@ -74,6 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common fp[idx] = value; } + public short GetValueAt(int x, int y) => this[(y * 8) + x]; public Block8x8F AsFloatBlock() { @@ -124,5 +135,34 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common bld.Append(']'); return bld.ToString(); } + + public bool Equals(Block8x8 other) + { + for (int i = 0; i < Size; i++) + { + if (this[i] != other[i]) + { + return false; + } + } + + return true; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + return obj is Block8x8 && this.Equals((Block8x8)obj); + } + + public override int GetHashCode() + { + return (this[0] * 31) + this[1]; + } + } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs index a028215ba..856e31b33 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs @@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// Gets the huffman trees /// public OldHuffmanTree[] HuffmanTrees { get; } - + /// /// Gets the quantization tables, in zigzag order. /// @@ -182,6 +182,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// public bool IgnoreMetadata { get; private set; } + /// + /// Gets the decoded by this decoder instance. + /// + public ImageMetaData MetaData { get; private set; } + /// /// Decodes the image from the specified and sets /// the data to image. @@ -192,10 +197,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort public Image Decode(Stream stream) where TPixel : struct, IPixel { - ImageMetaData metadata = new ImageMetaData(); - this.ProcessStream(metadata, stream, false); + this.ParseStream(stream, false); this.ProcessBlocksIntoJpegImageChannels(); - Image image = this.ConvertJpegPixelsToImagePixels(metadata); + Image image = this.ConvertJpegPixelsToImagePixels(); return image; } @@ -254,11 +258,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// /// Read metadata from stream and read the blocks in the scans into . /// - /// The metadata /// The stream /// Whether to decode metadata only. - private void ProcessStream(ImageMetaData metadata, Stream stream, bool metadataOnly) + public void ParseStream(Stream stream, bool metadataOnly) { + this.MetaData = new ImageMetaData(); this.InputStream = stream; this.InputProcessor = new InputProcessor(stream, this.Temp); @@ -405,10 +409,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort this.ProcessApplicationHeader(remaining); break; case OldJpegConstants.Markers.APP1: - this.ProcessApp1Marker(remaining, metadata); + this.ProcessApp1Marker(remaining); break; case OldJpegConstants.Markers.APP2: - this.ProcessApp2Marker(remaining, metadata); + this.ProcessApp2Marker(remaining); break; case OldJpegConstants.Markers.APP14: this.ProcessApp14Marker(remaining); @@ -475,12 +479,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// Convert the pixel data in and/or into pixels of /// /// The pixel type - /// The metadata for the image. /// The decoded image. - private Image ConvertJpegPixelsToImagePixels(ImageMetaData metadata) + private Image ConvertJpegPixelsToImagePixels() where TPixel : struct, IPixel { - Image image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, metadata); + var image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData); if (this.grayImage.IsInitialized) { @@ -929,7 +932,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// /// The remaining bytes in the segment block. /// The image. - private void ProcessApp1Marker(int remaining, ImageMetaData metadata) + private void ProcessApp1Marker(int remaining) { if (remaining < 6 || this.IgnoreMetadata) { @@ -948,7 +951,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort profile[5] == '\0') { this.isExif = true; - metadata.ExifProfile = new ExifProfile(profile); + this.MetaData.ExifProfile = new ExifProfile(profile); } } @@ -956,8 +959,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// Processes the App2 marker retrieving any stored ICC profile information /// /// The remaining bytes in the segment block. - /// The image. - private void ProcessApp2Marker(int remaining, ImageMetaData metadata) + private void ProcessApp2Marker(int remaining) { // Length is 14 though we only need to check 12. const int Icclength = 14; @@ -987,13 +989,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort byte[] profile = new byte[remaining]; this.InputProcessor.ReadFull(profile, 0, remaining); - if (metadata.IccProfile == null) + if (this.MetaData.IccProfile == null) { - metadata.IccProfile = new IccProfile(profile); + this.MetaData.IccProfile = new IccProfile(profile); } else { - metadata.IccProfile.Extend(profile); + this.MetaData.IccProfile.Extend(profile); } } else diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs index fafe56ee7..d77a46887 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs @@ -87,5 +87,43 @@ namespace SixLabors.ImageSharp.Tests Assert.Equal(data, result); } + + [Fact] + public void Equality_WhenTrue() + { + short[] data = Create8x8ShortData(); + var block1 = new Block8x8(data); + var block2 = new Block8x8(data); + + block1[0] = 42; + block2[0] = 42; + + Assert.Equal(block1, block2); + Assert.Equal(block1.GetHashCode(), block2.GetHashCode()); + } + + [Fact] + public void Equality_WhenFalse() + { + short[] data = Create8x8ShortData(); + var block1 = new Block8x8(data); + var block2 = new Block8x8(data); + + block1[0] = 42; + block2[0] = 666; + + Assert.NotEqual(block1, block2); + } + + [Fact] + public void GetValueAt() + { + var block = default(Block8x8); + block[8 * 3 + 5] = 42; + + short value = block.GetValueAt(5, 3); + + Assert.Equal(42, value); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Jpg/LibJpegTools.cs b/tests/ImageSharp.Tests/Formats/Jpg/LibJpegTools.cs index 04e755310..11b769103 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/LibJpegTools.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/LibJpegTools.cs @@ -8,6 +8,7 @@ namespace SixLabors.ImageSharp.Tests using BitMiracle.LibJpeg.Classic; + using SixLabors.ImageSharp.Formats.Jpeg.Common; using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort; using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components; using SixLabors.ImageSharp.PixelFormats; @@ -17,52 +18,6 @@ namespace SixLabors.ImageSharp.Tests internal static class LibJpegTools { - public unsafe struct Block : IEquatable - { - public Block(short[] data) - { - this.Data = data; - } - - public short[] Data { get; } - - public short this[int x, int y] - { - get => this.Data[y * 8 + x]; - set => this.Data[y * 8 + x] = value; - } - - public bool Equals(Block other) - { - for (int i = 0; i < 64; i++) - { - if (this.Data[i] != other.Data[i]) return false; - } - return true; - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - return obj is Block && Equals((Block)obj); - } - - public override int GetHashCode() - { - return (this.Data != null ? this.Data.GetHashCode() : 0); - } - - public static bool operator ==(Block left, Block right) - { - return left.Equals(right); - } - - public static bool operator !=(Block left, Block right) - { - return !left.Equals(right); - } - } - public class SpectralData : IEquatable { public int ComponentCount { get; private set; } @@ -187,9 +142,9 @@ namespace SixLabors.ImageSharp.Tests ComponentData c1 = this.Components[1]; ComponentData c2 = this.Components[2]; - Block block0 = c0.Blocks[by, bx]; - Block block1 = c1.Blocks[by, bx]; - Block block2 = c2.Blocks[by, bx]; + Block8x8 block0 = c0.Blocks[by, bx]; + Block8x8 block1 = c1.Blocks[by, bx]; + Block8x8 block2 = c2.Blocks[by, bx]; float d0 = (c0.MaxVal - c0.MinVal); float d1 = (c1.MaxVal - c1.MinVal); @@ -266,7 +221,7 @@ namespace SixLabors.ImageSharp.Tests this.YCount = yCount; this.XCount = xCount; this.Index = index; - this.Blocks = new Block[this.YCount, this.XCount]; + this.Blocks = new Block8x8[this.YCount, this.XCount]; } public Size Size => new Size(this.XCount, this.YCount); @@ -277,7 +232,7 @@ namespace SixLabors.ImageSharp.Tests public int XCount { get; } - public Block[,] Blocks { get; private set; } + public Block8x8[,] Blocks { get; private set; } public short MinVal { get; private set; } = short.MaxValue; @@ -311,7 +266,7 @@ namespace SixLabors.ImageSharp.Tests { this.MinVal = Math.Min(this.MinVal, data.Min()); this.MaxVal = Math.Max(this.MaxVal, data.Max()); - this.Blocks[y, x] = new Block(data); + this.Blocks[y, x] = new Block8x8(data); } public static ComponentData Load(FrameComponent sc, int index) @@ -353,7 +308,7 @@ namespace SixLabors.ImageSharp.Tests internal void WriteToImage(int bx, int by, Image image) { - Block block = this.Blocks[by, bx]; + Block8x8 block = this.Blocks[by, bx]; for (int y = 0; y < 8; y++) { @@ -372,10 +327,10 @@ namespace SixLabors.ImageSharp.Tests } } - internal float GetBlockValue(Block block, int x, int y) + internal float GetBlockValue(Block8x8 block, int x, int y) { float d = (this.MaxVal - this.MinVal); - float val = block[x, y]; + float val = block.GetValueAt(x, y); val -= this.MinVal; val /= d; return val; @@ -394,8 +349,8 @@ namespace SixLabors.ImageSharp.Tests { for (int j = 0; j < this.XCount; j++) { - Block a = this.Blocks[i, j]; - Block b = other.Blocks[i, j]; + Block8x8 a = this.Blocks[i, j]; + Block8x8 b = other.Blocks[i, j]; if (!a.Equals(b)) return false; } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs index 4a2d4939e..84a900f32 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32)] - public void JpegDecoderCore_ParseStream_SaveSpectralResult(TestImageProvider provider) + public void PdfJsDecoder_ParseStream_SaveSpectralResult(TestImageProvider provider) where TPixel : struct, IPixel { JpegDecoderCore decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); @@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Tests [Theory] [WithFileCollection(nameof(AllTestJpegs), PixelTypes.Rgba32)] - public void CompareSpectralResults(TestImageProvider provider) + public void CompareSpectralResults_PdfJs(TestImageProvider provider) where TPixel : struct, IPixel { JpegDecoderCore decoder = new JpegDecoderCore(Configuration.Default, new JpegDecoder()); @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Tests bool equality = libJpegData.Equals(imageSharpData); this.Output.WriteLine("Spectral data equality: " + equality); - // Assert.Equal(libJpegData, imageSharpData); + Assert.Equal(libJpegData, imageSharpData); } }