-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbooklet_a6_on_a4.go
159 lines (143 loc) · 4.29 KB
/
booklet_a6_on_a4.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
Assumes you have a PDF with A6-sized pages. With those, it calculates the new order for these A6 pages in your PDF so that you can print it out using 4x A6 per A4, front and back. After printing the A6 pages in the new order, cut your A4 paper stack horizontally and put the top halves into the center of the bottom halves. Fold the new stack vertically and you have an A6 booklet.
Urheberrecht and Copyright 2018 Ernst Rohlicek.
License: GPLv3 or (at your option) any later version, see https://www.gnu.org/licenses/gpl-3.0.html
*/
package main
import (
"fmt"
"flag"
)
type SheetA4 struct {
FrontPhysical [4]int
BackPhysical [4]int
}
type SheetA5Horizontal struct {
FrontPhysical [2]int
BackPhysical [2]int
}
func main() {
// parse flags
var help, debug bool
var inpath, outpath string
var nPages int
flag.BoolVar(&help, "h", false, "print usage information")
flag.BoolVar(&debug, "debug", false, "give detailed event output")
flag.StringVar(&inpath, "in", "", "input PDF with A6 pages")
flag.StringVar(&outpath, "out", "", "output PDF path")
flag.IntVar(&nPages, "pages", 0, "number of pages - must be multiple of 8")
flag.Parse()
if help {
flag.PrintDefaults()
return
}
// checks
if inpath == "" {
fmt.Println("ERROR: need input PDF path")
flag.PrintDefaults()
return
}
if outpath == "" {
fmt.Println("ERROR: need output PDF path")
flag.PrintDefaults()
return
}
if nPages == 0 {
fmt.Println("ERROR: need number of pages")
flag.PrintDefaults()
return
}
if nPages % 8 != 0 {
fmt.Println("ERROR: number of pages must be multiple of 8")
flag.PrintDefaults()
return
}
// create physical A4 sheets and number the physical A6 pages on them
nSheets := nPages / 8;
sheetsA4 := make([]SheetA4, nSheets)
curPage := 1
// number all A4 sheets
for n := 0 ; n < nSheets; n++ {
// front
sheetsA4[n].FrontPhysical[0] = curPage
curPage++
sheetsA4[n].FrontPhysical[1] = curPage
curPage++
sheetsA4[n].FrontPhysical[2] = curPage
curPage++
sheetsA4[n].FrontPhysical[3] = curPage
curPage++
// back
sheetsA4[n].BackPhysical[0] = curPage
curPage++
sheetsA4[n].BackPhysical[1] = curPage
curPage++
sheetsA4[n].BackPhysical[2] = curPage
curPage++
sheetsA4[n].BackPhysical[3] = curPage
curPage++
}
// virtually rip in half horizontally
sheetsA5 := make([]SheetA5Horizontal, nSheets*2)
// top half
for n := 0 ; n < nSheets; n++ {
// front
sheetsA5[n].FrontPhysical[0] = sheetsA4[n].FrontPhysical[0]
sheetsA5[n].FrontPhysical[1] = sheetsA4[n].FrontPhysical[1]
// back
sheetsA5[n].BackPhysical[0] = sheetsA4[n].BackPhysical[0]
sheetsA5[n].BackPhysical[1] = sheetsA4[n].BackPhysical[1]
}
// bottom half
for n := 0 ; n < nSheets; n++ {
// front
sheetsA5[nSheets+n].FrontPhysical[0] = sheetsA4[n].FrontPhysical[2]
sheetsA5[nSheets+n].FrontPhysical[1] = sheetsA4[n].FrontPhysical[3]
// back
sheetsA5[nSheets+n].BackPhysical[0] = sheetsA4[n].BackPhysical[2]
sheetsA5[nSheets+n].BackPhysical[1] = sheetsA4[n].BackPhysical[3]
}
// debug print for virtual ripping
if debug {
fmt.Println("virtual horizontal A5 sheets after cutting horizontally:")
for n := 0; n < nSheets*2; n++ {
fmt.Printf("front %v back %v\n", sheetsA5[n].FrontPhysical, sheetsA5[n].BackPhysical)
}
}
// number all physical pages in book order
curPage = 0 // index actually
// left pages of the stack going up = first half book pages
bookOrder := make([]int, nPages) // this is a translation table, i.e. book page 1 belongs to nth position
for n := 0 ; n < len(sheetsA5); n++ {
// back right
bookOrder[curPage] = sheetsA5[n].BackPhysical[1]
curPage++
// front left
bookOrder[curPage] = sheetsA5[n].FrontPhysical[0]
curPage++
}
// right pages of the stack going down = second half book pages
for n := len(sheetsA5)-1 ; n >= 0; n-- {
// front right
bookOrder[curPage] = sheetsA5[n].FrontPhysical[1]
curPage++
// back left
bookOrder[curPage] = sheetsA5[n].BackPhysical[0]
curPage++
}
// apply translation
printOrder := make([]int, nPages)
for index, pgNumber := range bookOrder {
printOrder[pgNumber-1] = index+1
}
// print result
if debug {
fmt.Println("print order:", printOrder)
}
// print pdftk command-line
fmt.Printf("pdftk A=%s cat", inpath)
for _, pgNumber := range printOrder {
fmt.Printf(" A%d", pgNumber)
}
fmt.Printf(" output %s\n", outpath)
}