A HotPDF három képkicsinyítő kernelt tesz elérhetővé a ImageDownsampleKernel tulajdonságon keresztül, és egy külön Floyd-Steinberg menetet a RenderOutputDither-ön. Az első azt irányítja, hogyan néznek ki a fényképek azután, hogy méretkeret eléréséhez kicsinyítette őket, a második azt, hogyan néznek ki azután, hogy egy oldal feketére és fehérré zsugorodott. Egyik sincs alapból bekapcsolva, és mindkettő ugyanazért opt-in: valós időbe kerülnek
A nyomás, amely ide vezeti az embereket, ismerős. Egy 60 MB-os szkennelt szerződésnek ki kell mennie egy e-mail átjárón, amely 10 MB felett mindent elutasít, vagy egy kimutatás kötegnek kell földet érintenie egy fax jellegű monokróm eszközön, amely minden szürke pixelt papírnak vagy tonernak rajzol. Mindkét probléma újramintavételezési probléma, és mindkettőnek van gyors válasza, amely rosszul néz ki, és lassú válasza, amely jól néz ki
Miben térnek el ténylegesen a három kernel?
A THPDFResampleKernel-nek három értéke van, és ténylegesen eltérő pontokon ülnek a sebesség-minőség görbén. A rkHalftone a történelmi GDI StretchBlt útra delegál HALFTONE móddal, amely a neve ellenére bilineáris osztályú szűrés: gyors, megfelelő vonalas ábrákhoz és képernyőképekhez, és hajlamos a ropogós élekhez, amelyeket leléptetett fényképeken azonnal felismer. A rkBicubic szétválasztható Catmull-Rom kernelt futtat, a rkLanczos3 pedig szétválasztható ablakolt sincet három lebenyű tartással
Mindkét szétválasztható kernel két menetben fut, vízszintesen aztán függőlegesen, célpixelenként 6-12 leolvasással tiszta Pascalban. Ez nagyjából egy nagyságrenddel lassabb a GDI útnál, és pontosan ezért marad a rkHalftone az alapértelmezett. Ezer oldalt feldolgozó éjszakai kötegnél a különbség ütemezési döntés, nem preferencia. Egyetlen, felhasználó által várt dokumentumnál a Lanczos3 majdnem ingyenes, és láthatóan jobb
Két implementációs tulajdonság érdemes ismerni, mert meghatározzák, mit tudhat és mit nem a kimenet. A szélek élreplikációval tapadnak, körbezárással vagy fakulással nem, és a súlyok célpixelenként normalizáltak. A kettő együtt azt jelenti, hogy az eredmény sosem cseng fekete alá vagy fehér fölé, tehát a klasszikus Lanczos túllövési haló egy kemény él körül nem jelenik meg kivágott artefaktként a kódolt képben
var
Pdf: THotPDF;
Info: THPDFLoadedResourceOptimizationInfo;
Changed: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('scanned-contract.pdf');
Pdf.ImageDownsampleKernel := rkLanczos3; // állítsa be a hívás előtt
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;
A MinimumSavingsBytes argumentum, fent 4096, az az őr, amely becsületben tartja a műveletet. Egy már hatékonyan tömörített kép újrakódolása nagyobb streamet adhat, mint az eredeti, és egy minden képet vakon kicserélő kicsinyítő alkanként megnöveli azt a fájlt, amelyet zsugorítani kérték. A küszöb azt mondja: a cserét csak akkor fogadja el, ha legalább ennyi bájtot takarít meg. A PreservedCalibratedImageCount a másik konzervatív döntést jelenti: érintetlenül hagyott képeket, mert kalibrált színteret hordoznak, amelyet az újramintavételezés rontaná
Miért ilyen nehéz észrevenni egy rossz polinomegyütthatót?
Mert egy törött interpolációs kernel nem crashel és nem dob, csak olyan képet ad, amely finoman rosszul néz ki olyan módon, amelyet senki nem tud hozzárendelni semmihez. A Catmull-Rom kernel szakaszonkénti kubikus, és a külső ága beágyazott Horner-formában ((-0.5t + 2.5)t - 4)t + 2. Írja azt a középső együtthatót -4 helyett -5-re, és a függvény továbbra is kiértékelődik, hihető tartományban lévő számokat ad, és továbbra is képet gyárt
A kár úgy mutatkozik meg, hogy a W(1) -1-re értékelődik, ahol nullának kellene lennie. A negatív súlyok felhalmozódnak, az összeg nullánál vágódik, és a látható tünet egy gradiens, amelynek a bal vége feketére megy, és egy lépcsős él, amely elveszíti a köztes tónusait. Semmi a hibában nem mutat polinomra. A másodpercek alatt elkaptó ellenőrzés számtani, nem vizuális: egy interpoláló kernelnek teljesítenie kell a W(0) = 1 és a W(±1) = W(±2) = 0 egyenleteket, és minden kernel, amely lemarad erről a három pontról, együtthatóhibás, és kész. Állítson unit tesztben erre a három értékre, és az elgépelt együttható hibák egész osztálya eltűnik
Floyd-Steinberg dithering, és hol van a helye a folyamatsorban
A dither menet más probléma, mint az újramintavételezés, és a folyamatsor más pontján él. A RenderOutputDither Floyd-Steinberg hibadiffúziót alkalmaz az oldal komponálása után, ami az egyetlen elhelyezés, amely értelmes monokróm nyomtatási előnézethez vagy fax jellegű exporthoz: a művelet arról szól, hogy egy elkészült rasztert pixelenként egy bitre zsugorít, nem arról, hogyan léptették az egyes képeket behúzáskor
Maguk az algoritmus rövid. A fényerő 50 százaléknál küszböleződik, és a kvantálási hiba négy szomszédba diffundál a klasszikus 7/16, 3/16, 5/16 és 1/16 súlyokkal, jobbra, balra le, le és jobbra le. A kimeneti pixel minden csatornában 0 vagy 255. Amit a naiv alternatíva helyette ad, egy kemény küszöb diffúzió nélkül, az a fényképet sziluetté teszi, és minden köztes tónus elveszik, amely a tartalmat hordozta
// Renderelésidejű dithering monokróm előnézeti eszközhöz
Pdf.RenderOutputDither := True;
// Vagy alkalmazza ugyanezt a menetet egy már birtokolt bitmapon. A bitmapnek
// pf24bitnek kell lennie; a függvény False-t ad vissza, nem találgat
if not HPDFFloydSteinbergDitherBitmap(Preview) then
raise Exception.Create('dither expects a 24-bit bitmap');
// Közvetlen kernelhozzáférés, ha a dokumentumfolyamaton kívül mintavételez újra
Small := HPDFResizeBitmapKernel(Large, 640, 480, rkLanczos3);
try
Small.SaveToFile('thumb.bmp');
finally
Small.Free;
end;
A hibadiffúzióban van egy implementációs részlet, amely mindenkit egyszer megharap. A sorok közti hibabuffernek fel kell halmoznia. A következő sor minden pixelje hozzájárulást kap az aktuális sor három különböző pixeljétől, a 3/16, 5/16 és 1/16 leolvasásoktól, és ha a kód hozzárendel az összeadás helyett, minden írás eldobja az előző hozzájárulást, és csak az utolsó leolvasás marad fenn. A kép továbbra is dithereltnek tűnik, ami megnehezíti észrevenni, de a textúra rossz, és a tónusreprodukáció sodródik. Az ezt elkaptó teszt kvantitatív: dithereljen egységes középszürke mezőt, és követelje meg, hogy a belső lefedettség 40 és 60 százalék közé érjen
Melyik kombinációt használjon egy méretcsökkentő folyamatsor?
Párosítsa a kernelt ahhoz, ami a képek ténylegesen, és a ditheringet kezelje eszközkérdésnek, tömörítéskérdés helyett. Fénykép szkennelésekhez, amelyeknek átvészerniük kell egy méretkeretet, a rkLanczos3 150 vagy 200 DPI-nél megtartja azt a részletet, amelyet az emberek észrevesznek, miközben a pixelszámot négyszörösével vagy többivel csökkenti. Képernyőképekhez, diagramokhoz és vonalas ábrákhoz a rkHalftone ténylegesen megfelelő és sokkal gyorsabb, mert azok a képek kevés tónusgradienst hordoznak. Vegyes kötegnél, ahol nem tudja megvizsgálni minden képet, a rkBicubic az észszerű középút: jobb, mint a bilineáris, nagyjából a Lanczos3 leolvasásszámának fele
A kicsinyítés az egyik kar a több közül, és nem mindig a legnagyobb. A bilevel szkennelések általában sokkal jobban reagálnak a natív JBIG2 bilevel tömörítés Delphiben cikkben tárgyalt kódolóra, ahol a nyereség szimbólumszótárakból jön, nem pixelszámokból. Mielőtt döntene, segít tudni, mi van ténylegesen a fájlban, erre való a képek és decode szűrőik kinyerése cikk: a képobjektumok és meglévő tömörítésük leltára megmondja, van-e mit nyernie az újramintavételezésnek
Ha az előnézeti felületet építi, amely megmutatja az eredményt, a PDF oldal bitmapre renderelése cikkben dokumentált ugyanaz a renderelési út az, ahol a RenderOutputDither hatni kezd, tehát a ditherelt előnézet és a ditherelt kimenet egy kódútból jön, nem két olyan implementációból, amely szétsodródik
Mindkét funkció mögötti tág elv az, hogy a minőségi beállítások explicitnek és visszavonhatónak kell lenniük. A HotPDF a történelmi viselkedést tartja alapértelmezésnek, így egy meglévő alkalmazás meglepetésváltozás nélkül frissít a kimenetben vagy az időzítésben, és a jobban kinéző, lassabb utakat egy tulajdonság-hozzárendelésre teszi. Mindkettő a HotPDF Delphi PDF komponens része, az erőforrás-optimalizálás és a renderelési gépezet mellett, amelyekre épülnek