From dd3aa98641ed92b4456240e3c1f640bf070000d3 Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Mon, 27 Jul 2020 13:08:03 +0200 Subject: [PATCH] Fix build issues after merging the master branch --- src/ImageSharp/Formats/WebP/WebPDecoder.cs | 37 ++++++++- .../Formats/WebP/WebPDecoderCore.cs | 77 ++++++++++--------- .../Formats/WebP/WebPEncoderCore.cs | 1 + 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/ImageSharp/Formats/WebP/WebPDecoder.cs b/src/ImageSharp/Formats/WebP/WebPDecoder.cs index 6e905173b2..f15b6c7af2 100644 --- a/src/ImageSharp/Formats/WebP/WebPDecoder.cs +++ b/src/ImageSharp/Formats/WebP/WebPDecoder.cs @@ -3,6 +3,9 @@ using System.IO; using System.Threading.Tasks; + +using SixLabors.ImageSharp.IO; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.WebP @@ -23,7 +26,19 @@ namespace SixLabors.ImageSharp.Formats.WebP { Guard.NotNull(stream, nameof(stream)); - return new WebPDecoderCore(configuration, this).Decode(stream); + var decoder = new WebPDecoderCore(configuration, this); + + try + { + using var bufferedStream = new BufferedReadStream(configuration, stream); + return decoder.Decode(bufferedStream); + } + catch (InvalidMemoryOperationException ex) + { + Size dims = decoder.Dimensions; + + throw new InvalidImageContentException($"Cannot decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}. This error can happen for very large RLE bitmaps, which are not supported.", ex); + } } /// @@ -31,7 +46,8 @@ namespace SixLabors.ImageSharp.Formats.WebP { Guard.NotNull(stream, nameof(stream)); - return new WebPDecoderCore(configuration, this).Identify(stream); + using var bufferedStream = new BufferedReadStream(configuration, stream); + return new WebPDecoderCore(configuration, this).Identify(bufferedStream); } /// @@ -43,7 +59,19 @@ namespace SixLabors.ImageSharp.Formats.WebP { Guard.NotNull(stream, nameof(stream)); - return new WebPDecoderCore(configuration, this).DecodeAsync(stream); + var decoder = new WebPDecoderCore(configuration, this); + + try + { + using var bufferedStream = new BufferedReadStream(configuration, stream); + return decoder.DecodeAsync(bufferedStream); + } + catch (InvalidMemoryOperationException ex) + { + Size dims = decoder.Dimensions; + + throw new InvalidImageContentException($"Cannot decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}. This error can happen for very large RLE bitmaps, which are not supported.", ex); + } } /// @@ -55,7 +83,8 @@ namespace SixLabors.ImageSharp.Formats.WebP { Guard.NotNull(stream, nameof(stream)); - return new WebPDecoderCore(configuration, this).IdentifyAsync(stream); + using var bufferedStream = new BufferedReadStream(configuration, stream); + return new WebPDecoderCore(configuration, this).IdentifyAsync(bufferedStream); } } } diff --git a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs index 8b0a32fab5..cb94f49b0c 100644 --- a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs +++ b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs @@ -8,6 +8,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.WebP.BitReader; using SixLabors.ImageSharp.Formats.WebP.Lossless; using SixLabors.ImageSharp.Formats.WebP.Lossy; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -41,6 +42,11 @@ namespace SixLabors.ImageSharp.Formats.WebP /// private WebPMetadata webpMetadata; + /// + /// Information about the webp image. + /// + private WebPImageInfo webImageInfo; + /// /// Initializes a new instance of the class. /// @@ -67,58 +73,59 @@ namespace SixLabors.ImageSharp.Formats.WebP public Configuration Configuration { get; } /// - /// Decodes the image from the specified and sets the data to the image. + /// Gets the dimensions of the image. /// - /// The pixel format. - /// The stream, where the image should be. - /// The decoded image. - public Image Decode(Stream stream) + public Size Dimensions => new Size((int)this.webImageInfo.Width, (int)this.webImageInfo.Height); + + /// + public Image Decode(BufferedReadStream stream) where TPixel : unmanaged, IPixel { this.Metadata = new ImageMetadata(); this.currentStream = stream; this.ReadImageHeader(); - using WebPImageInfo imageInfo = this.ReadVp8Info(); - if (imageInfo.Features != null && imageInfo.Features.Animation) - { - WebPThrowHelper.ThrowNotSupportedException("Animations are not supported"); - } - var image = new Image(this.Configuration, (int)imageInfo.Width, (int)imageInfo.Height, this.Metadata); - Buffer2D pixels = image.GetRootFramePixelBuffer(); - if (imageInfo.IsLossless) - { - var losslessDecoder = new WebPLosslessDecoder(imageInfo.Vp8LBitReader, this.memoryAllocator, this.Configuration); - losslessDecoder.Decode(pixels, image.Width, image.Height); - } - else + using (this.webImageInfo = this.ReadVp8Info()) { - var lossyDecoder = new WebPLossyDecoder(imageInfo.Vp8BitReader, this.memoryAllocator, this.Configuration); - lossyDecoder.Decode(pixels, image.Width, image.Height, imageInfo); - } + if (this.webImageInfo.Features != null && this.webImageInfo.Features.Animation) + { + WebPThrowHelper.ThrowNotSupportedException("Animations are not supported"); + } - // There can be optional chunks after the image data, like EXIF and XMP. - if (imageInfo.Features != null) - { - this.ParseOptionalChunks(imageInfo.Features); - } + var image = new Image(this.Configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata); + Buffer2D pixels = image.GetRootFramePixelBuffer(); + if (this.webImageInfo.IsLossless) + { + var losslessDecoder = new WebPLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.Configuration); + losslessDecoder.Decode(pixels, image.Width, image.Height); + } + else + { + var lossyDecoder = new WebPLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.Configuration); + lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo); + } + + // There can be optional chunks after the image data, like EXIF and XMP. + if (this.webImageInfo.Features != null) + { + this.ParseOptionalChunks(this.webImageInfo.Features); + } - return image; + return image; + } } - /// - /// Reads the raw image information from the specified stream. - /// - /// The containing image data. - public IImageInfo Identify(Stream stream) + /// + public IImageInfo Identify(BufferedReadStream stream) { this.currentStream = stream; this.ReadImageHeader(); - WebPImageInfo imageInfo = this.ReadVp8Info(); - - return new ImageInfo(new PixelTypeInfo((int)imageInfo.BitsPerPixel), (int)imageInfo.Width, (int)imageInfo.Height, this.Metadata); + using (this.webImageInfo = this.ReadVp8Info()) + { + return new ImageInfo(new PixelTypeInfo((int)this.webImageInfo.BitsPerPixel), (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata); + } } /// diff --git a/src/ImageSharp/Formats/WebP/WebPEncoderCore.cs b/src/ImageSharp/Formats/WebP/WebPEncoderCore.cs index 2d37b802a3..f99c524bad 100644 --- a/src/ImageSharp/Formats/WebP/WebPEncoderCore.cs +++ b/src/ImageSharp/Formats/WebP/WebPEncoderCore.cs @@ -3,6 +3,7 @@ using System.IO; using System.Threading.Tasks; + using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.WebP.Lossless; using SixLabors.ImageSharp.Formats.WebP.Lossy;