HotPDF vystavuje tri kernele na downscaling obrázkov cez vlastnosť ImageDownsampleKernel a osobitný Floyd-Steinberg prechod cez RenderOutputDither. Ten prvý riadi, ako vyzerajú fotografie potom, čo ich zmenšíte, aby ste sa zmestili do rozpočtu veľkosti, ten druhý riadi, ako vyzerajú potom, čo sa strana zredukuje na čierno-bielo. Ani jeden nie je zapnutý defaultne a oba sú opt-in z toho istého dôvodu: stoja reálny čas
Tlak, ktorý sem ľudí privádza, je známy. Naskenovaná zmluva s 60 MB musí vyjsť cez emailovú bránu, ktorá odmietne všetko nad 10 MB, alebo dávka výpisov musí dopadnúť na monochromatické zariadenie faxového typu, ktoré vykreslí každý sivý pixel buď ako papier, alebo ako toner. Oba problémy sú problémy resamplovania a oba majú rýchlu odpoveď, ktorá vyzerá zle, a pomalú odpoveď, ktorá vyzerá správne
V čom sa tri kernele reálne líšia
THPDFResampleKernel má tri hodnoty a stoja na reálne odlišných miestach krivky rýchlosť a kvalita. rkHalftone deleguje na historickú GDI cestu StretchBlt s režimom HALFTONE, ktorá napriek názvu je filtrovanie triedy bilinear: rýchla, postačujúca pre line art a screenshoty a náchylná na tie drsné hrany, ktoré spoznáte okamžite na zmenšených fotografiách. rkBicubic beží so separovateľným kernelom Catmull-Rom a rkLanczos3 beží so separovateľným okienkovaným sinc s podporou troch lalokov
Oba separovateľné kernele bežia ako dva prechody, najprv vodorovný, potom zvislý, s 6 až 12 tapmi na cieľový pixel v čistom Pascale. To je zhruba o rad pomalšie než GDI cesta a presne preto rkHalftone zostáva defaultom. V nočnej dávke tisícok strán je rozdiel rozhodnutím o plánovaní, nie preferenciou. Pri jedinom dokumente, na ktorý používateľ čaká, je Lanczos3 takmer zadarmo a viditeľne lepší
Dve implementačné vlastnosti stoja za poznanie, lebo určujú, čo výstup dokáže a čo nedokáže. Okraje sa upínajú replikáciou hrany namiesto zavinutia alebo blednutia a váhy sa normalizujú na každý cieľový pixel. Tieto dve veci spolu znamenajú, že výsledok nikdy nezvoní pod čiernou alebo nad bielou, takže klasická Lanczos prestreľovacia aura okolo tvrdej hrany sa neobjaví ako orezané artefakty v zakódovanom obrázku
var
Pdf: THotPDF;
Info: THPDFLoadedResourceOptimizationInfo;
Changed: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('scanned-contract.pdf');
Pdf.ImageDownsampleKernel := rkLanczos3; // nastav pred volaním
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;
Argument MinimumSavingsBytes, vyššie 4096, je ochrana, ktorá drží operáciu poctivú. Znovu zakódovať obrázok, ktorý už bol efektívne komprimovaný, môže vyprodukovať väčší stream než originál a downscaler, ktorý zaslepo nahrádza každý obrázok, občas zväčší súbor, ktorý mal zmenšiť. Táto prahová hodnota hovorí: potvrď náhradu len vtedy, keď ušetrí aspoň toľko bajtov. PreservedCalibratedImageCount hlási druhé konzervatívne rozhodnutie, obrázky ponechané nedotknuté, pretože nesú kalibrovaný farebný priestor, ktorý by resampling skompromitoval
Prečo je zlý polynomický koeficient taký ťažko postrehnuteľný?
Pretože pokazený interpolačný kernel nespadne ani nehodí výnimku, len vyprodukuje obrázok, ktorý vyzerá jemne zle spôsobom, ktorý nikto nepriradí. Kernel Catmull-Rom je po častiach kubický a jeho vonkajšia vetva vo vnorenom Hornerovom tvare je ((-0.5t + 2.5)t - 4)t + 2. Napíšte ten prostredný koeficient ako -5 namiesto -4 a funkcia stále vyhodnocuje, stále vracia čísla v plausible rozsahu a stále produkuje obrázok
Škoda sa ukáže ako W(1) vyhodnocujúce sa na -1, kde musí byť 0. Záporné váhy sa hromadia, suma sa oreže na nulu a viditeľným príznakom je gradient, ktorého ľavý koniec sčernie, a skoková hrana, ktorá stratí svoje medzitóny. Nič v zlyhaní neukazuje na polynóm. Kontrola, ktorá to chytí za sekundy, je aritmetická, nie vizuálna: interpolačný kernel musí spĺňať W(0) = 1 a W(±1) = W(±2) = 0 a každý kernel, ktorý míňa tieto tri body, má chybu v koeficiente, bodka. Tvrďte tieto tri hodnoty v unit teste a celá trieda preklepových defektov zmizne
Dithering Floyd-Steinberg a kde patrí do pipeline
Dither prechod je iný problém než resampling a býva na inom mieste pipeline. RenderOutputDither aplikuje error diffusion Floyd-Steinberg po zložení strany, čo je jediné umiestnenie, ktoré dáva zmysel pre monochromatický tlačový náhľad alebo export faxového typu: operácia je o redukcii hotového rastra na jeden bit na pixel, nie o tom, ako boli jednotlivé obrázky zmenšené na ceste dnu
Algoritmus sám je krátky. Luminancia sa prahuje na 50 percent a kvantizačná chyba sa difunduje štyrom susedom s klasickými váhami 7/16, 3/16, 5/16 a 1/16, doprava, doľava dole, dole a doprava dole. Výstupný pixel je 0 alebo 255 v každom kanáli. Naivná alternatíva vám namiesto toho, tvrdý prah bez difúzie, zmení fotografiu na siluetu a stratí každý poltón, ktorý niesol obsah
// Dithering pri vykresľovaní pre monochromatické náhľadové zariadenie
Pdf.RenderOutputDither := True;
// Alebo aplikujte ten istý prechod na bitmapu, ktorú už máte. Bitmapa
// musí byť pf24bit; funkcia vráti False namiesto hádania
if not HPDFFloydSteinbergDitherBitmap(Preview) then
raise Exception.Create('dither expects a 24-bit bitmap');
// Priamy prístup ku kernelu, keď resamplujete mimo dokumentovej pipeline
Small := HPDFResizeBitmapKernel(Large, 640, 480, rkLanczos3);
try
Small.SaveToFile('thumb.bmp');
finally
Small.Free;
end;
V error diffusion je jeden implementačný detail, ktorý každého raz zahryzne. Buffer chýb medzi riadkami musí akumulovať. Každý pixel v ďalšom riadku dostáva príspevky od troch rôznych pixelov v aktuálnom riadku, tapov 3/16, 5/16 a 1/16, a ak kód priraďuje namiesto sčítania, každý zápis zahodí predchádzajúci príspevok a prežije len posledný tap. Obrázok stále vyzerá ditherovane, čo je to, čo to robí ťažko postrehnuteľným, ale textúra je zlá a tónová reprodukcia driftuje. Test, ktorý to chytí, je kvantitatívny: dithernite uniformné pole stredne sivej a vyžadujte, aby vnútorné pokrytie dopadlo medzi 40 a 60 percent
Ktorú kombináciu má použiť pipeline na zmenšovanie veľkosti?
Priraďte kernel k tomu, čo obrázky skutočne sú, a berte dithering ako záležitosť zariadenia, nie kompresie. Pre fotografické skeny, ktoré musia prežiť rozpočet veľkosti, udrží rkLanczos3 pri 150 alebo 200 DPI detail, ktorý si ľudia všimnú, pri zrezaní počtu pixelov o faktor štyri a viac. Pre screenshoty, diagramy a line art je rkHalftone úprimne v poriadku a oveľa rýchlejší, lebo tie obrázky majú málo tónových gradientov na zachovanie. Pre zmiešanú dávku, kde nemôžete skontrolovať každý obrázok, je rkBicubic rozumný stred: lepší než bilinear, zhruba polovica počtu tapov Lanczos3
Downscaling je jedna páka z viacerých a nie je vždy tou najväčšou. Dvojúrovňové skeny zvyčajne reagujú oveľa lepšie na enkodér popísaný v článku natívna JBIG2 dvojúrovňová kompresia v Delphi, kde zisk pochádza zo symbolových slovníkov, nie z počtov pixelov. Pred rozhodnutím pomôže vedieť, čo je v súbore skutočne obsiahnuté, na čo slúži článok extrakcia obrázkov a ich decode filtrov: inventár objektov obrázkov a ich existujúcej kompresie vám povie, či má resampling čo získať
Ak staviate náhľadovú plochu, ktorá ukazuje výsledok, rovnaká renderovacia cesta popísaná v článku vykreslenie PDF strany do bitmapy je miesto, kde RenderOutputDither účinkuje, takže ditherovaný náhľad aj ditherovaný výstup pochádzajú z jednej kódovej cesty, nie z dvoch implementácií, ktoré sa rozídu
Široký princíp za oboma funkciami je, že nastavenia kvality majú byť explicitné a vratké. HotPDF necháva historické správanie ako default, aby existujúca aplikácia upgradovala bez prekvapivej zmeny vo výstupe alebo časovaní, a lepšie vyzerajúce, pomalšie cesty sú jedno priradenie vlastnosti ďaleko. Obe sú súčasťou HotPDF Delphi PDF komponentu, spolu s optimalizáciou resources a renderovacím strojárstvom, na ktorom stoja