PDF dosya boyutunun ekonomisi
Spec: ISO 32000-2, §7.5.7ISO 32000-2 §7.5.7
Bir bakışta
“Bir bakışta” başlıklı bölümİki PDF, ekranda piksel piksel özdeş görünebilir ve diskte on kat farklılaşabilir. Fark, neredeyse hiçbir zaman gördüğünüz içerik değildir; dosyanın altta nasıl monte edildiğidir. Bu sayfa bir boyut-ekonomisi turudur: bir PDF’nin byte’larının gerçekte nereye gittiği ve bir yazarın bir byte bütçesini harcadığı dört kol.
Bu, Akışlar ve filtreler sayfasının bir filtre nasıl çözer konusunu işleyen yanına karşı, dosyalar neden büyük yoldaşıdır. Bu sayfa bütçede kalır.
Bunun önemi nedir
“Bunun önemi nedir” başlıklı bölümDosya boyutu nadiren bir gösteriş metriğidir. Her indirmede bant genişliği, her arşivde depolama ve her önizlemede gecikmedir. 400 KB olması gereken 12 MB’lik bir fatura, ayda bir milyon tane ürettiğinizde kozmetik bir sorun değildir — otuz katlık bir faturadır.
Sinir bozucu kısım, şişkinliğin genellikle görünmez olmasıdır. Belge doğru oluşturulur, sorunsuz açılır, sorunsuz yazdırılır. Aynı eserin boyutun bir kesri olabileceğini size hiçbir şey söylemez; çünkü boşa harcanan byte’lar görsel değil, yapısaldır. Onları bulmak için sayfaya değil, bütçeye bakmanız gerekir.
Kısa açıklama
“Kısa açıklama” başlıklı bölümBir PDF’yi, dört kalem üzerinde harcadığınız bir bütçe olarak düşünün.
- Nesne başına ek yük. Her dolaylı nesne bir
N G obj/endobjzarfı taşır ve bir cross-reference girdisiyle izlenir. Sayfa-ağırlıklı bir belgede binlerce küçük nesne vardır ve zarflar birikir. Nesne akışları, bir grup nesnenin tümü için o zarfı düşürür; paketlenmiş her nesne kendi cross-reference girdisini hâlâ tutar, ama kompakt bir tip-2 girdisi olarak. - Görüntü byte’ları. Fotoğraf ya da taramaların olduğu herhangi bir belge için görüntüler baskındır ve en büyük tek kol filtre seçimidir — kayıpsız bir codec’e karşı kayıplı bir görüntü codec’i, megabyte ile kilobyte arasındaki farktır.
- Font byte’ları. Tam gömülü bir font, hiç kullanmadığınız yüzlerce kilobyte gliftir. Alt kümeleme, yalnızca belgenin gerçekten çizdiği glifleri tutar.
- Dizin. Bir okuyucunun her nesneyi bulmasını sağlayan cross-reference table, düz metin yerine kendisi bir sıkıştırılmış akış olabilir.
Dördünü de doğru yapın ve dosya küçük olur. Birini kaçırın ve o, iyi yaptığınız her şeye baskın gelir.
NextPDF’nin yaklaşımı
“NextPDF’nin yaklaşımı” başlıklı bölümNextPDF’nin yazıcısı tek geçişli, akış tabanlı bir serileştiricidir: her nesnenin byte’larını üretildikçe ekler ve her biri için klasik bir kullanımda cross-reference girdisi kaydeder. O varsayılan hızlı, öngörülebilir ve byte-kararlı bir dosya üretir — ama olası en küçük düzen değildir ve NextPDF bunu dürüstçe söyler.
Kol 1 — nesne akışları (ObjStm)
“Kol 1 — nesne akışları (ObjStm)” başlıklı bölümBir PDF, dolaylı nesnelerden oluşan bir grafiktir. Çoğu küçük sözlüklerdir: sayfa düğümleri,
açıklama sözlükleri, yapı-ağacı öğeleri, taslak girdileri. Her biri sabit bir vergi öder —
obj / endobj anahtar sözcükleri, nesne ve nesil numaraları ve onu konumlandıran bir
cross-reference girdisi. Binlerce küçük nesneli bir belgede, o vergi dosyanın anlamlı bir
dilimidir.
Bir nesne akışı, o küçük akış-dışı nesnelerin çoğunu tek bir akışta toplar ve onları
birlikte sıkıştırır (Spec: ISO 32000-2, §7.5.7ISO 32000-2 §7.5.7). obj / endobj zarfı,
tüm grup için düşürülür; içerideki değerler, nesne başına anahtar sözcük olmadan, art arda
saklanır ve sonra tek bir blok olarak deflate edilir — bu da daha iyi sıkıştırır; çünkü
yineleme-eleyen sıkıştırıcı artık o benzer sözlüklerin hepsini bir kerede görür. Cross-reference
girdisi yok olmaz — paketlenmiş her nesnenin hâlâ birine ihtiyacı vardır — ama cross-reference
akışında kompakt bir ikili tip-2 girdisine küçülür (bununla ilgili daha fazlası Kol 2’de).
NextPDF’de bu, ObjectStreamPacker tarafından sunulur; bitmiş bir cross-reference-akışlı PDF’yi
alan ve uygun nesneleri tek bir /Type /ObjStm’e yeniden yazan, bağımsız bir sonradan
işleyicidir. İzlediği kurallar doğrudan standarttan gelir: uygun bir nesne, doğrudan
adreslenebilir kalması gereken özel nesneler dışlandıktan sonra, nesil-sıfır, akış-dışı bir
nesnedir. §7.5.7, bir akış nesnesini bir nesne akışının içinde saklamayı yasaklar; bu yüzden
akış nesneleri — içerik, fontlar, görüntüler — kendi girdilerini tutar; ve ObjectStreamPacker
ek olarak belgenin kendi cross-reference akış nesnesini (o yeniden yazılır) ve /Encrypt
sözlüğünü reddeder; ikisi de doğrudan adreslenebilir kalmalıdır. Nesil-sıfır ve akış-dışı olan
diğer her şey paketlenir.
| Edition | Availability |
|---|---|
| Core | Full support in the open-source core via ObjectStreamPacker. It is opt-in: the single-pass writer’s default emits classic in-use entries, so output stays byte-identical unless you enable packing. The packer is deterministic, with its own reproducible golden baseline. |
| Pro | Not in this edition |
| Enterprise | Not in this edition |
İsteğe bağlı olmak, bir kısıtlamanın saklanması değil, bilinçli bir duruştur. Varsayılan çıktı byte-kararlıdır ve mevcut golden temellerle eşleşir; paketlemeyi açmak, farklı, daha küçük, eşit derecede deterministik bir düzene geçmektir. Ödünleşmeyi siz seçersiniz ve motor onu asla arkanızdan yapmaz.
Kol 2 — dizin de bir akış olabilir
“Kol 2 — dizin de bir akış olabilir” başlıklı bölümNesneler bir nesne akışının içinde yaşamaya başladığında, onlara işaret eden dizin biçim
değiştirir. Bir okuyucu, paketlenmiş bir nesneyi bir sıkıştırılmış cross-reference girdisi
aracılığıyla bulur — nesne akışını ve içindeki dizini adlandıran bir tip-2 girdisi
(Spec: ISO 32000-2, §7.5.8.3ISO 32000-2 §7.5.8.3). Tüm cross-reference’ın kendisi bir
/Type /XRef akışı olduğu için, binlerce nesne için olan dizin, düz metin satırları olarak
yazılmak yerine ikili-paketlenir ve deflate edilir. Harita, arazinin yanı sıra küçülür.
ObjectStreamPacker tam olarak bunu yeniden inşa eder: tek nesne akışını yayımlar, sonra
tutulan her nesne için kompakt bir tip-1 girdisi ve paketlenmiş her nesne için bir tip-2
girdisi taşıyan, yeniden yazılmış bir cross-reference akışı yayımlar; mevcut referansların
geçerli kalması için her nesne numarasını korur.
Kol 3 — görüntü filtresi seçimi
“Kol 3 — görüntü filtresi seçimi” başlıklı bölümGerçek görüntülerin olduğu herhangi bir belge için, bu kol diğerlerini cüceleştirir. Byte’lar aynı resimdir; codec, bütçedir. Filtre adları, standart filtre kümesinde yaşar (Spec: ISO 32000-2, §7.4ISO 32000-2 §7.4) ve aralarındaki seçim bir boyut kararıdır:
- FlateDecode kayıpsızdır. Çizgi sanatı, ekran görüntüleri ve düz renkli her şey için kusursuz — ve bir fotoğraf için yıkıcı; orada kayıpsız, özgünün her byte’ı demektir.
- DCTDecode JPEG’dir: kayıplı ve fotoğraflar için geniş bir farkla doğru tercih, çoğu zaman kimsenin fark etmediği bir kalite düşüşü için on katlık bir azalma.
- JPXDecode JPEG 2000’dir: farklı bir kalite/boyut eğrisiyle dalgacık sıkıştırma, ama düzensiz destek ve bazı arşivleme profilleri tarafından izin verilmez.
Tam olarak burası, bir filtre nasıl çözerin önemli olduğu yerdir ve bu, Akışlar ve filtreler makalesinin işidir. Ekonomi noktası daha dardır: kayıpsız saklanan bir fotoğraf, gereksizce devasa bir PDF’nin en yaygın tek nedenidir ve hiçbir nesne-akışı paketleme miktarı, gerçek ağırlığı tek bir JPEG’lenmemiş tarama olan bir dosyayı kurtarmaz.
Kol 4 — font alt kümeleme
“Kol 4 — font alt kümeleme” başlıklı bölümGömülü bir font, bir programdır. Tam olanı birkaç yüz kilobyte olabilir; çünkü yazı tipi tasarımcısının çizdiği her glifi taşır — bu belgede hiç kullanmayacağınız betikler arasında binlerce karakter. Alt kümeleme, yalnızca belgenin gerçekten çizdiği glifleri gömer; o programı kendisinin küçük bir kesrine çevirir. Tek sayfalık bir mektup, CJK-yetenekli bir fontun tümüne ihtiyaç duymaz; dizdiği birkaç düzine glife ihtiyaç duyar. Gliflerin nasıl seçilip yeniden dizinlendiğinin mekanikleri kendi başına bir konudur — bkz. Fontlar: zor kısım.
- Image bytesFor media-heavy files, the largest line item. The filter choice — lossless Flate vs a lossy image codec like DCT (or JPX in a lossy mode) — is the dominant size lever.
- Font bytesA full embedded font is mostly glyphs you never draw. Subsetting keeps only the used glyphs, often shrinking the program by an order of magnitude.
- Per-object overheadThousands of small dictionaries each pay an obj/endobj envelope plus a cross-reference entry. Object streams (ObjStm) drop the envelope for the whole group; each object keeps a compact type-2 cross-reference entry.
- The indexA compressed cross-reference stream with type-2 entries binary-packs and deflates the map of every object, replacing plaintext index rows.
Pratik örnek
“Pratik örnek” başlıklı bölümBurada gösterilecek uydurma bir API yoktur; çünkü en önemli boyut kararları, byte’lar yazıcıya ulaşmadan önce verilir — ve NextPDF’nin açtığı tek yapısal kol, isteğe bağlı tek bir anahtardır. Kavramsal olarak bütçe şöyle okunur:
- Fotoğrafları JPEG olarak besleyin ki
DCTDecodealtına insinler, kayıpsız yeniden kodlanmasın. En büyük kazanç, bir yazıcı bayrağı değil, kaynak veri hakkında bir seçimdir. - Yazıcının gömülü fontları alt kümelemesine izin verin ki yalnızca çizilen glifler gönderilsin.
- Çok sayıda küçük nesnesi olan bir belge için, nesne-akışı paketlemeyi tercih edin; bu, bitmiş
dosyayı
ObjectStreamPackerüzerinden yönlendirir; küçük akış-dışı nesneleri gruplar ve cross-reference akışını yeniden yazar.
Varsayılan yol — klasik kullanımda girdiler, ObjStm yok — doğru temeldir: deterministik, byte-kararlı ve doğrulaması kolay. Paketleme, dosyayı şişiren şeyin görüntü ağırlığı değil, nesne sayısı olduğunda düşünülmüş yükseltmedir.
Yaygın yanlış kanı
“Yaygın yanlış kanı” başlıklı bölümTuzak, bir “PDF’yi sıkıştır” düğmesine uzanmak ve onun her şeyi düzelteceğini beklemektir.
Sıkıştırma tek bir kol değildir; dörttür ve birbirlerinin yerine geçmezler. Nesne-akışı
paketleme bir fotoğrafı küçültemez — o, görüntü filtresinin işidir. Kusursuz bir JPEG, alt
kümelemeyi unuttuğunuz bir fontu telafi edemez. Ve gerçek şişkinlik, kimse onun için
DCTDecode seçmediği için kayıpsız saklanan 10 MB’lik bir tarama ise, bunların hiçbiri
yardımcı olmaz.
İkinci yanlış kanı, daha küçüğün her zaman kesinlikle daha iyi olduğudur. Değildir. Nesne akışları, linearization ile uyumsuzdur — ilk sayfanın erken akması için mutlak nesne yerleşimini sabitleyen fast-web-view düzeni. Ve bazı arşivleme profilleri, hangi görüntü filtrelerine izin verildiğini bile kısıtlar. Boyut bir eksendir. Akış, arşivleme uygunluğu ve yeniden üretilebilirlik ile takas eder ve eğri üzerindeki doğru nokta, belgenin ne için olduğuna bağlıdır.
Sınırlar ve hudutlar
“Sınırlar ve hudutlar” başlıklı bölümDört kol, dosya boyutunun yapısal ekonomisidir. Evrensel bir “küçült” garantisi değildir ve NextPDF, gelişigüzel gelen PDF’ler için bir yeniden-iyileştirici olmaya çalışmaz.
ObjectStreamPacker, doğruluğu asla tehlikeye atmayan, en-iyi-çaba bir iyileştirmedir.
Reddeder — girdiyi değiştirmeden döndürür — şu durumlarda: dosya bir cross-reference-akışlı PDF
olmadığında, şifreliyken, bir dijital imza taşıdığında (nesneleri yeniden yerleştirmek, bir
imzanın koruduğu byte aralıklarını kaydırır), zaten nesne akışları içerdiğinde ya da
paketlenecek uygun bir nesne olmadığında. Tüm belge için tam olarak bir nesne akışı yayımlar;
bir /Extends koleksiyonuna bölmez; bu kapsam dışıdır ve NextPDF’nin ürettiği belge boyutları
için uygundur.
Görüntü ve font kolları, büyük ölçüde girdi hakkında kararlardır. NextPDF’nin yazıcısı,
kayıpsız bir bit eşlemi örtük olarak kayıplı bir görüntü akışına dönüştürmez — bir fotoğrafı
DCTDecode ya da JPXDecode’a yeniden kodlamak, açık bir yukarı yön görüntü-kodlama kararıdır,
serileştiricinin arkanızdan yaptığı bir şey değil — ne de çağıranın tam olarak gömmesini
istediği bir fonttan glifleri geri kazanır. En büyük boyut kazançları, byte serileştiricisinin
yukarısında verilir; motorun işi, ona getirdiğiniz bütçeyi boşa harcamamaktır.
İlgili belgeler
“İlgili belgeler” başlıklı bölüm- Akışlar ve filtreler — bir filtre nasıl çözer yoldaşı; bu sayfa onu bilinçli olarak tamamlar, çoğaltmaz.
- Bir PDF gerçekte nedir — nesne-akışı kolunun azalttığı, nesne başına ek yüke sahip dolaylı-nesne modeli.
- Bir PDF dosyasının anatomisi — sıkıştırılmış bir akışa dönüşen cross-reference yapısı.
- Fontlar: zor kısım — alt kümelemenin, bir belgenin çizdiği glifleri nasıl seçip yeniden dizinlediği.
Sözlük
“Sözlük” başlıklı bölüm- Nesne akışı (ObjStm) — birçok küçük akış-dışı dolaylı nesneyi birlikte sıkıştırılmış
olarak tutan tek bir akış; böylece
obj/endobjzarfı grup için düşürülür. Paketlenmiş her nesne kendi cross-reference girdisini hâlâ tutar, kompakt bir tip-2 girdisi olarak. NextPDF’de isteğe bağlıdır. - Dolaylı nesne (indirect object) — bir PDF’nin grafiğinde numaralı bir nesne; bir
obj/endobjzarfına sarılı ve cross-reference dizini tarafından izlenir. Zarf, nesne başına ek yüktür. - Cross-reference akışı — her nesneyi dizinleyen
/Type /XRefakışı; düz metin satırları olarak yazılmak yerine ikili-paketlenir ve deflate edilir. - Sıkıştırılmış (tip-2) girdi — bir nesne akışının içinde yaşayan bir nesneye işaret eden, akışı ve içindeki dizini adlandıran bir cross-reference girdisi.
- Font alt kümeleme (font subsetting) — tam yazı tipi yerine, bir belgenin gerçekten çizdiği yalnızca glifleri gömmek; gömülü font programını küçültür.
- Kayıpsız ile kayıplı filtre — kayıpsız bir codec (FlateDecode) her byte’ı yeniden üretir; kayıplı bir görüntü codec’i (DCTDecode ya da kayıplı bir kipte JPXDecode), çok daha küçük bir sonuç için algılanamaz ayrıntıyı atar. (JPEG 2000 / JPX, kayıpsız da yapılandırılabilir.) Seçim, medya-ağırlıklı bir dosyada baskın koldur.