PDFで/Filter /FlateDecodeが指定されているストリームはdeflate圧縮されています。.NETのDeflateStreamで展開しようとしてもエラーになりますが、最初の2バイトを飛ばすと読み込めます。
/DecodeParmsが指定されていると更に差分圧縮されています。/XRefやPNGなどで使用されているようです。
- Dealing with Predictors when decoding PDFs
- Using PNG Predictors to Enhance GZIP/PKZIP/FLATE Compression
このようなストリームを展開するため、DeflateStreamをラップしたクラスを作成しました。パブリックドメインで置いておきます。ちなみに差分圧縮つながりでADPCMをいじったことがあります。 ⇒ id:n7shi:20090329
public class PdfDeflateStream : Stream { private DeflateStream ds; int columns, position, rowpos; byte[] prev, rows; public PdfDeflateStream(Stream s, int columns) { this.columns = columns; if (columns > 0) { prev = new byte[columns]; rows = new byte[columns]; rowpos = rows.Length; } s.ReadByte(); s.ReadByte(); ds = new DeflateStream(s, CompressionMode.Decompress); } public override long Length { get { throw new NotImplementedException(); } } public override bool CanRead { get { return true; } } public override bool CanWrite { get { return false; } } public override bool CanSeek { get { return false; } } public override void Flush() { } public override long Position { get { return position; } set { throw new NotImplementedException(); } } public override int Read(byte[] buffer, int offset, int count) { int ret = 0; if (columns == 0) ret = ds.Read(buffer, offset, count); else { while (ret < count) { if (rowpos >= rows.Length) { if (ds.ReadByte() != 2) throw new Exception("unknown predictor type"); Array.Copy(rows, prev, rows.Length); int len = ds.Read(rows, offset, rows.Length); if (len < rows.Length) break; for (int i = 0; i < rows.Length; i++) rows[i] += prev[i]; rowpos = 0; } int rlen = Math.Min(count - ret, rows.Length - rowpos); Array.Copy(rows, rowpos, buffer, ret, rlen); ret += rlen; rowpos += rlen; } } position += ret; return ret; } public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } }