Skip to content

Commit 5a711a8

Browse files
Merge remote-tracking branch 'upstream/main'
2 parents b0dc908 + d93bc6c commit 5a711a8

154 files changed

Lines changed: 2139 additions & 797 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build-and-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676
git config --global core.longpaths true
7777
7878
- name: Git Checkout
79-
uses: actions/checkout@v3
79+
uses: actions/checkout@v4
8080
with:
8181
fetch-depth: 0
8282
submodules: recursive
@@ -172,7 +172,7 @@ jobs:
172172
git config --global core.longpaths true
173173
174174
- name: Git Checkout
175-
uses: actions/checkout@v3
175+
uses: actions/checkout@v4
176176
with:
177177
fetch-depth: 0
178178
submodules: recursive

.github/workflows/code-coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
git config --global core.longpaths true
2525
2626
- name: Git Checkout
27-
uses: actions/checkout@v3
27+
uses: actions/checkout@v4
2828
with:
2929
fetch-depth: 0
3030
submodules: recursive

src/ImageSharp/Advanced/AdvancedImageExtensions.cs

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,25 @@ public static IImageEncoder DetectEncoder(this Image source, string filePath)
2727
Guard.NotNull(filePath, nameof(filePath));
2828

2929
string ext = Path.GetExtension(filePath);
30-
if (!source.GetConfiguration().ImageFormatsManager.TryFindFormatByFileExtension(ext, out IImageFormat? format))
30+
if (!source.Configuration.ImageFormatsManager.TryFindFormatByFileExtension(ext, out IImageFormat? format))
3131
{
3232
StringBuilder sb = new();
3333
sb = sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}'. Registered encoders include:");
34-
foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats)
34+
foreach (IImageFormat fmt in source.Configuration.ImageFormats)
3535
{
3636
sb = sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
3737
}
3838

3939
throw new UnknownImageFormatException(sb.ToString());
4040
}
4141

42-
IImageEncoder? encoder = source.GetConfiguration().ImageFormatsManager.GetEncoder(format);
42+
IImageEncoder? encoder = source.Configuration.ImageFormatsManager.GetEncoder(format);
4343

4444
if (encoder is null)
4545
{
4646
StringBuilder sb = new();
4747
sb = sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
48-
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
48+
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.Configuration.ImageFormatsManager.ImageEncoders)
4949
{
5050
sb = sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
5151
}
@@ -76,30 +76,6 @@ public static void AcceptVisitor(this Image source, IImageVisitor visitor)
7676
public static Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor, CancellationToken cancellationToken = default)
7777
=> source.AcceptAsync(visitor, cancellationToken);
7878

79-
/// <summary>
80-
/// Gets the configuration for the image.
81-
/// </summary>
82-
/// <param name="source">The source image.</param>
83-
/// <returns>Returns the configuration.</returns>
84-
public static Configuration GetConfiguration(this Image source)
85-
=> GetConfiguration((IConfigurationProvider)source);
86-
87-
/// <summary>
88-
/// Gets the configuration for the image frame.
89-
/// </summary>
90-
/// <param name="source">The source image.</param>
91-
/// <returns>Returns the configuration.</returns>
92-
public static Configuration GetConfiguration(this ImageFrame source)
93-
=> GetConfiguration((IConfigurationProvider)source);
94-
95-
/// <summary>
96-
/// Gets the configuration.
97-
/// </summary>
98-
/// <param name="source">The source image</param>
99-
/// <returns>Returns the bounds of the image</returns>
100-
private static Configuration GetConfiguration(IConfigurationProvider source)
101-
=> source?.Configuration ?? Configuration.Default;
102-
10379
/// <summary>
10480
/// Gets the representation of the pixels as a <see cref="IMemoryGroup{T}"/> containing the backing pixel data of the image
10581
/// stored in row major order, as a list of contiguous <see cref="Memory{T}"/> blocks in the source image's pixel format.
@@ -167,12 +143,4 @@ public static Memory<TPixel> DangerousGetPixelRowMemory<TPixel>(this Image<TPixe
167143

168144
return source.Frames.RootFrame.PixelBuffer.GetSafeRowMemory(rowIndex);
169145
}
170-
171-
/// <summary>
172-
/// Gets the <see cref="MemoryAllocator"/> assigned to 'source'.
173-
/// </summary>
174-
/// <param name="source">The source image.</param>
175-
/// <returns>Returns the configuration.</returns>
176-
internal static MemoryAllocator GetMemoryAllocator(this IConfigurationProvider source)
177-
=> GetConfiguration(source).MemoryAllocator;
178146
}

src/ImageSharp/Advanced/IConfigurationProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Advanced;
66
/// <summary>
77
/// Defines the contract for objects that can provide access to configuration.
88
/// </summary>
9-
internal interface IConfigurationProvider
9+
public interface IConfigurationProvider
1010
{
1111
/// <summary>
1212
/// Gets the configuration which allows altering default behaviour or extending the library.

src/ImageSharp/Color/Color.Conversions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public Color(Vector4 vector)
139139
/// </summary>
140140
/// <param name="color">The <see cref="Color"/>.</param>
141141
/// <returns>The <see cref="Vector4"/>.</returns>
142-
public static explicit operator Vector4(Color color) => color.ToVector4();
142+
public static explicit operator Vector4(Color color) => color.ToScaledVector4();
143143

144144
/// <summary>
145145
/// Converts an <see cref="Vector4"/> to <see cref="Color"/>.
@@ -228,7 +228,7 @@ internal Bgr24 ToBgr24()
228228
}
229229

230230
[MethodImpl(InliningOptions.ShortMethod)]
231-
internal Vector4 ToVector4()
231+
internal Vector4 ToScaledVector4()
232232
{
233233
if (this.boxedHighPrecisionPixel is null)
234234
{

src/ImageSharp/Color/Color.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,17 @@ public Color WithAlpha(float alpha)
251251
/// </summary>
252252
/// <returns>A hexadecimal string representation of the value.</returns>
253253
[MethodImpl(InliningOptions.ShortMethod)]
254-
public string ToHex() => this.data.ToRgba32().ToHex();
254+
public string ToHex()
255+
{
256+
if (this.boxedHighPrecisionPixel is not null)
257+
{
258+
Rgba32 rgba = default;
259+
this.boxedHighPrecisionPixel.ToRgba32(ref rgba);
260+
return rgba.ToHex();
261+
}
262+
263+
return this.data.ToRgba32().ToHex();
264+
}
255265

256266
/// <inheritdoc />
257267
public override string ToString() => this.ToHex();

src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,33 @@ public static Vector256<float> MultiplyAddNegated(
629629
return Avx.Subtract(c, Avx.Multiply(a, b));
630630
}
631631

632+
/// <summary>
633+
/// Blend packed 8-bit integers from <paramref name="left"/> and <paramref name="right"/> using <paramref name="mask"/>.
634+
/// The high bit of each corresponding <paramref name="mask"/> byte determines the selection.
635+
/// If the high bit is set the element of <paramref name="left"/> is selected.
636+
/// The element of <paramref name="right"/> is selected otherwise.
637+
/// </summary>
638+
/// <param name="left">The left vector.</param>
639+
/// <param name="right">The right vector.</param>
640+
/// <param name="mask">The mask vector.</param>
641+
/// <returns>The <see cref="Vector256{T}"/>.</returns>
642+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
643+
public static Vector128<byte> BlendVariable(Vector128<byte> left, Vector128<byte> right, Vector128<byte> mask)
644+
{
645+
if (Sse41.IsSupported)
646+
{
647+
return Sse41.BlendVariable(left, right, mask);
648+
}
649+
else if (Sse2.IsSupported)
650+
{
651+
return Sse2.Or(Sse2.And(right, mask), Sse2.AndNot(mask, left));
652+
}
653+
654+
// Use a signed shift right to create a mask with the sign bit.
655+
Vector128<short> signedMask = AdvSimd.ShiftRightArithmetic(mask.AsInt16(), 7);
656+
return AdvSimd.BitwiseSelect(signedMask, right.AsInt16(), left.AsInt16()).AsByte();
657+
}
658+
632659
/// <summary>
633660
/// <see cref="ByteToNormalizedFloat"/> as many elements as possible, slicing them down (keeping the remainder).
634661
/// </summary>

src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -161,29 +161,25 @@ public override int Read(byte[] buffer, int offset, int count)
161161
bytesToRead = Math.Min(count - totalBytesRead, this.currentDataRemaining);
162162
this.currentDataRemaining -= bytesToRead;
163163
bytesRead = this.innerStream.Read(buffer, offset, bytesToRead);
164+
if (bytesRead == 0)
165+
{
166+
return totalBytesRead;
167+
}
168+
164169
totalBytesRead += bytesRead;
165170
}
166171

167172
return totalBytesRead;
168173
}
169174

170175
/// <inheritdoc/>
171-
public override long Seek(long offset, SeekOrigin origin)
172-
{
173-
throw new NotSupportedException();
174-
}
176+
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
175177

176178
/// <inheritdoc/>
177-
public override void SetLength(long value)
178-
{
179-
throw new NotSupportedException();
180-
}
179+
public override void SetLength(long value) => throw new NotSupportedException();
181180

182181
/// <inheritdoc/>
183-
public override void Write(byte[] buffer, int offset, int count)
184-
{
185-
throw new NotSupportedException();
186-
}
182+
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
187183

188184
/// <inheritdoc/>
189185
protected override void Dispose(bool disposing)
@@ -246,22 +242,17 @@ private bool InitializeInflateStream(bool isCriticalChunk)
246242
// CINFO is not defined in this specification for CM not equal to 8.
247243
throw new ImageFormatException($"Invalid window size for ZLIB header: cinfo={cinfo}");
248244
}
249-
else
250-
{
251-
return false;
252-
}
245+
246+
return false;
253247
}
254248
}
249+
else if (isCriticalChunk)
250+
{
251+
throw new ImageFormatException($"Bad method for ZLIB header: cmf={cmf}");
252+
}
255253
else
256254
{
257-
if (isCriticalChunk)
258-
{
259-
throw new ImageFormatException($"Bad method for ZLIB header: cmf={cmf}");
260-
}
261-
else
262-
{
263-
return false;
264-
}
255+
return false;
265256
}
266257

267258
// The preset dictionary.
@@ -270,7 +261,11 @@ private bool InitializeInflateStream(bool isCriticalChunk)
270261
{
271262
// We don't need this for inflate so simply skip by the next four bytes.
272263
// https://tools.ietf.org/html/rfc1950#page-6
273-
this.innerStream.Read(ChecksumBuffer, 0, 4);
264+
if (this.innerStream.Read(ChecksumBuffer, 0, 4) != 4)
265+
{
266+
return false;
267+
}
268+
274269
this.currentDataRemaining -= 4;
275270
}
276271

src/ImageSharp/Formats/Bmp/BmpEncoder.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Six Labors Split License.
33

44
using SixLabors.ImageSharp.Advanced;
5+
using SixLabors.ImageSharp.Processing;
56

67
namespace SixLabors.ImageSharp.Formats.Bmp;
78

@@ -10,6 +11,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp;
1011
/// </summary>
1112
public sealed class BmpEncoder : QuantizingImageEncoder
1213
{
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="BmpEncoder"/> class.
16+
/// </summary>
17+
public BmpEncoder() => this.Quantizer = KnownQuantizers.Octree;
18+
1319
/// <summary>
1420
/// Gets the number of bits per pixel.
1521
/// </summary>
@@ -26,7 +32,7 @@ public sealed class BmpEncoder : QuantizingImageEncoder
2632
/// <inheritdoc/>
2733
protected override void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken cancellationToken)
2834
{
29-
BmpEncoderCore encoder = new(this, image.GetMemoryAllocator());
35+
BmpEncoderCore encoder = new(this, image.Configuration.MemoryAllocator);
3036
encoder.Encode(image, stream, cancellationToken);
3137
}
3238
}

src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using SixLabors.ImageSharp.Memory;
1010
using SixLabors.ImageSharp.Metadata;
1111
using SixLabors.ImageSharp.PixelFormats;
12+
using SixLabors.ImageSharp.Processing;
1213
using SixLabors.ImageSharp.Processing.Processors.Quantization;
1314

1415
namespace SixLabors.ImageSharp.Formats.Bmp;
@@ -100,7 +101,7 @@ public BmpEncoderCore(BmpEncoder encoder, MemoryAllocator memoryAllocator)
100101
{
101102
this.memoryAllocator = memoryAllocator;
102103
this.bitsPerPixel = encoder.BitsPerPixel;
103-
this.quantizer = encoder.Quantizer;
104+
this.quantizer = encoder.Quantizer ?? KnownQuantizers.Octree;
104105
this.pixelSamplingStrategy = encoder.PixelSamplingStrategy;
105106
this.infoHeaderType = encoder.SupportTransparency ? BmpInfoHeaderType.WinVersion4 : BmpInfoHeaderType.WinVersion3;
106107
}
@@ -118,7 +119,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
118119
Guard.NotNull(image, nameof(image));
119120
Guard.NotNull(stream, nameof(stream));
120121

121-
Configuration configuration = image.GetConfiguration();
122+
Configuration configuration = image.Configuration;
122123
ImageMetadata metadata = image.Metadata;
123124
BmpMetadata bmpMetadata = metadata.GetBmpMetadata();
124125
this.bitsPerPixel ??= bmpMetadata.BitsPerPixel;

0 commit comments

Comments
 (0)