// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO.Compression;
using SixLabors.ImageSharp.Compression.Zlib;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
{
///
/// Class to handle cases where TIFF image data is compressed using Deflate compression.
///
///
/// Note that the 'OldDeflate' compression type is identical to the 'Deflate' compression type.
///
internal class DeflateTiffCompression : TiffBaseDecompressor
{
private readonly bool isBigEndian;
private readonly TiffColorType colorType;
///
/// Initializes a new instance of the class.
///
/// The memoryAllocator to use for buffer allocations.
/// The image width.
/// The bits used per pixel.
/// The color type of the pixel data.
/// The tiff predictor used.
/// if set to true decodes the pixel data as big endian, otherwise as little endian.
public DeflateTiffCompression(MemoryAllocator memoryAllocator, int width, int bitsPerPixel, TiffColorType colorType, TiffPredictor predictor, bool isBigEndian)
: base(memoryAllocator, width, bitsPerPixel, predictor)
{
this.colorType = colorType;
this.isBigEndian = isBigEndian;
}
///
protected override void Decompress(BufferedReadStream stream, int byteCount, Span buffer)
{
long pos = stream.Position;
using (var deframeStream = new ZlibInflateStream(
stream,
() =>
{
int left = (int)(byteCount - (stream.Position - pos));
return left > 0 ? left : 0;
}))
{
deframeStream.AllocateNewBytes(byteCount, true);
DeflateStream dataStream = deframeStream.CompressedStream;
int totalRead = 0;
while (totalRead < buffer.Length)
{
int bytesRead = dataStream.Read(buffer, totalRead, buffer.Length - totalRead);
if (bytesRead <= 0)
{
break;
}
totalRead += bytesRead;
}
}
if (this.Predictor == TiffPredictor.Horizontal)
{
HorizontalPredictor.Undo(buffer, this.Width, this.colorType, this.isBigEndian);
}
}
///
protected override void Dispose(bool disposing)
{
}
}
}