pdfの連結と回転にqpdfが便利

pdfファイルを加工する2つのパッケージ

pdfファイルから画像を取り出したり、画像化をしたり、ページを分けたり、結合したりする方法を調べたので、記録しておく。

すでにgimpを使えば画像関係の処理ができることはわかっている。解像度を指定して読み込んだり、ページをレイヤーにしてエクスポートするときにレイヤーをページにして出すこともできる。

今回はスキャナで読み取ったり、スクリーンショットでとった複数画像を複数ページのpdfにまとめるために、端末からコマンドで行えると便利だということで調べることとなった。

pdfといっても内容は様々で文字データで構成されたものもあるし、画像がそのままページになっているものもある。画像を含む文字データの場合もあるかもしれない。今回主に扱うのは画像がそのままページになっているものである。

2つのパッケージをレポートします。

(1)poppler-utilsパッケージからpdfimagesやpdftoppm, pdfinfo, pdfseparate, pdfuniteなどのコマンド。

(2)qpdfパッケージからqpdfというコマンドが持つ分割、連結、回転などの機能。

ここでパッケージはdebian系のLinuxが使用するaptというパッケージマネージャのソフトウェアの管理単位です。

pdfinfoでpdfファイルの情報を得る

今回扱うのはプリンタ付属のスキャナで読み取ってUSBメモリに保存したデータ。

いつもはxsaneでPCから読み取ってpngなどで保存しているが、今回はスキャナだけで読み取った。

jpgとpdfを選択できるが、jpgでは1枚スキャンするごとに2回センサが動いて時間がかかる。たぶん1枚ごとに調整をしていると思われる。pdfだと1パスで読み取ってくれる。

このスキャナのjpgは圧縮率を指定できないので、文字データでは画質に不安が残ることもありpdfにした。

pdfinfoで情報を得ると

adachi@fumita:~/work$ pdfinfo EPSON001.PDF 
Tagged:         no
UserProperties: no
Suspects:       no
Form:           none
JavaScript:     no
Pages:          1
Encrypted:      no
Page size:      595 x 841 pts
Page rot:       0
File size:      1846117 bytes
Optimized:      no
PDF version:    1.4

841[pt]=841/72[in]=841/72*25.4[mm]=約297mm なので、A4サイズ。

pdfimagesでpdfから画像を取り出す

pdfimagesは含まれる画像を抽出するコマンド。-listで一覧が取れる。今回のページは全体が1つの画像のはず。

adachi@fumita:~/work$ pdfimages -list EPSON001.PDF
page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
--------------------------------------------------------------------------------------------
   1     0 image    2480  3507  rgb     3   8  jpeg   no         6  0   301   301 1802K 7.1%

なんと、中身はjpgだった。3507[px]=3507/841*72[dpi]=約300dpi これはスキャン時の指定通り。

adachi@fumita:~/work$ pdfimages  EPSON001.PDF img001

これでimg001-000.ppmができる。ppmは無圧縮なので26.1MBになる。最初のP6で確認できる。

adachi@fumita:~/work$ hd img001-000.ppm |head
00000000  50 36 0a 32 34 38 30 20  33 35 30 37 0a 32 35 35  |P6.2480 3507.255|
00000010  0a e2 cf b1 d7 c4 a6 e6  d3 b5 fb e8 ca fa e7 c7  |................|
00000020  f6 e3 c3 f8 e5 c5 f4 e1  c1 f4 df c0 f3 de bf f2  |................|
00000030  dd be f3 de bf f5 e0 c1  f6 e1 c2 f7 e0 c1 f6 df  |................|
00000040  c0 f2 dd be f4 df c0 f3  de bf ee d9 ba eb d6 b7  |................|
00000050  ec d7 b8 f1 dc bd f4 df  c0 f5 e1 c0 f6 e2 c1 f7  |................|
00000060  e3 c2 f7 e3 c2 f5 e1 c0  f3 df be ef db ba ed d9  |................|
00000070  b8 ef d8 b6 ee d7 b5 ee  d7 b5 f0 d9 b7 f4 dd bb  |................|
00000080  f8 e1 bf fb e4 c2 fc e5  c3 f3 dc ba f3 dc ba f3  |................|
00000090  dc ba f5 de bc f7 e0 be  f8 e1 bf f7 e0 be f7 df  |................|

オプションで出力形式を、png, tiff, jpg, JPEG2000 などにすることができる

adachi@fumita:~/work$ pdfimages -j EPSON001.PDF img001

これはjpg。拡張子は自動でつく。

adachi@fumita:~/work$ hd img001-000.jpg |head
00000000  ff d8 ff e1 01 06 45 78  69 66 00 00 49 49 2a 00  |......Exif..II*.|
00000010  08 00 00 00 08 00 0e 01  02 00 10 00 00 00 6e 00  |..............n.|
00000020  00 00 0f 01 02 00 12 00  00 00 7e 00 00 00 10 01  |..........~.....|
00000030  02 00 0f 00 00 00 90 00  00 00 1a 01 05 00 01 00  |................|
00000040  00 00 a0 00 00 00 1b 01  05 00 01 00 00 00 a8 00  |................|
00000050  00 00 28 01 03 00 01 00  00 00 02 00 00 00 13 02  |..(.............|
00000060  03 00 01 00 00 00 02 00  00 00 69 87 04 00 01 00  |..........i.....|
00000070  00 00 b0 00 00 00 00 00  00 00 45 50 53 4f 4e 20  |..........EPSON |
00000080  4d 46 50 20 69 6d 61 67  65 00 53 45 49 4b 4f 20  |MFP image.SEIKO |
00000090  45 50 53 4f 4e 20 43 4f  52 50 2e 00 45 50 2d 38  |EPSON CORP..EP-8|

出力ファイル名に-000がつくのは、ページ内にたくさんの画像が埋め込まれていることを想定しているからだろう。今回のファイルはページそのものが一つの画像なので-000しかない。

-rwxrwxrwx 1 adachi adachi  1846117  1月  1  2018 EPSON001.PDF
-rw-r--r-- 1 adachi adachi  1845247 10月 15 02:03 img001-000.jpg
-rw-r--r-- 1 adachi adachi 26092097 10月 15 02:00 img001-000.ppm

pdftoppmでpdfをページごとに画像化

今回はもともとpdfのページが画像だけで構成されているので、これを使う意味はないが、違いを把握しておく。

pdftoppmは文字データも含めてページを画像化する。デフォルトでは150dpiのppmという形式になる。今回のpdfimagesの出力と同様なものを得るには -jpegオプションと、-r 300 オプション(rの後にスペースが必要)を指定する必要がある。

adachi@fumita:~/work$ pdftoppm -jpeg -r 300 EPSON001.PDF img001bytoppm300

作成されるファイル名には-1がつくがページが複数ある時のためであろう。

中身がもともとjpegなのでエンコードし直していることになる。ファイルサイズから、圧縮率が上がっているように見受けられる。

-rwxrwxrwx 1 adachi adachi  1846117  1月  1  2018 EPSON001.PDF
-rw-r--r-- 1 adachi adachi   873337 10月 15 03:01 img001bytoppm300-1.jpg

jpgの指定が、pdfimagesが-jで、pdftoppmが-jpegなのは不統一だが、間違えるとオプション一覧が出るのでそれとわかる。pngは両方共 -png。

pdfuniteでpdfファイルを連結

この作業は後でqpdfで行うことにしたので、pdfuniteは試しただけになったが、一応記録しておく。

カレントディレクトリにあるEPSON001.PDF, EPSON002.PDF, EPSON003.PDF を連結してEall.pdfにするには、

adachi@fumita:~/work$ pdfunite EPSON001.PDF EPSON002.PDF EPSON003.PDF Eall.pdf

書かれた順で連結されて最後の引数のファイルが生成される。

shellの機能として、ls EPSON*.PDF や ls EPSON* が、EPSON001.PDF EPSON002.PDF EPSON003.PDF となるのであれば、それを使って簡素化できる。たとえば、

adachi@fumita:~/work$ pdfunite EPSON*.PDF Eall.pdf

qpdfでpdfのまま加工

今回の作業のきっかけは所有するスキャナで取る画像データが自由にならないことだった。

(1)jpgよりもpdfの方が動作が早いので文字中心の画像ならpdfにしたい。

(2)デフォルトで縦位置になってしまう。

(3)複数ページのデータは1ファイルにまとめたいが、複数ページのpdfにはしてくれない。

いままでは、画像ファイルにしてgimpで切り貼りしたり、htmlに貼り付けてページ送り機能をつけたりしたが、縦横比が違う画像データが扱いにくかったり、手間がかかったり、結局1ファイルにはならないという欠点がある。どうせpdfにするなら複数ページを持つpdfにしてしまうほうがよい。

今までpdfから画像ファイルを取り出して加工することを考えたのでpdfimagesなどを吟味していたが、pdfのままにしたほうが楽ができると気がついて方針を変更。qpdfを調べることにする。

qpdfを使えば全部のページをまとめて90, 180, 270度の回転ができるので、さらに手間が省ける。

qpdfでpdfファイルの連結

debian10(buster)ではqpdfは標準では入っていないので、qpdfパッケージを追加した。qpdfが依存しているlibqpdf21というパッケージはすでに入っていた。

先程同様、カレントディレクトリにあるEPSON001.PDF, EPSON002.PDF, EPSON003.PDF を連結してEall.pdfにするには、

adachi@fumita:~/work$ qpdf EPSON001.PDF --pages EPSON001.PDF EPSON002.PDF EPSON003.PDF -- Eall.pdf

--pages と -- の間に書かれたファイルがその順で連結されて最後の引数のファイルが生成される。最初の引数(ここではEPSON001.PDF)は、ページデータ以外の情報(Creator, Producer, CreationDate, PDF versionなど)をそのファイルから引き継ぐことを意味する。連結するファイル以外を指定しても受け入れられる。引き継ぎたくない場合はファイル名の代わりに --empty と入れておく。

adachi@fumita:~/work$ qpdf --empty --pages EPSON001.PDF EPSON002.PDF EPSON003.PDF -- Eall.pdf

shellの機能として、ls EPSON*.PDF や ls EPSON* が、EPSON001.PDF EPSON002.PDF EPSON003.PDF となるのであれば、それを使って簡素化できる。たとえば、

adachi@fumita:~/work$ qpdf --empty --pages EPSON*.PDF -- Eall.pdf

qpdf --help で冒頭に

Usage: qpdf [ options ] { infilename | --empty } [ outfilename ]

と書かれているが、これに順番を合わせて、

adachi@fumita:~/work$ qpdf --pages EPSON*.PDF -- EPSON001.PDF Eall.pdf

と書いても同じだ。

さらに、連結するファイルの順序を調整したければ、テキストファイルを作ってそれを指定してもよい。

例えば、次のようなファイルを作っておいて、

adachi@fumita:~/work$ cat Elist.txt 
EPSON003.PDF
EPSON002.PDF
EPSON001.PDF

@をつけて指定するとこの順番で連結してくれる。

adachi@fumita:~/work$ qpdf --pages @Elist.txt -- --empty Eallr.pdf

この他、連結する元のファイルがすでに複数のページから構成されている場合には、ページを選択して指定することも可能。

qpdfでpdfのページを回転

全部のページを一度に回転させることも可能だし、一部のページだけを異なる回転にすることもできる。角度は90, 180, 270度のどれか。

全部をまとめて回転する例だけを示すと、

adachi@fumita:~/work$ qpdf --rotate=90 Eall.pdf Eallyoko.pdf

Eall.pdf のデータを時計回りで90度回転させて、Eallyoko.pdfを生成する。

qpdfでpdfファイルのまま分割

1ページずつに分割するのは簡単。

adachi@fumita:~/work$ qpdf --split-pages Eall.pdf Esplited.pdf

出来上がるファイルには拡張子前に連番がつく。linuxの伝統で拡張子なしも許されるが、その場合は連番で終わる名前になる。

Esplited-1.pdf
Esplited-2.pdf
Esplited-3.pdf

もし、10ページからなるものを分割すると、次のようになる。

Esplited-01.pdf
Esplited-02.pdf
Esplited-03.pdf
......
Esplited-10.pdf

ページ番号を末尾以外に配置する場合は、%dで位置を指定する。

adachi@fumita:~/work$ qpdf --split-pages Eall.pdf E%dsplited.pdf
E1splited.pdf
E2splited.pdf
E3splited.pdf

こちらも、10ページなら0がついて二桁となる。

E01splited.pdf
E02splited.pdf
E03splited.pdf
......
E10splited.pdf

まとめ

連結

qpdf --pages 入力ファイルリスト -- メタデータのファイル 出力ファイル
qpdf --pages 入力ファイルリスト -- --empty 出力ファイル
qpdf --pages s01.pdf s02.pdf s03.pdf -- s01.pdf outfile.pdf
qpdf --pages s*.pdf -- s01.pdf outfile.pdf
qpdf --pages @sflist.txt -- --empty outfile.pdf

回転

qpdf --rotate=90  入力ファイル 出力ファイル
qpdf --rotate=90  infile.pdf outfile.pdf
qpdf --rotate=180 infile.pdf outfile.pdf
qpdf --rotate=270 infile.pdf outfile.pdf

分割

qpdf --split-pages 入力ファイル 出力ファイル(基本形)
qpdf --split-pages infile.pdf outfile.pdf
qpdf --split-pages infile.pdf out%dfile.pdf

ファイル情報

pdfinfo 入力ファイル

内部画像情報

pdfimages -list 入力ファイル

内部画像取出

ppmで:pdfimages 入力ファイル 出力画像ファイル
jpgで:pdfimages -j 入力ファイル 出力画像ファイル
pngで:pdfimages -png 入力ファイル 出力画像ファイル

ページの画像化

ppm,150dpiで:pdftoppm 入力ファイル 出力画像ファイル
jpg,300dpiで:pdftoppm -jpeg -r 300 入力ファイル 出力画像ファイル
png,300dpiで:pdftoppm -png  -r 300 入力ファイル 出力画像ファイル

複数画像ファイルから複数ページのpdf(A4限定)

A4は210x297mm 300dpiでは210/25.4*300≒2480px 297/25.4*300≒3508px

このサイズの画像を揃えたら次のどれかで

300dpi ≒ 300/2.54 ≒ 118dpcm

convert -density 118 tori*.jpg output.pdf

単位を指定する

convert -units PixelsPerInch -density 300 tori*.jpg output.pdf

ファイルの一覧をテキストファイルzfに用意して使う場合。

convert -units PixelsPerInch -density 300 `cat zf` output.pdf

詳しくはまたいつか。