Browse Source

Add identifier tests and begin cleanup

pull/525/head
James Jackson-South 8 years ago
parent
commit
81d68e244d
  1. 43
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponent.cs
  2. 32
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponentBlocks.cs
  3. 98
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs
  4. 67
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs
  5. 35
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
  6. 121
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
  7. 22
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  8. 6
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs

43
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponent.cs

@ -1,43 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
/// <summary>
/// Represents a component block
/// </summary>
internal class PdfJsComponent : IDisposable
{
#pragma warning disable SA1401
/// <summary>
/// Gets or sets the output
/// </summary>
public IBuffer<short> Output;
/// <summary>
/// Gets or sets the scaling factors
/// </summary>
public Vector2 Scale;
/// <summary>
/// Gets or sets the number of blocks per line
/// </summary>
public int BlocksPerLine;
/// <summary>
/// Gets or sets the number of blocks per column
/// </summary>
public int BlocksPerColumn;
/// <inheritdoc/>
public void Dispose()
{
this.Output?.Dispose();
this.Output = null;
}
}
}

32
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponentBlocks.cs

@ -1,32 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
/// <summary>
/// Contains all the decoded component blocks
/// </summary>
internal sealed class PdfJsComponentBlocks : IDisposable
{
/// <summary>
/// Gets or sets the component blocks
/// </summary>
public PdfJsComponent[] Components { get; set; }
/// <inheritdoc/>
public void Dispose()
{
if (this.Components != null)
{
for (int i = 0; i < this.Components.Length; i++)
{
this.Components[i].Dispose();
}
this.Components = null;
}
}
}
}

98
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs

@ -54,55 +54,55 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.componentData = this.memoryManager.Allocate<byte>(this.Width * this.Height * this.NumberOfComponents); this.componentData = this.memoryManager.Allocate<byte>(this.Width * this.Height * this.NumberOfComponents);
} }
/// <summary> //// <summary>
/// Organsizes the decoded jpeg components into a linear array ordered by component. //// Organsizes the decoded jpeg components into a linear array ordered by component.
/// This must be called before attempting to retrieve the data. //// This must be called before attempting to retrieve the data.
/// </summary> //// </summary>
/// <param name="components">The jpeg component blocks</param> //// <param name="components">The jpeg component blocks</param>
public void LinearizeBlockData(PdfJsComponentBlocks components) // public void LinearizeBlockData(PdfJsComponentBlocks components)
{ // {
ref byte componentDataRef = ref MemoryMarshal.GetReference(this.componentData.Span); // ref byte componentDataRef = ref MemoryMarshal.GetReference(this.componentData.Span);
const uint Mask3Lsb = 0xFFFFFFF8; // Used to clear the 3 LSBs // const uint Mask3Lsb = 0xFFFFFFF8; // Used to clear the 3 LSBs
using (IBuffer<int> xScaleBlockOffset = this.memoryManager.Allocate<int>(this.Width)) // using (IBuffer<int> xScaleBlockOffset = this.memoryManager.Allocate<int>(this.Width))
{ // {
ref int xScaleBlockOffsetRef = ref MemoryMarshal.GetReference(xScaleBlockOffset.Span); // ref int xScaleBlockOffsetRef = ref MemoryMarshal.GetReference(xScaleBlockOffset.Span);
int numberOfComponents = this.NumberOfComponents; // int numberOfComponents = this.NumberOfComponents;
int width = this.Width; // int width = this.Width;
int height = this.Height; // int height = this.Height;
//
for (int i = 0; i < numberOfComponents; i++) // for (int i = 0; i < numberOfComponents; i++)
{ // {
ref PdfJsComponent component = ref components.Components[i]; // ref PdfJsComponent component = ref components.Components[i];
ref short outputRef = ref MemoryMarshal.GetReference(component.Output.Span); // ref short outputRef = ref MemoryMarshal.GetReference(component.Output.Span);
Vector2 componentScale = component.Scale; // Vector2 componentScale = component.Scale;
float cX = componentScale.X; // float cX = componentScale.X;
float cY = componentScale.Y; // float cY = componentScale.Y;
int blocksPerScanline = (component.BlocksPerLine + 1) << 3; // int blocksPerScanline = (component.BlocksPerLine + 1) << 3;
//
// Precalculate the xScaleBlockOffset // // Precalculate the xScaleBlockOffset
int j; // int j;
for (int x = 0; x < width; x++) // for (int x = 0; x < width; x++)
{ // {
j = (int)(x * cX); // j = (int)(x * cX);
Unsafe.Add(ref xScaleBlockOffsetRef, x) = (int)((j & Mask3Lsb) << 3) | (j & 7); // Unsafe.Add(ref xScaleBlockOffsetRef, x) = (int)((j & Mask3Lsb) << 3) | (j & 7);
} // }
//
// Linearize the blocks of the component // // Linearize the blocks of the component
int offset = i; // int offset = i;
for (int y = 0; y < height; y++) // for (int y = 0; y < height; y++)
{ // {
j = (int)(y * cY); // j = (int)(y * cY);
int index = blocksPerScanline * (int)(j & Mask3Lsb) | ((j & 7) << 3); // int index = blocksPerScanline * (int)(j & Mask3Lsb) | ((j & 7) << 3);
for (int x = 0; x < width; x++) // for (int x = 0; x < width; x++)
{ // {
Unsafe.Add(ref componentDataRef, offset) = (byte)Unsafe.Add(ref outputRef, index + Unsafe.Add(ref xScaleBlockOffsetRef, x)); // Unsafe.Add(ref componentDataRef, offset) = (byte)Unsafe.Add(ref outputRef, index + Unsafe.Add(ref xScaleBlockOffsetRef, x));
offset += numberOfComponents; // offset += numberOfComponents;
} // }
} // }
} // }
} // }
} // }
/// <summary> /// <summary>
/// Gets a <see cref="Span{Byte}"/> representing the row 'y' beginning from the the first byte on that row. /// Gets a <see cref="Span{Byte}"/> representing the row 'y' beginning from the the first byte on that row.

67
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs

@ -1,67 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
/// <summary>
/// Contains the quantization tables.
/// </summary>
internal sealed class PdfJsQuantizationTables : IDisposable
{
public PdfJsQuantizationTables(MemoryManager memoryManager)
{
this.Tables = memoryManager.Allocate2D<short>(64, 4);
}
/// <summary>
/// Gets the ZigZag scan table
/// </summary>
public static byte[] DctZigZag
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
=
{
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
};
/// <summary>
/// Gets or sets the quantization tables.
/// </summary>
public Buffer2D<short> Tables
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get; set;
}
/// <inheritdoc/>
public void Dispose()
{
if (this.Tables != null)
{
this.Tables.Dispose();
this.Tables = null;
}
}
}
}

35
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs

@ -2,7 +2,9 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
#if DEBUG
using System.Diagnostics; using System.Diagnostics;
#endif
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -15,6 +17,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
internal struct PdfJsScanDecoder internal struct PdfJsScanDecoder
{ {
/// <summary>
/// Gets the ZigZag scan table
/// </summary>
private static readonly byte[] DctZigZag =
{
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
};
private byte[] markerBuffer; private byte[] markerBuffer;
private int bitsData; private int bitsData;
@ -203,11 +227,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1) if (componentsLength == 1)
{ {
PdfJsFrameComponent component = components[this.compIndex]; PdfJsFrameComponent component = components[this.compIndex];
// TODO: This is where our error is happening.
// We can't simply cast the span as I think the scan decoder expects data to be laid out in linear order
// rather than in the column major order expected by the Block8x8 struct and anything reading it down the pipeline.
// Ask Anton about this. It might be a lost cause.
ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<Block8x8, short>(component.SpectralBlocks.Span)); ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<Block8x8, short>(component.SpectralBlocks.Span));
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
@ -765,7 +784,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
break; break;
} }
ref byte z = ref PdfJsQuantizationTables.DctZigZag[k]; ref byte z = ref DctZigZag[k];
short re = (short)this.ReceiveAndExtend(s, stream); short re = (short)this.ReceiveAndExtend(s, stream);
Unsafe.Add(ref blockDataRef, offset + z) = re; Unsafe.Add(ref blockDataRef, offset + z) = re;
k++; k++;
@ -833,7 +852,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
k += r; k += r;
ref byte z = ref PdfJsQuantizationTables.DctZigZag[k]; ref byte z = ref DctZigZag[k];
Unsafe.Add(ref blockDataRef, offset + z) = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState)); Unsafe.Add(ref blockDataRef, offset + z) = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState));
k++; k++;
} }
@ -848,7 +867,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
while (k <= e) while (k <= e)
{ {
int offsetZ = offset + PdfJsQuantizationTables.DctZigZag[k]; int offsetZ = offset + DctZigZag[k];
ref short blockOffsetZRef = ref Unsafe.Add(ref blockDataRef, offsetZ); ref short blockOffsetZRef = ref Unsafe.Add(ref blockDataRef, offsetZ);
int sign = blockOffsetZRef < 0 ? -1 : 1; int sign = blockOffsetZRef < 0 ? -1 : 1;

121
src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

@ -39,19 +39,25 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
private readonly Configuration configuration; private readonly Configuration configuration;
/// <summary> /// <summary>
/// Gets the temporary buffer used to store bytes read from the stream. /// The buffer used to temporarily store bytes read from the stream.
/// </summary> /// </summary>
private readonly byte[] temp = new byte[2 * 16 * 4]; private readonly byte[] temp = new byte[2 * 16 * 4];
/// <summary>
/// The buffer used to read markers from the stream.
/// </summary>
private readonly byte[] markerBuffer = new byte[2]; private readonly byte[] markerBuffer = new byte[2];
// private PdfJsQuantizationTables quantizationTables; /// <summary>
/// The DC HUffman tables
/// </summary>
private PdfJsHuffmanTables dcHuffmanTables; private PdfJsHuffmanTables dcHuffmanTables;
/// <summary>
/// The AC HUffman tables
/// </summary>
private PdfJsHuffmanTables acHuffmanTables; private PdfJsHuffmanTables acHuffmanTables;
private PdfJsComponentBlocks components;
private PdfJsJpegPixelArea pixelArea; private PdfJsJpegPixelArea pixelArea;
private ushort resetInterval; private ushort resetInterval;
@ -185,14 +191,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
this.ParseStream(stream); this.ParseStream(stream);
return this.PostProcessIntoImage<TPixel>();
Image<TPixel> image = this.PostProcessIntoImage<TPixel>();
// this.QuantizeAndInverseAllComponents();
// var image = new Image<TPixel>(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData);
// this.FillPixelData(image.Frames.RootFrame);
this.AssignResolution();
return image;
} }
/// <summary> /// <summary>
@ -321,12 +320,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
break; break;
case PdfJsJpegConstants.Markers.SOS: case PdfJsJpegConstants.Markers.SOS:
if (metadataOnly) if (!metadataOnly)
{ {
return; this.ProcessStartOfScanMarker();
} }
this.ProcessStartOfScanMarker();
break; break;
} }
@ -336,58 +334,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.ImageWidth = this.Frame.SamplesPerLine; this.ImageWidth = this.Frame.SamplesPerLine;
this.ImageHeight = this.Frame.Scanlines; this.ImageHeight = this.Frame.Scanlines;
this.components = new PdfJsComponentBlocks { Components = new PdfJsComponent[this.Frame.ComponentCount] }; this.ComponentCount = this.Frame.ComponentCount;
for (int i = 0; i < this.components.Components.Length; i++)
{
PdfJsFrameComponent frameComponent = this.Frame.Components[i];
var component = new PdfJsComponent
{
Scale = new System.Numerics.Vector2(
frameComponent.HorizontalSamplingFactor / (float)this.Frame.MaxHorizontalFactor,
frameComponent.VerticalSamplingFactor / (float)this.Frame.MaxVerticalFactor),
BlocksPerLine = frameComponent.WidthInBlocks,
BlocksPerColumn = frameComponent.HeightInBlocks
};
// this.QuantizeAndInverseComponentData(ref component, frameComponent);
this.components.Components[i] = component;
}
this.ComponentCount = this.components.Components.Length;
} }
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() public void Dispose()
{ {
this.Frame?.Dispose(); this.Frame?.Dispose();
this.components?.Dispose();
// this.quantizationTables?.Dispose();
this.pixelArea.Dispose(); this.pixelArea.Dispose();
// Set large fields to null. // Set large fields to null.
this.Frame = null; this.Frame = null;
this.components = null;
// this.quantizationTables = null;
this.dcHuffmanTables = null; this.dcHuffmanTables = null;
this.acHuffmanTables = null; this.acHuffmanTables = null;
} }
internal void QuantizeAndInverseAllComponents()
{
for (int i = 0; i < this.components.Components.Length; i++)
{
PdfJsFrameComponent frameComponent = this.Frame.Components[i];
PdfJsComponent component = this.components.Components[i];
this.QuantizeAndInverseComponentData(component, frameComponent);
}
}
/// <summary> /// <summary>
/// Fills the given image with the color data /// Fills the given image with the color data. TODO: Delete ME!!
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="image">The image</param> /// <param name="image">The image</param>
@ -400,8 +363,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
} }
this.pixelArea = new PdfJsJpegPixelArea(this.configuration.MemoryManager, image.Width, image.Height, this.ComponentCount); this.pixelArea = new PdfJsJpegPixelArea(this.configuration.MemoryManager, image.Width, image.Height, this.ComponentCount);
this.pixelArea.LinearizeBlockData(this.components);
// this.pixelArea.LinearizeBlockData(this.components);
if (this.ComponentCount == 1) if (this.ComponentCount == 1)
{ {
this.FillGrayScaleImage(image); this.FillGrayScaleImage(image);
@ -433,6 +396,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
} }
} }
/// <summary>
/// Returns the correct colorspace based on the image component count
/// </summary>
/// <returns>The <see cref="JpegColorSpace"/></returns>
private JpegColorSpace DeduceJpegColorSpace() private JpegColorSpace DeduceJpegColorSpace()
{ {
if (this.ComponentCount == 1) if (this.ComponentCount == 1)
@ -536,12 +503,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
byte[] profile = new byte[remaining]; byte[] profile = new byte[remaining];
this.InputStream.Read(profile, 0, remaining); this.InputStream.Read(profile, 0, remaining);
if (profile[0] == PdfJsJpegConstants.Markers.Exif.E && if (ProfileResolver.IsProfile(profile, ProfileResolver.ExifMarker))
profile[1] == PdfJsJpegConstants.Markers.Exif.X &&
profile[2] == PdfJsJpegConstants.Markers.Exif.I &&
profile[3] == PdfJsJpegConstants.Markers.Exif.F &&
profile[4] == PdfJsJpegConstants.Markers.Exif.Null &&
profile[5] == PdfJsJpegConstants.Markers.Exif.Null)
{ {
this.isExif = true; this.isExif = true;
this.MetaData.ExifProfile = new ExifProfile(profile); this.MetaData.ExifProfile = new ExifProfile(profile);
@ -566,18 +528,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.InputStream.Read(identifier, 0, Icclength); this.InputStream.Read(identifier, 0, Icclength);
remaining -= Icclength; // We have read it by this point remaining -= Icclength; // We have read it by this point
if (identifier[0] == PdfJsJpegConstants.Markers.ICC.I && if (ProfileResolver.IsProfile(identifier, ProfileResolver.IccMarker))
identifier[1] == PdfJsJpegConstants.Markers.ICC.C &&
identifier[2] == PdfJsJpegConstants.Markers.ICC.C &&
identifier[3] == PdfJsJpegConstants.Markers.ICC.UnderScore &&
identifier[4] == PdfJsJpegConstants.Markers.ICC.P &&
identifier[5] == PdfJsJpegConstants.Markers.ICC.R &&
identifier[6] == PdfJsJpegConstants.Markers.ICC.O &&
identifier[7] == PdfJsJpegConstants.Markers.ICC.F &&
identifier[8] == PdfJsJpegConstants.Markers.ICC.I &&
identifier[9] == PdfJsJpegConstants.Markers.ICC.L &&
identifier[10] == PdfJsJpegConstants.Markers.ICC.E &&
identifier[11] == PdfJsJpegConstants.Markers.ICC.Null)
{ {
byte[] profile = new byte[remaining]; byte[] profile = new byte[remaining];
this.InputStream.Read(profile, 0, remaining); this.InputStream.Read(profile, 0, remaining);
@ -880,33 +831,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
successiveApproximation & 15); successiveApproximation & 15);
} }
/// <summary>
/// Build the data for the given component
/// </summary>
/// <param name="component">The component</param>
/// <param name="frameComponent">The frame component</param>
private void QuantizeAndInverseComponentData(PdfJsComponent component, PdfJsFrameComponent frameComponent)
{
int blocksPerLine = component.BlocksPerLine;
int blocksPerColumn = component.BlocksPerColumn;
using (IBuffer<short> computationBuffer = this.configuration.MemoryManager.Allocate<short>(64, true))
{
// ref short quantizationTableRef = ref MemoryMarshal.GetReference(this.quantizationTables.Tables.GetRowSpan(frameComponent.QuantizationTableIndex));
// ref short computationBufferSpan = ref MemoryMarshal.GetReference(computationBuffer.Span);
//
// for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++)
// {
// for (int blockCol = 0; blockCol < blocksPerLine; blockCol++)
// {
// int offset = 64 * (((blocksPerLine + 1) * blockRow) + blockCol);
// PdfJsIDCT.QuantizeAndInverse(frameComponent, offset, ref computationBufferSpan, ref quantizationTableRef);
// }
// }
}
// component.Output = frameComponent.BlockData;
}
/// <summary> /// <summary>
/// Builds the huffman tables /// Builds the huffman tables
/// </summary> /// </summary>
@ -1029,6 +953,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
this.ColorSpace = this.DeduceJpegColorSpace(); this.ColorSpace = this.DeduceJpegColorSpace();
this.AssignResolution();
using (var postProcessor = new JpegImagePostProcessor(this.configuration.MemoryManager, this)) using (var postProcessor = new JpegImagePostProcessor(this.configuration.MemoryManager, this))
{ {
var image = new Image<TPixel>(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData); var image = new Image<TPixel>(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData);

22
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -453,12 +453,28 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(TestImages.Jpeg.Baseline.Ycck, 32)] [InlineData(TestImages.Jpeg.Baseline.Ycck, 32)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg400, 8)] [InlineData(TestImages.Jpeg.Baseline.Jpeg400, 8)]
[InlineData(TestImages.Jpeg.Baseline.Snake, 24)] [InlineData(TestImages.Jpeg.Baseline.Snake, 24)]
public void DetectPixelSize(string imagePath, int expectedPixelSize) public void DetectPixelSizeGolang(string imagePath, int expectedPixelSize)
{ {
TestFile testFile = TestFile.Create(imagePath); var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false)) using (var stream = new MemoryStream(testFile.Bytes, false))
{ {
Assert.Equal(expectedPixelSize, Image.Identify(stream)?.PixelType?.BitsPerPixel); Assert.Equal(expectedPixelSize, ((IImageInfoDetector)OrigJpegDecoder).Identify(Configuration.Default, stream)?.PixelType?.BitsPerPixel);
}
}
[Theory]
[InlineData(TestImages.Jpeg.Progressive.Progress, 24)]
[InlineData(TestImages.Jpeg.Progressive.Fb, 24)]
[InlineData(TestImages.Jpeg.Baseline.Cmyk, 32)]
[InlineData(TestImages.Jpeg.Baseline.Ycck, 32)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg400, 8)]
[InlineData(TestImages.Jpeg.Baseline.Snake, 24)]
public void DetectPixelSizePdfJs(string imagePath, int expectedPixelSize)
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
{
Assert.Equal(expectedPixelSize, ((IImageInfoDetector)PdfJsJpegDecoder).Identify(Configuration.Default, stream)?.PixelType?.BitsPerPixel);
} }
} }
} }

6
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs

@ -117,10 +117,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
IEnumerable<ImageSimilarityReport<TPixelA, TPixelB>> reports = comparer.CompareImages(expected, actual); IEnumerable<ImageSimilarityReport<TPixelA, TPixelB>> reports = comparer.CompareImages(expected, actual);
if (reports.Any()) if (reports.Any())
{ {
List<ImageSimilarityReport<TPixelA, TPixelB>> cleanedReports = new List<ImageSimilarityReport<TPixelA, TPixelB>>(reports.Count()); var cleanedReports = new List<ImageSimilarityReport<TPixelA, TPixelB>>(reports.Count());
foreach (var r in reports) foreach (ImageSimilarityReport<TPixelA, TPixelB> r in reports)
{ {
var outsideChanges = r.Differences.Where(x => !( IEnumerable<PixelDifference> outsideChanges = r.Differences.Where(x => !(
ignoredRegion.X <= x.Position.X && ignoredRegion.X <= x.Position.X &&
x.Position.X <= ignoredRegion.Right && x.Position.X <= ignoredRegion.Right &&
ignoredRegion.Y <= x.Position.Y && ignoredRegion.Y <= x.Position.Y &&

Loading…
Cancel
Save