Ubuntu Weekly Recipe

第328回 「違いがわかる人」になろう

この記事を読むのに必要な時間:およそ 6 分

バイナリの差分

バイナリファイルの解析時などに,複数のバイナリデータの差分を取得できると便利な場合があります。手っ取り早いのは,hdコマンドでバイナリデータをASCII表現にしてしまって,それを前述の差分ツールで比較する方法です。手間はかかりますが特殊なソフトウェアが必要ないぶん,お手軽ではあるでしょう。

専用ビューワーで差分を表示したいのであれば,dhexがシンプルで使いやすいです。初回起動時にキーコードの入力が必要になりますので,適宜対応してください。~/.dhexrcで再設定も可能なので,自分好みのキーバインドに変更しても良いでしょう。

図6 初期設定でVimに近いキーバインドが割り当てられている

図6 初期設定でVimに近いキーバインドが割り当てられている

バイナリの差分を他のバイナリに「patch」として適用したい場合は,bsdiffパッケージに含まれるbsdiffとbspatchコマンドを使いましょう。bsdiffは専用フォーマットのパッチ用バイナリを生成します。

画像の差分を生成する

バイナリデータの中でも画像の差分であれば,重ね合わせて比較するのが一番簡単です。原始的には2つの画像ウィンドウを重ね合わせてAlt+Tabで切り替えたり,片方のウィンドウの透明度を変更することで,その違いがすぐにわかるでしょう。もう少し機械的に判別したい場合は,ImageMagickで重ね合わせてしまうことです注1⁠。

$ sudo apt install imagemagick
$ composite -compose difference imageA.png imageB.png diff.png

図7 左2つの画像の差分を取った結果が右の画像になる

図7 左2つの画像の差分を取った結果が右の画像になる

上記にあるように,差分がある場所だけ画像が残り,それ以外は黒で表示されます。ちなみに一致しているかどうかは,次のコマンドで色の平均値が0(黒)になっているかどうかでも確認できます。

$ identify -format "%[mean]" diff.png
0
(一致すると0と表示される)
注1)
ImageMagickのドキュメントには,他にもImageMagickを使った画像の比較方法が掲載されています。

PDFの差分を生成する

DiffPDFは2つのPDFファイルの内容の差異をグラフィカルに表示してくれるツールです注2⁠。Ubuntuのリポジトリからdiffpdfパッケージをインストールすることで利用できます。ガイドに合わせてPDFファイルを開き,Compareボタンを押すだけで,そのページの異なる部分を色で表示してくれます。

図8 日本語にも対応している

図8 日本語にも対応している

差分の表示方法は,Appearance(純粋な見た目,前述のImageMagickによる比較方法に近い方法⁠⁠,Char(文字単位⁠⁠,Words(単語単位,ただし日本語の単語区切りには未対応)の3種類から選べ,Appearanceの場合はさらにShowで差分の計算方法も選べます。このため,文字主体のページと画像主体のページでそれぞれ適切な差分表示ができます。

Save Asで比較対象の2つのページを見開きページに配置したPDFを生成できますので,他の人に差分データを提示するときも便利でしょう。

CUI上で比較を行いたい場合は,poppler-utilsパッケージ含まれる変換ツールを使うと良いでしょう。pdftoppmコマンドはPDFファイルを1ページずつ画像に変換します。pdftotextコマンドはPDFに含まれる文字列オブジェクトをテキストファイルに保存します。

$ sudo apt install poppler-utils
$ pdftoppm -png foo.pdf foo_images
(foo_images-(ページ番号).pngファイルが生成される)
$ pdftotext foo.pdf
(foo.txtファイルが生成される)

あとは前述の画像ファイルやテキストファイルの時と同様に差分を取得するだけです。

注2)
UbuntuでインストールできるのはGPL版だった2.x系までです。商用版となった3.x以降はWindows用バイナリしか提供されていません。

LibreOfficeの差分を生成する

LibreOfficeのファイルはいくつかのリソースファイルを固めたZipファイルです。よってそのまま差分を取得するよりも,他のファイルフォーマットに変換してから差分を取得するほうが読みやすくなります。変換方法には次の3つが考えられます。

  • PDFに変換して「PDFの差分を生成する」と同じ方法を行う
  • Flat ODFに変換して1つのXMLファイルとして差分を取得する
  • unoconvで任意の形式に変換して差分を取得する

最初のPDFへの変換は,LibreOfficeの標準機能を使います。GUI上の[ファイル][PDFとしてエクスポート]を選んでもいいですし,CUIから変換したければ,次のコマンドが使えます。ちなみにsofficeコマンドはLibreOfficeが起動していると動作しないので注意してください。

$ soffice --headless --convert-to pdf foo.odt
javaldx: Could not find a Java Runtime Environment!
Warning: failed to read path from javaldx
convert /home/shibata/temp/diff/foo.odt -> /home/shibata/temp/diff/foo.pdf using writer_pdf_Export
Overwriting: /home/shibata/temp/diff/foo.pdf

2つ目のFlat ODFは,LibreOfficeの標準ファイル形式であるOpenDocument Formatで定義されているファイル形式の1つで,すべてのデータを1つのXMLファイルにまとめた形式になります。バイナリデータもBase64エンコードしたうえで埋め込まれるので,ファイルサイズは大きくなるものの,テキストファイルとして扱えるため,今回のような差分を取得する場合に便利なファイル形式となります。

Flat ODFへの変換も,LibreOfficeで可能です。GUIなら[ファイル][名前を付けて保存]から「ファイルの種類」「Flat XML」にして保存してください。拡張子は,ODTファイルならfodt,ODSならfodsのようになります。CUIから変換したければ次のコマンドを使います。

$ soffice --headless --convert-to fodt foo.odt
javaldx: Could not find a Java Runtime Environment!
Warning: failed to read path from javaldx
convert /home/shibata/temp/diff/foo.odt -> /home/shibata/temp/diff/foo.fodt using OpenDocument Text Flat XML
Overwriting: /home/shibata/temp/diff/foo.fodt

あとはテキストとして差分を取得すれば変更箇所がわかります。メタデータも残っているので,差分をパッチとして適用することも可能です。Flat ODFから通常のODFへも「--conver-to」オプションを使って戻せます。ちなみに,XMLファイルの差分はxmldiffコマンドを使うともう少し見やすくなります。

図9 DocDiffで差分をとった例。ODFのタグもちゃんと残っていることがわかる

図9 DocDiffで差分をとった例。ODFのタグもちゃんと残っていることがわかる

最後のunoconvは,LibreOfficeのUNOバインディングを使って,ドキュメント形式の変換を行うツールです。対応フォーマットはLibreOfficeで対応しているものと同じなので,変換ツールという意味では上記の「--convert-to」オプションと大差ないのですが,クライアント/サーバー機能を備えているのでネットワーク越しのLibreOfficeインスタンスに変換を依頼できるところが特徴です。

$ sudo apt install unoconv
$ unoconv -f pdf foo.odt

著者プロフィール

柴田充也(しばたみつや)

Ubuntu Japanese Team Member。数年前にLaunchpad上でStellariumの翻訳をしたことがきっかけで,Ubuntuの翻訳にも関わるようになりました。