diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index b0acbf39d4..104d0dcd08 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -149,7 +149,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff var frames = new List>(); foreach (ExifProfile ifd in directories) { - ImageFrame frame = this.DecodeFrame(ifd); + cancellationToken.ThrowIfCancellationRequested(); + ImageFrame frame = this.DecodeFrame(ifd, cancellationToken); frames.Add(frame); } @@ -191,10 +192,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff /// /// The pixel format. /// The IFD tags. - /// - /// The tiff frame. - /// - private ImageFrame DecodeFrame(ExifProfile tags) + /// The token to monitor cancellation. + /// The tiff frame. + private ImageFrame DecodeFrame(ExifProfile tags, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { ImageFrameMetadata imageFrameMetaData = this.ignoreMetadata ? @@ -216,11 +216,11 @@ namespace SixLabors.ImageSharp.Formats.Tiff if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar) { - this.DecodeStripsPlanar(frame, rowsPerStrip, stripOffsets, stripByteCounts); + this.DecodeStripsPlanar(frame, rowsPerStrip, stripOffsets, stripByteCounts, cancellationToken); } else { - this.DecodeStripsChunky(frame, rowsPerStrip, stripOffsets, stripByteCounts); + this.DecodeStripsChunky(frame, rowsPerStrip, stripOffsets, stripByteCounts, cancellationToken); } return frame; @@ -268,14 +268,15 @@ namespace SixLabors.ImageSharp.Formats.Tiff } /// - /// Decodes the image data for strip encoded data. + /// Decodes the image data for planar encoded pixel data. /// /// The pixel format. /// The image frame to decode data into. /// The number of rows per strip of data. /// An array of byte offsets to each strip in the image. /// An array of the size of each strip (in bytes). - private void DecodeStripsPlanar(ImageFrame frame, int rowsPerStrip, Number[] stripOffsets, Number[] stripByteCounts) + /// The token to monitor cancellation. + private void DecodeStripsPlanar(ImageFrame frame, int rowsPerStrip, Number[] stripOffsets, Number[] stripByteCounts, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { int stripsPerPixel = this.BitsPerSample.Channels; @@ -319,6 +320,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff for (int i = 0; i < stripsPerPlane; i++) { + cancellationToken.ThrowIfCancellationRequested(); + int stripHeight = i < stripsPerPlane - 1 || frame.Height % rowsPerStrip == 0 ? rowsPerStrip : frame.Height % rowsPerStrip; int stripIndex = i; @@ -340,7 +343,16 @@ namespace SixLabors.ImageSharp.Formats.Tiff } } - private void DecodeStripsChunky(ImageFrame frame, int rowsPerStrip, Number[] stripOffsets, Number[] stripByteCounts) + /// + /// Decodes the image data for chunky encoded pixel data. + /// + /// The pixel format. + /// The image frame to decode data into. + /// The rows per strip. + /// The strip offsets. + /// The strip byte counts. + /// The token to monitor cancellation. + private void DecodeStripsChunky(ImageFrame frame, int rowsPerStrip, Number[] stripOffsets, Number[] stripByteCounts, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { // If the rowsPerStrip has the default value, which is effectively infinity. That is, the entire image is one strip. @@ -383,6 +395,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff for (int stripIndex = 0; stripIndex < stripOffsets.Length; stripIndex++) { + cancellationToken.ThrowIfCancellationRequested(); + int stripHeight = stripIndex < stripOffsets.Length - 1 || frame.Height % rowsPerStrip == 0 ? rowsPerStrip : frame.Height % rowsPerStrip; diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 16b3158a4d..1e4254a4ef 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -155,6 +155,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff Image metadataImage = image; foreach (ImageFrame frame in image.Frames) { + cancellationToken.ThrowIfCancellationRequested(); + var subfileType = (TiffNewSubfileType)(frame.Metadata.ExifProfile?.GetValue(ExifTag.SubfileType)?.Value ?? (int)TiffNewSubfileType.FullImage); ifdMarker = this.WriteFrame(writer, frame, image.Metadata, metadataImage, ifdMarker);