-
-
Notifications
You must be signed in to change notification settings - Fork 854
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #119 from Andy-Wilkinson/tiff-codec
[WIP] Implement Tiff codec
- Loading branch information
Showing
102 changed files
with
14,915 additions
and
4,105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
src/ImageSharp/Formats/Tiff/Compression/DeflateTiffCompression.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
using System; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Class to handle cases where TIFF image data is compressed using Deflate compression. | ||
/// </summary> | ||
/// <remarks> | ||
/// Note that the 'OldDeflate' compression type is identical to the 'Deflate' compression type. | ||
/// </remarks> | ||
internal static class DeflateTiffCompression | ||
{ | ||
/// <summary> | ||
/// Decompresses image data into the supplied buffer. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> to read image data from.</param> | ||
/// <param name="byteCount">The number of bytes to read from the input stream.</param> | ||
/// <param name="buffer">The output buffer for uncompressed data.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void Decompress(Stream stream, int byteCount, byte[] buffer) | ||
{ | ||
// Read the 'zlib' header information | ||
int cmf = stream.ReadByte(); | ||
int flag = stream.ReadByte(); | ||
|
||
if ((cmf & 0x0f) != 8) | ||
{ | ||
throw new Exception($"Bad compression method for ZLIB header: cmf={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; | ||
SubStream subStream = new SubStream(stream, byteCount - headerLength); | ||
using (DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress, true)) | ||
{ | ||
deflateStream.ReadFull(buffer); | ||
} | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/ImageSharp/Formats/Tiff/Compression/LzwTiffCompression.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
using System.IO; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Class to handle cases where TIFF image data is compressed using LZW compression. | ||
/// </summary> | ||
internal static class LzwTiffCompression | ||
{ | ||
/// <summary> | ||
/// Decompresses image data into the supplied buffer. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> to read image data from.</param> | ||
/// <param name="byteCount">The number of bytes to read from the input stream.</param> | ||
/// <param name="buffer">The output buffer for uncompressed data.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void Decompress(Stream stream, int byteCount, byte[] buffer) | ||
{ | ||
SubStream subStream = new SubStream(stream, byteCount); | ||
using (var decoder = new TiffLzwDecoder(subStream)) | ||
{ | ||
decoder.DecodePixels(buffer.Length, 8, buffer); | ||
} | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/ImageSharp/Formats/Tiff/Compression/NoneTiffCompression.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
using System.IO; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Class to handle cases where TIFF image data is not compressed. | ||
/// </summary> | ||
internal static class NoneTiffCompression | ||
{ | ||
/// <summary> | ||
/// Decompresses image data into the supplied buffer. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> to read image data from.</param> | ||
/// <param name="byteCount">The number of bytes to read from the input stream.</param> | ||
/// <param name="buffer">The output buffer for uncompressed data.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void Decompress(Stream stream, int byteCount, byte[] buffer) | ||
{ | ||
stream.ReadFull(buffer, byteCount); | ||
} | ||
} | ||
} |
77 changes: 77 additions & 0 deletions
77
src/ImageSharp/Formats/Tiff/Compression/PackBitsTiffCompression.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
using System; | ||
using System.Buffers; | ||
using System.IO; | ||
using System.Runtime.CompilerServices; | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Class to handle cases where TIFF image data is compressed using PackBits compression. | ||
/// </summary> | ||
internal static class PackBitsTiffCompression | ||
{ | ||
/// <summary> | ||
/// Decompresses image data into the supplied buffer. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> to read image data from.</param> | ||
/// <param name="byteCount">The number of bytes to read from the input stream.</param> | ||
/// <param name="buffer">The output buffer for uncompressed data.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static void Decompress(Stream stream, int byteCount, byte[] buffer) | ||
{ | ||
byte[] compressedData = ArrayPool<byte>.Shared.Rent(byteCount); | ||
|
||
try | ||
{ | ||
stream.ReadFull(compressedData, byteCount); | ||
int compressedOffset = 0; | ||
int decompressedOffset = 0; | ||
|
||
while (compressedOffset < byteCount) | ||
{ | ||
byte headerByte = compressedData[compressedOffset]; | ||
|
||
if (headerByte <= (byte)127) | ||
{ | ||
int literalOffset = compressedOffset + 1; | ||
int literalLength = compressedData[compressedOffset] + 1; | ||
|
||
Array.Copy(compressedData, literalOffset, buffer, decompressedOffset, literalLength); | ||
|
||
compressedOffset += literalLength + 1; | ||
decompressedOffset += literalLength; | ||
} | ||
else if (headerByte == (byte)0x80) | ||
{ | ||
compressedOffset += 1; | ||
} | ||
else | ||
{ | ||
byte repeatData = compressedData[compressedOffset + 1]; | ||
int repeatLength = 257 - headerByte; | ||
|
||
ArrayCopyRepeat(repeatData, buffer, decompressedOffset, repeatLength); | ||
|
||
compressedOffset += 2; | ||
decompressedOffset += repeatLength; | ||
} | ||
} | ||
} | ||
finally | ||
{ | ||
ArrayPool<byte>.Shared.Return(compressedData); | ||
} | ||
} | ||
|
||
private static void ArrayCopyRepeat(byte value, byte[] destinationArray, int destinationIndex, int length) | ||
{ | ||
for (int i = 0; i < length; i++) | ||
{ | ||
destinationArray[i + destinationIndex] = value; | ||
} | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/ImageSharp/Formats/Tiff/Compression/TiffCompressionType.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Provides enumeration of the various TIFF compression types. | ||
/// </summary> | ||
internal enum TiffCompressionType | ||
{ | ||
/// <summary> | ||
/// Image data is stored uncompressed in the TIFF file. | ||
/// </summary> | ||
None = 0, | ||
|
||
/// <summary> | ||
/// Image data is compressed using PackBits compression. | ||
/// </summary> | ||
PackBits = 1, | ||
|
||
/// <summary> | ||
/// Image data is compressed using Deflate compression. | ||
/// </summary> | ||
Deflate = 2, | ||
|
||
/// <summary> | ||
/// Image data is compressed using LZW compression. | ||
/// </summary> | ||
Lzw = 3, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Enumeration representing the compression formats defined by the Tiff file-format. | ||
/// </summary> | ||
internal enum TiffCompression | ||
{ | ||
/// <summary> | ||
/// No compression. | ||
/// </summary> | ||
None = 1, | ||
|
||
/// <summary> | ||
/// CCITT Group 3 1-Dimensional Modified Huffman run-length encoding. | ||
/// </summary> | ||
Ccitt1D = 2, | ||
|
||
/// <summary> | ||
/// PackBits compression | ||
/// </summary> | ||
PackBits = 32773, | ||
|
||
/// <summary> | ||
/// T4-encoding: CCITT T.4 bi-level encoding (see Section 11 of the TIFF 6.0 specification). | ||
/// </summary> | ||
CcittGroup3Fax = 3, | ||
|
||
/// <summary> | ||
/// T6-encoding: CCITT T.6 bi-level encoding (see Section 11 of the TIFF 6.0 specification). | ||
/// </summary> | ||
CcittGroup4Fax = 4, | ||
|
||
/// <summary> | ||
/// LZW compression (see Section 13 of the TIFF 6.0 specification). | ||
/// </summary> | ||
Lzw = 5, | ||
|
||
/// <summary> | ||
/// JPEG compression - obsolete (see Section 22 of the TIFF 6.0 specification). | ||
/// </summary> | ||
OldJpeg = 6, | ||
|
||
/// <summary> | ||
/// JPEG compression (see TIFF Specification, supplement 2). | ||
/// </summary> | ||
Jpeg = 7, | ||
|
||
/// <summary> | ||
/// Deflate compression, using zlib data format (see TIFF Specification, supplement 2). | ||
/// </summary> | ||
Deflate = 8, | ||
|
||
/// <summary> | ||
/// Deflate compression - old. | ||
/// </summary> | ||
OldDeflate = 32946, | ||
|
||
/// <summary> | ||
/// ITU-T Rec. T.82 coding, applying ITU-T Rec. T.85 (JBIG) (see RFC2301). | ||
/// </summary> | ||
ItuTRecT82 = 9, | ||
|
||
/// <summary> | ||
/// ITU-T Rec. T.43 representation, using ITU-T Rec. T.82 (JBIG) (see RFC2301). | ||
/// </summary> | ||
ItuTRecT43 = 10 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (c) Six Labors and contributors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
using System.Collections.Generic; | ||
|
||
namespace SixLabors.ImageSharp.Formats.Tiff | ||
{ | ||
/// <summary> | ||
/// Defines constants defined in the TIFF specification. | ||
/// </summary> | ||
internal static class TiffConstants | ||
{ | ||
/// <summary> | ||
/// Byte order markers for indicating little endian encoding. | ||
/// </summary> | ||
public const byte ByteOrderLittleEndian = 0x49; | ||
|
||
/// <summary> | ||
/// Byte order markers for indicating big endian encoding. | ||
/// </summary> | ||
public const byte ByteOrderBigEndian = 0x4D; | ||
|
||
/// <summary> | ||
/// Byte order markers for indicating little endian encoding. | ||
/// </summary> | ||
public const ushort ByteOrderLittleEndianShort = 0x4949; | ||
|
||
/// <summary> | ||
/// Byte order markers for indicating big endian encoding. | ||
/// </summary> | ||
public const ushort ByteOrderBigEndianShort = 0x4D4D; | ||
|
||
/// <summary> | ||
/// Magic number used within the image file header to identify a TIFF format file. | ||
/// </summary> | ||
public const ushort HeaderMagicNumber = 42; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of the TIFF file header. | ||
/// </summary> | ||
public const int SizeOfTiffHeader = 8; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of each individual TIFF IFD entry | ||
/// </summary> | ||
public const int SizeOfIfdEntry = 12; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of the Short and SShort data types | ||
/// </summary> | ||
public const int SizeOfShort = 2; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of the Long and SLong data types | ||
/// </summary> | ||
public const int SizeOfLong = 4; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of the Rational and SRational data types | ||
/// </summary> | ||
public const int SizeOfRational = 8; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of the Float data type | ||
/// </summary> | ||
public const int SizeOfFloat = 4; | ||
|
||
/// <summary> | ||
/// Size (in bytes) of the Double data type | ||
/// </summary> | ||
public const int SizeOfDouble = 8; | ||
|
||
/// <summary> | ||
/// The list of mimetypes that equate to a tiff. | ||
/// </summary> | ||
public static readonly IEnumerable<string> MimeTypes = new[] { "image/tiff", "image/tiff-fx" }; | ||
|
||
/// <summary> | ||
/// The list of file extensions that equate to a tiff. | ||
/// </summary> | ||
public static readonly IEnumerable<string> FileExtensions = new[] { "tiff", "tif" }; | ||
} | ||
} |
Oops, something went wrong.