Skip to content

Commit a2429cc

Browse files
Merge pull request #2364 from stefannikolei/stefannikolei/nullable/webp
#2231 First steps for removing nullable disable in webp
2 parents 75121b2 + 992361f commit a2429cc

22 files changed

+285
-291
lines changed

.gitattributes

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,19 @@
6464
# Set explicit file behavior to:
6565
# treat as text
6666
# normalize to Unix-style line endings and
67-
# use a union merge when resoling conflicts
67+
# use a union merge when resolving conflicts
6868
###############################################################################
6969
*.csproj text eol=lf merge=union
7070
*.dbproj text eol=lf merge=union
7171
*.fsproj text eol=lf merge=union
7272
*.ncrunchproject text eol=lf merge=union
7373
*.vbproj text eol=lf merge=union
74+
*.shproj text eol=lf merge=union
7475
###############################################################################
7576
# Set explicit file behavior to:
7677
# treat as text
7778
# normalize to Windows-style line endings and
78-
# use a union merge when resoling conflicts
79+
# use a union merge when resolving conflicts
7980
###############################################################################
8081
*.sln text eol=crlf merge=union
8182
###############################################################################

src/ImageSharp/Formats/Webp/AlphaDecoder.cs

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
3-
#nullable disable
43

54
using System.Buffers;
5+
using System.Diagnostics.CodeAnalysis;
66
using System.Runtime.CompilerServices;
77
using System.Runtime.InteropServices;
88
using System.Runtime.Intrinsics;
@@ -38,7 +38,7 @@ public AlphaDecoder(int width, int height, IMemoryOwner<byte> data, byte alphaCh
3838
this.LastRow = 0;
3939
int totalPixels = width * height;
4040

41-
var compression = (WebpAlphaCompressionMethod)(alphaChunkHeader & 0x03);
41+
WebpAlphaCompressionMethod compression = (WebpAlphaCompressionMethod)(alphaChunkHeader & 0x03);
4242
if (compression is not WebpAlphaCompressionMethod.NoCompression and not WebpAlphaCompressionMethod.WebpLosslessCompression)
4343
{
4444
WebpThrowHelper.ThrowImageFormatException($"unexpected alpha compression method {compression} found");
@@ -59,7 +59,7 @@ public AlphaDecoder(int width, int height, IMemoryOwner<byte> data, byte alphaCh
5959

6060
if (this.Compressed)
6161
{
62-
var bitReader = new Vp8LBitReader(data);
62+
Vp8LBitReader bitReader = new(data);
6363
this.LosslessDecoder = new WebpLosslessDecoder(bitReader, memoryAllocator, configuration);
6464
this.LosslessDecoder.DecodeImageStream(this.Vp8LDec, width, height, true);
6565

@@ -110,6 +110,7 @@ public AlphaDecoder(int width, int height, IMemoryOwner<byte> data, byte alphaCh
110110
/// <summary>
111111
/// Gets a value indicating whether the alpha channel uses compression.
112112
/// </summary>
113+
[MemberNotNullWhen(true, nameof(LosslessDecoder))]
113114
private bool Compressed { get; }
114115

115116
/// <summary>
@@ -120,7 +121,7 @@ public AlphaDecoder(int width, int height, IMemoryOwner<byte> data, byte alphaCh
120121
/// <summary>
121122
/// Gets the Vp8L decoder which is used to de compress the alpha channel, if needed.
122123
/// </summary>
123-
private WebpLosslessDecoder LosslessDecoder { get; }
124+
private WebpLosslessDecoder? LosslessDecoder { get; }
124125

125126
/// <summary>
126127
/// Gets a value indicating whether the decoding needs 1 byte per pixel for decoding.
@@ -173,17 +174,14 @@ public void Decode()
173174
dst = dst[this.Width..];
174175
}
175176
}
177+
else if (this.Use8BDecode)
178+
{
179+
this.LosslessDecoder.DecodeAlphaData(this);
180+
}
176181
else
177182
{
178-
if (this.Use8BDecode)
179-
{
180-
this.LosslessDecoder.DecodeAlphaData(this);
181-
}
182-
else
183-
{
184-
this.LosslessDecoder.DecodeImageData(this.Vp8LDec, this.Vp8LDec.Pixels.Memory.Span);
185-
this.ExtractAlphaRows(this.Vp8LDec);
186-
}
183+
this.LosslessDecoder.DecodeImageData(this.Vp8LDec, this.Vp8LDec.Pixels.Memory.Span);
184+
this.ExtractAlphaRows(this.Vp8LDec);
187185
}
188186
}
189187

@@ -261,8 +259,7 @@ private void ExtractAlphaRows(Vp8LDecoder dec)
261259
{
262260
int numRowsToProcess = dec.Height;
263261
int width = dec.Width;
264-
Span<uint> pixels = dec.Pixels.Memory.Span;
265-
Span<uint> input = pixels;
262+
Span<uint> input = dec.Pixels.Memory.Span;
266263
Span<byte> output = this.Alpha.Memory.Span;
267264

268265
// Extract alpha (which is stored in the green plane).
@@ -327,7 +324,7 @@ private static void HorizontalUnfilter(Span<byte> prev, Span<byte> input, Span<b
327324
ref byte srcRef = ref MemoryMarshal.GetReference(input);
328325
for (i = 1; i + 8 <= width; i += 8)
329326
{
330-
var a0 = Vector128.Create(Unsafe.As<byte, long>(ref Unsafe.Add(ref srcRef, i)), 0);
327+
Vector128<long> a0 = Vector128.Create(Unsafe.As<byte, long>(ref Unsafe.Add(ref srcRef, i)), 0);
331328
Vector128<byte> a1 = Sse2.Add(a0.AsByte(), last.AsByte());
332329
Vector128<byte> a2 = Sse2.ShiftLeftLogical128BitLane(a1, 1);
333330
Vector128<byte> a3 = Sse2.Add(a1, a2);
@@ -365,32 +362,29 @@ private static void VerticalUnfilter(Span<byte> prev, Span<byte> input, Span<byt
365362
{
366363
HorizontalUnfilter(null, input, dst, width);
367364
}
368-
else
365+
else if (Avx2.IsSupported)
369366
{
370-
if (Avx2.IsSupported)
367+
nint i;
368+
int maxPos = width & ~31;
369+
for (i = 0; i < maxPos; i += 32)
371370
{
372-
nint i;
373-
int maxPos = width & ~31;
374-
for (i = 0; i < maxPos; i += 32)
375-
{
376-
Vector256<int> a0 = Unsafe.As<byte, Vector256<int>>(ref Unsafe.Add(ref MemoryMarshal.GetReference(input), i));
377-
Vector256<int> b0 = Unsafe.As<byte, Vector256<int>>(ref Unsafe.Add(ref MemoryMarshal.GetReference(prev), i));
378-
Vector256<byte> c0 = Avx2.Add(a0.AsByte(), b0.AsByte());
379-
ref byte outputRef = ref Unsafe.Add(ref MemoryMarshal.GetReference(dst), i);
380-
Unsafe.As<byte, Vector256<byte>>(ref outputRef) = c0;
381-
}
371+
Vector256<int> a0 = Unsafe.As<byte, Vector256<int>>(ref Unsafe.Add(ref MemoryMarshal.GetReference(input), i));
372+
Vector256<int> b0 = Unsafe.As<byte, Vector256<int>>(ref Unsafe.Add(ref MemoryMarshal.GetReference(prev), i));
373+
Vector256<byte> c0 = Avx2.Add(a0.AsByte(), b0.AsByte());
374+
ref byte outputRef = ref Unsafe.Add(ref MemoryMarshal.GetReference(dst), i);
375+
Unsafe.As<byte, Vector256<byte>>(ref outputRef) = c0;
376+
}
382377

383-
for (; i < width; i++)
384-
{
385-
dst[(int)i] = (byte)(prev[(int)i] + input[(int)i]);
386-
}
378+
for (; i < width; i++)
379+
{
380+
dst[(int)i] = (byte)(prev[(int)i] + input[(int)i]);
387381
}
388-
else
382+
}
383+
else
384+
{
385+
for (int i = 0; i < width; i++)
389386
{
390-
for (int i = 0; i < width; i++)
391-
{
392-
dst[i] = (byte)(prev[i] + input[i]);
393-
}
387+
dst[i] = (byte)(prev[i] + input[i]);
394388
}
395389
}
396390
}

src/ImageSharp/Formats/Webp/AlphaEncoder.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
3-
#nullable disable
43

54
using System.Buffers;
65
using SixLabors.ImageSharp.Advanced;
@@ -13,10 +12,8 @@ namespace SixLabors.ImageSharp.Formats.Webp;
1312
/// <summary>
1413
/// Methods for encoding the alpha data of a VP8 image.
1514
/// </summary>
16-
internal class AlphaEncoder : IDisposable
15+
internal static class AlphaEncoder
1716
{
18-
private IMemoryOwner<byte> alphaData;
19-
2017
/// <summary>
2118
/// Encodes the alpha channel data.
2219
/// Data is either compressed as lossless webp image or uncompressed.
@@ -29,12 +26,18 @@ internal class AlphaEncoder : IDisposable
2926
/// <param name="compress">Indicates, if the data should be compressed with the lossless webp compression.</param>
3027
/// <param name="size">The size in bytes of the alpha data.</param>
3128
/// <returns>The encoded alpha data.</returns>
32-
public IMemoryOwner<byte> EncodeAlpha<TPixel>(Image<TPixel> image, Configuration configuration, MemoryAllocator memoryAllocator, bool skipMetadata, bool compress, out int size)
29+
public static IMemoryOwner<byte> EncodeAlpha<TPixel>(
30+
Image<TPixel> image,
31+
Configuration configuration,
32+
MemoryAllocator memoryAllocator,
33+
bool skipMetadata,
34+
bool compress,
35+
out int size)
3336
where TPixel : unmanaged, IPixel<TPixel>
3437
{
3538
int width = image.Width;
3639
int height = image.Height;
37-
this.alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator);
40+
IMemoryOwner<byte> alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator);
3841

3942
if (compress)
4043
{
@@ -55,15 +58,15 @@ public IMemoryOwner<byte> EncodeAlpha<TPixel>(Image<TPixel> image, Configuration
5558
// The transparency information will be stored in the green channel of the ARGB quadruplet.
5659
// The green channel is allowed extra transformation steps in the specification -- unlike the other channels,
5760
// that can improve compression.
58-
using Image<Rgba32> alphaAsImage = DispatchAlphaToGreen(image, this.alphaData.GetSpan());
61+
using Image<Rgba32> alphaAsImage = DispatchAlphaToGreen(image, alphaData.GetSpan());
5962

60-
size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, this.alphaData);
63+
size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, alphaData);
6164

62-
return this.alphaData;
65+
return alphaData;
6366
}
6467

6568
size = width * height;
66-
return this.alphaData;
69+
return alphaData;
6770
}
6871

6972
/// <summary>
@@ -128,7 +131,4 @@ private static IMemoryOwner<byte> ExtractAlphaChannel<TPixel>(Image<TPixel> imag
128131

129132
return alphaDataBuffer;
130133
}
131-
132-
/// <inheritdoc/>
133-
public void Dispose() => this.alphaData?.Dispose();
134134
}

src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Six Labors Split License.
3-
#nullable disable
43

54
using System.Buffers;
65
using SixLabors.ImageSharp.Memory;
@@ -14,22 +13,30 @@ internal abstract class BitReaderBase : IDisposable
1413
{
1514
private bool isDisposed;
1615

16+
protected BitReaderBase(IMemoryOwner<byte> data)
17+
=> this.Data = data;
18+
19+
protected BitReaderBase(Stream inputStream, int imageDataSize, MemoryAllocator memoryAllocator)
20+
=> this.Data = ReadImageDataFromStream(inputStream, imageDataSize, memoryAllocator);
21+
1722
/// <summary>
18-
/// Gets or sets the raw encoded image data.
23+
/// Gets the raw encoded image data.
1924
/// </summary>
20-
public IMemoryOwner<byte> Data { get; set; }
25+
public IMemoryOwner<byte> Data { get; }
2126

2227
/// <summary>
2328
/// Copies the raw encoded image data from the stream into a byte array.
2429
/// </summary>
2530
/// <param name="input">The input stream.</param>
2631
/// <param name="bytesToRead">Number of bytes to read as indicated from the chunk size.</param>
2732
/// <param name="memoryAllocator">Used for allocating memory during reading data from the stream.</param>
28-
protected void ReadImageDataFromStream(Stream input, int bytesToRead, MemoryAllocator memoryAllocator)
33+
protected static IMemoryOwner<byte> ReadImageDataFromStream(Stream input, int bytesToRead, MemoryAllocator memoryAllocator)
2934
{
30-
this.Data = memoryAllocator.Allocate<byte>(bytesToRead);
31-
Span<byte> dataSpan = this.Data.Memory.Span;
35+
IMemoryOwner<byte> data = memoryAllocator.Allocate<byte>(bytesToRead);
36+
Span<byte> dataSpan = data.Memory.Span;
3237
input.Read(dataSpan[..bytesToRead], 0, bytesToRead);
38+
39+
return data;
3340
}
3441

3542
protected virtual void Dispose(bool disposing)
@@ -41,7 +48,7 @@ protected virtual void Dispose(bool disposing)
4148

4249
if (disposing)
4350
{
44-
this.Data?.Dispose();
51+
this.Data.Dispose();
4552
}
4653

4754
this.isDisposed = true;

src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ internal class Vp8BitReader : BitReaderBase
5757
/// <param name="partitionLength">The partition length.</param>
5858
/// <param name="startPos">Start index in the data array. Defaults to 0.</param>
5959
public Vp8BitReader(Stream inputStream, uint imageDataSize, MemoryAllocator memoryAllocator, uint partitionLength, int startPos = 0)
60+
: base(inputStream, (int)imageDataSize, memoryAllocator)
6061
{
6162
Guard.MustBeLessThan(imageDataSize, int.MaxValue, nameof(imageDataSize));
6263

6364
this.ImageDataSize = imageDataSize;
6465
this.PartitionLength = partitionLength;
65-
this.ReadImageDataFromStream(inputStream, (int)imageDataSize, memoryAllocator);
6666
this.InitBitreader(partitionLength, startPos);
6767
}
6868

@@ -73,8 +73,8 @@ public Vp8BitReader(Stream inputStream, uint imageDataSize, MemoryAllocator memo
7373
/// <param name="partitionLength">The partition length.</param>
7474
/// <param name="startPos">Start index in the data array. Defaults to 0.</param>
7575
public Vp8BitReader(IMemoryOwner<byte> imageData, uint partitionLength, int startPos = 0)
76+
: base(imageData)
7677
{
77-
this.Data = imageData;
7878
this.ImageDataSize = (uint)imageData.Memory.Length;
7979
this.PartitionLength = partitionLength;
8080
this.InitBitreader(partitionLength, startPos);

src/ImageSharp/Formats/Webp/BitReader/Vp8LBitReader.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ internal class Vp8LBitReader : BitReaderBase
6363
/// </summary>
6464
/// <param name="data">Lossless compressed image data.</param>
6565
public Vp8LBitReader(IMemoryOwner<byte> data)
66+
: base(data)
6667
{
67-
this.Data = data;
6868
this.len = data.Memory.Length;
6969
this.value = 0;
7070
this.bitPos = 0;
@@ -88,11 +88,10 @@ public Vp8LBitReader(IMemoryOwner<byte> data)
8888
/// <param name="imageDataSize">The raw image data size in bytes.</param>
8989
/// <param name="memoryAllocator">Used for allocating memory during reading data from the stream.</param>
9090
public Vp8LBitReader(Stream inputStream, uint imageDataSize, MemoryAllocator memoryAllocator)
91+
: base(inputStream, (int)imageDataSize, memoryAllocator)
9192
{
9293
long length = imageDataSize;
9394

94-
this.ReadImageDataFromStream(inputStream, (int)imageDataSize, memoryAllocator);
95-
9695
this.len = length;
9796
this.value = 0;
9897
this.bitPos = 0;
@@ -193,7 +192,7 @@ public void FillBitWindow()
193192
[MethodImpl(InliningOptions.ShortMethod)]
194193
private void ShiftBytes()
195194
{
196-
System.Span<byte> dataSpan = this.Data.Memory.Span;
195+
System.Span<byte> dataSpan = this.Data!.Memory.Span;
197196
while (this.bitPos >= 8 && this.pos < this.len)
198197
{
199198
this.value >>= 8;

src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ protected static uint AlphaChunkSize(Span<byte> alphaBytes)
123123
/// <param name="stream">The stream to write to.</param>
124124
/// <param name="metadataBytes">The metadata profile's bytes.</param>
125125
/// <param name="chunkType">The chuck type to write.</param>
126-
protected void WriteMetadataProfile(Stream stream, byte[] metadataBytes, WebpChunkType chunkType)
126+
protected void WriteMetadataProfile(Stream stream, byte[]? metadataBytes, WebpChunkType chunkType)
127127
{
128128
DebugGuard.NotNull(metadataBytes, nameof(metadataBytes));
129129

@@ -207,7 +207,7 @@ protected void WriteColorProfile(Stream stream, byte[] iccProfileBytes)
207207
/// <param name="width">The width of the image.</param>
208208
/// <param name="height">The height of the image.</param>
209209
/// <param name="hasAlpha">Flag indicating, if a alpha channel is present.</param>
210-
protected void WriteVp8XHeader(Stream stream, ExifProfile exifProfile, XmpProfile xmpProfile, byte[] iccProfileBytes, uint width, uint height, bool hasAlpha)
210+
protected void WriteVp8XHeader(Stream stream, ExifProfile? exifProfile, XmpProfile? xmpProfile, byte[]? iccProfileBytes, uint width, uint height, bool hasAlpha)
211211
{
212212
if (width > MaxDimension || height > MaxDimension)
213213
{

0 commit comments

Comments
 (0)