2016-08-16 2 views
0

4on1 twosideプリンタ設定で印刷したいPDF文書cards.pdfがあります。私はGNU makefileを使って文書を作成しています。そこで私は解決策を探しています。4on1印刷用GNU make PDF文書の再調整

用紙を節約するために1ページに4ページが印刷されます(実際には6枚のカードが必要です)、一部のページが背面に印刷されます。しかし、私はまた、紙を切った後に正しいバックを見つけるためにページをめくることができるようにしたい。私は、この順序に従ってページを再配置する必要があることを理解:

1 3 5 7 4 2 8 6 
9 11 13 15 ... 

私はこれを行うためにpdftkを使用することができますが、問題がある:

  1. 文書cards.pdfのページ数は不明であるが。
  2. cards.pdfのページ数は、必ずしも8の倍数である必要はありません。
  3. 並べ替えられたドキュメントのサイズが大きくなります。

(338kBから91ページと私の例では1.6メガバイトに)私はGNUドキュメントを膨満感なしにページを再配置するためのソリューションを作る扱いやすい探しています。

答えて

0

ここには部分的なGNU makeと部分的なCの解決策があります。私は400ページの文書をチェックしたが、膨らんでいなかった。これが満足であれば、Cプログラムはシェルスクリプトとして書き直され、makefileに組み込まれます。

この問題は、pdftkの正しいページ番号のシーケンスを生成することから成り立っています。私はそのシーケンスを生成するprint_order.cと呼ばれる小さな(< 70行)Cプログラムを書いています。そして、私はそれを使用するようにmakefileを変更しました。

print_order.c

#include <stdio.h> 
#include <stdlib.h> 

int pg_eight [] = {1, 3, 5, 7, 4, 2, 8, 6}; 

const char* blank_page = "B1"; 

void advance_pg_eight() 
{ 
    int j=0; 
    for(j=0; j < 8; j++) 
     pg_eight[j] += 8; 
} 

void print_pg_eight (long int npages) 
{ 
    int j=0; 
    static int nprinted = 0; 
    for (j=0; j < 8 && nprinted < npages; j++) { 
     if(pg_eight[j] > npages) 
      printf("%4s ", blank_page); 
     else 
     { 
      printf("%4d ", pg_eight[j]); 
      nprinted++; 
     } 
    } 
} 

long int get_npages(const char *first_arg) 
{ 
    char *endptr = "Hello"; 
    long int npages = strtol(first_arg, &endptr, 10); 

    if (*endptr != '\0' || npages <= 0) 
     return 0; 

    return npages; 
} 

int main (int argc, char* argv[]) 
{ 
    long int npages = 0; 
    int neights = 0, j=0; 

    if (argc < 2) { 
     fprintf(stderr, "%s: Insufficient number of arguments\n", argv[0]); 
     return 0; 
    } 
    npages = get_npages(argv[1]); 
    if (0 == npages) { 
     fprintf(stderr, "%s: Failed to parse number of pages (%s)\n", argv[0], argv[1]); 
     return 0; 
    } 

    neights = npages/8; 
    if (npages % 8 != 0) 
     neights++; 

    for(j = 0; j < neights; j++) { 
     print_pg_eight(npages); 
     advance_pg_eight(); 
     printf("\n"); 
    } 

    printf("\n"); 
} 

makefile

# 
# use a shell escape to get the number of pages of the pdf file with: 
# qpdf --show-npages ./cards.pdf 
NPAGES := $(shell qpdf --show-npages ./cards.pdf) 
# 
PRINT := $(shell ./print_order $(NPAGES)) 

print.pdf: makefile cards.pdf blank.pdf print_order 
    pdftk B=blank.pdf cards.pdf cat $(PRINT) output print.pdf 

print_order: print_order.c 

91ページのprint_orderのサンプル出力日時:

1 3 5 7 4 2 8 6 
9 11 13 15 12 10 16 14 
17 19 21 23 20 18 24 22 
25 27 29 31 28 26 32 30 
33 35 37 39 36 34 40 38 
41 43 45 47 44 42 48 46 
49 51 53 55 52 50 56 54 
57 59 61 63 60 58 64 62 
65 67 69 71 68 66 72 70 
73 75 77 79 76 74 80 78 
81 83 85 87 84 82 88 86 
89 91 B1 B1 B1 90 

B1は、最初のページが空白のpdfの最初のページです。このソリューションを使用するには

blank.pdf

  • コピーcards.pdf
  • として再発注する必要がありPDFとして print_order.c
  • コピー空白の最初のページでPDFを作成するためのCコード上記

    1. コピー
    2. 実行make

    希望します。

  • +0

    私はあなたの解決策を働かせようとしています。まず、print_orderを作成する指示がないようです: 'gcc print_order.c -o print_order' –

    +0

    第二に、少なくとも私のマシンでは、' pdftk'コマンドを 'pdftk cards.pdf B = blank 'に再配置する必要があります。 pdf cat $(PRINT)出力print.pdf'。 これは、ハンドルのないページが最初の入力ファイルを参照するためです。 'pdftk'のヘルプから引用:ページ範囲からハンドルが省略された場合、ページは最初の入力PDFから取り出されます。 –

    +0

    以外は正常に動作します。ありがとう –

    0

    次のメークファイルは、私が思う非常に悪い方法でしたいものです。私は便宜のために文書の冒頭に空のページを追加します。

    qpdfを使用して、ページ数をcards.pdfにします。 規則PG_EIGHTを使用して、印刷の正しい順序で8ページのブロックに展開します。

    # declare following rule with = only, no := 
    PG_EIGHT = $$((8*$(1)+2)) $$((8*$(1)+4)) $$((8*$(1)+6)) $$((8*$(1)+8)) $$((8*$(1)+5)) $$((8*$(1)+3)) $$((8*$(1)+9)) $$((8*$(1)+7)) 
    # 
    # use a shell escape to get the number of pages of the pdf file with: 
    # qpdf --show-npages ./cards.pdf 
    PG_MAX := $$(($(shell qpdf --show-npages ./cards.pdf) -1)) 
    # 
    #division discards remainder: 
    BLOCKS := $(shell seq 0 $$(($(PG_MAX)/8 - 1))) 
    PRINT := $(foreach BLOCK,$(BLOCKS),$(call PG_EIGHT,$(BLOCK))) 
    # 
    # get the rest (remainder) of the pages with modulo division: 
    PG_RM := $(shell echo $(PG_MAX)%8 | bc) 
    # get last page of last BLOCK: 
    PG_MAX := $$(($(PG_MAX) - $(PG_RM))) 
    # 
    # do nothing if remainder is 0. 
    ifeq ($(PG_RM),1) 
    PRINT += $$(($(PG_MAX) + 2)) 
    else ifeq ($(PG_RM),2) 
    PRINT += $$(($(PG_MAX) + 2)) 0 0 0 0 $$(($(PG_MAX) + 3)) 
    else ifeq ($(PG_RM),3) 
    PRINT += $$(($(PG_MAX) + 2)) $$(($(PG_MAX) + 4)) 0 0 0 $$(($(PG_MAX) + 2)) 
    else ifeq ($(PG_RM),4) 
    PRINT += $$(($(PG_MAX) + 2)) $$(($(PG_MAX) + 4)) 0 0 $$(($(PG_MAX) + 5)) $$(($(PG_MAX) + 3)) 
    else ifeq ($(PG_RM),5) 
    PRINT += $$(($(PG_MAX) + 2)) $$(($(PG_MAX) + 4)) $$(($(PG_MAX) + 6)) 0 $$(($(PG_MAX) + 5)) $$(($(PG_MAX) + 3)) 
    else ifeq ($(PG_RM),6) 
    PRINT += $$(($(PG_MAX) + 2)) $$(($(PG_MAX) + 4)) $$(($(PG_MAX) + 6)) 0 $$(($(PG_MAX) + 5)) $$(($(PG_MAX) + 3)) 0 $$(($(PG_MAX) + 7)) 
    else ifeq ($(PG_RM),7) 
    PRINT += $$(($(PG_MAX) + 2)) $$(($(PG_MAX) + 4)) $$(($(PG_MAX) + 6)) $$(($(PG_MAX) + 8)) $$(($(PG_MAX) + 5)) $$(($(PG_MAX) + 3)) 0 $$(($(PG_MAX) + 7)) 
    # remainder cannot be equal to 8. 
    endif 
    
    # fully evaluate the PRINT string: 
    PRINT := $(shell echo $(PRINT)) 
    
    print.pdf: makefile cards.pdf 
        echo $(BLOCKS) 
        pdftk cards.pdf cat $(PRINT) output print.pdf 
    

    このコードに関してひどいのは、残りの部分と頻繁なシェルエスケープの処理です。

    私はそれがなぜファイルサイズを膨らませるのか分かりません。