From 73a9278a82bc83ad4cd4ebc8c239bb284ed1764f Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Sat, 22 Nov 2025 10:02:27 +0100 Subject: [PATCH] Remove Nullable disable from Png Code I added a new Property to PngChunk --> DataSpan. On all places Data was used the same way. So we have the guard on this place and can just use it. --- .../Formats/Png/Chunks/PngHeader.cs | 3 +- src/ImageSharp/Formats/Png/PngChunk.cs | 15 ++++-- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 52 +++++++++---------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/ImageSharp/Formats/Png/Chunks/PngHeader.cs b/src/ImageSharp/Formats/Png/Chunks/PngHeader.cs index 77fb706f60..1ee2d01bde 100644 --- a/src/ImageSharp/Formats/Png/Chunks/PngHeader.cs +++ b/src/ImageSharp/Formats/Png/Chunks/PngHeader.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers.Binary; @@ -88,7 +87,7 @@ public PngHeader( /// public void Validate() { - if (!PngConstants.ColorTypes.TryGetValue(this.ColorType, out byte[] supportedBitDepths)) + if (!PngConstants.ColorTypes.TryGetValue(this.ColorType, out byte[]? supportedBitDepths)) { throw new NotSupportedException($"Invalid or unsupported color type. Was '{this.ColorType}'."); } diff --git a/src/ImageSharp/Formats/Png/PngChunk.cs b/src/ImageSharp/Formats/Png/PngChunk.cs index 3883986d06..5af7962eff 100644 --- a/src/ImageSharp/Formats/Png/PngChunk.cs +++ b/src/ImageSharp/Formats/Png/PngChunk.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; +using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Png; @@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Png; /// internal readonly struct PngChunk { - public PngChunk(int length, PngChunkType type, IMemoryOwner data = null) + public PngChunk(int length, PngChunkType type, IMemoryOwner? data = null) { this.Length = length; this.Type = type; @@ -36,7 +36,16 @@ public PngChunk(int length, PngChunkType type, IMemoryOwner data = null) /// Gets the data bytes appropriate to the chunk type, if any. /// This field can be of zero length or null. /// - public IMemoryOwner Data { get; } + public IMemoryOwner? Data { get; } + + public ReadOnlySpan DataSpan + { + get + { + DebugGuard.NotNull(this.Data); + return this.Data.GetSpan(); + } + } /// /// Gets a value indicating whether the given chunk is critical to decoding diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 38f964d37b..79d3066e85 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -192,24 +192,24 @@ protected override Image Decode(BufferedReadStream stream, Cance PngThrowHelper.ThrowInvalidHeader(); } - this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); + this.ReadHeaderChunk(pngMetadata, chunk.DataSpan); break; case PngChunkType.AnimationControl: - this.ReadAnimationControlChunk(pngMetadata, chunk.Data.GetSpan()); + this.ReadAnimationControlChunk(pngMetadata, chunk.DataSpan); break; case PngChunkType.Physical: - ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + ReadPhysicalChunk(metadata, chunk.DataSpan); break; case PngChunkType.Gamma: - ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); + ReadGammaChunk(pngMetadata, chunk.DataSpan); break; case PngChunkType.Cicp: - ReadCicpChunk(metadata, chunk.Data.GetSpan()); + ReadCicpChunk(metadata, chunk.DataSpan); break; case PngChunkType.FrameControl: frameCount++; currentFrame = null; - currentFrameControl = this.ReadFrameControlChunk(chunk.Data.GetSpan()); + currentFrameControl = this.ReadFrameControlChunk(chunk.DataSpan); break; case PngChunkType.FrameData: if (frameCount >= this.maxFrames) @@ -277,32 +277,32 @@ protected override Image Decode(BufferedReadStream stream, Cance break; case PngChunkType.Palette: - this.palette = chunk.Data.GetSpan().ToArray(); + this.palette = chunk.DataSpan.ToArray(); break; case PngChunkType.Transparency: - this.paletteAlpha = chunk.Data.GetSpan().ToArray(); + this.paletteAlpha = chunk.DataSpan.ToArray(); this.AssignTransparentMarkers(this.paletteAlpha, pngMetadata); break; case PngChunkType.Text: - this.ReadTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadTextChunk(metadata, pngMetadata, chunk.DataSpan); break; case PngChunkType.CompressedText: - this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.DataSpan); break; case PngChunkType.InternationalText: - this.ReadInternationalTextChunk(metadata, chunk.Data.GetSpan()); + this.ReadInternationalTextChunk(metadata, chunk.DataSpan); break; case PngChunkType.Exif: if (!this.skipMetadata) { byte[] exifData = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(exifData); + chunk.DataSpan.CopyTo(exifData); MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); } break; case PngChunkType.EmbeddedColorProfile: - this.ReadColorProfileChunk(metadata, chunk.Data.GetSpan()); + this.ReadColorProfileChunk(metadata, chunk.DataSpan); break; case PngChunkType.End: goto EOF; @@ -360,10 +360,10 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); + this.ReadHeaderChunk(pngMetadata, chunk.DataSpan); break; case PngChunkType.AnimationControl: - this.ReadAnimationControlChunk(pngMetadata, chunk.Data.GetSpan()); + this.ReadAnimationControlChunk(pngMetadata, chunk.DataSpan); break; case PngChunkType.Physical: if (this.colorMetadataOnly) @@ -372,7 +372,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + ReadPhysicalChunk(metadata, chunk.DataSpan); break; case PngChunkType.Gamma: if (this.colorMetadataOnly) @@ -381,7 +381,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); + ReadGammaChunk(pngMetadata, chunk.DataSpan); break; case PngChunkType.Cicp: if (this.colorMetadataOnly) @@ -390,7 +390,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - ReadCicpChunk(metadata, chunk.Data.GetSpan()); + ReadCicpChunk(metadata, chunk.DataSpan); break; case PngChunkType.FrameControl: ++frameCount; @@ -399,7 +399,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - currentFrameControl = this.ReadFrameControlChunk(chunk.Data.GetSpan()); + currentFrameControl = this.ReadFrameControlChunk(chunk.DataSpan); break; case PngChunkType.FrameData: @@ -445,11 +445,11 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok this.SkipChunkDataAndCrc(chunk); break; case PngChunkType.Palette: - this.palette = chunk.Data.GetSpan().ToArray(); + this.palette = chunk.DataSpan.ToArray(); break; case PngChunkType.Transparency: - this.paletteAlpha = chunk.Data.GetSpan().ToArray(); + this.paletteAlpha = chunk.DataSpan.ToArray(); this.AssignTransparentMarkers(this.paletteAlpha, pngMetadata); // Spec says tRNS must be after PLTE so safe to exit. @@ -466,7 +466,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - this.ReadTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadTextChunk(metadata, pngMetadata, chunk.DataSpan); break; case PngChunkType.CompressedText: if (this.colorMetadataOnly) @@ -475,7 +475,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.DataSpan); break; case PngChunkType.InternationalText: if (this.colorMetadataOnly) @@ -484,7 +484,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok break; } - this.ReadInternationalTextChunk(metadata, chunk.Data.GetSpan()); + this.ReadInternationalTextChunk(metadata, chunk.DataSpan); break; case PngChunkType.Exif: if (this.colorMetadataOnly) @@ -496,7 +496,7 @@ protected override ImageInfo Identify(BufferedReadStream stream, CancellationTok if (!this.skipMetadata) { byte[] exifData = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(exifData); + chunk.DataSpan.CopyTo(exifData); MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); } @@ -2015,7 +2015,7 @@ private void ValidateChunk(in PngChunk chunk, Span buffer) this.crc32.Reset(); this.crc32.Append(chunkType); - this.crc32.Append(chunk.Data.GetSpan()); + this.crc32.Append(chunk.DataSpan); if (this.crc32.GetCurrentHashAsUInt32() != inputCrc) {