diff --git a/src/UglyToad.PdfPig/Filters/FlateFilter.cs b/src/UglyToad.PdfPig/Filters/FlateFilter.cs index 9c230a40..fb1583ed 100644 --- a/src/UglyToad.PdfPig/Filters/FlateFilter.cs +++ b/src/UglyToad.PdfPig/Filters/FlateFilter.cs @@ -27,6 +27,9 @@ private const int DefaultBitsPerComponent = 8; private const int DefaultColumns = 1; + private const byte Deflate32KbWindow = 120; + private const byte ChecksumBits = 1; + private readonly IDecodeParameterResolver decodeParameterResolver; private readonly IPngPredictor pngPredictor; private readonly ILog log; @@ -106,17 +109,45 @@ public byte[] Encode(Stream input, DictionaryToken streamDictionary, int index) { - var resx = new List{ 120, 156 }; - using (var output = new MemoryStream()) - using (var flater = new DeflateStream(output, CompressionMode.Compress, true)) - { - input.CopyTo(flater); - flater.Close(); + const int headerLength = 2; + const int checksumLength = 4; - resx.AddRange(output.ToArray()); + byte[] data; + using (var temp = new MemoryStream()) + { + input.CopyTo(temp); + data = temp.ToArray(); } - return resx.ToArray(); + using (var compressStream = new MemoryStream()) + using (var compressor = new DeflateStream(compressStream, CompressionLevel.Fastest)) + { + compressor.Write(data, 0, data.Length); + compressor.Close(); + + var compressed = compressStream.ToArray(); + + var result = new byte[headerLength + compressed.Length + checksumLength]; + + // Write the ZLib header. + result[0] = Deflate32KbWindow; + result[1] = ChecksumBits; + + // Write the compressed data. + Array.Copy(compressed, 0, result, headerLength, compressed.Length); + + // Write Checksum of raw data. + var checksum = Adler32Checksum.Calculate(data); + + var offset = headerLength + compressed.Length; + + result[offset++] = (byte)(checksum >> 24); + result[offset++] = (byte)(checksum >> 16); + result[offset++] = (byte)(checksum >> 8); + result[offset] = (byte)(checksum >> 0); + + return result; + } } } } \ No newline at end of file diff --git a/src/UglyToad.PdfPig/Util/Adler32Checksum.cs b/src/UglyToad.PdfPig/Util/Adler32Checksum.cs new file mode 100644 index 00000000..cde46aa4 --- /dev/null +++ b/src/UglyToad.PdfPig/Util/Adler32Checksum.cs @@ -0,0 +1,35 @@ +namespace UglyToad.PdfPig.Util +{ + using System.Collections.Generic; + + /// + /// Used to calculate the Adler-32 checksum used for ZLIB data in accordance with + /// RFC 1950: ZLIB Compressed Data Format Specification. + /// + public static class Adler32Checksum + { + // Both sums (s1 and s2) are done modulo 65521. + private const int AdlerModulus = 65521; + + /// + /// Calculate the Adler-32 checksum for some data. + /// + public static int Calculate(IEnumerable data) + { + // s1 is the sum of all bytes. + var s1 = 1; + + // s2 is the sum of all s1 values. + var s2 = 0; + + foreach (var b in data) + { + s1 = (s1 + b) % AdlerModulus; + s2 = (s1 + s2) % AdlerModulus; + } + + // The Adler-32 checksum is stored as s2*65536 + s1. + return s2 * 65536 + s1; + } + } +}