From 94fd43f71ff34fb714e32f892bd5c37a8928b442 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Sun, 5 Feb 2023 18:09:53 +0100 Subject: [PATCH] remove nullable disable from format gif --- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 139 ++++++++++--------- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 24 ++-- src/ImageSharp/Image.Decode.cs | 2 +- src/ImageSharp/Image.cs | 4 +- src/ImageSharp/ImageInfo.cs | 4 +- src/ImageSharp/Image{TPixel}.cs | 4 +- 6 files changed, 90 insertions(+), 87 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 8c5915800..0ccbe3db5 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -24,15 +24,10 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// private readonly byte[] buffer = new byte[16]; - /// - /// The currently loaded stream. - /// - private BufferedReadStream stream; - /// /// The global color table. /// - private IMemoryOwner globalColorTable; + private IMemoryOwner? globalColorTable; /// /// The area to restore. @@ -77,12 +72,12 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// /// The abstract metadata. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// The gif specific metadata. /// - private GifMetadata gifMetadata; + private GifMetadata? gifMetadata; /// /// Initializes a new instance of the class. @@ -108,8 +103,8 @@ internal sealed class GifDecoderCore : IImageDecoderInternals where TPixel : unmanaged, IPixel { uint frameCount = 0; - Image image = null; - ImageFrame previousFrame = null; + Image? image = null; + ImageFrame? previousFrame = null; try { this.ReadLogicalScreenDescriptorAndGlobalColorTable(stream); @@ -125,7 +120,7 @@ internal sealed class GifDecoderCore : IImageDecoderInternals break; } - this.ReadFrame(ref image, ref previousFrame); + this.ReadFrame(stream, ref image, ref previousFrame); // Reset per-frame state. this.imageDescriptor = default; @@ -136,16 +131,16 @@ internal sealed class GifDecoderCore : IImageDecoderInternals switch (stream.ReadByte()) { case GifConstants.GraphicControlLabel: - this.ReadGraphicalControlExtension(); + this.ReadGraphicalControlExtension(stream); break; case GifConstants.CommentLabel: - this.ReadComments(); + this.ReadComments(stream); break; case GifConstants.ApplicationExtensionLabel: - this.ReadApplicationExtension(); + this.ReadApplicationExtension(stream); break; case GifConstants.PlainTextLabel: - this.SkipBlock(); // Not supported by any known decoder. + this.SkipBlock(stream); // Not supported by any known decoder. break; } } @@ -187,23 +182,23 @@ internal sealed class GifDecoderCore : IImageDecoderInternals { if (nextFlag == GifConstants.ImageLabel) { - this.ReadImageDescriptor(); + this.ReadImageDescriptor(stream); } else if (nextFlag == GifConstants.ExtensionIntroducer) { switch (stream.ReadByte()) { case GifConstants.GraphicControlLabel: - this.SkipBlock(); // Skip graphic control extension block + this.SkipBlock(stream); // Skip graphic control extension block break; case GifConstants.CommentLabel: - this.ReadComments(); + this.ReadComments(stream); break; case GifConstants.ApplicationExtensionLabel: - this.ReadApplicationExtension(); + this.ReadApplicationExtension(stream); break; case GifConstants.PlainTextLabel: - this.SkipBlock(); // Not supported by any known decoder. + this.SkipBlock(stream); // Not supported by any known decoder. break; } } @@ -239,9 +234,10 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// /// Reads the graphic control extension. /// - private void ReadGraphicalControlExtension() + /// The containing image data. + private void ReadGraphicalControlExtension(BufferedReadStream stream) { - int bytesRead = this.stream.Read(this.buffer, 0, 6); + int bytesRead = stream.Read(this.buffer, 0, 6); if (bytesRead != 6) { GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the graphic control extension"); @@ -253,9 +249,10 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// /// Reads the image descriptor. /// - private void ReadImageDescriptor() + /// The containing image data. + private void ReadImageDescriptor(BufferedReadStream stream) { - int bytesRead = this.stream.Read(this.buffer, 0, 9); + int bytesRead = stream.Read(this.buffer, 0, 9); if (bytesRead != 9) { GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the image descriptor"); @@ -271,9 +268,10 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// /// Reads the logical screen descriptor. /// - private void ReadLogicalScreenDescriptor() + /// The containing image data. + private void ReadLogicalScreenDescriptor(BufferedReadStream stream) { - int bytesRead = this.stream.Read(this.buffer, 0, 7); + int bytesRead = stream.Read(this.buffer, 0, 7); if (bytesRead != 7) { GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the logical screen descriptor"); @@ -286,84 +284,87 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// Reads the application extension block parsing any animation or XMP information /// if present. /// - private void ReadApplicationExtension() + /// The containing image data. + private void ReadApplicationExtension(BufferedReadStream stream) { - int appLength = this.stream.ReadByte(); + int appLength = stream.ReadByte(); // If the length is 11 then it's a valid extension and most likely // a NETSCAPE, XMP or ANIMEXTS extension. We want the loop count from this. - long position = this.stream.Position; + long position = stream.Position; if (appLength == GifConstants.ApplicationBlockSize) { - this.stream.Read(this.buffer, 0, GifConstants.ApplicationBlockSize); + stream.Read(this.buffer, 0, GifConstants.ApplicationBlockSize); bool isXmp = this.buffer.AsSpan().StartsWith(GifConstants.XmpApplicationIdentificationBytes); if (isXmp && !this.skipMetadata) { - GifXmpApplicationExtension extension = GifXmpApplicationExtension.Read(this.stream, this.memoryAllocator); + GifXmpApplicationExtension extension = GifXmpApplicationExtension.Read(stream, this.memoryAllocator); if (extension.Data.Length > 0) { - this.metadata.XmpProfile = new XmpProfile(extension.Data); + this.metadata!.XmpProfile = new XmpProfile(extension.Data); } else { // Reset the stream position and continue. - this.stream.Position = position; - this.SkipBlock(appLength); + stream.Position = position; + this.SkipBlock(stream, appLength); } return; } - int subBlockSize = this.stream.ReadByte(); + int subBlockSize = stream.ReadByte(); // TODO: There's also a NETSCAPE buffer extension. // http://www.vurdalakov.net/misc/gif/netscape-buffering-application-extension if (subBlockSize == GifConstants.NetscapeLoopingSubBlockSize) { - this.stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize); - this.gifMetadata.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer.AsSpan(1)).RepeatCount; - this.stream.Skip(1); // Skip the terminator. + stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize); + this.gifMetadata!.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer.AsSpan(1)).RepeatCount; + stream.Skip(1); // Skip the terminator. return; } // Could be something else not supported yet. // Skip the subblock and terminator. - this.SkipBlock(subBlockSize); + this.SkipBlock(stream, subBlockSize); return; } - this.SkipBlock(appLength); // Not supported by any known decoder. + this.SkipBlock(stream, appLength); // Not supported by any known decoder. } /// /// Skips over a block or reads its terminator. /// The length of the block to skip. + /// The containing image data. /// - private void SkipBlock(int blockSize = 0) + private void SkipBlock(BufferedReadStream stream, int blockSize = 0) { if (blockSize > 0) { - this.stream.Skip(blockSize); + stream.Skip(blockSize); } int flag; - while ((flag = this.stream.ReadByte()) > 0) + while ((flag = stream.ReadByte()) > 0) { - this.stream.Skip(flag); + stream.Skip(flag); } } /// /// Reads the gif comments. /// - private void ReadComments() + /// The containing image data. + private void ReadComments(BufferedReadStream stream) { int length; var stringBuilder = new StringBuilder(); - while ((length = this.stream.ReadByte()) != 0) + while ((length = stream.ReadByte()) != 0) { if (length > GifConstants.MaxCommentSubBlockLength) { @@ -372,21 +373,21 @@ internal sealed class GifDecoderCore : IImageDecoderInternals if (this.skipMetadata) { - this.stream.Seek(length, SeekOrigin.Current); + stream.Seek(length, SeekOrigin.Current); continue; } using IMemoryOwner commentsBuffer = this.memoryAllocator.Allocate(length); Span commentsSpan = commentsBuffer.GetSpan(); - this.stream.Read(commentsSpan); + stream.Read(commentsSpan); string commentPart = GifConstants.Encoding.GetString(commentsSpan); stringBuilder.Append(commentPart); } if (stringBuilder.Length > 0) { - this.gifMetadata.Comments.Add(stringBuilder.ToString()); + this.gifMetadata!.Comments.Add(stringBuilder.ToString()); } } @@ -394,15 +395,16 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// Reads an individual gif frame. /// /// The pixel format. + /// The containing image data. /// The image to decode the information to. /// The previous frame. - private void ReadFrame(ref Image image, ref ImageFrame previousFrame) + private void ReadFrame(BufferedReadStream stream, ref Image? image, ref ImageFrame? previousFrame) where TPixel : unmanaged, IPixel { - this.ReadImageDescriptor(); + this.ReadImageDescriptor(stream); - IMemoryOwner localColorTable = null; - Buffer2D indices = null; + IMemoryOwner? localColorTable = null; + Buffer2D? indices = null; try { // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table. @@ -410,11 +412,11 @@ internal sealed class GifDecoderCore : IImageDecoderInternals { int length = this.imageDescriptor.LocalColorTableSize * 3; localColorTable = this.configuration.MemoryAllocator.Allocate(length, AllocationOptions.Clean); - this.stream.Read(localColorTable.GetSpan()); + stream.Read(localColorTable.GetSpan()); } indices = this.configuration.MemoryAllocator.Allocate2D(this.imageDescriptor.Width, this.imageDescriptor.Height, AllocationOptions.Clean); - this.ReadFrameIndices(indices); + this.ReadFrameIndices(stream, indices); Span rawColorTable = default; if (localColorTable != null) @@ -430,7 +432,7 @@ internal sealed class GifDecoderCore : IImageDecoderInternals this.ReadFrameColors(ref image, ref previousFrame, indices, colorTable, this.imageDescriptor); // Skip any remaining blocks - this.SkipBlock(); + this.SkipBlock(stream); } finally { @@ -442,12 +444,13 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// /// Reads the frame indices marking the color to use for each pixel. /// + /// The containing image data. /// The 2D pixel buffer to write to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadFrameIndices(Buffer2D indices) + private void ReadFrameIndices(BufferedReadStream stream, Buffer2D indices) { - int minCodeSize = this.stream.ReadByte(); - using var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, this.stream); + int minCodeSize = stream.ReadByte(); + using LzwDecoder lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, stream); lzwDecoder.DecodePixels(minCodeSize, indices); } @@ -460,15 +463,15 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// The indexed pixels. /// The color table containing the available colors. /// The - private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Buffer2D indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor) + private void ReadFrameColors(ref Image? image, ref ImageFrame? previousFrame, Buffer2D indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor) where TPixel : unmanaged, IPixel { int imageWidth = this.logicalScreenDescriptor.Width; int imageHeight = this.logicalScreenDescriptor.Height; bool transFlag = this.graphicsControlExtension.TransparencyFlag; - ImageFrame prevFrame = null; - ImageFrame currentFrame = null; + ImageFrame? prevFrame = null; + ImageFrame? currentFrame = null; ImageFrame imageFrame; if (previousFrame is null) @@ -494,7 +497,7 @@ internal sealed class GifDecoderCore : IImageDecoderInternals prevFrame = previousFrame; } - currentFrame = image.Frames.CreateFrame(); + currentFrame = image!.Frames.CreateFrame(); this.SetFrameMetadata(currentFrame.Metadata, false); @@ -661,13 +664,13 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// Reads the logical screen descriptor and global color table blocks /// /// The stream containing image data. + [MemberNotNull(nameof(metadata))] + [MemberNotNull(nameof(gifMetadata))] private void ReadLogicalScreenDescriptorAndGlobalColorTable(BufferedReadStream stream) { - this.stream = stream; - // Skip the identifier - this.stream.Skip(6); - this.ReadLogicalScreenDescriptor(); + stream.Skip(6); + this.ReadLogicalScreenDescriptor(stream); ImageMetadata meta = new(); diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index eaa685293..0e59a0f05 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; @@ -93,7 +93,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals bool useGlobalTable = this.colorTableMode == GifColorTableMode.Global; // Quantize the image returning a palette. - IndexedImageFrame quantized; + IndexedImageFrame? quantized; using (IQuantizer frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer(this.configuration)) { if (useGlobalTable) @@ -129,7 +129,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals this.WriteComments(gifMetadata, stream); // Write application extensions. - XmpProfile xmpProfile = image.Metadata.XmpProfile ?? image.Frames.RootFrame.Metadata.XmpProfile; + XmpProfile? xmpProfile = image.Metadata.XmpProfile ?? image.Frames.RootFrame.Metadata.XmpProfile; this.WriteApplicationExtensions(stream, image.Frames.Count, gifMetadata.RepeatCount, xmpProfile); } @@ -141,7 +141,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals private void EncodeFrames( Stream stream, Image image, - IndexedImageFrame quantized, + IndexedImageFrame? quantized, ReadOnlyMemory palette) where TPixel : unmanaged, IPixel { @@ -152,8 +152,8 @@ internal sealed class GifEncoderCore : IImageEncoderInternals // Gather the metadata for this frame. ImageFrame frame = image.Frames[i]; ImageFrameMetadata metadata = frame.Metadata; - bool hasMetadata = metadata.TryGetGifMetadata(out GifFrameMetadata frameMetadata); - bool useLocal = this.colorTableMode == GifColorTableMode.Local || (hasMetadata && frameMetadata.ColorTableMode == GifColorTableMode.Local); + bool hasMetadata = metadata.TryGetGifMetadata(out GifFrameMetadata? frameMetadata); + bool useLocal = this.colorTableMode == GifColorTableMode.Local || (hasMetadata && frameMetadata!.ColorTableMode == GifColorTableMode.Local); if (!useLocal && !hasPaletteQuantizer && i > 0) { @@ -164,7 +164,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals paletteQuantizer = new(this.configuration, this.quantizer.Options, palette); } - this.EncodeFrame(stream, frame, i, useLocal, frameMetadata, ref quantized, ref paletteQuantizer); + this.EncodeFrame(stream, frame, i, useLocal, frameMetadata, ref quantized!, ref paletteQuantizer); // Clean up for the next run. quantized.Dispose(); @@ -182,7 +182,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals ImageFrame frame, int frameIndex, bool useLocal, - GifFrameMetadata metadata, + GifFrameMetadata? metadata, ref IndexedImageFrame quantized, ref PaletteQuantizer paletteQuantizer) where TPixel : unmanaged, IPixel @@ -193,7 +193,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals if (useLocal) { // Reassign using the current frame and details. - QuantizerOptions options = null; + QuantizerOptions? options = null; int colorTableLength = metadata?.ColorTableLength ?? 0; if (colorTableLength > 0) { @@ -338,7 +338,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals /// The frame count fo this image. /// The animated image repeat count. /// The XMP metadata profile. Null if profile is not to be written. - private void WriteApplicationExtensions(Stream stream, int frameCount, ushort repeatCount, XmpProfile xmpProfile) + private void WriteApplicationExtensions(Stream stream, int frameCount, ushort repeatCount, XmpProfile? xmpProfile) { // Application Extension: Loop repeat count. if (frameCount > 1 && repeatCount != 1) @@ -350,7 +350,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals // Application Extension: XMP Profile. if (xmpProfile != null) { - GifXmpApplicationExtension xmpExtension = new(xmpProfile.Data); + GifXmpApplicationExtension xmpExtension = new(xmpProfile.Data!); this.WriteExtension(xmpExtension, stream); } } @@ -439,7 +439,7 @@ internal sealed class GifEncoderCore : IImageEncoderInternals private void WriteExtension(TGifExtension extension, Stream stream) where TGifExtension : struct, IGifExtension { - IMemoryOwner owner = null; + IMemoryOwner? owner = null; Span extensionBuffer; int extensionSize = extension.ContentLength; diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index ae38144c0..887cb23ca 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -91,7 +91,7 @@ public abstract partial class Image ImageFormatManager.ThrowInvalidDecoder(configuration.ImageFormatsManager); } - return format!; + return format; } /// diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs index 65b2d68b0..af1b1916f 100644 --- a/src/ImageSharp/Image.cs +++ b/src/ImageSharp/Image.cs @@ -28,7 +28,7 @@ public abstract partial class Image : ImageInfo, IDisposable, IConfigurationProv /// The pixel type information. /// The image metadata. /// The size in px units. - protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata metadata, Size size) + protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetadata? metadata, Size size) : base(pixelType, size, metadata) => this.configuration = configuration ?? Configuration.Default; @@ -43,7 +43,7 @@ public abstract partial class Image : ImageInfo, IDisposable, IConfigurationProv internal Image( Configuration configuration, PixelTypeInfo pixelType, - ImageMetadata metadata, + ImageMetadata? metadata, int width, int height) : this(configuration, pixelType, metadata, new Size(width, height)) diff --git a/src/ImageSharp/ImageInfo.cs b/src/ImageSharp/ImageInfo.cs index 9a6452ab8..fdc15a812 100644 --- a/src/ImageSharp/ImageInfo.cs +++ b/src/ImageSharp/ImageInfo.cs @@ -18,7 +18,7 @@ public class ImageInfo /// The width of the image in px units. /// The height of the image in px units. /// The image metadata. - public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetadata metadata) + public ImageInfo(PixelTypeInfo pixelType, int width, int height, ImageMetadata? metadata) : this(pixelType, new(width, height), metadata) { } @@ -29,7 +29,7 @@ public class ImageInfo /// The pixel type information. /// The size of the image in px units. /// The image metadata. - public ImageInfo(PixelTypeInfo pixelType, Size size, ImageMetadata metadata) + public ImageInfo(PixelTypeInfo pixelType, Size size, ImageMetadata? metadata) { this.PixelType = pixelType; this.Metadata = metadata ?? new ImageMetadata(); diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 9e3cc065c..ed0db9b85 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -77,7 +77,7 @@ public sealed class Image : Image /// The width of the image in pixels. /// The height of the image in pixels. /// The images metadata. - internal Image(Configuration configuration, int width, int height, ImageMetadata metadata) + internal Image(Configuration configuration, int width, int height, ImageMetadata? metadata) : base(configuration, PixelTypeInfo.Create(), metadata, width, height) => this.frames = new ImageFrameCollection(this, width, height, default(TPixel)); @@ -128,7 +128,7 @@ public sealed class Image : Image int width, int height, TPixel backgroundColor, - ImageMetadata metadata) + ImageMetadata? metadata) : base(configuration, PixelTypeInfo.Create(), metadata, width, height) => this.frames = new ImageFrameCollection(this, width, height, backgroundColor);