1

さて、始める前に。私は、さまざまな発行元からの PDF ファイルをあらゆるメディア形式で再配布するライセンスを持つ会社で働いています。そうは言っても、特定の PDF ファイルからの埋め込みフォントの抽出は合法であるだけでなく、プレゼンテーションにも不可欠です。

このサイトで見つかったコードを使用していますが、作成者を思い出せません。見つけたら参照します。埋め込みフォントを含む PDF ファイル内にストリームを配置しました。このエンコードされたストリームを文字列として分離し、byte[]. 次のコードを使用すると、エラーが発生します

Block length does not match with its complement.

コード (エラーはwhile以下の行で発生します):

private static byte[] DecodeFlateDecodeData(byte[] data)
{
    MemoryStream outputStream;
    using (outputStream = new MemoryStream())
    {
        using (var compressedDataStream = new MemoryStream(data))
        {
            // Remove the first two bytes to skip the header (it isn't recognized by the DeflateStream class)
            compressedDataStream.ReadByte();
            compressedDataStream.ReadByte();

            var deflateStream = new DeflateStream(compressedDataStream, CompressionMode.Decompress, true);
            var decompressedBuffer = new byte[compressedDataStream.Length];
            int read;

            // The error occurs in the following line
            while ((read = deflateStream.Read(decompressedBuffer, 0, decompressedBuffer.Length)) != 0)
            {
                outputStream.Write(decompressedBuffer, 0, read);
            }
            outputStream.Flush();
            compressedDataStream.Close();
        }

        return ReadFully(outputStream);
    }
}

通常のツール (Google、Bing、アーカイブはこちら) を使用した後、これが発生する時間の大部分は、エンコード ストリームの最初の 2 バイトが消費されていない場合に発生することがわかりましたが、これはここで行われるため、ソースを見つけることができません。このエラーの。以下は、エンコードされたストリームです。

H‰LT}lg?7ñù¤aŽÂ½ãnÕ´jh›Ú?-T’ÑRL–¦
ëš:Uí6Ÿ¶“ø+ñ÷ùü™”ÒÆŸŸíóWlDZ“ºu“°tƒ¦t0ÊD¶jˆ
Ö   m:$½×^*qABBï?Þç÷|ýÞßóJÖˆD"yâP—òpgÇó¦Q¾S¯9£Û¾mçÁçÚ„cÂÛO¡É‡·¥ï~á³ÇãO¡ŸØö=öPD"d‚ìA—$H'‚DC¢D®¤·éC'Å:È—€ìEV%cÿŽS;þÔ’kYkùcË_ZÇZ/·þYº(ý݇Ã_ó3m¤[3¤²4ÿo?²õñÖ*Z/Þiãÿ¿¾õ8Ü    ?»„O Ê£ðÅ­P9ÿ•¿Â¯*–z×No˜0ãÆ-êàîoR‹×ÉêÊêÂulaƒÝü

助けてください、私はここで壁に頭をぶつけています!

注: 上記のストリームは、Arial Black のエンコードされたバージョンです - PDF 内の仕様によると:

661 0 obj
<< 
/Type /FontDescriptor 
/FontFile3 662 0 R 
/FontBBox [ -194 -307 1688 1083 ] 
/FontName /HLJOBA+ArialBlack 
/Flags 4 
/StemV 0 
/CapHeight 715 
/XHeight 518 
/Ascent 0 
/Descent -209 
/ItalicAngle 0 
/CharSet (/space/T/e/s/t/a/k/i/n/g/S/r/E/x/m/O/u/l)
>> 
endobj
662 0 obj
<< /Length 1700 /Filter /FlateDecode /Subtype /Type1C >> 
stream
H‰LT}lg?7ñù¤aŽÂ½ãnÕ´jh›Ú?-T’ÑRL–¦
ëš:Uí6Ÿ¶“ø+ñ÷ùü™”ÒÆŸŸíóWlDZ“ºu“°tƒ¦t0ÊD¶jˆ
Ö   m:$½×^*qABBï?Þç÷|ýÞßóJÖˆD"yâP—òpgÇó¦Q¾S¯9£Û¾mçÁçÚ„cÂÛO¡É‡·¥ï~á³ÇãO¡ŸØö=öPD"d‚ìA—$H'‚DC¢D®¤·éC'Å:È—€ìEV%cÿŽS;þÔ’kYkùcË_ZÇZ/·þYº(ý݇Ã_ó3m¤[3¤²4ÿo?²õñÖ*Z/Þiãÿ¿¾õ8Ü    ?»„O Ê£ðÅ­P9ÿ•¿Â¯*–z×No˜0ãÆ-êàîoR‹×ÉêÊêÂulaƒÝü
4

3 に答える 3

1

GetStreamBytes() が問題を解決するように見えますが、行末マーカーに関して危険なことをしていると思います。7.3.8.1 の PDF 仕様には、次のように記載されています。

ストリーム ディクショナリに続くキーワード ストリームの後には、CARRIAGE RETURN と LINE FEED、または LINE FEED だけで構成される行末マーカーが続きます。CARRIAGE RETURN だけではありません。

あなたのコードでは、仕様では 1 つまたは 2 つ (CR LF または LF) のいずれかであると述べられていますが、常に 2 バイトをスキップしているように見えます。

デコードしたい正確なバイト数をストリーム ディクショナリの (必須) "Length" キーの値と比較することで、これに遭遇しているかどうかを確認できるはずです。

于 2013-03-31T21:15:32.503 に答える
0

さて、この問題に出くわす可能性のある人のために、警告させてください - これは多くの良い解決策がない困難な道です. 最終的には、自分でフォントを抽出するためのすべてのコードを書くことから離れました。MuPDF (オープン ソース) をダウンロードしてから、コマンド ラインで mutool.exe を呼び出しました。

    mutool extract C:\mypdf.pdf

これにより、すべてのフォントが mutool が存在するフォルダーに取り込まれます (いくつかの画像も抽出されます (これらは変換できなかったフォントです (通常は小さなサブセットだと思います)))。次に、それらをそのフォルダーから必要なフォルダーに移動するメソッドを作成しました。

もちろん、これらを使用可能なものに変換すること自体が頭痛の種ですが、実行可能であることがわかりました。

念のために言っておきますが、フォントの著作権侵害は著作権侵害です。

于 2013-04-16T17:47:55.277 に答える