Menulis PDF dari Nol (01): Hello, World—Membangun PDF Minimal yang Dapat Digunakan
Menulis PDF dari Nol (01): Hello, World—Membangun PDF Minimal yang Dapat Digunakan
Tujuan Seri: Memahami PDF sebagai format file yang dapat dibaca—mulai dari contoh minimal yang "bisa berjalan", kemudian secara bertahap memperluas ke grafik, multi-halaman, kompresi, dan penggunaan kembali sumber daya.
Daftar Seri
- Bagian 01 (Artikel ini): Menulis PDF minimal (1 halaman + 1 baris teks), dan menggunakan alat untuk melengkapinya menjadi PDF standar yang dapat dibuka
- Bagian 02: Menggambar garis/menggambar persegi panjang dalam aliran konten (memahami jalur, garis tepi, pengisian)
- Bagian 03: PDF multi-halaman (bagaimana pohon Halaman terbentuk)
- Bagian 04: Lebih mendekati dunia nyata (aliran kompresi, penggunaan kembali sumber daya, struktur opsional, dll.)
Mengapa Penting untuk Memahami Struktur Dasar PDF?
PDF (Portable Document Format, format dokumen portabel) adalah salah satu bahasa deskripsi halaman yang paling populer saat ini. Berbeda dengan HTML/CSS yang memiliki pemisahan "konten dan presentasi, dapat mengalir (Reflowable)", PDF lebih menekankan pada tata letak tetap, apa yang Anda lihat adalah apa yang Anda dapatkan—apapun perangkat yang digunakan, tata letaknya tetap konsisten.
Memahami struktur dasar PDF memiliki beberapa manfaat praktis:
- Debugging masalah pembuatan PDF: Ketika Anda mengalami kesalahan saat menghasilkan PDF dengan pustaka kode, memahami struktur dasar akan membantu Anda dengan cepat menemukan masalah
- Pemrosesan otomatis: Ekstraksi teks secara massal, penggabungan dokumen, penambahan watermark, dan operasi lainnya, pemahaman struktur diperlukan untuk melakukan operasi dengan tepat
- Audit keamanan: Memahami konten apa yang dapat disematkan dalam PDF (JavaScript, lampiran, formulir, dll.) membantu dalam analisis keamanan
- Belajar desain format file: Desain "grafik objek + akses acak" PDF adalah contoh klasik yang layak dipelajari
Persiapan
Artikel ini akan terlebih dahulu menulis hello-broken.pdf yang "struktur tidak lengkap tetapi logis benar", kemudian menggunakan pdftk untuk secara otomatis melengkapi struktur kunci dan menghasilkan hello.pdf.
- Alat yang Diperlukan: pdftk (alat baris perintah gratis, mendukung Windows/macOS/Linux)
- File Output:
hello-broken.pdf(tulis tangan),hello.pdf(setelah diperbaiki dapat dibuka)
Konsep Inti: Tiga Lapisan Struktur PDF
Memahami PDF yang paling penting adalah membangun model mental tiga lapisan:

1. Lapisan Objek (Konten Dokumen)
Dokumen PDF terdiri dari banyak objek, yang saling terhubung dengan referensi tidak langsung (seperti 2 0 R) membentuk sebuah grafik. Jenis objek yang umum:
| Tipe | Contoh | Keterangan |
|---|---|---|
| Nama | /Page | Nama yang diawali dengan / |
| Bilangan bulat/pecahan | 50, 36.0 | Nilai numerik |
| String | (Hello, World!) | Dikelilingi oleh tanda kurung |
| Array | [0 0 612 792] | Kumpulan terurut |
| Dictionary | << /Type /Page >> | Kumpulan pasangan kunci-nilai |
| Referensi tidak langsung | 2 0 R | Merujuk objek 2 (nomor generasi 0) |
| Aliran | stream...endstream | Data biner (seperti instruksi menggambar, gambar) |
2. Lapisan Konten (Konten Halaman)
Seri instruksi yang benar-benar "menggambar teks/grafik di halaman", biasanya ditulis dalam stream ... endstream. Formatnya adalah: operand di depan, operator di belakang.
/F0 36 Tf ← Operand: /F0, 36 Operator: Tf (mengatur font)
(Hello, World!) Tj ← Operand: String Operator: Tj (menggambar teks)
3. Lapisan Struktur File (Struktur File)
Memungkinkan pembaca untuk mengakses acak objek mana pun dengan cepat, tanpa harus membaca dari awal hingga akhir:
| Elemen | Fungsi |
|---|---|
%PDF-1.x | Header file, menandakan versi PDF |
xref | Tabel referensi silang: nomor objek → offset byte |
trailer | Dictionary akhir: menunjuk objek akar /Root |
startxref | Menunjukkan posisi awal tabel xref |
%%EOF | Penanda akhir file |
Objek Apa Saja yang Diperlukan untuk PDF Minimal?
Sebuah PDF "minimal tetapi dapat menampilkan teks", hubungan referensi antar objek adalah sebagai berikut:

Daftar Objek Minimal:
| Objek | Fungsi | Bidang Kunci |
|---|---|---|
| Katalog | Objek akar, pintu masuk dokumen | /Type /Catalog, /Pages |
| Halaman | Pohon halaman | /Type /Pages, /Kids, /Count |
| Halaman | Halaman tunggal | /Type /Page, /MediaBox, /Resources, /Contents, /Parent |
| Sumber Daya | Kontainer sumber daya | /Font (kamus font) |
| Font | Definisi font | /Type /Font, /BaseFont, /Subtype |
| Konten | Aliran konten | Aliran instruksi menggambar |
Praktik: Menulis hello-broken.pdf
Buat file hello-broken.pdf, dan tempelkan konten berikut secara lengkap:
%PDF-1.0
1 0 obj
<< /Type /Pages
/Count 1
/Kids [2 0 R]
>>
endobj
2 0 obj
<< /Type /Page
/MediaBox [0 0 612 792]
/Resources 3 0 R
/Parent 1 0 R
/Contents [4 0 R]
>>
endobj
3 0 obj
<< /Font
<< /F0
<< /Type /Font
/BaseFont /Times-Italic
/Subtype /Type1 >>
>>
>>
endobj
4 0 obj
<< >>
stream
1. 0. 0. 1. 50. 700. cm
BT
/F0 36. Tf
(Hello, World!) Tj
ET
endstream
endobj
5 0 obj
<< /Type /Catalog
/Pages 1 0 R
>>
endobj
xref
0 6
trailer
<< /Size 6
/Root 5 0 R
>>
startxref
0
%%EOF
Mengapa File Ini "Rusak"?
Kami sengaja menghilangkan atau mengisi salah informasi berikut:
| Item yang Hilang/Salah | Keterangan |
|---|---|
Offset xref | Tidak mengisi offset byte nyata untuk setiap objek |
startxref | Diisi 0, bukan posisi nyata dari xref |
/Length | Aliran konten tidak menyatakan panjang |
| Penanda biner | Kurang baris penanda biner di header |
Semua ini adalah informasi kunci yang dibutuhkan pembaca, dan kekurangan dapat menyebabkan file tidak dapat dibuka atau hanya dapat dibuka dengan toleransi kesalahan.
Penjelasan Detail Instruksi Aliran Konten Kunci
Aliran konten berada di antara stream ... endstream objek 4 0 obj, dijelaskan baris per baris:
1. 0. 0. 1. 50. 700. cm ← Mengatur matriks transformasi (perhatikan 1. mewakili angka pecahan 1.0)
BT ← Memulai objek teks
/F0 36. Tf ← Memilih font F0, ukuran 36pt
(Hello, World!) Tj ← Menggambar string
ET ← Mengakhiri objek teks
Operator Matriks Transformasi cm
1 0 0 1 50 700 cm adalah matriks transformasi 6 elemen [a b c d e f], yang sesuai dengan:
| a b 0 | | 1 0 0 |
| c d 0 | = | 0 1 0 |
| e f 1 | | 50 700 1 |
Ketika a=1, b=0, c=0, d=1, ini adalah matriks translasi murni, yang memindahkan titik asal koordinat (yaitu titik (0,0) untuk operasi menggambar berikutnya) ke (50, 700). Jika tidak dipindahkan, titik asal default berada di sudut kiri bawah halaman.
Operator Teks
| Operator | Arti | Contoh |
|---|---|---|
BT | Mulai Teks, memulai objek teks | BT |
ET | Akhiri Teks, mengakhiri objek teks | ET |
Tf | Mengatur font dan ukuran | /F0 36 Tf |
Tj | Menggambar string | (Hello!) Tj |
Menggunakan pdftk untuk Memperbaiki Menjadi PDF yang Dapat Dibuka
Jalankan perintah berikut di direktori tempat hello-broken.pdf berada:
pdftk hello-broken.pdf output hello.pdf
Buka hello.pdf dengan pembaca PDF mana pun, Anda seharusnya dapat melihat halaman menampilkan "Hello, World!" (font Times-Italic, 36pt, terletak di sudut kiri atas halaman).
Apa yang Dilakukan pdftk untuk Melengkapinya?
| Item yang Dilengkapi | Keterangan |
|---|---|
| Baris penanda biner | Menambahkan satu baris karakter tidak dapat dicetak setelah %PDF-1.0, memastikan dikenali sebagai file biner |
/Length | Menghitung dan menambahkan panjang byte untuk aliran konten |
Tabel xref | Menghitung offset byte untuk setiap objek dan mengisinya |
startxref | Mengisi posisi awal tabel xref yang sebenarnya |
Mengapa Membutuhkan xref / trailer / startxref?
Tujuan Utama: Akses Acak
Bayangkan sebuah PDF 500 halaman, jika tidak ada xref, pembaca harus mem-parsing dari awal hingga halaman 449 untuk menampilkan halaman 450—ini terlalu lambat.
Dengan xref, pembaca dapat:
- Membaca
startxref→ Menemukan posisi xref - Membaca
trailer→ Menemukan objek akar/Root - Dari objek akar, melacak → Langsung melompat ke objek halaman 450
- Melalui xref, memeriksa offset byte objek tersebut → Langsung mencari dan membacanya
Kompleksitas waktu dari O(n) menjadi O(1).
Latihan Artikel Ini
Disarankan Anda benar-benar mengubah hello-broken.pdf, lalu memperbaikinya kembali dengan pdftk, dan amati hasilnya:
| Latihan | Konten yang Diubah | Titik Pengamatan |
|---|---|---|
| A | Mengubah (Hello, World!) menjadi kalimat pendek bahasa Inggris lainnya | Perubahan teks |
| B | Mengubah 36 menjadi 12 atau 72 | Perubahan ukuran font |
| C | Mengubah 50 700 menjadi 50 100 | Posisi turun (sistem koordinat PDF memiliki titik asal di kiri bawah) |
| D | Mengubah /Times-Italic menjadi /Helvetica atau /Courier | Perubahan font |
| E | Mengubah /MediaBox [0 0 612 792] menjadi [0 0 595 842] | Kertas berubah dari US Letter menjadi A4 |
Tips: Titik asal sistem koordinat PDF berada di sudut kiri bawah halaman, sumbu Y mengarah ke atas.
(50, 700)menunjukkan jarak 50pt dari kiri, dan 700pt dari bawah.
Pertanyaan Umum
Q: Mengapa menggunakan font bawaan Type1 dan bukan TrueType?
A: 14 font standar Type1 (Times, Helvetica, Courier, dll.) adalah font yang harus ada di dalam pembaca PDF, tidak perlu menyematkan file font, yang paling sederhana. Dalam skenario nyata, biasanya perlu menyematkan font untuk memastikan konsistensi lintas platform.
Q: Apa arti angka-angka dalam /MediaBox [0 0 612 792]?
A: Satuan adalah point (1 point = 1/72 inci). 612 × 792 point = 8.5 × 11 inci = kertas US Letter. A4 adalah 595 × 842 point.
Q: Apa itu nomor generasi (seperti 0 dalam 2 0 R)?
A: Digunakan untuk pembaruan inkremental. Ketika objek dimodifikasi, nomor generasi bertambah 1. Dalam PDF baru, semua objek biasanya memiliki nomor generasi 0.
Preview Artikel Selanjutnya
Di Bagian 02, kita akan melanjutkan dengan cara "menulis aliran konten" dan menambahkan operasi jalur grafik yang paling dasar:
m(moveto),l(lineto): mendefinisikan jalurS(stroke): menggambar garis tepire(rectangle),f(fill): menggambar persegi panjang dan mengisinya
Agar Anda dapat menggambar di halaman yang sama: teks judul + satu garis pemisah horizontal + satu kotak persegi panjang, dari "bisa menulis" menjadi "bisa menggambar".
