First commit
Send all results
This commit is contained in:
285
PdfSharp/Pdf.Filters/Ascii85Decode.cs
Normal file
285
PdfSharp/Pdf.Filters/Ascii85Decode.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace PdfSharp.Pdf.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the ASCII85Decode filter.
|
||||
/// </summary>
|
||||
public class Ascii85Decode : Filter
|
||||
{
|
||||
// Reference: 3.3.2 ASCII85Decode Filter / Page 69
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Encode(byte[] data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
int length = data.Length; // length == 0 is must not be treated as a special case.
|
||||
int words = length / 4;
|
||||
int rest = length - (words * 4);
|
||||
byte[] result = new byte[words * 5 + (rest == 0 ? 0 : rest + 1) + 2];
|
||||
|
||||
int idxIn = 0, idxOut = 0;
|
||||
int wCount = 0;
|
||||
while (wCount < words)
|
||||
{
|
||||
uint val = ((uint)data[idxIn++] << 24) + ((uint)data[idxIn++] << 16) + ((uint)data[idxIn++] << 8) + data[idxIn++];
|
||||
if (val == 0)
|
||||
{
|
||||
result[idxOut++] = (byte)'z';
|
||||
}
|
||||
else
|
||||
{
|
||||
byte c5 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c4 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c3 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c2 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c1 = (byte)(val + '!');
|
||||
|
||||
result[idxOut++] = c1;
|
||||
result[idxOut++] = c2;
|
||||
result[idxOut++] = c3;
|
||||
result[idxOut++] = c4;
|
||||
result[idxOut++] = c5;
|
||||
}
|
||||
wCount++;
|
||||
}
|
||||
if (rest == 1)
|
||||
{
|
||||
uint val = (uint)data[idxIn] << 24;
|
||||
val /= 85 * 85 * 85;
|
||||
byte c2 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c1 = (byte)(val + '!');
|
||||
|
||||
result[idxOut++] = c1;
|
||||
result[idxOut++] = c2;
|
||||
}
|
||||
else if (rest == 2)
|
||||
{
|
||||
uint val = ((uint)data[idxIn++] << 24) + ((uint)data[idxIn] << 16);
|
||||
val /= 85 * 85;
|
||||
byte c3 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c2 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c1 = (byte)(val + '!');
|
||||
|
||||
result[idxOut++] = c1;
|
||||
result[idxOut++] = c2;
|
||||
result[idxOut++] = c3;
|
||||
}
|
||||
else if (rest == 3)
|
||||
{
|
||||
uint val = ((uint)data[idxIn++] << 24) + ((uint)data[idxIn++] << 16) + ((uint)data[idxIn] << 8);
|
||||
val /= 85;
|
||||
byte c4 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c3 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c2 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c1 = (byte)(val + '!');
|
||||
|
||||
result[idxOut++] = c1;
|
||||
result[idxOut++] = c2;
|
||||
result[idxOut++] = c3;
|
||||
result[idxOut++] = c4;
|
||||
}
|
||||
result[idxOut++] = (byte)'~';
|
||||
result[idxOut++] = (byte)'>';
|
||||
|
||||
if (idxOut < result.Length)
|
||||
Array.Resize(ref result, idxOut);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Decode(byte[] data, FilterParms parms)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
int idx;
|
||||
int length = data.Length;
|
||||
int zCount = 0;
|
||||
int idxOut = 0;
|
||||
for (idx = 0; idx < length; idx++)
|
||||
{
|
||||
char ch = (char)data[idx];
|
||||
if (ch >= '!' && ch <= 'u')
|
||||
data[idxOut++] = (byte)ch;
|
||||
else if (ch == 'z')
|
||||
{
|
||||
data[idxOut++] = (byte)ch;
|
||||
zCount++;
|
||||
}
|
||||
else if (ch == '~')
|
||||
{
|
||||
if ((char)data[idx + 1] != '>')
|
||||
throw new ArgumentException("Illegal character.", "data");
|
||||
break;
|
||||
}
|
||||
// ingnore unknown character
|
||||
}
|
||||
// Loop not ended with break?
|
||||
if (idx == length)
|
||||
throw new ArgumentException("Illegal character.", "data");
|
||||
|
||||
length = idxOut;
|
||||
int nonZero = length - zCount;
|
||||
int byteCount = 4 * (zCount + (nonZero / 5)); // full 4 byte blocks
|
||||
|
||||
int remainder = nonZero % 5;
|
||||
if (remainder == 1)
|
||||
throw new InvalidOperationException("Illegal character.");
|
||||
|
||||
if (remainder != 0)
|
||||
byteCount += remainder - 1;
|
||||
|
||||
byte[] output = new byte[byteCount];
|
||||
|
||||
idxOut = 0;
|
||||
idx = 0;
|
||||
while (idx + 4 < length)
|
||||
{
|
||||
char ch = (char)data[idx];
|
||||
if (ch == 'z')
|
||||
{
|
||||
idx++;
|
||||
idxOut += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: check
|
||||
long value =
|
||||
(long)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
|
||||
(uint)(data[idx++] - '!') * (85 * 85 * 85) +
|
||||
(uint)(data[idx++] - '!') * (85 * 85) +
|
||||
(uint)(data[idx++] - '!') * 85 +
|
||||
(uint)(data[idx++] - '!');
|
||||
|
||||
if (value > UInt32.MaxValue)
|
||||
throw new InvalidOperationException("Value of group greater than 2 power 32 - 1.");
|
||||
|
||||
output[idxOut++] = (byte)(value >> 24);
|
||||
output[idxOut++] = (byte)(value >> 16);
|
||||
output[idxOut++] = (byte)(value >> 8);
|
||||
output[idxOut++] = (byte)value;
|
||||
}
|
||||
}
|
||||
|
||||
// I have found no appropriate algorithm, so I write my own. In some rare cases the value must not
|
||||
// increased by one, but I cannot found a general formula or a proof.
|
||||
// All possible cases are tested programmatically.
|
||||
if (remainder == 2) // one byte
|
||||
{
|
||||
uint value =
|
||||
(uint)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
|
||||
(uint)(data[idx] - '!') * (85 * 85 * 85);
|
||||
|
||||
// Always increase if not zero (tried out).
|
||||
if (value != 0)
|
||||
value += 0x01000000;
|
||||
|
||||
output[idxOut] = (byte)(value >> 24);
|
||||
}
|
||||
else if (remainder == 3) // two bytes
|
||||
{
|
||||
int idxIn = idx;
|
||||
uint value =
|
||||
(uint)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
|
||||
(uint)(data[idx++] - '!') * (85 * 85 * 85) +
|
||||
(uint)(data[idx] - '!') * (85 * 85);
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
value &= 0xFFFF0000;
|
||||
uint val = value / (85 * 85);
|
||||
byte c3 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c2 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c1 = (byte)(val + '!');
|
||||
if (c1 != data[idxIn] || c2 != data[idxIn + 1] || c3 != data[idxIn + 2])
|
||||
{
|
||||
value += 0x00010000;
|
||||
//Count2++;
|
||||
}
|
||||
}
|
||||
output[idxOut++] = (byte)(value >> 24);
|
||||
output[idxOut] = (byte)(value >> 16);
|
||||
}
|
||||
else if (remainder == 4) // three bytes
|
||||
{
|
||||
int idxIn = idx;
|
||||
uint value =
|
||||
(uint)(data[idx++] - '!') * (85 * 85 * 85 * 85) +
|
||||
(uint)(data[idx++] - '!') * (85 * 85 * 85) +
|
||||
(uint)(data[idx++] - '!') * (85 * 85) +
|
||||
(uint)(data[idx] - '!') * 85;
|
||||
|
||||
if (value != 0)
|
||||
{
|
||||
value &= 0xFFFFFF00;
|
||||
uint val = value / 85;
|
||||
byte c4 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c3 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c2 = (byte)(val % 85 + '!');
|
||||
val /= 85;
|
||||
byte c1 = (byte)(val + '!');
|
||||
if (c1 != data[idxIn] || c2 != data[idxIn + 1] || c3 != data[idxIn + 2] || c4 != data[idxIn + 3])
|
||||
{
|
||||
value += 0x00000100;
|
||||
//Count3++;
|
||||
}
|
||||
}
|
||||
output[idxOut++] = (byte)(value >> 24);
|
||||
output[idxOut++] = (byte)(value >> 16);
|
||||
output[idxOut] = (byte)(value >> 8);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
98
PdfSharp/Pdf.Filters/AsciiHexDecode.cs
Normal file
98
PdfSharp/Pdf.Filters/AsciiHexDecode.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace PdfSharp.Pdf.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the ASCIIHexDecode filter.
|
||||
/// </summary>
|
||||
public class AsciiHexDecode : Filter
|
||||
{
|
||||
// Reference: 3.3.1 ASCIIHexDecode Filter / Page 69
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Encode(byte[] data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
int count = data.Length;
|
||||
byte[] bytes = new byte[2 * count];
|
||||
for (int i = 0, j = 0; i < count; i++)
|
||||
{
|
||||
byte b = data[i];
|
||||
bytes[j++] = (byte)((b >> 4) + ((b >> 4) < 10 ? (byte)'0' : (byte)('A' - 10)));
|
||||
bytes[j++] = (byte)((b & 0xF) + ((b & 0xF) < 10 ? (byte)'0' : (byte)('A' - 10)));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Decode(byte[] data, FilterParms parms)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
data = RemoveWhiteSpace(data);
|
||||
int count = data.Length;
|
||||
// Ignore EOD (end of data) character.
|
||||
// EOD can be anywhere in the stream, but makes sense only at the end of the stream.
|
||||
if (count > 0 && data[count - 1] == '>')
|
||||
--count;
|
||||
if (count % 2 == 1)
|
||||
{
|
||||
count++;
|
||||
byte[] temp = data;
|
||||
data = new byte[count];
|
||||
temp.CopyTo(data, 0);
|
||||
}
|
||||
count >>= 1;
|
||||
byte[] bytes = new byte[count];
|
||||
for (int i = 0, j = 0; i < count; i++)
|
||||
{
|
||||
// Must support 0-9, A-F, a-f - "Any other characters cause an error."
|
||||
byte hi = data[j++];
|
||||
byte lo = data[j++];
|
||||
if (hi >= 'a' && hi <= 'f')
|
||||
hi -= 32;
|
||||
if (lo >= 'a' && lo <= 'f')
|
||||
lo -= 32;
|
||||
// TODO Throw on invalid characters. Stop when encountering EOD. Add one more byte if EOD is the lo byte.
|
||||
bytes[i] = (byte)((hi > '9' ? hi - '7'/*'A' + 10*/: hi - '0') * 16 + (lo > '9' ? lo - '7'/*'A' + 10*/: lo - '0'));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
130
PdfSharp/Pdf.Filters/Filter.cs
Normal file
130
PdfSharp/Pdf.Filters/Filter.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using PdfSharp.Pdf.IO;
|
||||
using PdfSharp.Pdf.Internal;
|
||||
|
||||
namespace PdfSharp.Pdf.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved for future extension.
|
||||
/// </summary>
|
||||
public class FilterParms
|
||||
{
|
||||
// not yet used
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for all stream filters
|
||||
/// </summary>
|
||||
public abstract class Filter
|
||||
{
|
||||
/// <summary>
|
||||
/// When implemented in a derived class encodes the specified data.
|
||||
/// </summary>
|
||||
public abstract byte[] Encode(byte[] data);
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a raw string.
|
||||
/// </summary>
|
||||
public virtual byte[] Encode(string rawString)
|
||||
{
|
||||
byte[] bytes = PdfEncoders.RawEncoding.GetBytes(rawString);
|
||||
bytes = Encode(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When implemented in a derived class decodes the specified data.
|
||||
/// </summary>
|
||||
public abstract byte[] Decode(byte[] data, FilterParms parms);
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified data.
|
||||
/// </summary>
|
||||
public byte[] Decode(byte[] data)
|
||||
{
|
||||
return Decode(data, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes to a raw string.
|
||||
/// </summary>
|
||||
public virtual string DecodeToString(byte[] data, FilterParms parms)
|
||||
{
|
||||
byte[] bytes = Decode(data, parms);
|
||||
string text = PdfEncoders.RawEncoding.GetString(bytes, 0, bytes.Length);
|
||||
return text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes to a raw string.
|
||||
/// </summary>
|
||||
public string DecodeToString(byte[] data)
|
||||
{
|
||||
return DecodeToString(data, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all white spaces from the data. The function assumes that the bytes are characters.
|
||||
/// </summary>
|
||||
protected byte[] RemoveWhiteSpace(byte[] data)
|
||||
{
|
||||
int count = data.Length;
|
||||
int j = 0;
|
||||
for (int i = 0; i < count; i++, j++)
|
||||
{
|
||||
switch (data[i])
|
||||
{
|
||||
case (byte)Chars.NUL: // 0 Null
|
||||
case (byte)Chars.HT: // 9 Tab
|
||||
case (byte)Chars.LF: // 10 Line feed
|
||||
case (byte)Chars.FF: // 12 Form feed
|
||||
case (byte)Chars.CR: // 13 Carriage return
|
||||
case (byte)Chars.SP: // 32 Space
|
||||
j--;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (i != j)
|
||||
data[j] = data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < count)
|
||||
{
|
||||
byte[] temp = data;
|
||||
data = new byte[j];
|
||||
for (int idx = 0; idx < j; idx++)
|
||||
data[idx] = temp[idx];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
242
PdfSharp/Pdf.Filters/Filtering.cs
Normal file
242
PdfSharp/Pdf.Filters/Filtering.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PdfSharp.Pdf.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Applies standard filters to streams.
|
||||
/// </summary>
|
||||
public static class Filtering
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the filter specified by the case sensitive name.
|
||||
/// </summary>
|
||||
public static Filter GetFilter(string filterName)
|
||||
{
|
||||
if (filterName.StartsWith("/"))
|
||||
filterName = filterName.Substring(1);
|
||||
|
||||
// Some tools use abbreviations
|
||||
switch (filterName)
|
||||
{
|
||||
case "ASCIIHexDecode":
|
||||
case "AHx":
|
||||
return _asciiHexDecode ?? (_asciiHexDecode = new AsciiHexDecode());
|
||||
|
||||
case "ASCII85Decode":
|
||||
case "A85":
|
||||
return _ascii85Decode ?? (_ascii85Decode = new Ascii85Decode());
|
||||
|
||||
case "LZWDecode":
|
||||
case "LZW":
|
||||
return _lzwDecode ?? (_lzwDecode = new LzwDecode());
|
||||
|
||||
case "FlateDecode":
|
||||
case "Fl":
|
||||
return _flateDecode ?? (_flateDecode = new FlateDecode());
|
||||
|
||||
//case "RunLengthDecode":
|
||||
// if (RunLengthDecode == null)
|
||||
// RunLengthDecode = new RunLengthDecode();
|
||||
// return RunLengthDecode;
|
||||
//
|
||||
//case "CCITTFaxDecode":
|
||||
// if (CCITTFaxDecode == null)
|
||||
// CCITTFaxDecode = new CCITTFaxDecode();
|
||||
// return CCITTFaxDecode;
|
||||
//
|
||||
//case "JBIG2Decode":
|
||||
// if (JBIG2Decode == null)
|
||||
// JBIG2Decode = new JBIG2Decode();
|
||||
// return JBIG2Decode;
|
||||
//
|
||||
//case "DCTDecode":
|
||||
// if (DCTDecode == null)
|
||||
// DCTDecode = new DCTDecode();
|
||||
// return DCTDecode;
|
||||
//
|
||||
//case "JPXDecode":
|
||||
// if (JPXDecode == null)
|
||||
// JPXDecode = new JPXDecode();
|
||||
// return JPXDecode;
|
||||
//
|
||||
//case "Crypt":
|
||||
// if (Crypt == null)
|
||||
// Crypt = new Crypt();
|
||||
// return Crypt;
|
||||
|
||||
case "RunLengthDecode":
|
||||
case "CCITTFaxDecode":
|
||||
case "JBIG2Decode":
|
||||
case "DCTDecode":
|
||||
case "JPXDecode":
|
||||
case "Crypt":
|
||||
Debug.WriteLine("Filter not implemented: " + filterName);
|
||||
return null;
|
||||
}
|
||||
throw new NotImplementedException("Unknown filter: " + filterName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the filter singleton.
|
||||
/// </summary>
|
||||
// ReSharper disable InconsistentNaming
|
||||
public static AsciiHexDecode ASCIIHexDecode
|
||||
// ReSharper restore InconsistentNaming
|
||||
{
|
||||
get { return _asciiHexDecode ?? (_asciiHexDecode = new AsciiHexDecode()); }
|
||||
}
|
||||
static AsciiHexDecode _asciiHexDecode;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the filter singleton.
|
||||
/// </summary>
|
||||
public static Ascii85Decode ASCII85Decode
|
||||
{
|
||||
get { return _ascii85Decode ?? (_ascii85Decode = new Ascii85Decode()); }
|
||||
}
|
||||
static Ascii85Decode _ascii85Decode;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the filter singleton.
|
||||
/// </summary>
|
||||
public static LzwDecode LzwDecode
|
||||
{
|
||||
get { return _lzwDecode ?? (_lzwDecode = new LzwDecode()); }
|
||||
}
|
||||
static LzwDecode _lzwDecode;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the filter singleton.
|
||||
/// </summary>
|
||||
public static FlateDecode FlateDecode
|
||||
{
|
||||
get { return _flateDecode ?? (_flateDecode = new FlateDecode()); }
|
||||
}
|
||||
static FlateDecode _flateDecode;
|
||||
|
||||
//runLengthDecode
|
||||
//ccittFaxDecode
|
||||
//jbig2Decode
|
||||
//dctDecode
|
||||
//jpxDecode
|
||||
//crypt
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the data with the specified filter.
|
||||
/// </summary>
|
||||
public static byte[] Encode(byte[] data, string filterName)
|
||||
{
|
||||
Filter filter = GetFilter(filterName);
|
||||
if (filter != null)
|
||||
return filter.Encode(data);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes a raw string with the specified filter.
|
||||
/// </summary>
|
||||
public static byte[] Encode(string rawString, string filterName)
|
||||
{
|
||||
Filter filter = GetFilter(filterName);
|
||||
if (filter != null)
|
||||
return filter.Encode(rawString);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the data with the specified filter.
|
||||
/// </summary>
|
||||
public static byte[] Decode(byte[] data, string filterName, FilterParms parms)
|
||||
{
|
||||
Filter filter = GetFilter(filterName);
|
||||
if (filter != null)
|
||||
return filter.Decode(data, parms);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the data with the specified filter.
|
||||
/// </summary>
|
||||
public static byte[] Decode(byte[] data, string filterName)
|
||||
{
|
||||
Filter filter = GetFilter(filterName);
|
||||
if (filter != null)
|
||||
return filter.Decode(data, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the data with the specified filter.
|
||||
/// </summary>
|
||||
public static byte[] Decode(byte[] data, PdfItem filterItem)
|
||||
{
|
||||
byte[] result = null;
|
||||
if (filterItem is PdfName)
|
||||
{
|
||||
Filter filter = GetFilter(filterItem.ToString());
|
||||
if (filter != null)
|
||||
result = filter.Decode(data);
|
||||
}
|
||||
else if (filterItem is PdfArray)
|
||||
{
|
||||
PdfArray array = (PdfArray)filterItem;
|
||||
foreach (PdfItem item in array)
|
||||
data = Decode(data, item);
|
||||
result = data;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes to a raw string with the specified filter.
|
||||
/// </summary>
|
||||
public static string DecodeToString(byte[] data, string filterName, FilterParms parms)
|
||||
{
|
||||
Filter filter = GetFilter(filterName);
|
||||
if (filter != null)
|
||||
return filter.DecodeToString(data, parms);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes to a raw string with the specified filter.
|
||||
/// </summary>
|
||||
public static string DecodeToString(byte[] data, string filterName)
|
||||
{
|
||||
Filter filter = GetFilter(filterName);
|
||||
if (filter != null)
|
||||
return filter.DecodeToString(data, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
220
PdfSharp/Pdf.Filters/FlateDecode.cs
Normal file
220
PdfSharp/Pdf.Filters/FlateDecode.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// Stefan Lange
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using PdfSharp.Internal;
|
||||
#if NET_ZIP
|
||||
using System.IO.Compression;
|
||||
#else
|
||||
using PdfSharp.SharpZipLib.Zip.Compression;
|
||||
using PdfSharp.SharpZipLib.Zip.Compression.Streams;
|
||||
#endif
|
||||
|
||||
namespace PdfSharp.Pdf.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the FlateDecode filter by wrapping SharpZipLib.
|
||||
/// </summary>
|
||||
public class FlateDecode : Filter
|
||||
{
|
||||
// Reference: 3.3.3 LZWDecode and FlateDecode Filters / Page 71
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Encode(byte[] data)
|
||||
{
|
||||
return Encode(data, PdfFlateEncodeMode.Default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the specified data.
|
||||
/// </summary>
|
||||
public byte[] Encode(byte[] data, PdfFlateEncodeMode mode)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
// DeflateStream/GZipStream does not work immediately and I have not the leisure to work it out.
|
||||
// So I keep on using SharpZipLib even with .NET 2.0.
|
||||
#if NET_ZIP
|
||||
// See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97064
|
||||
//
|
||||
// Excerpt from the RFC 1950 specs for first byte:
|
||||
//
|
||||
// CMF (Compression Method and flags)
|
||||
// This byte is divided into a 4-bit compression method and a 4-
|
||||
// bit information field depending on the compression method.
|
||||
//
|
||||
// bits 0 to 3 CM Compression method
|
||||
// bits 4 to 7 CINFO Compression info
|
||||
//
|
||||
// CM (Compression method)
|
||||
// This identifies the compression method used in the file. CM = 8
|
||||
// denotes the "deflate" compression method with a window size up
|
||||
// to 32K. This is the method used by gzip and PNG (see
|
||||
// references [1] and [2] in Chapter 3, below, for the reference
|
||||
// documents). CM = 15 is reserved. It might be used in a future
|
||||
// version of this specification to indicate the presence of an
|
||||
// extra field before the compressed data.
|
||||
//
|
||||
// CINFO (Compression info)
|
||||
// For CM = 8, CINFO is the base-2 logarithm of the LZ77 window
|
||||
// size, minus eight (CINFO=7 indicates a 32K window size). Values
|
||||
// of CINFO above 7 are not allowed in this version of the
|
||||
// specification. CINFO is not defined in this specification for
|
||||
// CM not equal to 8.
|
||||
ms.WriteByte(0x78);
|
||||
|
||||
// Excerpt from the RFC 1950 specs for second byte:
|
||||
//
|
||||
// FLG (FLaGs)
|
||||
// This flag byte is divided as follows:
|
||||
//
|
||||
// bits 0 to 4 FCHECK (check bits for CMF and FLG)
|
||||
// bit 5 FDICT (preset dictionary)
|
||||
// bits 6 to 7 FLEVEL (compression level)
|
||||
//
|
||||
// The FCHECK value must be such that CMF and FLG, when viewed as
|
||||
// a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG),
|
||||
// is a multiple of 31.
|
||||
//
|
||||
// FDICT (Preset dictionary)
|
||||
// If FDICT is set, a DICT dictionary identifier is present
|
||||
// immediately after the FLG byte. The dictionary is a sequence of
|
||||
// bytes which are initially fed to the compressor without
|
||||
// producing any compressed output. DICT is the Adler-32 checksum
|
||||
// of this sequence of bytes (see the definition of ADLER32
|
||||
// below). The decompressor can use this identifier to determine
|
||||
// which dictionary has been used by the compressor.
|
||||
//
|
||||
// FLEVEL (Compression level)
|
||||
// These flags are available for use by specific compression
|
||||
// methods. The "deflate" method (CM = 8) sets these flags as
|
||||
// follows:
|
||||
//
|
||||
// 0 - compressor used fastest algorithm
|
||||
// 1 - compressor used fast algorithm
|
||||
// 2 - compressor used default algorithm
|
||||
// 3 - compressor used maximum compression, slowest algorithm
|
||||
//
|
||||
// The information in FLEVEL is not needed for decompression; it
|
||||
// is there to indicate if recompression might be worthwhile.
|
||||
ms.WriteByte(0x49);
|
||||
|
||||
DeflateStream zip = new DeflateStream(ms, CompressionMode.Compress, true);
|
||||
zip.Write(data, 0, data.Length);
|
||||
zip.Close();
|
||||
#else
|
||||
int level = Deflater.DEFAULT_COMPRESSION;
|
||||
switch (mode)
|
||||
{
|
||||
case PdfFlateEncodeMode.BestCompression:
|
||||
level = Deflater.BEST_COMPRESSION;
|
||||
break;
|
||||
case PdfFlateEncodeMode.BestSpeed:
|
||||
level = Deflater.BEST_SPEED;
|
||||
break;
|
||||
}
|
||||
DeflaterOutputStream zip = new DeflaterOutputStream(ms, new Deflater(level, false));
|
||||
zip.Write(data, 0, data.Length);
|
||||
zip.Finish();
|
||||
#endif
|
||||
#if !NETFX_CORE && !UWP
|
||||
ms.Capacity = (int)ms.Length;
|
||||
return ms.GetBuffer();
|
||||
#else
|
||||
return ms.ToArray();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Decode(byte[] data, FilterParms parms)
|
||||
{
|
||||
MemoryStream msInput = new MemoryStream(data);
|
||||
MemoryStream msOutput = new MemoryStream();
|
||||
#if NET_ZIP
|
||||
// See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97064
|
||||
// It seems to work when skipping the first two bytes.
|
||||
byte header; // 0x30 0x59
|
||||
header = (byte)msInput.ReadByte();
|
||||
//Debug.Assert(header == 48);
|
||||
header = (byte)msInput.ReadByte();
|
||||
//Debug.Assert(header == 89);
|
||||
DeflateStream zip = new DeflateStream(msInput, CompressionMode.Decompress, true);
|
||||
int cbRead;
|
||||
byte[] abResult = new byte[1024];
|
||||
do
|
||||
{
|
||||
cbRead = zip.Read(abResult, 0, abResult.Length);
|
||||
if (cbRead > 0)
|
||||
msOutput.Write(abResult, 0, cbRead);
|
||||
}
|
||||
while (cbRead > 0);
|
||||
zip.Close();
|
||||
msOutput.Flush();
|
||||
if (msOutput.Length >= 0)
|
||||
{
|
||||
msOutput.Capacity = (int)msOutput.Length;
|
||||
return msOutput.GetBuffer();
|
||||
}
|
||||
return null;
|
||||
#else
|
||||
InflaterInputStream iis = new InflaterInputStream(msInput, new Inflater(false));
|
||||
int cbRead;
|
||||
byte[] abResult = new byte[32768];
|
||||
do
|
||||
{
|
||||
cbRead = iis.Read(abResult, 0, abResult.Length);
|
||||
if (cbRead > 0)
|
||||
msOutput.Write(abResult, 0, cbRead);
|
||||
}
|
||||
while (cbRead > 0);
|
||||
#if UWP
|
||||
iis.Dispose();
|
||||
#else
|
||||
iis.Close();
|
||||
#endif
|
||||
msOutput.Flush();
|
||||
if (msOutput.Length >= 0)
|
||||
{
|
||||
#if NETFX_CORE || UWP
|
||||
return msOutput.ToArray();
|
||||
#else
|
||||
msOutput.Capacity = (int)msOutput.Length;
|
||||
return msOutput.GetBuffer();
|
||||
#endif
|
||||
}
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
189
PdfSharp/Pdf.Filters/LzwDecode.cs
Normal file
189
PdfSharp/Pdf.Filters/LzwDecode.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
#region PDFsharp - A .NET library for processing PDF
|
||||
//
|
||||
// Authors:
|
||||
// David Stephensen
|
||||
//
|
||||
// Copyright (c) 2005-2017 empira Software GmbH, Cologne Area (Germany)
|
||||
//
|
||||
// http://www.pdfsharp.com
|
||||
// http://sourceforge.net/projects/pdfsharp
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace PdfSharp.Pdf.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the LzwDecode filter.
|
||||
/// </summary>
|
||||
public class LzwDecode : Filter
|
||||
{
|
||||
// Reference: 3.3.3 LZWDecode and FlateDecode Filters / Page 71
|
||||
|
||||
/// <summary>
|
||||
/// Throws a NotImplementedException because the obsolete LZW encoding is not supported by PDFsharp.
|
||||
/// </summary>
|
||||
public override byte[] Encode(byte[] data)
|
||||
{
|
||||
throw new NotImplementedException("PDFsharp does not support LZW encoding.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the specified data.
|
||||
/// </summary>
|
||||
public override byte[] Decode(byte[] data, FilterParms parms)
|
||||
{
|
||||
if (data[0] == 0x00 && data[1] == 0x01)
|
||||
throw new Exception("LZW flavour not supported.");
|
||||
|
||||
MemoryStream outputStream = new MemoryStream();
|
||||
|
||||
InitializeDictionary();
|
||||
|
||||
_data = data;
|
||||
_bytePointer = 0;
|
||||
_nextData = 0;
|
||||
_nextBits = 0;
|
||||
int code, oldCode = 0;
|
||||
byte[] str;
|
||||
|
||||
while ((code = NextCode) != 257)
|
||||
{
|
||||
if (code == 256)
|
||||
{
|
||||
InitializeDictionary();
|
||||
code = NextCode;
|
||||
if (code == 257)
|
||||
{
|
||||
break;
|
||||
}
|
||||
outputStream.Write(_stringTable[code], 0, _stringTable[code].Length);
|
||||
oldCode = code;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (code < _tableIndex)
|
||||
{
|
||||
str = _stringTable[code];
|
||||
outputStream.Write(str, 0, str.Length);
|
||||
AddEntry(_stringTable[oldCode], str[0]);
|
||||
oldCode = code;
|
||||
}
|
||||
else
|
||||
{
|
||||
str = _stringTable[oldCode];
|
||||
outputStream.Write(str, 0, str.Length);
|
||||
AddEntry(str, str[0]);
|
||||
oldCode = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outputStream.Length >= 0)
|
||||
{
|
||||
#if !NETFX_CORE && !UWP
|
||||
outputStream.Capacity = (int)outputStream.Length;
|
||||
return outputStream.GetBuffer();
|
||||
#else
|
||||
return outputStream.ToArray();
|
||||
#endif
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the dictionary.
|
||||
/// </summary>
|
||||
void InitializeDictionary()
|
||||
{
|
||||
_stringTable = new byte[8192][];
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
_stringTable[i] = new byte[1];
|
||||
_stringTable[i][0] = (byte)i;
|
||||
}
|
||||
|
||||
_tableIndex = 258;
|
||||
_bitsToGet = 9;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new entry to the Dictionary.
|
||||
/// </summary>
|
||||
void AddEntry(byte[] oldstring, byte newstring)
|
||||
{
|
||||
int length = oldstring.Length;
|
||||
byte[] str = new byte[length + 1];
|
||||
Array.Copy(oldstring, 0, str, 0, length);
|
||||
str[length] = newstring;
|
||||
|
||||
_stringTable[_tableIndex++] = str;
|
||||
|
||||
if (_tableIndex == 511)
|
||||
_bitsToGet = 10;
|
||||
else if (_tableIndex == 1023)
|
||||
_bitsToGet = 11;
|
||||
else if (_tableIndex == 2047)
|
||||
_bitsToGet = 12;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next set of bits.
|
||||
/// </summary>
|
||||
int NextCode
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
_nextData = (_nextData << 8) | (_data[_bytePointer++] & 0xff);
|
||||
_nextBits += 8;
|
||||
|
||||
if (_nextBits < _bitsToGet)
|
||||
{
|
||||
_nextData = (_nextData << 8) | (_data[_bytePointer++] & 0xff);
|
||||
_nextBits += 8;
|
||||
}
|
||||
|
||||
int code = (_nextData >> (_nextBits - _bitsToGet)) & _andTable[_bitsToGet - 9];
|
||||
_nextBits -= _bitsToGet;
|
||||
|
||||
return code;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 257;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readonly int[] _andTable = { 511, 1023, 2047, 4095 };
|
||||
byte[][] _stringTable;
|
||||
byte[] _data;
|
||||
int _tableIndex, _bitsToGet = 9;
|
||||
int _bytePointer;
|
||||
int _nextData = 0;
|
||||
int _nextBits = 0;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user