diff --git a/.travis.yml b/.travis.yml
index a4f68b1d1b..70501a484b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ matrix:
- os: linux # Ubuntu 14.04
dist: trusty
sudo: required
- dotnet: 1.0.1
+ dotnet: 1.0.4
mono: latest
# - os: osx # OSX 10.11
# osx_image: xcode7.3.1
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 453197b0ca..ae20be7d5d 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -7,6 +7,7 @@ using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
@@ -38,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The global color table.
///
- private byte[] globalColorTable;
+ private Buffer globalColorTable;
///
/// The global color table length
@@ -123,10 +124,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{
this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
- this.globalColorTable = ArrayPool.Shared.Rent(this.globalColorTableLength);
+ this.globalColorTable = Buffer.CreateClean(this.globalColorTableLength);
// Read the global color table from the stream
- stream.Read(this.globalColorTable, 0, this.globalColorTableLength);
+ stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength);
}
// Loop though the respective gif parts and read the data.
@@ -154,10 +155,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.ReadComments();
break;
case GifConstants.ApplicationExtensionLabel:
- this.Skip(12); // No need to read.
+
+ // The application extension length should be 11 but we've got test images that incorrectly
+ // set this to 252.
+ int appLength = stream.ReadByte();
+ this.Skip(appLength); // No need to read.
break;
case GifConstants.PlainTextLabel:
- this.Skip(13); // Not supported by any known decoder.
+ int plainLength = stream.ReadByte();
+ this.Skip(plainLength); // Not supported by any known decoder.
break;
}
}
@@ -175,10 +181,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
finally
{
- if (this.globalColorTable != null)
- {
- ArrayPool.Shared.Return(this.globalColorTable);
- }
+ this.globalColorTable?.Dispose();
}
return this.image;
@@ -309,19 +312,19 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
GifImageDescriptor imageDescriptor = this.ReadImageDescriptor();
- byte[] localColorTable = null;
- byte[] indices = null;
+ Buffer localColorTable = null;
+ Buffer indices = null;
try
{
// Determine the color table for this frame. If there is a local one, use it otherwise use the global color table.
if (imageDescriptor.LocalColorTableFlag)
{
int length = imageDescriptor.LocalColorTableSize * 3;
- localColorTable = ArrayPool.Shared.Rent(length);
- this.currentStream.Read(localColorTable, 0, length);
+ localColorTable = Buffer.CreateClean(length);
+ this.currentStream.Read(localColorTable.Array, 0, length);
}
- indices = ArrayPool.Shared.Rent(imageDescriptor.Width * imageDescriptor.Height);
+ indices = Buffer.CreateClean(imageDescriptor.Width * imageDescriptor.Height);
this.ReadFrameIndices(imageDescriptor, indices);
this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, imageDescriptor);
@@ -331,12 +334,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
finally
{
- if (localColorTable != null)
- {
- ArrayPool.Shared.Return(localColorTable);
- }
-
- ArrayPool.Shared.Return(indices);
+ localColorTable?.Dispose();
+ indices?.Dispose();
}
}
@@ -346,7 +345,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The .
/// The pixel array to write to.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ReadFrameIndices(GifImageDescriptor imageDescriptor, byte[] indices)
+ private void ReadFrameIndices(GifImageDescriptor imageDescriptor, Span indices)
{
int dataSize = this.currentStream.ReadByte();
using (var lzwDecoder = new LzwDecoder(this.currentStream))
@@ -361,7 +360,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The indexed pixels.
/// The color table containing the available colors.
/// The
- private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
+ private void ReadFrameColors(Span indices, Span colorTable, GifImageDescriptor descriptor)
{
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;
@@ -444,7 +443,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
var rgba = new Rgba32(0, 0, 0, 255);
- for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
+ // #403 The left + width value can be larger than the image width
+ for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < rowSpan.Length; x++)
{
int index = indices[i];
diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index b8f12f930a..3284dad657 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The height of the pixel index array.
/// Size of the data.
/// The pixel array to decode to.
- public void DecodePixels(int width, int height, int dataSize, byte[] pixels)
+ public void DecodePixels(int width, int height, int dataSize, Span pixels)
{
Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize));
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
index 92c7ebe114..67abba9f33 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.cs
@@ -583,7 +583,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
}
zig = this.RefineNonZeroes(ref bp, zig, val0, delta);
- if (bp.ReachedEOF)
+
+ if (bp.ReachedEOF || bp.HasError)
{
return;
}
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
index e7ffaa9d1a..61b18af551 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
@@ -688,7 +688,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
}
int th = this.Temp[0] & 0x0f;
- if (th > OrigHuffmanTree.MaxTh || (!this.IsProgressive && (th > 1)))
+ if (th > OrigHuffmanTree.MaxTh)
{
throw new ImageFormatException("Bad Th value");
}
diff --git a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
index 6841c1cb82..1cce90c0b7 100644
--- a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
@@ -74,9 +75,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
///
- public long Value => this.checksum;
+ public long Value
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return this.checksum;
+ }
+ }
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
this.checksum = 1;
@@ -88,6 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
/// The data value to add. The high byte of the int is ignored.
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(int value)
{
// We could make a length 1 byte array and call update again, but I
@@ -102,6 +112,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer)
{
if (buffer == null)
@@ -113,32 +124,14 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer, int offset, int count)
{
- if (buffer == null)
- {
- throw new ArgumentNullException(nameof(buffer));
- }
-
- if (offset < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "cannot be negative");
- }
-
- if (count < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count), "cannot be negative");
- }
-
- if (offset >= buffer.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset), "not a valid index into buffer");
- }
-
- if (offset + count > buffer.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(count), "exceeds buffer size");
- }
+ DebugGuard.NotNull(buffer, nameof(buffer));
+ DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset));
+ DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
+ DebugGuard.MustBeLessThan(offset, buffer.Length, nameof(offset));
+ DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count));
// (By Per Bothner)
uint s1 = this.checksum & 0xFFFF;
@@ -169,4 +162,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
this.checksum = (s2 << 16) | s1;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs
index 14a29b7aff..bd686f2b9f 100644
--- a/src/ImageSharp/Formats/Png/Zlib/Crc32.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/Crc32.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
@@ -108,18 +109,15 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
public long Value
{
- get
- {
- return this.crc;
- }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => this.crc;
- set
- {
- this.crc = (uint)value;
- }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ set => this.crc = (uint)value;
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
this.crc = 0;
@@ -129,6 +127,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// Updates the checksum with the given value.
///
/// The byte is taken as the lower 8 bits of value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(int value)
{
this.crc ^= CrcSeed;
@@ -137,6 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer)
{
if (buffer == null)
@@ -148,22 +148,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Update(byte[] buffer, int offset, int count)
{
- if (buffer == null)
- {
- throw new ArgumentNullException(nameof(buffer));
- }
-
- if (count < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(count), "Count cannot be less than zero");
- }
-
- if (offset < 0 || offset + count > buffer.Length)
- {
- throw new ArgumentOutOfRangeException(nameof(offset));
- }
+ DebugGuard.NotNull(buffer, nameof(buffer));
+ DebugGuard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
+ DebugGuard.MustBeGreaterThanOrEqualTo(offset, 0, nameof(offset));
+ DebugGuard.MustBeLessThanOrEqualTo(offset + count, buffer.Length, nameof(count));
this.crc ^= CrcSeed;
diff --git a/src/ImageSharp/Image/PixelArea{TPixel}.cs b/src/ImageSharp/Image/PixelArea{TPixel}.cs
index e9924f8235..1c7256455e 100644
--- a/src/ImageSharp/Image/PixelArea{TPixel}.cs
+++ b/src/ImageSharp/Image/PixelArea{TPixel}.cs
@@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp
///
/// The underlying buffer containing the raw pixel data.
///
- private Buffer byteBuffer;
+ private readonly Buffer byteBuffer;
///
/// Initializes a new instance of the class.
@@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp
this.RowStride = (width * GetComponentCount(componentOrder)) + padding;
this.Length = this.RowStride * height;
- this.byteBuffer = new Buffer(this.Length);
+ this.byteBuffer = Buffer.CreateClean(this.Length);
}
///
diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs
index 401003eedd..ac5ab09dbd 100644
--- a/src/ImageSharp/Memory/Buffer2DExtensions.cs
+++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Memory
///
/// The element type
/// The
- /// The rectangel subarea
+ /// The rectangle subarea
/// The
public static BufferArea GetArea(this IBuffer2D buffer, Rectangle rectangle)
where T : struct => new BufferArea(buffer, rectangle);
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
index 1169d2eadc..22a7c90b75 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal abstract partial class ResamplingWeightedProcessor
{
///
- /// Points to a collection of of weights allocated in .
+ /// Points to a collection of weights allocated in .
///
internal struct WeightsWindow
{
@@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
///
- /// Holds the values in an optimized contigous memory region.
+ /// Holds the values in an optimized contiguous memory region.
///
internal class WeightsBuffer : IDisposable
{
@@ -196,4 +196,4 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
index a4fdb1a1b4..17b42c5040 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
@@ -58,9 +58,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
// We will always be creating the clone even for mutate because thats the way this base processor works
// ------------
// For resize we know we are going to populate every pixel with fresh data and we want a different target size so
- // let's manually clone an empty set of images at the correct target and then have the base class processs them in turn.
+ // let's manually clone an empty set of images at the correct target and then have the base class process them in turn.
IEnumerable> frames = source.Frames.Select(x => new ImageFrame(this.Width, this.Height, x.MetaData.Clone())); // this will create places holders
- var image = new Image(config, source.MetaData.Clone(), frames); // base the place holder images in to prevet a extra frame being added
+ var image = new Image(config, source.MetaData.Clone(), frames); // base the place holder images in to prevent a extra frame being added
return image;
}
diff --git a/src/ImageSharp/Quantizers/Box.cs b/src/ImageSharp/Quantizers/Box.cs
index 4a1e17753f..cd1936b653 100644
--- a/src/ImageSharp/Quantizers/Box.cs
+++ b/src/ImageSharp/Quantizers/Box.cs
@@ -5,9 +5,8 @@ namespace SixLabors.ImageSharp.Quantizers
{
///
/// Represents a box color cube.
- /// TODO: This should be a struct for performance
///
- internal sealed class Box
+ internal struct Box
{
///
/// Gets or sets the min red value, exclusive.
@@ -54,4 +53,4 @@ namespace SixLabors.ImageSharp.Quantizers
///
public int Volume { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
index 44311e080b..cb9eb9b0e3 100644
--- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
@@ -168,20 +168,19 @@ namespace SixLabors.ImageSharp.Quantizers
this.palette = new TPixel[this.colors];
for (int k = 0; k < this.colors; k++)
{
- this.Mark(this.colorCube[k], (byte)k);
+ this.Mark(ref this.colorCube[k], (byte)k);
- float weight = Volume(this.colorCube[k], this.vwt);
+ float weight = Volume(ref this.colorCube[k], this.vwt);
if (MathF.Abs(weight) > Constants.Epsilon)
{
- float r = Volume(this.colorCube[k], this.vmr) / weight;
- float g = Volume(this.colorCube[k], this.vmg) / weight;
- float b = Volume(this.colorCube[k], this.vmb) / weight;
- float a = Volume(this.colorCube[k], this.vma) / weight;
-
- var color = default(TPixel);
- color.PackFromVector4(new Vector4(r, g, b, a) / 255F);
- this.palette[k] = color;
+ float r = Volume(ref this.colorCube[k], this.vmr);
+ float g = Volume(ref this.colorCube[k], this.vmg);
+ float b = Volume(ref this.colorCube[k], this.vmb);
+ float a = Volume(ref this.colorCube[k], this.vma);
+
+ ref TPixel color = ref this.palette[k];
+ color.PackFromVector4(new Vector4(r, g, b, a) / weight / 255F);
}
}
}
@@ -197,19 +196,21 @@ namespace SixLabors.ImageSharp.Quantizers
var rgba = default(Rgba32);
pixel.ToRgba32(ref rgba);
- int r = rgba.R >> 2; // 8 - IndexBits
- int g = rgba.G >> 2;
- int b = rgba.B >> 2;
- int a = rgba.A >> 5; // 8 - IndexAlphaBits
+ int r = rgba.R >> (8 - IndexBits);
+ int g = rgba.G >> (8 - IndexBits);
+ int b = rgba.B >> (8 - IndexBits);
+ int a = rgba.A >> (8 - IndexAlphaBits);
+
+ int index = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1);
- int ind = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1);
+ this.vwt[index]++;
+ this.vmr[index] += rgba.R;
+ this.vmg[index] += rgba.G;
+ this.vmb[index] += rgba.B;
+ this.vma[index] += rgba.A;
- this.vwt[ind]++;
- this.vmr[ind] += r;
- this.vmg[ind] += g;
- this.vmb[ind] += b;
- this.vma[ind] += a;
- this.m2[ind] += (r * r) + (g * g) + (b * b) + (a * a);
+ var vector = new Vector4(rgba.R, rgba.G, rgba.B, rgba.A);
+ this.m2[index] += Vector4.Dot(vector, vector);
}
///
@@ -301,7 +302,7 @@ namespace SixLabors.ImageSharp.Quantizers
/// The cube.
/// The moment.
/// The result.
- private static float Volume(Box cube, long[] moment)
+ private static float Volume(ref Box cube, long[] moment)
{
return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)]
- moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)]
@@ -328,12 +329,12 @@ namespace SixLabors.ImageSharp.Quantizers
/// The direction.
/// The moment.
/// The result.
- private static long Bottom(Box cube, int direction, long[] moment)
+ private static long Bottom(ref Box cube, int direction, long[] moment)
{
switch (direction)
{
// Red
- case 0:
+ case 3:
return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)]
+ moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)]
+ moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)]
@@ -344,7 +345,7 @@ namespace SixLabors.ImageSharp.Quantizers
+ moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
// Green
- case 1:
+ case 2:
return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)]
@@ -355,7 +356,7 @@ namespace SixLabors.ImageSharp.Quantizers
+ moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
// Blue
- case 2:
+ case 1:
return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)]
+ moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)]
@@ -366,7 +367,7 @@ namespace SixLabors.ImageSharp.Quantizers
+ moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
// Alpha
- case 3:
+ case 0:
return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)]
+ moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)]
@@ -389,12 +390,12 @@ namespace SixLabors.ImageSharp.Quantizers
/// The position.
/// The moment.
/// The result.
- private static long Top(Box cube, int direction, int position, long[] moment)
+ private static long Top(ref Box cube, int direction, int position, long[] moment)
{
switch (direction)
{
// Red
- case 0:
+ case 3:
return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)]
- moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A0)]
- moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)]
@@ -405,7 +406,7 @@ namespace SixLabors.ImageSharp.Quantizers
- moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)];
// Green
- case 1:
+ case 2:
return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)]
- moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A0)]
- moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)]
@@ -416,7 +417,7 @@ namespace SixLabors.ImageSharp.Quantizers
- moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)];
// Blue
- case 2:
+ case 1:
return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)]
- moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)]
- moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)]
@@ -427,7 +428,7 @@ namespace SixLabors.ImageSharp.Quantizers
- moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)];
// Alpha
- case 3:
+ case 0:
return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)]
- moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)]
- moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)]
@@ -553,12 +554,12 @@ namespace SixLabors.ImageSharp.Quantizers
///
/// The cube.
/// The .
- private float Variance(Box cube)
+ private float Variance(ref Box cube)
{
- float dr = Volume(cube, this.vmr);
- float dg = Volume(cube, this.vmg);
- float db = Volume(cube, this.vmb);
- float da = Volume(cube, this.vma);
+ float dr = Volume(ref cube, this.vmr);
+ float dg = Volume(ref cube, this.vmg);
+ float db = Volume(ref cube, this.vmb);
+ float da = Volume(ref cube, this.vma);
float xx =
this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)]
@@ -578,7 +579,8 @@ namespace SixLabors.ImageSharp.Quantizers
- this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)]
+ this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)];
- return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(cube, this.vwt));
+ var vector = new Vector4(dr, dg, db, da);
+ return xx - (Vector4.Dot(vector, vector) / Volume(ref cube, this.vwt));
}
///
@@ -599,38 +601,33 @@ namespace SixLabors.ImageSharp.Quantizers
/// The whole alpha.
/// The whole weight.
/// The .
- private float Maximize(Box cube, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW)
+ private float Maximize(ref Box cube, int direction, int first, int last, out int cut, float wholeR, float wholeG, float wholeB, float wholeA, float wholeW)
{
- long baseR = Bottom(cube, direction, this.vmr);
- long baseG = Bottom(cube, direction, this.vmg);
- long baseB = Bottom(cube, direction, this.vmb);
- long baseA = Bottom(cube, direction, this.vma);
- long baseW = Bottom(cube, direction, this.vwt);
+ long baseR = Bottom(ref cube, direction, this.vmr);
+ long baseG = Bottom(ref cube, direction, this.vmg);
+ long baseB = Bottom(ref cube, direction, this.vmb);
+ long baseA = Bottom(ref cube, direction, this.vma);
+ long baseW = Bottom(ref cube, direction, this.vwt);
float max = 0F;
cut = -1;
for (int i = first; i < last; i++)
{
- float halfR = baseR + Top(cube, direction, i, this.vmr);
- float halfG = baseG + Top(cube, direction, i, this.vmg);
- float halfB = baseB + Top(cube, direction, i, this.vmb);
- float halfA = baseA + Top(cube, direction, i, this.vma);
- float halfW = baseW + Top(cube, direction, i, this.vwt);
-
- float temp;
+ float halfR = baseR + Top(ref cube, direction, i, this.vmr);
+ float halfG = baseG + Top(ref cube, direction, i, this.vmg);
+ float halfB = baseB + Top(ref cube, direction, i, this.vmb);
+ float halfA = baseA + Top(ref cube, direction, i, this.vma);
+ float halfW = baseW + Top(ref cube, direction, i, this.vwt);
if (MathF.Abs(halfW) < Constants.Epsilon)
{
continue;
}
- temp = ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW;
+ var vector = new Vector4(halfR, halfG, halfB, halfA);
+ float temp = Vector4.Dot(vector, vector) / halfW;
- halfR = wholeR - halfR;
- halfG = wholeG - halfG;
- halfB = wholeB - halfB;
- halfA = wholeA - halfA;
halfW = wholeW - halfW;
if (MathF.Abs(halfW) < Constants.Epsilon)
@@ -638,7 +635,14 @@ namespace SixLabors.ImageSharp.Quantizers
continue;
}
- temp += ((halfR * halfR) + (halfG * halfG) + (halfB * halfB) + (halfA * halfA)) / halfW;
+ halfR = wholeR - halfR;
+ halfG = wholeG - halfG;
+ halfB = wholeB - halfB;
+ halfA = wholeA - halfA;
+
+ vector = new Vector4(halfR, halfG, halfB, halfA);
+
+ temp += Vector4.Dot(vector, vector) / halfW;
if (temp > max)
{
@@ -656,24 +660,24 @@ namespace SixLabors.ImageSharp.Quantizers
/// The first set.
/// The second set.
/// Returns a value indicating whether the box has been split.
- private bool Cut(Box set1, Box set2)
+ private bool Cut(ref Box set1, ref Box set2)
{
- float wholeR = Volume(set1, this.vmr);
- float wholeG = Volume(set1, this.vmg);
- float wholeB = Volume(set1, this.vmb);
- float wholeA = Volume(set1, this.vma);
- float wholeW = Volume(set1, this.vwt);
+ float wholeR = Volume(ref set1, this.vmr);
+ float wholeG = Volume(ref set1, this.vmg);
+ float wholeB = Volume(ref set1, this.vmb);
+ float wholeA = Volume(ref set1, this.vma);
+ float wholeW = Volume(ref set1, this.vwt);
- float maxr = this.Maximize(set1, 0, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW);
- float maxg = this.Maximize(set1, 1, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW);
- float maxb = this.Maximize(set1, 2, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW);
- float maxa = this.Maximize(set1, 3, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW);
+ float maxr = this.Maximize(ref set1, 3, set1.R0 + 1, set1.R1, out int cutr, wholeR, wholeG, wholeB, wholeA, wholeW);
+ float maxg = this.Maximize(ref set1, 2, set1.G0 + 1, set1.G1, out int cutg, wholeR, wholeG, wholeB, wholeA, wholeW);
+ float maxb = this.Maximize(ref set1, 1, set1.B0 + 1, set1.B1, out int cutb, wholeR, wholeG, wholeB, wholeA, wholeW);
+ float maxa = this.Maximize(ref set1, 0, set1.A0 + 1, set1.A1, out int cuta, wholeR, wholeG, wholeB, wholeA, wholeW);
int dir;
if ((maxr >= maxg) && (maxr >= maxb) && (maxr >= maxa))
{
- dir = 0;
+ dir = 3;
if (cutr < 0)
{
@@ -682,15 +686,15 @@ namespace SixLabors.ImageSharp.Quantizers
}
else if ((maxg >= maxr) && (maxg >= maxb) && (maxg >= maxa))
{
- dir = 1;
+ dir = 2;
}
else if ((maxb >= maxr) && (maxb >= maxg) && (maxb >= maxa))
{
- dir = 2;
+ dir = 1;
}
else
{
- dir = 3;
+ dir = 0;
}
set2.R1 = set1.R1;
@@ -701,7 +705,7 @@ namespace SixLabors.ImageSharp.Quantizers
switch (dir)
{
// Red
- case 0:
+ case 3:
set2.R0 = set1.R1 = cutr;
set2.G0 = set1.G0;
set2.B0 = set1.B0;
@@ -709,7 +713,7 @@ namespace SixLabors.ImageSharp.Quantizers
break;
// Green
- case 1:
+ case 2:
set2.G0 = set1.G1 = cutg;
set2.R0 = set1.R0;
set2.B0 = set1.B0;
@@ -717,7 +721,7 @@ namespace SixLabors.ImageSharp.Quantizers
break;
// Blue
- case 2:
+ case 1:
set2.B0 = set1.B1 = cutb;
set2.R0 = set1.R0;
set2.G0 = set1.G0;
@@ -725,7 +729,7 @@ namespace SixLabors.ImageSharp.Quantizers
break;
// Alpha
- case 3:
+ case 0:
set2.A0 = set1.A1 = cuta;
set2.R0 = set1.R0;
set2.G0 = set1.G0;
@@ -744,7 +748,7 @@ namespace SixLabors.ImageSharp.Quantizers
///
/// The cube.
/// A label.
- private void Mark(Box cube, byte label)
+ private void Mark(ref Box cube, byte label)
{
for (int r = cube.R0 + 1; r <= cube.R1; r++)
{
@@ -769,23 +773,21 @@ namespace SixLabors.ImageSharp.Quantizers
this.colorCube = new Box[this.colors];
float[] vv = new float[this.colors];
- for (int i = 0; i < this.colors; i++)
- {
- this.colorCube[i] = new Box();
- }
-
- this.colorCube[0].R0 = this.colorCube[0].G0 = this.colorCube[0].B0 = this.colorCube[0].A0 = 0;
- this.colorCube[0].R1 = this.colorCube[0].G1 = this.colorCube[0].B1 = IndexCount - 1;
- this.colorCube[0].A1 = IndexAlphaCount - 1;
+ ref var cube = ref this.colorCube[0];
+ cube.R0 = cube.G0 = cube.B0 = cube.A0 = 0;
+ cube.R1 = cube.G1 = cube.B1 = IndexCount - 1;
+ cube.A1 = IndexAlphaCount - 1;
int next = 0;
for (int i = 1; i < this.colors; i++)
{
- if (this.Cut(this.colorCube[next], this.colorCube[i]))
+ ref var nextCube = ref this.colorCube[next];
+ ref var currentCube = ref this.colorCube[i];
+ if (this.Cut(ref nextCube, ref currentCube))
{
- vv[next] = this.colorCube[next].Volume > 1 ? this.Variance(this.colorCube[next]) : 0F;
- vv[i] = this.colorCube[i].Volume > 1 ? this.Variance(this.colorCube[i]) : 0F;
+ vv[next] = nextCube.Volume > 1 ? this.Variance(ref nextCube) : 0F;
+ vv[i] = currentCube.Volume > 1 ? this.Variance(ref currentCube) : 0F;
}
else
{
@@ -805,7 +807,7 @@ namespace SixLabors.ImageSharp.Quantizers
}
}
- if (temp <= 0.0)
+ if (temp <= 0F)
{
this.colors = i + 1;
break;
diff --git a/tests/ImageSharp.Benchmarks/Image/DecodePng.cs b/tests/ImageSharp.Benchmarks/Image/DecodePng.cs
index b9a9d5cfa2..eb13cf9290 100644
--- a/tests/ImageSharp.Benchmarks/Image/DecodePng.cs
+++ b/tests/ImageSharp.Benchmarks/Image/DecodePng.cs
@@ -10,29 +10,39 @@ namespace SixLabors.ImageSharp.Benchmarks.Image
using BenchmarkDotNet.Attributes;
+ using SixLabors.ImageSharp.Tests;
+
using CoreImage = ImageSharp.Image;
using CoreSize = SixLabors.Primitives.Size;
+ [Config(typeof(Config.ShortClr))]
public class DecodePng : BenchmarkBase
{
private byte[] pngBytes;
+ private string TestImageFullPath => Path.Combine(
+ TestEnvironment.InputImagesDirectoryFullPath,
+ this.TestImage);
+
+ [Params(TestImages.Png.Splash)]
+ public string TestImage { get; set; }
+
[GlobalSetup]
public void ReadImages()
{
if (this.pngBytes == null)
{
- this.pngBytes = File.ReadAllBytes("../ImageSharp.Tests/TestImages/Formats/Png/splash.png");
+ this.pngBytes = File.ReadAllBytes(this.TestImageFullPath);
}
}
[Benchmark(Baseline = true, Description = "System.Drawing Png")]
public Size PngSystemDrawing()
{
- using (MemoryStream memoryStream = new MemoryStream(this.pngBytes))
+ using (var memoryStream = new MemoryStream(this.pngBytes))
{
- using (Image image = Image.FromStream(memoryStream))
+ using (var image = Image.FromStream(memoryStream))
{
return image.Size;
}
@@ -42,9 +52,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Image
[Benchmark(Description = "ImageSharp Png")]
public CoreSize PngCore()
{
- using (MemoryStream memoryStream = new MemoryStream(this.pngBytes))
+ using (var memoryStream = new MemoryStream(this.pngBytes))
{
- using (Image image = CoreImage.Load(memoryStream))
+ using (var image = CoreImage.Load(memoryStream))
{
return new CoreSize(image.Width, image.Height);
}
diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
index cd78add758..76a31c1864 100644
--- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs
@@ -10,12 +10,16 @@ using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
{
+ using SixLabors.ImageSharp.Advanced;
+
public class GifDecoderTests
{
private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32;
public static readonly string[] TestFiles = { TestImages.Gif.Giphy, TestImages.Gif.Rings, TestImages.Gif.Trans };
+ public static readonly string[] BadAppExtFiles = { TestImages.Gif.Issues.BadAppExtLength, TestImages.Gif.Issues.BadAppExtLength_2 };
+
[Theory]
[WithFileCollection(nameof(TestFiles), PixelTypes)]
public void DecodeAndReSave(TestImageProvider imageProvider)
@@ -27,6 +31,7 @@ namespace SixLabors.ImageSharp.Tests
imageProvider.Utility.SaveTestOutputFile(image, "gif");
}
}
+
[Theory]
[WithFileCollection(nameof(TestFiles), PixelTypes)]
public void DecodeResizeAndSave(TestImageProvider imageProvider)
@@ -113,5 +118,43 @@ namespace SixLabors.ImageSharp.Tests
Assert.True(image.Frames.Count > 1);
}
}
+
+ [Fact]
+ public void CanDecodeIntermingledImages()
+ {
+ using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes))
+ using (var icon = Image.Load(TestFile.Create(TestImages.Png.Icon).Bytes))
+ using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes))
+ {
+ for (int i = 0; i < kumin1.Frames.Count; i++)
+ {
+ ImageFrame first = kumin1.Frames[i];
+ ImageFrame second = kumin2.Frames[i];
+ first.ComparePixelBufferTo(second.GetPixelSpan());
+ }
+ }
+ }
+
+ [Theory]
+ [WithFileCollection(nameof(BadAppExtFiles), PixelTypes.Rgba32)]
+ public void DecodeBadApplicationExtensionLength(TestImageProvider imageProvider)
+ where TPixel : struct, IPixel
+ {
+ using (Image image = imageProvider.GetImage())
+ {
+ imageProvider.Utility.SaveTestOutputFile(image, "bmp");
+ }
+ }
+
+ [Theory]
+ [WithFile(TestImages.Gif.Issues.BadDescriptorWidth, PixelTypes.Rgba32)]
+ public void DecodeBadDescriptorDimensionsLength(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ using (Image image = provider.GetImage())
+ {
+ provider.Utility.SaveTestOutputFile(image, "bmp");
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
index e26ab2cc9f..d529bbaeb6 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
@@ -42,6 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Baseline.Jpeg444,
TestImages.Jpeg.Baseline.Bad.BadEOF,
TestImages.Jpeg.Baseline.Bad.ExifUndefType,
+ TestImages.Jpeg.Issues.MultiHuffmanBaseline394,
};
public static string[] ProgressiveTestJpegs =
@@ -50,6 +51,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Progressive.Festzug, TestImages.Jpeg.Progressive.Bad.BadEOF,
TestImages.Jpeg.Issues.BadCoeffsProgressive178,
TestImages.Jpeg.Issues.MissingFF00ProgressiveGirl159,
+ TestImages.Jpeg.Issues.BadZigZagProgressive385
};
private static readonly Dictionary CustomToleranceValues = new Dictionary
@@ -67,6 +69,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[TestImages.Jpeg.Progressive.Festzug] = 0.02f / 100,
[TestImages.Jpeg.Progressive.Fb] = 0.16f / 100,
[TestImages.Jpeg.Progressive.Progress] = 0.31f / 100,
+ [TestImages.Jpeg.Issues.BadZigZagProgressive385] = 0.23f / 100,
};
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.RgbaVector;
diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs
index 9137049ee1..365aea04ae 100644
--- a/tests/ImageSharp.Tests/TestImages.cs
+++ b/tests/ImageSharp.Tests/TestImages.cs
@@ -31,6 +31,7 @@ namespace SixLabors.ImageSharp.Tests
public const string BikeGrayscale = "Png/BikeGrayscale.png";
public const string Rgb48BppInterlaced = "Png/rgb-48bpp-interlaced.png";
public const string SnakeGame = "Png/SnakeGame.png";
+ public const string Icon = "Png/icon.png";
// Filtered test images from http://www.schaik.com/pngsuite/pngsuite_fil_png.html
public const string Filter0 = "Png/filter0.png";
@@ -122,6 +123,8 @@ namespace SixLabors.ImageSharp.Tests
public const string CriticalEOF214 = "Jpg/issues/Issue214-CriticalEOF.jpg";
public const string MissingFF00ProgressiveGirl159 = "Jpg/issues/Issue159-MissingFF00-Progressive-Girl.jpg";
public const string BadCoeffsProgressive178 = "Jpg/issues/Issue178-BadCoeffsProgressive-Lemon.jpg";
+ public const string BadZigZagProgressive385 = "Jpg/issues/Issue385-BadZigZag-Progressive.jpg";
+ public const string MultiHuffmanBaseline394 = "Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg";
}
public static readonly string[] All = Baseline.All.Concat(Progressive.All).ToArray();
@@ -152,8 +155,16 @@ namespace SixLabors.ImageSharp.Tests
public const string Giphy = "Gif/giphy.gif";
public const string Cheers = "Gif/cheers.gif";
public const string Trans = "Gif/trans.gif";
+ public const string Kumin = "Gif/kumin.gif";
- public static readonly string[] All = { Rings, Giphy, Cheers, Trans };
+ public class Issues
+ {
+ public const string BadAppExtLength = "Gif/issues/issue405_badappextlength252.gif";
+ public const string BadAppExtLength_2 = "Gif/issues/issue405_badappextlength252-2.gif";
+ public const string BadDescriptorWidth = "Gif/issues/issue403_baddescriptorwidth.gif";
+ }
+
+ public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin };
}
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
index 505cdc1729..2b3cb1bcc3 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
@@ -29,7 +29,6 @@ namespace SixLabors.ImageSharp.Tests
/// The image provider
/// Details to be concatenated to the test output file, describing the parameters of the test.
/// The extension
- /// A boolean indicating whether we should save a smaller in size.
/// A boolean indicating whether to append the pixel type to the output file name.
public static Image DebugSave(
this Image image,
diff --git a/tests/Images/External b/tests/Images/External
index f99c2ea414..dc5479d00b 160000
--- a/tests/Images/External
+++ b/tests/Images/External
@@ -1 +1 @@
-Subproject commit f99c2ea41419cb3b3e80e5beeab611682252df78
+Subproject commit dc5479d00b2312f691e6249b9f7765e2316d4a30
diff --git a/tests/Images/Input/Gif/issues/issue403_baddescriptorwidth.gif b/tests/Images/Input/Gif/issues/issue403_baddescriptorwidth.gif
new file mode 100644
index 0000000000..fd13fbfb76
Binary files /dev/null and b/tests/Images/Input/Gif/issues/issue403_baddescriptorwidth.gif differ
diff --git a/tests/Images/Input/Gif/issues/issue405_badappextlength252-2.gif b/tests/Images/Input/Gif/issues/issue405_badappextlength252-2.gif
new file mode 100644
index 0000000000..6b7caa31d5
Binary files /dev/null and b/tests/Images/Input/Gif/issues/issue405_badappextlength252-2.gif differ
diff --git a/tests/Images/Input/Gif/issues/issue405_badappextlength252.gif b/tests/Images/Input/Gif/issues/issue405_badappextlength252.gif
new file mode 100644
index 0000000000..f3e36c9417
Binary files /dev/null and b/tests/Images/Input/Gif/issues/issue405_badappextlength252.gif differ
diff --git a/tests/Images/Input/Gif/kumin.gif b/tests/Images/Input/Gif/kumin.gif
new file mode 100644
index 0000000000..98f6d75692
Binary files /dev/null and b/tests/Images/Input/Gif/kumin.gif differ
diff --git a/tests/Images/Input/Jpg/issues/Issue385-BadZigZag-Progressive.jpg b/tests/Images/Input/Jpg/issues/Issue385-BadZigZag-Progressive.jpg
new file mode 100644
index 0000000000..3cb840622a
Binary files /dev/null and b/tests/Images/Input/Jpg/issues/Issue385-BadZigZag-Progressive.jpg differ
diff --git a/tests/Images/Input/Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg b/tests/Images/Input/Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg
new file mode 100644
index 0000000000..4a6ffaeeb2
Binary files /dev/null and b/tests/Images/Input/Jpg/issues/Issue394-MultiHuffmanBaseline-Speakers.jpg differ
diff --git a/tests/Images/Input/Png/icon.png b/tests/Images/Input/Png/icon.png
new file mode 100644
index 0000000000..edc8293701
Binary files /dev/null and b/tests/Images/Input/Png/icon.png differ