diff --git a/src/ImageSharp/Formats/Tiff/Compression/DeflateTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/DeflateTiffCompression.cs index 4ea98d95af..074b04c6b5 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/DeflateTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/DeflateTiffCompression.cs @@ -5,9 +5,11 @@ using System; using System.IO; using System.IO.Compression; +using SixLabors.ImageSharp.Compression.Zlib; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; using SixLabors.ImageSharp.Formats.Tiff.Compression; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -33,34 +35,20 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression } /// - public override void Decompress(Stream stream, int byteCount, Span buffer) + protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer) { - // Read the 'zlib' header information - int cmf = stream.ReadByte(); - int flag = stream.ReadByte(); - - if ((cmf & 0x0f) != 8) - { - TiffThrowHelper.ThrowBadZlibHeader(cmf); - } - - // If the 'fdict' flag is set then we should skip the next four bytes - bool fdict = (flag & 32) != 0; - - if (fdict) - { - stream.ReadByte(); - stream.ReadByte(); - stream.ReadByte(); - stream.ReadByte(); - } - - // The subsequent data is the Deflate compressed data (except for the last four bytes of checksum) - int headerLength = fdict ? 10 : 6; - var subStream = new SubStream(stream, byteCount - headerLength); - using (var deflateStream = new DeflateStream(subStream, CompressionMode.Decompress, true)) + long pos = stream.Position; + using (var deframeStream = new ZlibInflateStream( + stream, + () => + { + int left = (int)(byteCount - (stream.Position - pos)); + return left > 0 ? left : 0; + })) { - deflateStream.Read(buffer, 0, buffer.Length); + deframeStream.AllocateNewBytes(byteCount, true); + DeflateStream dataStream = deframeStream.CompressedStream; + dataStream.Read(buffer, 0, buffer.Length); } if (this.Predictor == TiffPredictor.Horizontal) diff --git a/src/ImageSharp/Formats/Tiff/Compression/LzwTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/LzwTiffCompression.cs index b01f141914..92468a00c2 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/LzwTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/LzwTiffCompression.cs @@ -3,9 +3,11 @@ using System; using System.IO; + using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; using SixLabors.ImageSharp.Formats.Tiff.Compression; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -28,10 +30,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression } /// - public override void Decompress(Stream stream, int byteCount, Span buffer) + protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer) { - var subStream = new SubStream(stream, byteCount); - var decoder = new TiffLzwDecoder(subStream, this.Allocator); + var decoder = new TiffLzwDecoder(stream, this.Allocator); decoder.DecodePixels(buffer.Length, 8, buffer); if (this.Predictor == TiffPredictor.Horizontal) diff --git a/src/ImageSharp/Formats/Tiff/Compression/ModifiedHuffmanTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/ModifiedHuffmanTiffCompression.cs index 6176d75652..1d7c2eef57 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/ModifiedHuffmanTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/ModifiedHuffmanTiffCompression.cs @@ -5,6 +5,7 @@ using System; using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression } /// - public override void Decompress(Stream stream, int byteCount, Span buffer) + protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer) { bool isWhiteZero = this.PhotometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero; byte whiteValue = (byte)(isWhiteZero ? 0 : 1); diff --git a/src/ImageSharp/Formats/Tiff/Compression/NoneTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/NoneTiffCompression.cs index a07b42112a..9140a52e04 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/NoneTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/NoneTiffCompression.cs @@ -5,6 +5,7 @@ using System; using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -24,9 +25,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression } /// - public override void Decompress(Stream stream, int byteCount, Span buffer) + protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer) { - stream.Read(buffer, 0, byteCount); + _ = stream.Read(buffer, 0, byteCount); } } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/PackBitsTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/PackBitsTiffCompression.cs index d77ee78e44..a7c8b93481 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/PackBitsTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/PackBitsTiffCompression.cs @@ -6,6 +6,7 @@ using System.Buffers; using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -25,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression } /// - public override void Decompress(Stream stream, int byteCount, Span buffer) + protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer) { using IMemoryOwner compressedDataMemory = this.Allocator.Allocate(byteCount); diff --git a/src/ImageSharp/Formats/Tiff/Compression/T4TiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/T4TiffCompression.cs index b8649d2101..f0c3a29bdd 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/T4TiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/T4TiffCompression.cs @@ -5,6 +5,7 @@ using System; using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression } /// - public override void Decompress(Stream stream, int byteCount, Span buffer) + protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer) { bool isWhiteZero = this.PhotometricInterpretation == TiffPhotometricInterpretation.WhiteIsZero; byte whiteValue = (byte)(isWhiteZero ? 0 : 1); diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs index d4f287adc8..4a5962f05d 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/TiffBaseCompression.cs @@ -6,6 +6,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; using SixLabors.ImageSharp.Formats.Tiff.Compression; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression @@ -55,9 +56,32 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression /// /// Decompresses image data into the supplied buffer. /// - /// The to read image data from. + /// The to read image data from. + /// The strip offset of stream. + /// The number of bytes to read from the input stream. + /// The output buffer for uncompressed data. + public void Decompress(BufferedReadStream stream, uint stripOffset, uint stripByteCount, Span buffer) + { + if (stripByteCount > int.MaxValue) + { + TiffThrowHelper.ThrowImageFormatException("Too big value of StripByteCount."); + } + + stream.Seek(stripOffset, SeekOrigin.Begin); + this.Decompress(stream, (int)stripByteCount, buffer); + + if (stripOffset + stripByteCount < stream.Position) + { + TiffThrowHelper.ThrowImageFormatException("Out of range when reading a strip."); + } + } + + /// + /// Decompresses image data into the supplied buffer. + /// + /// The to read image data from. /// The number of bytes to read from the input stream. /// The output buffer for uncompressed data. - public abstract void Decompress(Stream stream, int byteCount, Span buffer); + protected abstract void Decompress(BufferedReadStream stream, int byteCount, Span buffer); } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffCompressionFactory.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffCompressionFactory.cs index c261e91d34..2e2fa51458 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/TiffCompressionFactory.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/TiffCompressionFactory.cs @@ -13,17 +13,27 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression switch (compressionType) { case TiffDecoderCompressionType.None: + DebugGuard.IsTrue(predictor == TiffPredictor.None, "predictor"); return new NoneTiffCompression(allocator); + case TiffDecoderCompressionType.PackBits: + DebugGuard.IsTrue(predictor == TiffPredictor.None, "predictor"); return new PackBitsTiffCompression(allocator); + case TiffDecoderCompressionType.Deflate: return new DeflateTiffCompression(allocator, width, bitsPerPixel, predictor); + case TiffDecoderCompressionType.Lzw: return new LzwTiffCompression(allocator, width, bitsPerPixel, predictor); + case TiffDecoderCompressionType.T4: + DebugGuard.IsTrue(predictor == TiffPredictor.None, "predictor"); return new T4TiffCompression(allocator, photometricInterpretation, width); + case TiffDecoderCompressionType.HuffmanRle: + DebugGuard.IsTrue(predictor == TiffPredictor.None, "predictor"); return new ModifiedHuffmanTiffCompression(allocator, photometricInterpretation, width); + default: throw TiffThrowHelper.NotSupportedCompression(nameof(compressionType)); } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index e6595653ce..a62c5946f7 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -347,8 +347,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff { int stripIndex = (i * stripsPerPixel) + planeIndex; - this.inputStream.Seek(stripOffsets[stripIndex], SeekOrigin.Begin); - decompressor.Decompress(this.inputStream, (int)stripByteCounts[stripIndex], stripBuffers[planeIndex].GetSpan()); + decompressor.Decompress(this.inputStream, stripOffsets[stripIndex], stripByteCounts[stripIndex], stripBuffers[planeIndex].GetSpan()); } colorDecoder.Decode(stripBuffers, pixels, 0, rowsPerStrip * i, frame.Width, stripHeight); @@ -385,8 +384,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff { int stripHeight = stripIndex < stripOffsets.Length - 1 || frame.Height % rowsPerStrip == 0 ? rowsPerStrip : frame.Height % rowsPerStrip; - this.inputStream.Seek(stripOffsets[stripIndex], SeekOrigin.Begin); - decompressor.Decompress(this.inputStream, (int)stripByteCounts[stripIndex], stripBuffer.GetSpan()); + decompressor.Decompress(this.inputStream, stripOffsets[stripIndex], stripByteCounts[stripIndex], stripBuffer.GetSpan()); colorDecoder.Decode(stripBuffer.GetSpan(), pixels, 0, rowsPerStrip * stripIndex, frame.Width, stripHeight); } diff --git a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs index ff44e0d6e4..3709bca04b 100644 --- a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs +++ b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs @@ -18,9 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff /// The error message for the exception. [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowImageFormatException(string errorMessage) - { - throw new ImageFormatException(errorMessage); - } + => throw new ImageFormatException(errorMessage); [MethodImpl(InliningOptions.ColdPath)] public static Exception TagNotFound(string tagName) diff --git a/src/ImageSharp/Formats/Tiff/Utils/SubStream.cs b/src/ImageSharp/Formats/Tiff/Utils/SubStream.cs deleted file mode 100644 index 22cdaf5e8e..0000000000 --- a/src/ImageSharp/Formats/Tiff/Utils/SubStream.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.IO; - -namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils -{ - /// - /// Utility class to encapsulate a sub-portion of another . - /// - /// - /// Note that disposing of the does not dispose the underlying - /// . - /// - internal class SubStream : Stream - { - private Stream innerStream; - private long offset; - private long endOffset; - private long length; - - /// - /// Initializes a new instance of the class. - /// - /// The underlying to wrap. - /// The length of the sub-stream. - /// - /// Note that calling the sub-stream with start from the current offset of the - /// underlying - /// - public SubStream(Stream innerStream, long length) - { - this.innerStream = innerStream; - this.offset = this.innerStream.Position; - this.endOffset = this.offset + length; - this.length = length; - } - - /// - /// Initializes a new instance of the class. - /// - /// The underlying to wrap. - /// The offset of the sub-stream within the underlying . - /// The length of the sub-stream. - /// - /// Note that calling the constructor will immediately move the underlying - /// to the specified offset. - /// - public SubStream(Stream innerStream, long offset, long length) - { - this.innerStream = innerStream; - this.offset = offset; - this.endOffset = offset + length; - this.length = length; - - innerStream.Seek(offset, SeekOrigin.Begin); - } - - /// - public override bool CanRead - { - get - { - return true; - } - } - - /// - public override bool CanWrite - { - get - { - return false; - } - } - - /// - public override bool CanSeek - { - get - { - return this.innerStream.CanSeek; - } - } - - /// - public override long Length - { - get - { - return this.length; - } - } - - /// - public override long Position - { - get - { - return this.innerStream.Position - this.offset; - } - - set - { - this.Seek(value, SeekOrigin.Begin); - } - } - - /// - public override void Flush() - { - throw new NotSupportedException(); - } - - /// - public override int Read(byte[] buffer, int offset, int count) - { - long bytesRemaining = this.endOffset - this.innerStream.Position; - - if (bytesRemaining < count) - { - count = (int)bytesRemaining; - } - - return this.innerStream.Read(buffer, offset, count); - } - - /// - public override int ReadByte() - { - if (this.innerStream.Position < this.endOffset) - { - return this.innerStream.ReadByte(); - } - else - { - return -1; - } - } - - /// - public override void Write(byte[] array, int offset, int count) - { - throw new NotSupportedException(); - } - - /// - public override void WriteByte(byte value) - { - throw new NotSupportedException(); - } - - /// - public override long Seek(long offset, SeekOrigin origin) - { - switch (origin) - { - case SeekOrigin.Current: - return this.innerStream.Seek(offset, SeekOrigin.Current) - this.offset; - case SeekOrigin.Begin: - return this.innerStream.Seek(this.offset + offset, SeekOrigin.Begin) - this.offset; - case SeekOrigin.End: - return this.innerStream.Seek(this.endOffset - offset, SeekOrigin.Begin) - this.offset; - default: - throw new ArgumentException("Invalid seek origin."); - } - } - - /// - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - } -} diff --git a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs index 09db488903..3605869256 100644 --- a/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs +++ b/src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs @@ -186,7 +186,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils { int bytesWritten = 0; using var memoryStream = new MemoryStream(); - using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel); // TODO: move zlib compression from png to a common place? + using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel); for (int y = 0; y < image.Height; y++) { @@ -534,7 +534,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils { int bytesWritten = 0; using var memoryStream = new MemoryStream(); - using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel); // TODO: move zlib compression from png to a common place? + using var deflateStream = new ZlibDeflateStream(this.memoryAllocator, memoryStream, compressionLevel); for (int y = 0; y < image.Height; y++) { diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs index fbac89e9ac..18025eecbd 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/DeflateTiffCompressionTests.cs @@ -5,6 +5,8 @@ using System.IO; using SixLabors.ImageSharp.Compression.Zlib; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; +using SixLabors.ImageSharp.IO; + using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression @@ -20,17 +22,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression [InlineData(new byte[] { 1, 2, 42, 53, 42, 53, 42, 53, 42, 53, 42, 53, 3, 4 })] // Repeated sequence public void Compress_Decompress_Roundtrip_Works(byte[] data) { - using (Stream stream = CreateCompressedStream(data)) + using (BufferedReadStream stream = CreateCompressedStream(data)) { var buffer = new byte[data.Length]; - new DeflateTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffPredictor.None).Decompress(stream, (int)stream.Length, buffer); + new DeflateTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffPredictor.None).Decompress(stream, 0, (uint)stream.Length, buffer); Assert.Equal(data, buffer); } } - private static Stream CreateCompressedStream(byte[] data) + private static BufferedReadStream CreateCompressedStream(byte[] data) { Stream compressedStream = new MemoryStream(); @@ -41,7 +43,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression } compressedStream.Seek(0, SeekOrigin.Begin); - return compressedStream; + return new BufferedReadStream(Configuration.Default, compressedStream); } } } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/LzwTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/LzwTiffCompressionTests.cs index 79cc1b1a88..6ba1b32261 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/LzwTiffCompressionTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/LzwTiffCompressionTests.cs @@ -7,6 +7,7 @@ using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Constants; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using Xunit; @@ -36,15 +37,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression public void Compress_Decompress_Roundtrip_Works(byte[] data) { - using Stream stream = CreateCompressedStream(data); + using BufferedReadStream stream = CreateCompressedStream(data); var buffer = new byte[data.Length]; - new LzwTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffPredictor.None).Decompress(stream, (int)stream.Length, buffer); + new LzwTiffCompression(Configuration.Default.MemoryAllocator, 10, 8, TiffPredictor.None).Decompress(stream, 0, (uint)stream.Length, buffer); Assert.Equal(data, buffer); } - private static Stream CreateCompressedStream(byte[] inputData) + private static BufferedReadStream CreateCompressedStream(byte[] inputData) { Stream compressedStream = new MemoryStream(); using System.Buffers.IMemoryOwner data = Configuration.Default.MemoryAllocator.Allocate(inputData.Length); @@ -57,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression compressedStream.Seek(0, SeekOrigin.Begin); - return compressedStream; + return new BufferedReadStream(Configuration.Default, compressedStream); } } } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs index 50a0b29f3d..dcdd327c27 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/NoneTiffCompressionTests.cs @@ -3,6 +3,8 @@ using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression; +using SixLabors.ImageSharp.IO; + using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression @@ -13,12 +15,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression [Theory] [InlineData(new byte[] { 10, 15, 20, 25, 30, 35, 40, 45 }, 8, new byte[] { 10, 15, 20, 25, 30, 35, 40, 45 })] [InlineData(new byte[] { 10, 15, 20, 25, 30, 35, 40, 45 }, 5, new byte[] { 10, 15, 20, 25, 30 })] - public void Decompress_ReadsData(byte[] inputData, int byteCount, byte[] expectedResult) + public void Decompress_ReadsData(byte[] inputData, uint byteCount, byte[] expectedResult) { - Stream stream = new MemoryStream(inputData); + var stream = new BufferedReadStream(Configuration.Default, new MemoryStream(inputData)); var buffer = new byte[expectedResult.Length]; - new NoneTiffCompression(null).Decompress(stream, byteCount, buffer); + new NoneTiffCompression(null).Decompress(stream, 0, byteCount, buffer); Assert.Equal(expectedResult, buffer); } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs index e95e6abbb3..f272c7cb9d 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/Compression/PackBitsTiffCompressionTests.cs @@ -5,6 +5,7 @@ using System; using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Tiff.Compression; +using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using Xunit; @@ -25,10 +26,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff.Compression [InlineData(new byte[] { 0xFE, 0xAA, 0x02, 0x80, 0x00, 0x2A, 0xFD, 0xAA, 0x03, 0x80, 0x00, 0x2A, 0x22, 0xF7, 0xAA }, new byte[] { 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0x22, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA })] // Apple PackBits sample public void Decompress_ReadsData(byte[] inputData, byte[] expectedResult) { - Stream stream = new MemoryStream(inputData); + var stream = new BufferedReadStream(Configuration.Default, new MemoryStream(inputData)); var buffer = new byte[expectedResult.Length]; - new PackBitsTiffCompression(new ArrayPoolMemoryAllocator()).Decompress(stream, inputData.Length, buffer); + new PackBitsTiffCompression(new ArrayPoolMemoryAllocator()).Decompress(stream, 0, (uint)inputData.Length, buffer); Assert.Equal(expectedResult, buffer); } diff --git a/tests/ImageSharp.Tests/Formats/Tiff/Utils/SubStreamTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/Utils/SubStreamTests.cs deleted file mode 100644 index 0aefa76cf7..0000000000 --- a/tests/ImageSharp.Tests/Formats/Tiff/Utils/SubStreamTests.cs +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.IO; - -using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Formats.Tiff -{ - [Trait("Format", "Tiff")] - public class SubStreamTests - { - [Fact] - public void Constructor_PositionsStreamCorrectly_WithSpecifiedOffset() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - innerStream.Position = 2; - - SubStream stream = new SubStream(innerStream, 4, 6); - - Assert.Equal(0, stream.Position); - Assert.Equal(6, stream.Length); - Assert.Equal(4, innerStream.Position); - } - - [Fact] - public void Constructor_PositionsStreamCorrectly_WithCurrentOffset() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - innerStream.Position = 2; - - SubStream stream = new SubStream(innerStream, 6); - - Assert.Equal(0, stream.Position); - Assert.Equal(6, stream.Length); - Assert.Equal(2, innerStream.Position); - } - - [Fact] - public void CanRead_ReturnsTrue() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.True(stream.CanRead); - } - - [Fact] - public void CanWrite_ReturnsFalse() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.False(stream.CanWrite); - } - - [Fact] - public void CanSeek_ReturnsTrue() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.True(stream.CanSeek); - } - - [Fact] - public void Length_ReturnsTheConstrainedLength() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.Equal(6, stream.Length); - } - - [Fact] - public void Position_ReturnsZeroBeforeReading() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.Equal(0, stream.Position); - Assert.Equal(2, innerStream.Position); - } - - [Fact] - public void Position_ReturnsPositionAfterReading() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Read(new byte[2], 0, 2); - - Assert.Equal(2, stream.Position); - Assert.Equal(4, innerStream.Position); - } - - [Fact] - public void Position_ReturnsPositionAfterReadingTwice() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Read(new byte[2], 0, 2); - stream.Read(new byte[2], 0, 2); - - Assert.Equal(4, stream.Position); - Assert.Equal(6, innerStream.Position); - } - - [Fact] - public void Position_SettingPropertySeeksToNewPosition() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 3; - - Assert.Equal(3, stream.Position); - Assert.Equal(5, innerStream.Position); - } - - [Fact] - public void Flush_ThrowsNotSupportedException() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.Throws(() => stream.Flush()); - } - - [Fact] - public void Read_Reads_FromStartOfSubStream() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - byte[] buffer = new byte[3]; - var result = stream.Read(buffer, 0, 3); - - Assert.Equal(new byte[] { 3, 4, 5 }, buffer); - Assert.Equal(3, result); - } - - [Theory] - [InlineData(2, SeekOrigin.Begin)] - [InlineData(1, SeekOrigin.Current)] - [InlineData(4, SeekOrigin.End)] - public void Read_Reads_FromMiddleOfSubStream(long offset, SeekOrigin origin) - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 1; - stream.Seek(offset, origin); - byte[] buffer = new byte[3]; - var result = stream.Read(buffer, 0, 3); - - Assert.Equal(new byte[] { 5, 6, 7 }, buffer); - Assert.Equal(3, result); - } - - [Theory] - [InlineData(3, SeekOrigin.Begin)] - [InlineData(2, SeekOrigin.Current)] - [InlineData(3, SeekOrigin.End)] - public void Read_Reads_FromEndOfSubStream(long offset, SeekOrigin origin) - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 1; - stream.Seek(offset, origin); - byte[] buffer = new byte[3]; - var result = stream.Read(buffer, 0, 3); - - Assert.Equal(new byte[] { 6, 7, 8 }, buffer); - Assert.Equal(3, result); - } - - [Theory] - [InlineData(4, SeekOrigin.Begin)] - [InlineData(3, SeekOrigin.Current)] - [InlineData(2, SeekOrigin.End)] - public void Read_Reads_FromBeyondEndOfSubStream(long offset, SeekOrigin origin) - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 1; - stream.Seek(offset, origin); - byte[] buffer = new byte[3]; - var result = stream.Read(buffer, 0, 3); - - Assert.Equal(new byte[] { 7, 8, 0 }, buffer); - Assert.Equal(2, result); - } - - [Fact] - public void ReadByte_Reads_FromStartOfSubStream() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - var result = stream.ReadByte(); - - Assert.Equal(3, result); - } - - [Fact] - public void ReadByte_Reads_FromMiddleOfSubStream() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 3; - var result = stream.ReadByte(); - - Assert.Equal(6, result); - } - - [Fact] - public void ReadByte_Reads_FromEndOfSubStream() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 5; - var result = stream.ReadByte(); - - Assert.Equal(8, result); - } - - [Fact] - public void ReadByte_Reads_FromBeyondEndOfSubStream() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 5; - stream.ReadByte(); - var result = stream.ReadByte(); - - Assert.Equal(-1, result); - } - - [Fact] - public void Write_ThrowsNotSupportedException() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.Throws(() => stream.Write(new byte[] { 1, 2 }, 0, 2)); - } - - [Fact] - public void WriteByte_ThrowsNotSupportedException() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.Throws(() => stream.WriteByte(42)); - } - - [Fact] - public void Seek_MovesToNewPosition_FromBegin() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 1; - long result = stream.Seek(2, SeekOrigin.Begin); - - Assert.Equal(2, result); - Assert.Equal(2, stream.Position); - Assert.Equal(4, innerStream.Position); - } - - [Fact] - public void Seek_MovesToNewPosition_FromCurrent() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 1; - long result = stream.Seek(2, SeekOrigin.Current); - - Assert.Equal(3, result); - Assert.Equal(3, stream.Position); - Assert.Equal(5, innerStream.Position); - } - - [Fact] - public void Seek_MovesToNewPosition_FromEnd() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - stream.Position = 1; - long result = stream.Seek(2, SeekOrigin.End); - - Assert.Equal(4, result); - Assert.Equal(4, stream.Position); - Assert.Equal(6, innerStream.Position); - } - - [Fact] - public void Seek_ThrowsException_WithInvalidOrigin() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - var e = Assert.Throws(() => stream.Seek(2, (SeekOrigin)99)); - Assert.Equal("Invalid seek origin.", e.Message); - } - - [Fact] - public void SetLength_ThrowsNotSupportedException() - { - Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - SubStream stream = new SubStream(innerStream, 2, 6); - - Assert.Throws(() => stream.SetLength(5)); - } - } -}