### Espaço de Tecnologias e Artes - Sesc Avenida Paulista
## Grupo de estudos em Python
### `hackmd.io/@sesc-av-paulista/estudos-em-python-19-agosto`
### Manipulando PDFs
- Fundindo 2 PDFs lado a lado: https://gist.github.com/villares/e902bdbe093ef832f770bdd451cdb03e
- Encolhe PDF (4 páginas por página) https://gist.github.com/villares/e902bdbe093ef832f770bdd451cdb03e
- Fazedor de zines https://gist.github.com/villares/0402a1c9033e6f4baf55554c16d25f4e
- Tirar nome do PDF: https://github.com/villares/anonymize-pdf-annotations
- PyMuPDF https://pymupdf.readthedocs.io/en/latest/
- Zine maker com interface GUI para selecionar arquivo:
```python=
"""
Make a PDF A3 zine combining 8 pages from a source PDF
WIP: I'd like to have an option for the 9th page (index=8) to be a poster in the backside or not.
-------------------------------------------------------------------------------
License: GNU GPL V3
(c) 2025 Alexandre Villares
Based on https://github.com/fitz/fitz-Utilities/blob/master/examples/combine-pages/combine.py
(c) 2018 Jorj X. McKie
Dependencies (install!)
------------
PyMuPDF (the fitz engine)
FreeSimpleGUI
Usage
-----
python combine.py input.pdf
|----|----|----|----|
| 0d | 7d | 6d | 5d |
|----|----|----|----|
| 1u | 2u | 3u | 4u |
|----|----|----|----|
|----|----|----|----|
| |
| 8s |
| |
|----|----|----|----|
N = page 0-based
u = normal orientation
d = upside down (rotated 180)
s = big poster (rotated 90)
Notes
-----
(1) Output file is chosen to have A3 landscape pages. Input pages are scaled
maintaining side proportions.
"""
from pathlib import Path
import fitz
import FreeSimpleGUI as sg
L_FONT = ('Courier', 20)
I_FONT = ('Courier', 16)
# Define the GUI layout
layout = [
[sg.Text('Input file:', font=L_FONT)],
[sg.InputText(font=I_FONT), sg.FileBrowse(font=I_FONT)],
[sg.Button('Create PDF', font=L_FONT),
sg.Button('CLOSE/EXIT', font=L_FONT)]
]
# Create the GUI window
window = sg.Window('Modify PDF annotations & metadata', layout)
while True:
# Get the next GUI event
event, values = window.read()
# Exit the event loop if the window was closed or the Cancel button was clicked
if event in (None, 'CLOSE/EXIT'):
break
elif event == 'Create PDF' and values:
input_file = Path(values[0])
output_file = input_file.parent / (input_file.stem + '_zine.pdf')
src = fitz.open(input_file)
doc = fitz.open() # empty output PDF
height, width = fitz.paper_size("a3") # A3 output page format
# define the 4 rectangles per page
r0 = fitz.Rect(0, 0, width / 4, height / 2) # top left rect
r7 = r0 + (r0.width, 0, r0.width, 0)
r6 = r7 + (r0.width, 0, r0.width, 0)
r5 = r6 + (r0.width, 0, r0.width, 0) # top right
r1 = r0 + (0, r0.height, 0, r0.height) # bottom left
r2 = r1 + (r0.width, 0, r0.width, 0)
r3 = r2 + (r0.width, 0, r0.width, 0)
r4 = r3 + (r0.width, 0, r0.width, 0)# bottom right
r8 = fitz.Rect(0, 0, width, height)
# put them in a list
r_tab = [r0, r1, r2, r3, r4, r5, r6, r7, r8]
front_and_back = False
big_poster = True
poster_offset = 0
# now copy input pages to output
for spage in src:
if (spage.number - poster_offset) % 8 == 0: # create new output page
page = doc.new_page(-1, width=width, height=height)
# insert input page into the correct rectangle
r_position = (spage.number - poster_offset) % (9 if big_poster else 8)
# imposition rotation rule
rotation = (180 if r_position in (0, 7, 6, 5)
else 90 if r_position == 8 else 0)
page.show_pdf_page(
r_tab[r_position], # select output rect
src, # input document
spage.number,
rotate=rotation
) # input page number
# by all means, save new file using garbage collection and compression
doc.save(output_file, garbage=4, deflate=True)
sg.popup(f'{output_file.name} saved.')
```