HotPDF eksponerer tre kjerner for bildenedskalering gjennom egenskapen ImageDownsampleKernel og et separat Floyd-Steinberg-trinn gjennom RenderOutputDither. Det første styrer hvordan fotografier ser ut etter at du har krympet dem for å treffe et størrelsesbudsjett, det andre styrer hvordan de ser ut etter at en side er redusert til svart-hvitt. Ingen av dem er på som standard, og begge er opt-in av samme grunn: de koster ekte tid
Presset som fører folk hit, er kjent. En skannet kontrakt på 60 MB må sendes gjennom en e-postgateway som avviser alt over 10 MB, eller en bunke med kontoutskrifter må lande på en fakslignende monokrom enhet som rendrer hver grå piksel som enten papir eller toner. Begge problemer er resamplingsproblemer, og begge har et raskt svar som ser dårlig ut og et sakte svar som ser riktig ut
Hva de tre kjernene egentlig skiller seg på
THPDFResampleKernel har tre verdier, og de ligger på genuint forskjellige punkter på fart- og kvalitetskurven. rkHalftone delegerer til den historiske GDI StretchBlt-veien med HALFTONE-modus, som til tross for navnet er bilinearklasse-filtrering: rask, adekvat for strektegninger og skjermbilder, og utsatt for de harde kantene du gjenkjenner umiddelbart på nedskalerte fotografier. rkBicubic kjører en separabel Catmull-Rom-kjerne, og rkLanczos3 kjører en separat windowed sinc med tre-lobe-støtte
Begge separable kjernene kjører som to gjennomløp, horisontalt så vertikalt, med 6 til 12 taps per destinasjonspiksel i ren Pascal. Det er omtrent en størrelsesorden tregere enn GDI-veien, noe som er nøyaktig grunnen til at rkHalftone forblir standard. På et nattlig parti av tusenvis av sider er forskjellen en planleggingsbeslutning, ikke en preferanse. På ett enkelt dokument en bruker venter på, er Lanczos3 nesten gratis og merkbar bedre
To implementasjonsegenskaper er verdt å kjenne fordi de bestemmer hva utdataen kan og ikke kan gjøre. Kanter klemmes ved kantreplikering snarere enn innbrytning eller utfading, og vektene normaliseres per destinasjonspiksel. Sammen betyr de to at resultatet aldri ringer under svart eller over hvitt, så den klassiske Lanczos-overshoot-haloen rundt en hard kant dukker ikke opp som klippede artefakter i det kodede bildet
var
Pdf: THotPDF;
Info: THPDFLoadedResourceOptimizationInfo;
Changed: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('scanned-contract.pdf');
Pdf.ImageDownsampleKernel := rkLanczos3; // sett før kallet
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;
Argumentet MinimumSavingsBytes, 4096 ovenfor, er vakten som holder operasjonen ærlig. Re-koding av et bilde som allerede var effektivt komprimert, kan gi en større strøm enn originalen, og en nedskalerer som blindt erstatter hvert bilde, vil av og til få filen den ble bedt om å krympe, til å vokse. Terskelen sier: bare forplikt erstatningen når den sparer minst dette antallet byte. PreservedCalibratedImageCount rapporterer den andre konservative beslutningen, bilder latt i fred fordi de bærer et kalibrert fargerom som resampling ville kompromittert
Hvorfor er en feil polynomkoeffisient så vanskelig å oppdage?
Fordi en ødelagt interpolasjonskjerne ikke krasjer eller kaster unntak, produserer den bare et bilde som ser subtilt galt ut på en måte ingen kan tilskrive noe. Catmull-Rom-kjernen er piecewise kubikk, og dens ytterste gren i nøstet Horner-form er ((-0.5t + 2.5)t - 4)t + 2. Skriv den midterste koeffisienten som -5 i stedet for -4, og funksjonen evaluerer fortsatt, returnerer fortsatt tall i et plausibelt område, og produserer fortsatt et bilde
Skaden viser seg som W(1) som evaluerer til -1 der den må være 0. Negative vekter akkumuleres, summen klippes ved null, og det synlige symptomet er en gradient hvis venstre ende blir svart og en sprangkant som mister sine mellomtoner. Ingenting i feilen peker på et polynom. Kontrollen som fanger det på sekunder, er aritmetikk snarere enn visuell: en interpolerende kjerne må tilfredsstille W(0) = 1 og W(±1) = W(±2) = 0, og enhver kjerne som bommer på de tre punktene, har en koeffisientfeil, punktum. Test på de tre verdiene i en enhetstest, og hele klassen av skrivefeildefekter forsvinner
Floyd-Steinberg-dithering, og hvor den hører hjemme i rørledningen
Dither-trinnet er et annet problem enn resampling og bor på et annet sted i rørledningen. RenderOutputDither anvender Floyd-Steinberg-feildiffusjon etter sidekomponering, noe som er den eneste plasseringen som gir mening for en monokrom utskriftsforhåndsvisning eller en fakslignende eksport: operasjonen handler om å redusere et ferdig raster til én bit per piksel, ikke om hvordan enkeltbilder ble skalert på veien inn
Algoritmen i seg selv er kort. Luminansen terskles ved 50 prosent, og kvantiseringsfeilen diffunderes til fire naboer med de klassiske vektene 7/16, 3/16, 5/16 og 1/16, mot høyre, under-venstre, under og under-høyre. Utdatapikselen er 0 eller 255 i hver kanal. Det det naive alternativet gir deg i stedet, en hard terskel uten diffusjon, forvandler et fotografi til en silhuett og mister hver mellomtone som bar innholdet
// Dithering ved rendring for en monokrom forhåndsvisningsenhet
Pdf.RenderOutputDither := True;
// Eller bruk samme trinn på en bitmap du allerede eier. Bitmapen må
// være pf24bit; funksjonen returnerer False i stedet for å gjette
if not HPDFFloydSteinbergDitherBitmap(Preview) then
raise Exception.Create('dither expects a 24-bit bitmap');
// Direkte kjerne-tilgang når du resampler utenfor dokumentrørledningen
Small := HPDFResizeBitmapKernel(Large, 640, 480, rkLanczos3);
try
Small.SaveToFile('thumb.bmp');
finally
Small.Free;
end;
Det er én implementasjonsdetalj i feildiffusjon som biter alle én gang. Feilbufferen fra rad til rad må akkumulere. Hver piksel i neste rad mottar bidrag fra tre forskjellige piksler i gjeldende rad, tapene 3/16, 5/16 og 1/16, og hvis koden tilordner i stedet for å legge til, forkaster hver skriving det forrige bidraget, og bare siste tap overlever. Bildet ser fortsatt dithret ut, noe som er det som gjør det vanskelig å legge merke til, men teksturen er feil og tonalreproduksjonen driver. Testen som fanger det, er kvantitativ: dither et jevnt mellomgrått felt og krev at interiørdekningen lander mellom 40 og 60 prosent
Hvilken kombinasjon bør en størrelsesreduserende rørledning bruke?
Match kjernen mot hva bildene faktisk er, og behandle dithering som et enhetsanliggende snarere enn et kompresjonsanliggende. For fotografiske skanninger som må overleve et størrelsesbudsjett, holder rkLanczos3 ved 150 eller 200 DPI detaljene folk legger merke til, mens pikselantallet kuttes med en faktor fire eller mer. For skjermbilder, diagrammer og strektegninger er rkHalftone genuint fint og mye raskere, fordi de bildene har få tonale gradienter å bevare. For et blandet parti der du ikke kan inspisere hvert bilde, er rkBicubic det fornuftige midtpunktet: bedre enn bilinear, omtrent halvparten av tap-antallet til Lanczos3
Nedskalering er én spak blant flere, og den er ikke alltid den største. Bilevel-skanninger responderer vanligvis langt bedre på encoderen dekket i innfødt JBIG2 bilevel-kompresjon i Delphi, der gevinsten kommer fra symbolordbøker snarere enn pikselantall. Før du bestemmer deg, hjelper det å vite hva som faktisk er i filen, noe uttrekk av bilder og deres dekodefiltre er til for: et inventar av bildeobjekter og deres eksisterende kompresjon forteller deg om resampling har noe å hente
Hvis du bygger forhåndsvisningsflaten som viser resultatet, er det samme rendringsveien dokumentert i rendring av en PDF-side til en bitmap der RenderOutputDither virker, så den dithrede forhåndsvisningen og det dithrede utdataet kommer fra én kodevei snarere enn to implementasjoner som driver fra hverandre
Bredprinsippet bak begge funksjonene er at kvalitetsinnstillinger bør være eksplisitte og reversible. HotPDF beholder den historiske atferden som standard, slik at en eksisterende applikasjon oppgraderes uten en overraskende endring i utdata eller timing, og legger de penere, saktere veiene én egenskapstilordning unna. Begge er del av HotPDF Delphi PDF-komponent, ved siden av ressursoptimaliseringen og rendringsmaskineriet de bygger på