HotPDF, üç imge küçültme çekirdeğini ImageDownsampleKernel özelliği üzerinden, ayrı bir Floyd-Steinberg geçişini ise RenderOutputDither üzerinden açar. İlki, boyut bütçesine oturmak için fotoğrafları küçülttükten sonraki görünümlerini kontrol eder; ikincisi, bir sayfa siyah beyaza indirildikten sonraki görünümlerini. İkisi de varsayılan olarak kapalıdır ve her ikisi de aynı nedenle opt-in'dir: gerçek zaman maliyetleri vardır
İnsanları buraya getiren baskı tanıdıktır. 60 MB'lık taranmış bir sözleşme, 10 MB üzerindeki her şeyi reddeden bir e-posta ağ geçidinden çıkmalıdır ya da bir hesap özeti kümesinin, her gri pikseli ya kağıt ya da toner olarak render eden faks tarzı bir monokrom cihaza düşmesi gerekir. İki sorun da yeniden örnekleme sorunudur ve ikisinin de kötü görünen hızlı bir cevabı, doğru görünen yavaş bir cevabı vardır
Üç çekirdeğin gerçekte ayrıştığı nokta
THPDFResampleKernel üç değer taşır ve bunlar hız-kalite eğrisinde gerçekten farklı noktalarda durur. rkHalftone, HALFTONE modlu tarihî GDI StretchBlt yoluna devreder; adına rağmen bu bilinear sınıfı bir filtredir: hızlıdır, çizgi sanatı ve ekran görüntüleri için yeterlidir ve küçültülmüş fotoğraflarda anında tanıdığınız pütürlü kenarlara yatkındır. rkBicubic ayrılabilir bir Catmull-Rom çekirdeği, rkLanczos3 ise üç loblu desteği olan ayrılabilir bir pencere sinc çalıştırır
Her iki ayrılabilir çekirdek de saf Pascal'da, önce yatay sonra dikey olmak üzere iki geçiş halinde, hedef piksel başına 6-12 tap ile çalışır. Bu, GDI yolundan kabaca bir mertebeye kadar yavaştır; rkHalftone'un varsayılan kalmasının nedeni de tam olarak budur. Binlerce sayfalık bir gece toplu işinde fark bir zamanlama kararıdır, tercih değil. Bir kullanıcının beklediği tekil bir belgede ise Lanczos3 neredeyse bedavadır ve gözle görülür biçimde daha iyidir
İki uygulama özelliği bilmeye değer; çünkü çıktının neyi yapıp yapamayacağını belirlerler. Kenarlar, sarmalama ya da sönme yerine kenar tekrarıyla kırpılır ve ağırlıklar hedef piksel başına normalize edilir. Bu ikisi birlikte, sonucun asla siyahın altına ya da beyazın üstüne çınlamadığı anlamına gelir; sert bir kenarın çevresindeki klasik Lanczos overshoot halo'su, kodlanan imgede kırpılmış artifact'ler olarak görünmez
var
Pdf: THotPDF;
Info: THPDFLoadedResourceOptimizationInfo;
Changed: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('scanned-contract.pdf');
Pdf.ImageDownsampleKernel := rkLanczos3; // çağrıdan önce ayarlanır
Changed := Pdf.DownsampleLoadedImages(150, 82, 4096, Info);
if Changed > 0 then
begin
Writeln('resampled images: ', Info.DownsampledImageCount);
Writeln('kept calibrated : ', Info.PreservedCalibratedImageCount);
Pdf.SaveToFile('scanned-contract-150dpi.pdf');
end;
finally
Pdf.Free;
end;
end;
Yukarıdaki 4096 değerindeki MinimumSavingsBytes argümanı, işlemin dürüst kalmasını sağlayan guard'dır. Halihazırda verimli sıkıştırılmış bir imgeyi yeniden kodlamak, orijinalden daha büyük bir akış üretebilir ve her imgeyi körlemesine değiştiren bir küçültücü, küçültmesi istenen dosyayı arada büyütür. Eşik şunu söyler: değişikliği en az bu kadar bayt tasarruf sağladığında uygula. PreservedCalibratedImageCount ise öteki muhafazakar kararı bildirir: yeniden örnekleme tehlikeye atacağı için kalibre renk alanı taşıyan imgeler dokunulmadan bırakılır
Yanlış bir polinom katsayısı neden bu kadar zor fark edilir?
Çünkü bozuk bir interpolasyon çekirdeği çökmez ya da istisna fırlatmaz; kimseye atfedilemeyen bir şekilde hafif yanlış görünen bir imge üretir. Catmull-Rom çekirdeği parça parça kübiktir ve iç içe Horner biçimindeki dış dalı ((-0.5t + 2.5)t - 4)t + 2'dir. O orta katsayıyı -4 yerine -5 yazın; işlev yine hesaplanır, hâlâ makul aralıkta sayılar döndürür ve hâlâ bir imge üretir
Hasar, 0 olması gereken W(1) değerinin -1 çıkması olarak görünür. Negatif ağırlıklar birikir, toplam sıfırda kırılır ve gözle görünen belirti, sol ucu simsiyah olan bir gradyan ile ara tonlarını kaybeden bir basamak kenarıdır. Hatada polinoma işaret eden hiçbir şey yoktur. Saniyeler içinde yakalayan kontrol aritmetiktir, görsel değil: enterpole eden bir çekirdek W(0) = 1 ile W(±1) = W(±2) = 0 koşullarını sağlamak zorundadır ve o üç noktayı ıskalayan her çekirdekte katsayı hatası vardır, nokta. Bir unit test'te o üç değere doğrulama kurun; yazım hatası sınıfındaki kusurların tamamı kaybolur
Floyd-Steinberg dithering ve işlem hattındaki yeri
Dither geçişi, yeniden örneklemeden farklı bir sorundur ve işlem hattında başka bir noktada durur. RenderOutputDither, Floyd-Steinberg hata difüzyonunu sayfa kompozisyonunun ardından uygular; bu, monokrom bir baskı önizlemesi ya da faks tarzı bir dışa aktarım için anlamlı olan tek konumdur: işlem, tamamlanmış bir raster'i piksel başına tek bite indirmekle ilgilidir, girdi yolda imgelerin nasıl ölçeklendiğiyle değil
Algoritmanın kendisi kısadır. Luminance yüzde 50'de eşiklenir ve nicemleme hatası, klasik 7/16, 3/16, 5/16 ve 1/16 ağırlıklarıyla dört komşuya yayılır: sağa, sol alta, alta ve sağ alta. Çıktı pikseli her kanalda 0 ya da 255'tir. Naif alternatifin verdiği şey, difüzyonsuz sert bir eşik, fotoğrafı bir siluete çevirir ve içeriği taşıyan her ara tonu kaybeder
// Monokrom bir önizleme cihazı için render zamanı dithering
Pdf.RenderOutputDither := True;
// Ya da zaten sahibi olduğunuz bir bit eşleme aynı geçişi uygulayın.
// Bit eşlem pf24bit olmalı; işlev tahmin yürütmek yerine False döndürür
if not HPDFFloydSteinbergDitherBitmap(Preview) then
raise Exception.Create('dither expects a 24-bit bitmap');
// Belge işlem hattı dışında yeniden örneklerken doğrudan çekirdek erişimi
Small := HPDFResizeBitmapKernel(Large, 640, 480, rkLanczos3);
try
Small.SaveToFile('thumb.bmp');
finally
Small.Free;
end;
Hata difüzyonunda herkesi bir kez ısıran tek bir uygulama ayrıntısı vardır. Satırdan satıra hata tamponu biriktirmek zorundadır. Bir sonraki satırdaki her piksel, güncel satırdaki üç farklı pikselden katkı alır (3/16, 5/16 ve 1/16 tap'leri) ve kod ekleme yerine atama yaparsa her yazım önceki katkıyı atar, yalnızca son tap hayatta kalır. İmge hâlâ dithering'li görünür; fark edilmesini zorlaştıran budur ama doku yanlıştır ve tonal üretim sürüklenir. Yakalayan test niceldir: düzgün bir orta gri alanı dithering'e sokun ve iç kapsamanın yüzde 40 ile 60 arasında çıkmasını şart koşun
Boyut düşürme işlem hattı hangi kombinasyonu kullanmalı?
Çekirdeği imgelerin gerçekte ne olduğuna göre seçin ve dithering'i bir sıkıştırma konusu değil cihaz konusu sayın. Boyut bütçesinden geçmek zorunda olan fotoğrafik taramalar için 150 ya da 200 DPI'daki rkLanczos3, piksel sayısını dört kat ya da daha fazla keserken insanların fark ettiği detayı korur. Ekran görüntüleri, diyagramlar ve çizgi sanatı için rkHalftone gerçekten yeterlidir ve çok daha hızlıdır; o imgelerde korunacak az sayıda tonal gradyan vardır. Her imgeyi inceleyemediğiniz karma bir kümede makul orta yol rkBicubic'tir: bilinear'dan iyi, Lanczos3 tap sayısının kabaca yarısı
Küçültme, birkaç kaldıraçtan biridir ve her zaman en büyüğü değildir. İki seviyeli taramalar genellikle Delphi'de yerli JBIG2 bilevel sıkıştırma makalesinde ele alınan kodlayıcıya çok daha iyi yanıt verir; kazanç orada piksel sayısından değil sembol sözlüklerinden gelir. Karar vermeden önce dosyada gerçekte ne olduğunu bilmek işe yarar; imgeleri ve decode filtrelerini çıkarma tam bunun içindir: imge nesnelerinin ve mevcut sıkıştırmalarının envanteri, yeniden örneklemenin kazanacak bir şeyi olup olmadığını söyler
Sonucu gösteren önizleme yüzeyini kuruyorsanız, bir PDF sayfasını bit eşleme render etme makalesinde belgelenen aynı render yolu, RenderOutputDither'ın devreye girdiği yerdir; böylece dithering'li önizleme ile dithering'li çıktı, birbirinden ayrışan iki uygulama değil tek bir kod yolundan gelir
İki özelliğin ardındaki genel ilke, kalite ayarlarının açık ve geri alınabilir olması gerektiğidir. HotPDF, tarihî davranışı varsayılan olarak tutar; böylece mevcut bir uygulama, çıktısında ya da süresinde sürpriz bir değişiklik olmadan yükselir ve daha iyi görünen, daha yavaş yollar tek bir özellik ataması uzaklıktadır. Her ikisi de, üzerine kuruldukları kaynak optimizasyonu ve render mekanizmasıyla birlikte HotPDF Delphi PDF bileşeni kapsamındadır