HotPDF eksponerer tre image downsampling-kernels gennem ImageDownsampleKernel-egenskaben og en separat Floyd-Steinberg-omgang gennem RenderOutputDither. Den første styrer, hvordan fotografier ser ud, efter du har formindsket dem for at ramme et størrelsesbudget, den anden styrer, hvordan de ser ud, efter en side er reduceret til sort-hvid. Ingen af dem er slået til som default, og begge er opt-in af samme grund: de koster ægte tid
Pressen, der fører folk hertil, er velkendt. En 60 MB scannet kontrakt skal ud gennem en email-gateway, der afviser alt over 10 MB, eller en bunke kontoudtog skal lande på en fax-agtig monokrom enhed, der renderer hver grå pixel som enten papir eller toner. Begge problemer er resampling-problemer, og begge har et hurtigt svar, der ser dårligt ud, og et langsomt svar, der ser rigtigt ud
Hvad de tre kernels reelt adskiller sig i
THPDFResampleKernel har tre værdier, og de sidder på reelt forskellige punkter på fart- og kvalitetskurven. rkHalftone delegerer til den historiske GDI StretchBlt-vej med HALFTONE-mode, som trods navnet er bilinear-klasse filtrering: hurtig, tilstrækkelig til line art og screenshots og tilbøjelig til de knaggede kanter, du genkender med det samme på nedskalerede fotografier. rkBicubic kører en separabel Catmull-Rom-kernel, og rkLanczos3 kører en separabel windowed sinc med tre-lobe support
Begge separable kernels kører som to passes, vandret og derefter lodret, med 6 til 12 taps per destinationspixel i ren Pascal. Det er omtrent en størrelsesorden langsommere end GDI-vejen, hvilket netop er grunden til, at rkHalftone forbliver default. På en natlig batch af tusindvis af sider er forskellen en scheduling-beslutning, ikke en præference. På et enkelt dokument, en bruger venter på, er Lanczos3 næsten gratis og synligt bedre
To implementationsegenskaber er værd at kende, for de afgør, hvad output kan og ikke kan. Rammer clampes ved edge-replikering snarere end wrapping eller fading, og vægtene normaliseres per destinationspixel. Tilsammen betyder de to, at resultatet aldrig ringer under sort eller over hvid, så den klassiske Lanczos overshoot-halo omkring en hård kant ikke optræder som clippede artefakter i det indkodede billede
var
Pdf: THotPDF;
Info: THPDFLoadedResourceOptimizationInfo;
Changed: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('scanned-contract.pdf');
Pdf.ImageDownsampleKernel := rkLanczos3; // sæt før kaldet
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;
MinimumSavingsBytes-argumentet, 4096 ovenfor, er guarden, der holder operationen ærlig. Genkodning af et billede, der allerede var effektivt komprimeret, kan producere en større stream end originalen, og en downsampler, der blindt erstatter hvert billede, vil af og til få filen, den blev bedt om at formindske, til at vokse. Tærsklen siger: commit kun erstatningen, når den sparer mindst dette antal byte. PreservedCalibratedImageCount melder den anden konservative beslutning, billeder efterladt urørte, fordi de bærer et kalibreret color space, som resampling ville kompromittere
Hvorfor er en forkert polynomiumskoefficient så svær at få øje på?
Fordi en ødelagt interpolationskernel hverken crasher eller kaster, producerer den bare et billede, der ser diskret forkert ud på en måde, ingen kan tilskrive noget. Catmull-Rom-kernelen er piecewise cubic, og dens ydre gren i indlejret Horner-form er ((-0.5t + 2.5)t - 4)t + 2. Skrives den midterste koefficient som -5 i stedet for -4, evaluerer funktionen stadig, returnerer stadig tal i et plausibelt område og producerer stadig et billede
Skaden viser sig som W(1), der evaluerer til -1, hvor den skal være 0. Negative vægte akkumulerer, summen clipper ved nul, og det synlige symptom er en gradient, hvis venstre ende går sort, og en step-kant, der mister sine mellotoner. Intet i fejlen peger på et polynomium. Tjekket, der fanger det på sekunder, er aritmetik snarere end visuelt: en interpolerende kernel skal opfylde W(0) = 1 og W(±1) = W(±2) = 0, og enhver kernel, der misser de tre punkter, har en koefficientfejl, punktum. Assert på de tre værdier i en unit test, og hele klassen af stavefejl-defekter forsvinder
Floyd-Steinberg-dithering, og hvor den hører hjemme i pipelinen
Dither-omgangen er et andet problem end resampling og bor på et andet sted i pipelinen. RenderOutputDither anvender Floyd-Steinberg error diffusion efter sidekomposition, hvilket er den eneste placering, der giver mening for et monokromt print preview eller en fax-agtig eksport: operationen handler om at reducere et færdigt raster til én bit per pixel, ikke om hvordan de enkelte billeder blev skaleret på vejen ind
Algoritmen selv er kort. Luminans tærskles ved 50 procent, og kvantiseringsfejlen diffunderes til fire naboer med de klassiske 7/16-, 3/16-, 5/16- og 1/16-vægte, mod højre, nederst-venstre, nedenfor og nederst-højre. Outputpixelen er 0 eller 255 i hver kanal. Det, det naive alternativ giver dig i stedet, en hård tærskel uden diffusion, forvandler et fotografi til en silhuet og mister hver mellotone, der bar indholdet
// Render-tids dithering til en monokrom preview-enhed
Pdf.RenderOutputDither := True;
// Eller anvend samme omgang på en bitmap, du allerede ejer. Bitmapmen skal
// være pf24bit; funktionen returnerer False i stedet for at gætte
if not HPDFFloydSteinbergDitherBitmap(Preview) then
raise Exception.Create('dither expects a 24-bit bitmap');
// Direkte kernel-adgang, når du resampler uden for dokumentpipelinen
Small := HPDFResizeBitmapKernel(Large, 640, 480, rkLanczos3);
try
Small.SaveToFile('thumb.bmp');
finally
Small.Free;
end;
Der er én implementationdetalje i error diffusion, der bider alle én gang. Række-til-række error-bufferen skal akkumulere. Hver pixel i næste række modtager bidrag fra tre forskellige pixels i den aktuelle række, 3/16-, 5/16- og 1/16-tappene, og tildeler koden i stedet for at lægge til, kasserer hver skrivning det forrige bidrag, og kun den sidste tap overlever. Billedet ser stadig ditheret ud, hvilket er det, der gør det svært at lægge mærke til, men teksturen er forkert, og den tonale gengivelse driver. Testen, der fanger det, er kvantitativ: dither et ensartet mellemgråt felt og kræv, at dækningen i det indre lander mellem 40 og 60 procent
Hvilken kombination skal en størrelsesreduktionspipeline bruge?
Match kernelen til, hvad billederne reelt er, og behandl dithering som en enhedsbekymring snarere end en komprimeringsbekymring. Til fotografiske scans, der skal overleve et størrelsesbudget, bevarer rkLanczos3 ved 150 eller 200 DPI detaljen, folk lægger mærke til, mens pixeltallet skæres ned med en faktor fire eller mere. Til screenshots, diagrammer og line art er rkHalftone reelt fint og meget hurtigere, for de billeder har få tonale gradienter at bevare. Til en blandet batch, hvor du ikke kan inspicere hvert billede, er rkBicubic det fornuftige midterste: bedre end bilinear, omtrent halvt så mange taps som Lanczos3
Downsampling er ét håndtag blandt flere, og det er ikke altid det største. Bilevel-scans responderer normalt langt bedre på encoderen dækket i native JBIG2 bilevel-komprimering i Delphi, hvor gevinsten kommer fra symbol dictionaries snarere end pixeltal. Inden du beslutter dig, hjælper det at vide, hvad der reelt er i filen, hvilket er, hvad udtrækning af billeder og deres decode filters er til: et inventar af billedobjekter og deres eksisterende komprimering fortæller dig, om resampling har noget at hente
Bygger du preview-fladen, der viser resultatet, er det den renderingsvej dokumenteret i rendering af en PDF-side til en bitmap, RenderOutputDither træder i kraft, så det ditherede preview og det ditherede output kommer fra én kodevej snarere end to implementationer, der driver fra hinanden
Det brede princip bag begge features er, at kvalitetsindstillinger bør være eksplicitte og reversible. HotPDF beholder den historiske adfærd som default, så en eksisterende applikation opgraderer uden en uventet ændring i output eller timing, og lægger de bedre udseende, langsommere veje én egenskabstildeling væk. Begge er del af HotPDF Delphi PDF-komponenten, sammen med det resource-optimiserings- og renderingsmaskineri, de bygger på