@ -20,24 +20,33 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
private readonly byte blackValue ;
private readonly byte blackValue ;
private readonly int width ;
/// <summary>
/// <summary>
/// Initializes a new instance of the <see cref="T4TiffCompression" /> class.
/// Initializes a new instance of the <see cref="T4TiffCompression" /> class.
/// </summary>
/// </summary>
/// <param name="allocator">The memory allocator.</param>
/// <param name="allocator">The memory allocator.</param>
/// <param name="fillOrder">The logical order of bits within a byte.</param>
/// <param name="width">The image width.</param>
/// <param name="width">The image width.</param>
/// <param name="bitsPerPixel">The number of bits per pixel.</param>
/// <param name="bitsPerPixel">The number of bits per pixel.</param>
/// <param name="faxOptions">Fax compression options.</param>
/// <param name="faxOptions">Fax compression options.</param>
/// <param name="photometricInterpretation">The photometric interpretation.</param>
/// <param name="photometricInterpretation">The photometric interpretation.</param>
public T4TiffCompression ( MemoryAllocator allocator , int width , int bitsPerPixel , FaxCompressionOptions faxOptions , TiffPhotometricInterpretation photometricInterpretation )
public T4TiffCompression ( MemoryAllocator allocator , TiffFillOrder fillOrder , int width , int bitsPerPixel , FaxCompressionOptions faxOptions , TiffPhotometricInterpretation photometricInterpretation )
: base ( allocator , width , bitsPerPixel )
: base ( allocator , width , bitsPerPixel )
{
{
this . faxCompressionOptions = faxOptions ;
this . faxCompressionOptions = faxOptions ;
this . FillOrder = fillOrder ;
this . width = width ;
bool isWhiteZero = photometricInterpretation = = TiffPhotometricInterpretation . WhiteIsZero ;
bool isWhiteZero = photometricInterpretation = = TiffPhotometricInterpretation . WhiteIsZero ;
this . whiteValue = ( byte ) ( isWhiteZero ? 0 : 1 ) ;
this . whiteValue = ( byte ) ( isWhiteZero ? 0 : 1 ) ;
this . blackValue = ( byte ) ( isWhiteZero ? 1 : 0 ) ;
this . blackValue = ( byte ) ( isWhiteZero ? 1 : 0 ) ;
}
}
/// <summary>
/// Gets the logical order of bits within a byte.
/// </summary>
protected TiffFillOrder FillOrder { get ; }
/// <inheritdoc/>
/// <inheritdoc/>
protected override void Decompress ( BufferedReadStream stream , int byteCount , Span < byte > buffer )
protected override void Decompress ( BufferedReadStream stream , int byteCount , Span < byte > buffer )
{
{
@ -46,27 +55,22 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
TiffThrowHelper . ThrowNotSupported ( "TIFF CCITT 2D compression is not yet supported" ) ;
TiffThrowHelper . ThrowNotSupported ( "TIFF CCITT 2D compression is not yet supported" ) ;
}
}
var eolPadding = this . faxCompressionOptions . HasFlag ( FaxCompressionOptions . EolPadding ) ;
bool eolPadding = this . faxCompressionOptions . HasFlag ( FaxCompressionOptions . EolPadding ) ;
using var bitReader = new T4BitReader ( stream , byteCount , this . Allocator , eolPadding ) ;
using var bitReader = new T4BitReader ( stream , this . FillOrder , byteCount , this . Allocator , eolPadding ) ;
buffer . Clear ( ) ;
buffer . Clear ( ) ;
uint bitsWritten = 0 ;
uint bitsWritten = 0 ;
uint pixelWritten = 0 ;
while ( bitReader . HasMoreData )
while ( bitReader . HasMoreData )
{
{
bitReader . ReadNextRun ( ) ;
bitReader . ReadNextRun ( ) ;
if ( bitReader . RunLength > 0 )
if ( bitReader . RunLength > 0 )
{
{
if ( bitReader . IsWhiteRun )
this . WritePixelRun ( buffer , bitReader , bitsWritten ) ;
{
BitWriterUtils . WriteBits ( buffer , ( int ) bitsWritten , bitReader . RunLength , this . whiteValue ) ;
bitsWritten + = bitReader . RunLength ;
bitsWritten + = bitReader . RunLength ;
pixelWritten + = bitReader . RunLength ;
}
else
{
BitWriterUtils . WriteBits ( buffer , ( int ) bitsWritten , bitReader . RunLength , this . blackValue ) ;
bitsWritten + = bitReader . RunLength ;
}
}
}
if ( bitReader . IsEndOfScanLine )
if ( bitReader . IsEndOfScanLine )
@ -78,8 +82,29 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
BitWriterUtils . WriteBits ( buffer , ( int ) bitsWritten , pad , 0 ) ;
BitWriterUtils . WriteBits ( buffer , ( int ) bitsWritten , pad , 0 ) ;
bitsWritten + = pad ;
bitsWritten + = pad ;
}
}
pixelWritten = 0 ;
}
}
}
}
// Edge case for when we are at the last byte, but there are still some unwritten pixels left.
if ( pixelWritten > 0 & & pixelWritten < this . width )
{
bitReader . ReadNextRun ( ) ;
this . WritePixelRun ( buffer , bitReader , bitsWritten ) ;
}
}
private void WritePixelRun ( Span < byte > buffer , T4BitReader bitReader , uint bitsWritten )
{
if ( bitReader . IsWhiteRun )
{
BitWriterUtils . WriteBits ( buffer , ( int ) bitsWritten , bitReader . RunLength , this . whiteValue ) ;
}
else
{
BitWriterUtils . WriteBits ( buffer , ( int ) bitsWritten , bitReader . RunLength , this . blackValue ) ;
}
}
}
/// <inheritdoc/>
/// <inheritdoc/>