From c9f7e6ea60c516b887256a32f47aee42a448fc21 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 7 Apr 2026 23:19:38 +1000 Subject: [PATCH] Add ImageInfo.GetPixelMemorySize; docs & tests --- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 2 +- src/ImageSharp/ImageInfo.cs | 32 ++++++++++++++++++-- tests/ImageSharp.Tests/ImageInfoTests.cs | 30 ++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 78ceb0b233..3d32c7cdac 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -468,7 +468,7 @@ internal sealed class GifDecoderCore : ImageDecoderCore int length = this.currentLocalColorTableSize = this.imageDescriptor.LocalColorTableSize * 3; this.currentLocalColorTable ??= this.configuration.MemoryAllocator.Allocate(768, AllocationOptions.Clean); stream.Read(this.currentLocalColorTable.GetSpan()[..length]); - rawColorTable = this.currentLocalColorTable!.GetSpan()[..length]; + rawColorTable = this.currentLocalColorTable.GetSpan()[..length]; } else if (this.globalColorTable != null) { diff --git a/src/ImageSharp/ImageInfo.cs b/src/ImageSharp/ImageInfo.cs index 0bbd73b63a..d27c4b9330 100644 --- a/src/ImageSharp/ImageInfo.cs +++ b/src/ImageSharp/ImageInfo.cs @@ -63,8 +63,12 @@ public class ImageInfo public int Height => this.Size.Height; /// - /// Gets the number of frames in the image. + /// Gets the number of frame metadata entries available for the image. /// + /// + /// This value is the same as count and may be 0 when frame + /// metadata was not populated by the decoder. + /// public int FrameCount => this.FrameMetadataCollection.Count; /// @@ -73,8 +77,12 @@ public class ImageInfo public ImageMetadata Metadata { get; } /// - /// Gets the collection of metadata associated with individual image frames. + /// Gets the metadata associated with the decoded image frames, if available. /// + /// + /// For multi-frame formats, decoders populate one entry per decoded frame. For single-frame formats, this + /// collection is typically empty. + /// public IReadOnlyList FrameMetadataCollection { get; } /// @@ -86,4 +94,24 @@ public class ImageInfo /// Gets the bounds of the image. /// public Rectangle Bounds => new(Point.Empty, this.Size); + + /// + /// Gets the total number of bytes required to store the image pixels in memory. + /// + /// + /// This reports the in-memory size of the pixel data represented by this , not the + /// encoded size of the image file. The value is computed from the image dimensions and + /// . When contains decoded frame metadata, the + /// per-frame size is multiplied by that count. Otherwise, the value is the in-memory size of the single + /// image frame represented by this . + /// + /// The total number of bytes required to store the image pixels in memory. + public long GetPixelMemorySize() + { + int count = this.FrameMetadataCollection.Count > 0 + ? this.FrameMetadataCollection.Count + : 1; + + return (long)this.Size.Width * this.Size.Height * (this.PixelType.BitsPerPixel / 8) * count; + } } diff --git a/tests/ImageSharp.Tests/ImageInfoTests.cs b/tests/ImageSharp.Tests/ImageInfoTests.cs index 322b0af196..748c8a4f6d 100644 --- a/tests/ImageSharp.Tests/ImageInfoTests.cs +++ b/tests/ImageSharp.Tests/ImageInfoTests.cs @@ -54,4 +54,34 @@ public class ImageInfoTests Assert.Equal(meta, info.Metadata); Assert.Equal(frameMetadata.Count, info.FrameMetadataCollection.Count); } + + [Fact] + public void GetPixelMemorySize_UsesSingleFrameWhenFrameMetadataIsEmpty() + { + const int width = 10; + const int height = 20; + + ImageMetadata meta = new() { DecodedImageFormat = PngFormat.Instance }; + meta.GetPngMetadata(); + + ImageInfo info = new(new Size(width, height), meta); + + Assert.Equal(width * height * 4, info.GetPixelMemorySize()); + } + + [Fact] + public void GetPixelMemorySize_UsesFrameMetadataCountWhenAvailable() + { + const int width = 10; + const int height = 20; + IReadOnlyList frameMetadata = [new(), new(), new()]; + + ImageMetadata meta = new() { DecodedImageFormat = PngFormat.Instance }; + meta.GetPngMetadata(); + + ImageInfo info = new(new Size(width, height), meta, frameMetadata); + + Assert.Equal(width * height * 4 * frameMetadata.Count, info.GetPixelMemorySize()); + } + }