
Gammaでプレゼンテーションを作成し、PDFとしてエクスポートすると、ファイルの右下に「Made with Gamma」という表示が含まれる場合があります。
このような表示を整理しようとすると、最初に思いつくのは次のような方法かもしれません。
- PDFを画像に変換する
- 表示部分を背景色で塗りつぶす
- 画像編集ソフトでページごとに修正する
- PDF全体を作り直す
しかし、PDFは必ずしも1枚の画像として保存されているわけではありません。
ページ内のテキスト、画像、リンク、注釈、ベクター図形などが、別々のオブジェクトとして保持されている場合があります。
この記事では、自分で作成したGammaのPDFエクスポートを例に、ページ全体を画像化せず、特定の表示要素だけをブラウザ内で整理できる理由を紹介します。
PDFは完成画像の集合とは限らない
PDFの1ページには、次のような要素を含めることができます。
- テキストオブジェクト
- 埋め込みフォント
- 画像
- ベクター図形
- 外部リンク
- リンク注釈
- ページ注釈
- 描画命令
- 座標やサイズの情報
画面上では完成した1枚のページに見えても、内部では複数の要素を順番に描画しています。
例えば、ページ右下に表示されるブランド表示が、次のように分かれている場合があります。
表示用の画像またはテキスト
+
クリック可能なリンク領域
+
外部URLへのリンク情報
+
ページ内の座標情報
このような構造であれば、ページ全体を画像として再生成せず、対象となる要素だけを確認・整理できる可能性があります。
文字列だけを検索してはいけない理由
対象を探すときに、単純に「Gamma」という文字列だけを検索するのは安全ではありません。
ユーザー自身が本文中に次のような文章を書いている可能性があるためです。
This presentation was created with Gamma.
この文章まで削除すると、本来残すべき資料内容を変更してしまいます。
対象を限定するためには、複数の条件を組み合わせる必要があります。
例えば次のような条件です。
-
gamma.appへのリンクが設定されている - ページの右下付近に配置されている
- 小さなバッジやロゴとして保存されている
- 複数ページで同じ位置に繰り返し存在する
- 特定のサイズや座標を持っている
- 表示要素の近くにリンク注釈がある
文字列、リンク先、位置、サイズ、繰り返しパターンを組み合わせることで、本文や通常の画像を誤って処理するリスクを減らせます。
リンク注釈が重要な手掛かりになる
PDFでは、見た目の画像とクリック可能な領域が別々に保存される場合があります。
例えば、右下に小さなバッジが表示され、その上にgamma.appへ移動する透明なリンク領域が重なっている構造です。
この場合、画面上では1つの要素に見えても、内部では次のように分かれています。
見た目を構成する画像・テキスト
+
リンク注釈
+
リンク先URL
そのため、見た目だけを画像比較するよりも、リンク先URLやページ内座標を組み合わせて確認する方が、対象を特定しやすくなります。
ただし、PDFの生成方法やエクスポート時期によって構造が変わる場合があります。常に同じ条件で検出できるとは限りません。
ブラウザ内でPDFを処理する流れ
ブラウザでPDFを処理する場合、概念的には次のような流れになります。
PDFファイルを選択
↓
File APIでファイルを読み込む
↓
ArrayBufferへ変換する
↓
PDFのページ構造を解析する
↓
リンク・注釈・画像・座標を確認する
↓
条件に一致する対象だけを処理する
↓
新しいPDFを生成する
↓
Blobとしてダウンロードする
JavaScriptでは、選択したファイルをArrayBufferとして読み込めます。
const file = input.files?.[0]
if (!file) {
throw new Error("PDF file is required")
}
const buffer = await file.arrayBuffer()
その後、PDF処理ライブラリやWebAssemblyモジュールを利用して、各ページの構造を確認します。
処理の考え方を簡略化すると、次のようになります。
const pdf = await loadPdf(buffer)
for (const page of pdf.pages) {
const elements = inspectPage(page)
for (const element of elements) {
if (isSupportedGammaBranding(element)) {
removeElement(page, element)
}
}
}
const output = await pdf.save()
downloadPdf(output)
これは処理の概念を示す疑似コードです。
実際の実装では、使用するPDFライブラリによって、注釈、オブジェクト参照、コンテンツストリームなどの扱いが異なります。
なぜPDF全体を画像化しないのか
PDFを画像に変換してから編集する方法は分かりやすいですが、次のような問題があります。
- テキストを選択できなくなる
- 文書内検索ができなくなる
- コピー操作ができなくなる
- ベクター画像がぼやける
- 本文中のリンクが失われる
- ページ全体が再圧縮される
- ファイルサイズが増える可能性がある
- 印刷品質が変わる可能性がある
対象が独立したPDFオブジェクトとして保存されている場合、ページ全体を再描画する必要はありません。
元のテキスト、画像、リンク、ページサイズをできるだけ維持しながら、対象要素だけを整理する方が自然です。
ブラウザ内処理のメリット
ブラウザ内処理には、サーバーへファイルを送信する方式とは異なる特徴があります。
- 専用ソフトをインストールする必要がない
- サーバー側でユーザーファイルを保存する必要がない
- アカウント登録を必須にしなくてよい
- 静的なWebアプリとして提供しやすい
- サーバーのファイル処理コストを抑えられる
- 処理対象のファイルを端末内に留めやすい
一方で、ブラウザのメモリや端末性能には上限があります。
ページ数が多いPDFやサイズの大きなPDFでは、処理に時間がかかったり、ブラウザが利用できるメモリを超えたりする場合があります。
うまく処理できないケース
すべてのPDFで同じ方法が使えるわけではありません。
ページ全体が画像になっている
各ページが1枚の画像として保存され、その画像内に表示が焼き込まれている場合、独立したオブジェクトとして分離できません。
背景画像に統合されている
ブランド表示が背景画像の一部になっている場合も、対象部分だけを安全に削除するのは困難です。
別のPDF編集ソフトで再保存されている
他のソフトで編集・再保存すると、複数のオブジェクトが統合されたり、リンク注釈が削除されたりする場合があります。
エクスポート仕様が変更されている
Gamma側の出力形式が変更されると、以前利用できた検出条件が使えなくなる可能性があります。
このような場合に無理に変更を続けると、本文や画像まで破損させる恐れがあります。
対象を安全に検出できない場合は、ファイルを変更せず終了する設計の方が安全です。
処理後に確認する項目
処理後のPDFは、必ず元ファイルと比較します。
最低限、次の項目を確認します。
- ページ数が変わっていないか
- テキストを選択できるか
- 文書内検索が利用できるか
- 画像が欠けていないか
- ページサイズが維持されているか
- 本文中のリンクが動作するか
- フォント表示が崩れていないか
- 意図しない要素が消えていないか
- PDFビューアで警告なく開けるか
元ファイルを直接上書きせず、処理後のファイルを別名で保存することも重要です。
実際にブラウザで確認する
自分で作成したGammaのPDFエクスポートをブラウザ上で確認する場合は、次のページを利用できます。
基本的な流れは次のとおりです。
- GammaからPDFをエクスポートする
- 元のPDFをバックアップする
- PDFファイルを選択する
- ブラウザ内で処理する
- 処理後のPDFをダウンロードする
- 元ファイルと比較する
利用する場合は、自分で作成したファイル、または編集する権限のあるファイルだけを対象にしてください。
まとめ
PDFは、単純なページ画像の集合ではありません。
テキスト、画像、リンク、注釈などが独立したオブジェクトとして保存されている場合があります。
対象の表示が独立したバッジやリンク注釈として保存されていれば、ページ全体を画像化せず、その要素だけを整理できる可能性があります。
重要なのは次の点です。
- 文字列だけで対象を判断しない
- リンク、位置、サイズ、繰り返しパターンを組み合わせる
- ページ全体を画像化しない
- 安全に検出できない場合は無理に変更しない
- 元ファイルを残し、処理結果を必ず確認する
- 自分が所有する、または編集権限を持つファイルだけを扱う
PDFの内部構造を理解すると、リンク監査、注釈整理、メタデータ処理、ページ編集など、他のブラウザベースツールにも応用できます。