PDF処理エンジン内部
PDF 処理エンジン内部
日常的な PDF 処理で使用する Document、Page、および Annotation クラスは、下位レベルの aspose_pdf.engine パッケージへのファサードです。エンジンは実際の PDF メカニクスを実装しています:すべての PDF ファイルが構築される COS (Carousel Object Structure) オブジェクトモデル、COS オブジェクトと PDF バイト間の変換を行うパーサーとライター、注釈外観の合成、ページのラスタライズ、フォントおよび画像コーデックの内部、そして文書暗号化とデジタル署名の背後にある暗号プリミティブです。ほとんどのアプリケーションは aspose_pdf.engine から直接インポートする必要はありませんが、カスタムツール、フォレンジック PDF 検査、または高レベルの API が公開していない動作を必要とする場合に見るべき正しい場所です。
単一注釈の外観を生成する
四角形、円形、スタンプなどのインタラクティブ注釈は、通常の外観ストリーム (/AP /N) を自動的に持ちません。Annotation.generate_appearance を呼び出すと、エンジンの外観合成内部が注釈のプロパティからオンデマンドでそれを構築します。
from aspose_pdf import Document
doc = Document()
doc.pages.add()
ann = doc.pages[0].annotations.add(
"Square", (100, 100, 200, 200), "", properties={"C": [1, 0, 0], "IC": [0, 1, 0]}
)
print(ann.has_appearance) # False -- no appearance stream yet
ann.generate_appearance()
print(ann.has_appearance) # True -- the engine synthesised one
print(b"1 0 0 RG" in ann.appearance_normal) # True -- red stroke operator
print(b"0 1 0 rg" in ann.appearance_normal) # True -- green fill operatorページと文書全体で外観を一括生成する
AnnotationCollection.generate_appearances は、ページ上の対象となるすべての注釈に対して、1 回の呼び出しで外観を合成し、エンジンが描画方法を知らないサブタイプ(例えば Text)はスキップします:
from aspose_pdf import Document
doc = Document()
doc.pages.add()
page = doc.pages[0]
page.annotations.add("Square", (0, 0, 50, 50), "")
page.annotations.add("Circle", (60, 0, 110, 50), "")
page.annotations.add("Text", (0, 60, 20, 80), "") # unsupported subtype -> skipped
print(page.annotations.generate_appearances()) # 2Document.generate_appearances は文書内のすべてのページに対して同様に実行され、冪等です — すでに外観が存在すれば、2 回目の呼び出しは何も行いません:
from aspose_pdf import Document
doc = Document()
doc.pages.add()
doc.pages.add()
doc.pages[0].annotations.add("Square", (0, 0, 50, 50), "")
doc.pages[1].annotations.add(
"Line", (0, 0, 50, 50), "", properties={"L": [0, 0, 50, 50]}
)
print(doc.generate_appearances()) # 2 -- one per page
print(doc.generate_appearances()) # 0 -- already generated, no-op注釈を静的ページコンテンツにフラット化する
Document.flatten() は、すべての注釈の外観をページのコンテンツストリームに直接描画します(Do XObject 呼び出しとして)そして注釈オブジェクト自体を削除します。その結果、注釈を完全に無視するビューアでもページは同一に表示されます:
from aspose_pdf import Document
doc = Document()
doc.pages.add()
doc.pages[0].annotations.add(
"Square", (100, 100, 200, 200), "", properties={"C": [0, 0, 0]}
)
doc.flatten()この呼び出しの後、ページのコンテンツストリームは以前より長くなります(インライン化された四角形が含まれるようになります)そして doc.pages[0].annotations にはフラット化された注釈が残っていません。
パスワードベース暗号化キーの導出(リビジョン 4 / AES-128)
EncryptionUtils は PDF 標準セキュリティハンドラのキー導出と AES-CBC プリミティブを直接実装し、Document API から独立しています。これはカスタムツールや暗号化された PDF の鑑識検査に役立ちます:
import os
from aspose_pdf.engine.encryption import EncryptionUtils
file_id = os.urandom(16)
user_pwd = "mypassword"
# Derive the owner (O) and user (U) key material for Revision 4 (128-bit AES)
o_value = EncryptionUtils.compute_owner_key_v4("owner", user_pwd, 16, 4)
u_value, enc_key = EncryptionUtils.compute_user_key_v4(
user_pwd, o_value, -4, file_id, 16, 4
)
# Encrypt data with the derived file-encryption key
plaintext = b"Confidential PDF content"
ciphertext = EncryptionUtils.encrypt_aes_cbc(enc_key, plaintext)
# Re-derive the key from the password before trusting it to decrypt
verified_key = EncryptionUtils.verify_password_v4(
user_pwd, u_value, o_value, -4, file_id, 16, 4
)
print(verified_key is not None) # True -- password matches
decrypted = EncryptionUtils.decrypt_aes_cbc(verified_key, ciphertext)
print(decrypted == plaintext) # True生コンテンツを AES-CBC で暗号化する
低レベルのニーズ向けに、EncryptionUtils.encrypt_aes_cbc() と decrypt_aes_cbc() はパスワードベースのキー導出を全く経由せず、16 バイト、24 バイト、または 32 バイトのキーに直接作用します:
import os
from aspose_pdf.engine.encryption import EncryptionUtils
key = os.urandom(32) # AES-256; 16 and 24-byte keys are also accepted
plaintext = b"Hello, PDF AES 256!"
ciphertext = EncryptionUtils.encrypt_aes_cbc(key, plaintext)
decrypted = EncryptionUtils.decrypt_aes_cbc(key, ciphertext)
print(decrypted == plaintext) # Trueヒントとベストプラクティス
- 日常的な文書処理には、ハイレベルな
Document、Page、Annotationファサードを優先してください。aspose_pdf.engineパッケージは、これらのクラスが構築されている内部実装です — カスタムツール、フォレンジック検査、またはファサードが公開していない動作が必要なときだけ使用してください。 - 対象とするセキュリティハンドラに合わせて
revision引数を設定してください:compute_owner_key_v4/compute_user_key_v4はリビジョン 2–4(40 ビットおよび 128 ビット RC4/AES)をカバーし、compute_hash_v5は AES-256 が使用するリビジョン 5/6 アルゴリズムを実装しています。リビジョンと鍵長を混在させると、何も警告なく誤った鍵が生成されます。 Document.generate_appearancesとAnnotationCollection.generate_appearancesは冪等です — 自分で作成していない文書をレンダリングまたはフラット化する前に、予防的に呼び出してください。Document.flatten()は破壊的です:ページコンテンツに描画されたすべてのアノテーションを削除します。まず他のアノテーション編集を完了するか、コピーで作業してください。- すべてのアノテーションサブタイプが組み込みの外観シンセサイザーを持っているわけではありません —
TextとPopupが一般的な例です。generate_appearance()を呼び出した後は、成功したと仮定せずにhas_appearanceを確認してください。
一般的な問題
| 問題 | 原因 | 修正 |
|---|---|---|
EncryptionUtils.encrypt_aes_cbc/decrypt_aes_cbc は “AES key must be 16, 24, or 32 bytes” エラーを発生させます | 無効な長さのキーが提供されました | キーは os.urandom(16)、os.urandom(24)、または os.urandom(32) で生成してください |
EncryptionUtils.verify_password_v4 は例外を発生させる代わりに None を返します | 提供されたパスワードがドキュメントから導出された U/O の値と一致しません | 結果を decrypt_aes_cbc に渡す前に、None を明示的にチェックしてください |
Annotation.generate_appearance は False を返します | アノテーションのサブタイプには組み込みの外観合成器がありません(例: Text または Popup) | 独自の appearance_normal バイトを提供するか、ビューアのデフォルトレンダリングを受け入れてください |
Document.generate_appearances の2回目の呼び出しは 0 を返します | この呼び出しは冪等です — すでに has_appearance == True を持つアノテーションはスキップされます | 期待される動作で、エラーではありません |
FAQ
日常的な文書処理のために aspose_pdf.engine からインポートする必要がありますか?
いいえ。Document、Page、およびAnnotationクラスは標準的な文書ワークフローをカバーしています。エンジン層はこれらのクラスの動作が実装されている場所で、カスタムツールや PDF の内部を直接検査する際に最も有用です。
Annotation.generate_appearance と AnnotationCollection.generate_appearances の違いは何ですか?
最初のものは単一のアノテーションの外観ストリームを合成し、bool を返します。2番目のものは、コレクション内の対象となるすべてのアノテーション(ページのアノテーション、または Document.generate_appearances を介して文書内のすべてのページ)に対して同様の処理を行い、作成した外観の数を返します。
なぜ鍵導出メソッドは revision 引数を受け取るのですか?
PDF 標準のセキュリティハンドラは ISO 32000 のリビジョンを通じて進化してきました — リビジョン 2 は 40 ビット RC4 を使用し、リビジョン 3/4 は 128 ビット RC4 または AES をサポートし、リビジョン 5/6(AES-256 に使用)では全く異なるハッシュアルゴリズム(compute_hash_v5)が使われます。revision 引数は、EncryptionUtils メソッドが実行する導出方式を選択します。
生の PDF オブジェクトを直接検査したり作成したりできますか?
はい。aspose_pdf.engine.cos は COS オブジェクトモデルを公開します — PdfObject、PdfDictionary、PdfArray、PdfStream、PdfName および関連タイプ — これらは PdfCosWriter と PdfCosParser が PDF バイト列にシリアライズおよびパースします。
ページから画像へのレンダリングはどこで行われますか?
Document.render_page は RasterizedPage を返します。これはエンジンレベルのオブジェクトで、to_png()、to_tiff()、および save() メソッドを備えており、レンダリングされたページを画像ファイルに変換します。
API Reference の概要
| クラス / メソッド | 説明 |
|---|---|
Annotation.generate_appearance(force) -> bool | 要求に応じて、1つの注釈の標準外観ストリームを合成する |
AnnotationCollection.generate_appearances(force) -> int | ページ上の対象となるすべての注釈の外観を一括生成する |
Document.generate_appearances(force) -> int | 文書内の対象となるすべての注釈の外観を一括生成する |
Document.flatten() -> Document | 注釈の外観をページコンテンツにインラインで組み込み、注釈を削除する |
Document.render_page(page_index, dpi, scale, background, antialias) -> RasterizedPage | エンジンのレンダリングパイプラインを介してページをラスタライズする |
RasterizedPage | パックされたRGB形式のレンダリング済みページ、to_png()、to_tiff()、およびsave()を含む |
GeneratedAppearance | 外観合成の内部結果: コンテンツバイトに加えて必要なExtGState/フォントリソース |
EncryptionUtils | AES-CBC/RC4暗号化およびPDF標準セキュリティハンドラのキー導出(リビジョン2–6) |
PdfObject | すべての COS (Carousel Object Structure) オブジェクトの抽象基底クラス |
PdfDictionary / PdfArray / PdfStream | 低レベルのドキュメントツリーを構成する具体的な COS コンテナ型 |
PdfName / PdfNumber / PdfString / PdfBoolean / PdfNull | プリミティブ COS 値型 |
PdfIndirectReference | 別のオブジェクトへの COS 間接参照 (n g R) |
PdfCosWriter | インメモリの COS PdfDocument を PDF バイトにシリアライズします |
PdfCosParser / LazyPdfObjectStore | PDF バイトを COS オブジェクトに解析し、必要に応じて実体化します |
IncrementalUpdate / IncrementalWriter | 既存の PDF を再書き込みせずに、インクリメンタル更新セクションを追加します |
SimplePdf | ネイティブ-Python の低レベル文書表現であり、ハイレベルな Document API はこれ上に構築されています |
TextFragmentAbsorber / TextFragmentCollection | 低レベルのテキストフラグメント抽出を SimplePdf インスタンス上で実行 |
ImagePlacementAbsorber / ImagePlacement | ページに配置されたラスター画像を検索、保存、置換、または非表示にする |
SigningUtils | デジタル署名のために自己署名証明書と PKCS#7/CAdES 署名を生成する |
DssMaterial / ChainResult / RevocationResult / TimestampInfo | 署名検証サポート:DSS マテリアル、証明書チェーンの結果、失効チェック、RFC 3161 タイムスタンプの検証 |
StandardFonts | 14 の PDF 標準フォントのメトリクスとエンコーディング |
CidTextCodec | 複合(Type0)フォント用の show-strings をエンコードおよびデコードする |
Shading | 軸方向、放射状、関数ベースのシェーディング全体で RGB カラーをサンプリングする |
Color / Matrix | エンジン全体で使用される低レベルのカラーと 2-D アフィン変換プリミティブ |