PDF あれこれ

研究者でも、なにかの会議の予稿集とかジャーナルの編集とかで原稿PDFを集めてまとめる仕事が降ってくることがあります。そんな時に役に立つツールあれこれ。LINUXでちょっとしたテキスト処理はCで書いてやっちゃう人向け。しかしこれでバリバリ仕事終えちゃうと他の雑用も任せられるかもしれないという諸刃の剣。素人にはお勧めできない。

これは入れとけ1: pdftk

http://www.pdflabs.com/docs/build-pdftk/
これは必須。いろいろな事がコマンドラインで出来ます。

  • >pdftk page[1234].pdf cat output page1-4.pdf

4つのPDFをまとめて1つにします。

  • >pdftk page1-4.pdf burst

1つのPDFをページごとにバラします。

  • >pdftk paper_orig.pdf multibackground header_footer.pdf output paper.pdf

ヘッダとフッタを追加したい時、TeXで微調整してヘッダとフッタのみのファイルを作りPDF化、それを透かしとして入れることでヘッダとフッタを入れ込みます。paper_orig.pdfに透明でない部分があると隠れてしまうので注意。

  • >pdftk input_old.pdf dump_data_utf8 > tmp.data
  • >pdftk input_new.pdf update_info_utf8 tmp.data output final.pdf

input_old.pdfから作成者などのプロパティを抜き出し、それをinput_new.pdfにインポートしてfinal.pdfに書き出す。著者原稿に編集者がいろいろプロパティを設定したのに後で著者が訂正を送りつけてきたような場合に。

  • >pdftk orig.pdf output locked.pdf owner_pw somepassword allow printing CopyContents

orig.pdfを暗号化、内容書き換えを禁止するが印刷やコピペは許可するlocked.pdfを生成

  • >pdftk orig.pdf output aaa.pdf uncompress
  • >vi aaa.pdf 文字書き換え
  • >pdftk aaa.pdf output revised.pdf compress

ちょっとした文字書き換えや削除。Acrobatのタッチアップツールで書き換えや削除をするとフォントを変換されてしまう。それを避ける方法。vi で編集すると以下のようになっている

Td[(Numerical)-283(e)24(v)25(aluation)-282(of)-283(ph)4(ysical)

ぶつ切れになってるので文字列を探すのが若干大変。ただしフォント埋め込みで使ってない文字に変えると表示されない。

これは入れとけ2: poppler

http://ja.wikipedia.org/wiki/Poppler
pdftoppmでPDFを画像化できる。1ドット単位で修正の影響をチェックする時に。
convert でも出来なくはないがエラーが頻出するし品質もよくない。
画像の差分には以下の自作コード ppmdif.cを使った。

  • >pdftoppm -gray -r 180 -f 1 -l 1 input1.pdf >a1.ppm
  • >pdftoppm -gray -r 180 -f 1 -l 1 input2.pdf >a2.ppm
  • >ppmdif a1.ppm a2.ppm
  • >xv dif.ppm

// ppmdif.c
#include <stdio.h>
#include <stdlib.h>

unsigned char *buf1;
unsigned char *buf2;
unsigned char *buft;
unsigned char *bufm1;
unsigned char *bufm2;

int lx1,ly1,lx2,ly2;
int lx,ly;
char st[256];
unsigned char *obuf;

void init_mask(unsigned char *orig, unsigned char *mask, int lx, int ly,int smax)
{
    int i,s,x,y;
    for(i=0;i<lx*ly;i++)
    {
	if(orig[i]<128)mask[i]=0;
	else mask[i]=255;
	buft[i]=mask[i];
    }

    for(s=0;s<smax;s++)
    {
	for(x=1;x<lx-1;x++) {
	for(y=1;y<ly-1;y++) {
	    int i=x+y*lx;
	    buft[i]=mask[i];
	    buft[i]&=mask[i-1];
	    buft[i]&=mask[i+1];
	    buft[i]&=mask[i-lx];
	    buft[i]&=mask[i+lx];
	}}
        for(i=0;i<lx*ly;i++) mask[i]=buft[i];
    }
}


int main(int argc, char **argv)
{

    FILE *fp=fopen(argv[1],"r");
    fgets(st,255,fp);
    fgets(st,255,fp);
    sscanf(st, "%d %d", &lx1,&ly1);
    buf1=(unsigned char *)malloc(lx1*ly1);
    fgets(st,255,fp);
    fread(buf1, 1,lx1*ly1, fp);
    fclose(fp);

    fp=fopen(argv[2],"r");
    fgets(st,255,fp);
    fgets(st,255,fp);
    sscanf(st, "%d %d", &lx2,&ly2);
    buf2=(unsigned char *)malloc(lx2*ly2);
    //buf4=(unsigned char *)malloc(lx2*ly2*3);
    fgets(st,255,fp);
    fread(buf2, 1,lx2*ly2, fp);
    fclose(fp);

    lx=lx1;if(lx2>lx)lx=lx2;
    ly=ly1;if(ly2>ly)ly=ly2;
    buft=(unsigned char *)malloc(lx*ly);
    bufm1=(unsigned char *)malloc(lx*ly);
    bufm2=(unsigned char *)malloc(lx*ly);
    obuf=(unsigned char *)malloc(3*lx*ly);

    init_mask(buf1, bufm1, lx1,ly1, 2);
    init_mask(buf2, bufm2, lx2,ly2, 2);

    int i;
    int c,ix,iy, s;

    int nred=0, nbl=0;
    // make diff
    for(i=0;i<lx1*ly1;i++)
    {
	int x1=i%lx1;
	int y1=i/lx1;
	int i2=(x1+y1*lx2);
	int d1=buf1[i];
	int d2=buf2[i2];
	int m1=bufm1[i];
	int m2=bufm2[i];

	int flag=0; // no difference
	if(d1<220 && m2==255) flag=1;
	if(d2<220 && m1==255) flag=2;
	if(abs(d1-d2)<16)flag=0;
	if(flag==1)nred++;
	if(flag==2)nbl++;

	if(flag==0)
	{
	    int d=(d1+d2)/2;
	    int dd= (255*9 + d)/10;

	    obuf[i*3+0]= dd;
	    obuf[i*3+1]= dd;
	    obuf[i*3+2]= dd;
	}
	else if(flag==1)
	{
	    obuf[i*3+0]= 0;
	    obuf[i*3+1]= 0;
	    obuf[i*3+2]= d1;
	}
	else
	{
	    obuf[i*3+0]= d2;
	    obuf[i*3+1]= 0;
	    obuf[i*3+2]= 0;
	}
    }
#if 1
    if(nred==0 && nbl==0)exit(1);
    fp=fopen("dif.ppm","w");
    fprintf(fp, "P6\n%d %d\n255\n",lx1,ly1);
    fwrite(obuf,1,3*lx1*ly1,fp);
    fclose(fp);
#else

    fp=fopen("dif1.ppm","w");
    fprintf(fp, "P6\n%d %d\n255\n",lx1,ly1/2);
    fwrite(obuf,1,3*lx1*ly1/2,fp);
    fclose(fp);

    fp=fopen("dif2.ppm","w");
    int adrs= lx1*(ly1/2)*3;
    fprintf(fp, "P6\n%d %d\n255\n",lx1,ly1/2);
    fwrite(&obuf[adrs],1,3*lx1*ly1/2,fp);
    fclose(fp);
#endif
    free(buf1);
    free(buf2);
    free(obuf);

    free(buft);
    free(bufm1);
    free(bufm2);

    fp=fopen("pdif.log","a");
    fprintf(fp,"N %d  %d\n", nred, nbl);
    fclose(fp);
}