Sebuah tim pemrosesan klaim memiliki tiga puluh tahun file kertas yang melewati pemindai sheet-fed. Pemindai mengeluarkan satu JPEG per halaman ke dalam folder, bernama 0001.jpg, 0002.jpg, dan seterusnya. Yang sebenarnya dibutuhkan arsip adalah satu PDF per berkas kasus, dengan halaman dalam urutan, sehingga seorang peninjau bisa membuka satu dokumen alih-alih mengklik melalui seratus gambar mini. Langkah terakhir itu, mengubah tumpukan scan bernomor menjadi satu PDF terurut, adalah pekerjaan di sini
PDFium Component menanganinya secara langsung. Di luar rendering dan ekstraksi teks, komponen bisa membangun PDF dari nol: membuat dokumen kosong, menambahkan halaman kosong berukuran sesuka Anda, menjatuhkan gambar ke halaman itu dalam koordinat user-space, lalu menyimpan. Seluruh pipeline hidup pada komponen TPdf, jadi pengonversi batch adalah loop atas nama file ditambah segelintir panggilan
Bentuk konversi
Tiga hal harus terjadi untuk setiap scan. Anda memutuskan ukuran halaman, menempatkan gambar di dalam halaman menyisakan margin, dan maju ke halaman berikutnya. PDFium Component memberi Anda satu metode untuk masing-masing: AddPage membuat halaman kosong pada ukuran tertentu, AddImage (atau AddPicture jika Anda sudah memegang TPicture) menggambar bitmap ke halaman saat ini, dan PageNumber memberi tahu komponen halaman mana yang dituju panggilan gambar berikutnya
Satu detail yang menjebak orang adalah sistem koordinat. PDF user space menempatkan origin di sudut kiri-bawah halaman, dengan Y meningkat ke atas, kebalikan dari koordinat layar yang dijangkau pengembang Delphi secara refleks. X, Y yang Anda berikan ke AddImage adalah sudut kiri-bawah persegi panjang gambar, dan Width, Height adalah ukuran penempatan dalam poin, bukan ukuran piksel file sumber. Dapatkan itu terbalik dan scan Anda mendarat di luar halaman atau terbalik relatif terhadap di mana Anda mengharapkannya
Membuat dokumen dan satu halaman per scan
Mulai dengan dokumen kosong. CreateDocument mengalokasikan PDF segar dan meninggalkan komponen aktif, jadi tidak ada langkah buka terpisah. Dari sana Anda berjalan melalui daftar file yang dipindai, dan untuk setiap satu Anda menambahkan halaman, menjadikannya saat ini, dan menempatkan gambar. Dimensi halaman di sini adalah A4 dalam poin (595 × 842 potret), ukuran lembar standar untuk korespondensi yang diarsipkan
procedure TArchiveForm.ScansToPdf(const Files: TStrings; const OutputPath: string);
const
PageW = 595.0; // lebar A4 dalam poin
PageH = 842.0; // tinggi A4 dalam poin
Margin = 36.0; // batas setengah-inci di sekitar setiap scan
var
I: Integer;
Pdf: TPdf;
begin
Pdf := TPdf.Create(nil);
try
Pdf.CreateDocument; // baru, kosong, sudah aktif
for I := 0 to Files.Count - 1 do
begin
Pdf.AddPage(I + 1, PageW, PageH); // indeks halaman berbasis 1
Pdf.PageNumber := I + 1; // jadikan halaman baru sebagai halaman saat ini
PlaceScan(Pdf, Files[I], PageW, PageH, Margin);
end;
Pdf.SaveAs(OutputPath);
finally
Pdf.Free;
end;
end;
Setiap iterasi membuat halaman dan segera menyetel PageNumber ke sana. Baris kedua itu penting: AddPage menyisipkan halaman tetapi metode gambar bertindak pada halaman mana pun yang saat ini, jadi menyetel PageNumber adalah yang mengarahkan AddImage ke halaman yang baru Anda buat. Lewati dan gambar Anda menumpuk ke halaman mana pun yang kebetulan dimuat sebelumnya
Satu asumsi bersembunyi dalam loop itu: urutan Files. Pemindai menamai halaman 0001.jpg sampai 0100.jpg, tetapi enumerasi direktori tidak selalu mengembalikannya terurut, dan saat Anda menekan page9.jpg di sebelah page10.jpg pengurutan string polos menempatkan halaman 10 sebelum halaman 9. Urutkan daftar secara eksplisit sebelum loop, dan lebih suka nama zero-padded saat pemindaian agar urutan leksikal cocok dengan urutan halaman. Urutan halaman adalah satu hal yang segera diperhatikan peninjau, dan itu kesalahan termurah untuk dicegah
Menempatkan scan dan menjaga rasio aspeknya
Scan jarang berbentuk sama dengan halaman. Jika Anda meregangkannya untuk mengisi lembar Anda mendistorsi teks; jika Anda menempatkannya pada ukuran piksel penuh meluap. Perbaikannya adalah menskalakan dengan rasio yang lebih kecil dari dua rasio, fit-lebar atau fit-tinggi, dan memusatkan apa yang tersisa. Karena origin duduk di kiri-bawah, pemusatan berarti membagi ruang sisa secara merata dan menambahkannya ke X dan Y
procedure TArchiveForm.PlaceScan(Pdf: TPdf; const FileName: string;
PageW, PageH, Margin: Double);
var
Pic: TPicture;
AvailW, AvailH, Scale, DrawW, DrawH, X, Y: Double;
begin
Pic := TPicture.Create;
try
Pic.LoadFromFile(FileName); // BMP, JPG, PNG, dll. melalui unit grafis VCL
AvailW := PageW - 2 * Margin;
AvailH := PageH - 2 * Margin;
// Muat di dalam margin tanpa mendistorsi scan.
Scale := Min(AvailW / Pic.Width, AvailH / Pic.Height);
DrawW := Pic.Width * Scale;
DrawH := Pic.Height * Scale;
// Pusatkan: sisa ruang dibagi merata. Y diukur dari bawah halaman.
X := (PageW - DrawW) / 2;
Y := (PageH - DrawH) / 2;
Pdf.AddImage(FileName, X, Y, DrawW, DrawH);
finally
Pic.Free;
end;
end;
Ini memuat file sekali untuk membaca dimensi pikselnya, menghitung satu skala seragam, dan meneruskan persegi panjang penempatan ke AddImage. AddImage menerima jalur file secara langsung dan merutekannya melalui pipeline gambar yang sama seperti AddPicture, jadi format apa pun yang dikenali unit grafis VCL bekerja tanpa penanganan khusus. Jika Anda sudah memiliki gambar terdekode dalam TPicture dari panel pratinjau, panggil AddPicture(Pic, X, Y, DrawW, DrawH) dengan persegi panjang yang sama dan lewati pembacaan file kedua
Melewati decode untuk scan JPEG
Pemindai hampir selalu memancarkan JPEG. Memuat JPEG ke TPicture mendekodekannya ke bitmap, lalu PDFium mengenkodenya kembali saat simpan, dua perjalanan bolak-balik lossy yang tidak Anda butuhkan. AddJpegImage menanam byte terkompresi asli langsung ke halaman dari stream, yang lebih cepat dan lebih bersih secara visual untuk batch volume tinggi
var
Stream: TFileStream;
begin
// ... setelah AddPage + PageNumber untuk halaman saat ini ...
Stream := TFileStream.Create(FileName, fmOpenRead);
try
// Menanam byte JPEG apa adanya; tanpa siklus decode/re-encode.
Pdf.AddJpegImage(Stream, X, Y, DrawW, DrawH);
finally
Stream.Free;
end;
end;
Anda tetap menghitung X, Y, DrawW, dan DrawH dengan cara yang sama, karena Anda membutuhkan dimensi piksel untuk menskalakan. Baca itu dari file atau parse header cepat, lalu serahkan stream mentah ke AddJpegImage. Untuk scan PNG atau TIFF jalur AddImage adalah yang benar; cadangkan pintasan JPEG untuk format yang benar-benar berlaku
Melabeli setiap halaman
Scan yang diarsipkan lebih mudah diaudit ketika setiap halaman membawa nama file sumbernya. AddText menggambar string pada koordinat user-space, jadi keterangan duduk tepat di bawah gambar. Ingatlah sumbu Y yang terbalik: untuk meletakkan label di bawah scan, Anda mengurangi dari tepi bawah gambar alih-alih menambahkannya
// Keterangan di bawah scan: Y menurun menuju bawah halaman.
Pdf.AddText('File: ' + ExtractFileName(FileName), 'Helvetica', 9,
X, Y - 14, clGray);
Satu poin terakhir tentang penyimpanan. SaveAs adalah fungsi yang mengembalikan Boolean, jadi dalam kode produksi periksa hasilnya alih-alih mengasumsikan penulisan berhasil; disk penuh atau jalur keluaran terkunci gagal diam-diam jika tidak. Setelah loop selesai dan file ditulis, Anda memiliki persis yang dibutuhkan arsip: satu PDF terurut per berkas kasus, halaman diskalakan agar pas, siap dibaca di penampil mana pun
Bangunan pembangun yang sama mencakup pekerjaan terkait. Tukar aturan penentuan ukuran per-halaman dan Anda mendapatkan buku foto dengan satu gambar per lembar; pertahankan loop tetapi baca dari sumber TIFF multi-halaman dan Anda memiliki pengonversi arsip-faks. Jika Anda menginginkan gambaran yang lebih luas tentang membangun PDF secara terprogram, lihat membuat dokumen PDF dari nol dengan PDFium Component; untuk merender hasil kembali ke layar nanti, lihat mengonversi halaman PDF ke gambar JPEG dengan PDFium Component
PDFium Component dari loslab.com membundel API pembuatan-dokumen, rendering, dan teks yang digunakan di sepanjang seri ini