Rust programlama diliyle geliştirilen ve Axum çatısını kullanan Convertify adlı ücretsiz bir resim dönüştürücü uygulamasının arkasındaki geliştirici, bu hafta PDF dosyalarını JPG ve PNG formatlarına çevirme özelliğini ekledi. Geliştirme sürecinde karşılaştığı teknik detaylar ve libvips kütüphanesinin sunduğu olanaklar, beklenenden çok daha karmaşık bir hal aldı.
Basit Görünen İlk Yaklaşım: Tek Sayfalı PDF’ler
Convertify’in mevcut resim işleme hattı oldukça basitti: VipsImage::new_from_file(path) komutu ile dosya yükleniyor, işlemler yapılıyor ve image_write_to_file(out_path) ile çıktı alınıyordu. Geliştirici, PDF dosyalarının da benzer şekilde işleneceğini varsaymıştı. İlk denemede, dosya yoluna dpi parametresini ekleyerek libvips’in PDF dosyalarını doğrudan resme çevirebileceğini keşfetti. Örneğin, "dosya.pdf[dpi=300]" şeklindeki bir yol, libvips tarafından kabul edildi ve bir VipsImage nesnesi olarak döndürüldü. Tek sayfalık PDF’ler için bu yaklaşım neredeyse sorunsuz çalıştı.
Çok Sayfalı PDF’ler: Yeni Bir Zorluk Alanı
Ancak işler çok sayfalı PDF’ler söz konusu olduğunda karmaşıklaşmaya başladı. Her bir sayfanın ayrı ayrı render edilmesi ve ya tek tek dosyalar olarak kaydedilmesi ya da bir ZIP dosyasına paketlenmesi gerekiyordu. Geliştirici, load_pdf adlı bir fonksiyon yazarak dosyayı öncelikle analiz etti ve sayfa sayısını aldı: probe.get_n_pages() komutu ile sayfa sayısı belirlendi.
Daha sonra her bir sayfa için ayrı bir render işlemi gerçekleştirildi. Dosya yolu, dpi ve sayfa numarası parametreleriyle birlikte VipsImage::new_from_file fonksiyonuna gönderildi: "dosya.pdf[dpi=300,page=0]" gibi bir yol kullanıldı. Sayfa numarası sıfırdan başlayan bir indeksleme sistemiyle tanımlandı. Her sayfa ayrı bir dosyaya kaydedildikten sonra, bu dosyalar bir ZIP arşivine eklendi.
PDF Render Motoru: poppler ve pdfium Arasındaki Farklar
libvips’in kendi PDF render motoru bulunmuyor; bunun yerine derleme sırasında hangi kütüphaneye bağlı olarak çalıştığına bağlı olarak ya poppler ya da pdfium kütüphanelerine yönlendiriliyor. Örneğin, çoğu Linux dağıtımında libvips-dev paketiyle birlikte poppler yükleniyor. Temiz bir Ubuntu 24 EC2 örneğinde geliştirici, bu kurulumun sorunsuz çalıştığını gözlemledi.
Ancak bazı PDF dosyalarında, Acrobat’ta doğru şekilde render edilen metinlerin uygulama çıktısında farklı konumlarda göründüğünü fark etti. Yapılan araştırmalar, poppler’in Splash rasterizer’ının ve pdfium’un Skia arka planının karmaşık düzenlemelerde oldukça farklı sonuçlar ürettiğini ortaya koydu. Üretim ortamında çalışan uygulamalarda render kalitesinin önemli olduğu durumlarda, libvips’in hangi PDF yükleyiciye bağlı olarak derlendiğinin kontrol edilmesi gerekiyor. Bu kontrol için vips --version komutu kullanılabilirken, hangi PDF yükleyicilerin mevcut olduğunu görmek için vips -l | grep pdf komutu çalıştırılabilir.
Metin yoğun PDF dosyalarında, Skia’nın analitik kenar kaplama rasterizer’ının Splash’a göre daha temiz kenarlar ürettiği görüldü. Bu nedenle, eğer uygulamanızda yüksek kaliteli render önem taşıyorsa, pdfium’un kullanımını açıkça belirtmek faydalı olabilir.
DPI Sınırlaması: Performans ve Dosya Boyutu Dengesi
Geliştirici, sunucu tarafında kullanıcıların istediği herhangi bir DPI değerini kabul etmek yerine, 72 ile 300 arasında bir sınırlama getirdi. Bu sınırlama şu şekilde uygulandı: kullanıcıdan gelen dpi parametresi önce bir sayıya dönüştürülüyor, ardından bu sayı 72 ile 300 arasında bir değere sıkıştırılıyordu. Eğer parametre geçersizse varsayılan olarak 150 DPI kullanıldı.
Bu sınırlamanın nedeni, 600 DPI’lık bir A4 sayfasının yaklaşık 139 MB’lık ham bir RGBA buffer’ına denk gelmesiydi. libvips, veriyi parçalar halinde işleyerek bellek taşmasını önlese de, işlem süresi oldukça uzuyor ve çıktı dosyası çok büyük oluyordu. 300 DPI ise basılı kalite için ideal bir denge noktasıydı ve bu değerde A4 sayfası yaklaşık 2480×3508 piksel boyutunda olup, JPG olarak yaklaşık 900 KB boyutunda kaydediliyordu.
Temizlik Hatası: Düzenlenmemiş Dosya Kayıtları
PDF dönüştürme özelliğine odaklanan geliştirici, tamamen farklı bir konuda da bir hata fark etti. Log kayıtlarında, ./tmp dizinindeki dosyaların aslında boş olmasına rağmen yüzlerce dosyanın silindiğinin rapor edildiği görüldü. Hatanın kökeni, silinmesi gereken dosya sayısının, aslında silinmeden önceki kayıt sayısına dayanmasıydı.
Çok sayfalı PDF’lerden elde edilen sayfa dosyaları, ZIP oluşturulduktan hemen sonra diskten siliniyordu. Ancak kayıt defterindeki (registry) girişler silinmiyordu. Bu nedenle temizlik fonksiyonu, diskte karşılığı olmayan kayıtlı girişleri sayarak başarılı bir şekilde silindi olarak kaydediyordu. Düzeltilen kodda, yalnızca diskten başarıyla silinen dosyalar sayıldı ve NotFound hatası veren dosyalar için kayıt defterinden ilgili girişler çıkarıldı.
Gelecek Planları: PDF Ön Ucu ve Geliştirme Seçenekleri
PDF ön ucu artık kullanıma sunuldu. Kullanıcılar, 72, 150 ve 300 DPI seçenekleri arasında seçim yapabilirken, çok sayfalı PDF dosyalarını ZIP olarak indirebiliyor. Bu özellikler ve adreslerinde deneyimlenebilir.
Geliştirici, gelecek adımlarda pdfium’un açıkça bir derleme seçeneği olarak sunulup sunulmaması konusunda değerlendirme yapıyor. Bu seçenek, render kalitesini artırabilirken, çoğu kullanıcının yüklediği PDF dosyaları için poppler’in varsayılan davranışı yeterli görünüyor. Şu aşamada, poppler’in çoğu durumda iyi sonuçlar verdiği gözlemleniyor.
Yapay zeka özeti
Learn how Rust and libvips simplify PDF to image conversion, revealing rendering backends, DPI trade-offs, and cleanup pitfalls in a real-world project.