Teknisk artikkel

Rendre PDF-sider til Bitmap i Delphi med HotPDF

HotPDF rendrer en lastet PDF-side til en Delphi TBitmap gjennom et enkelt kall: RenderLoadedPageToBitmap(PageIndex, DPI). Funksjonen tolker sidens innholdsstrøm og returnerer en 24-bit RGB-bitmap som eies av kaller ved oppløsningen du velger, noe som er akkurat det en miniatyrbilde-stripe, en forhåndsvisning eller en PDF-til-bilde eksportpipeline trenger. Denne artikkelen går gjennom API-et, og deretter delen som skiller en brukbar rendrer fra et leketøy: å tegne tekst direkte fra de innebygde fontprogrammene i stedet for fra lignende systemfonter

Hvorfor er rendring av en PDF-side vanskeligere enn å tegne et bilde?

En PDF-side er ikke et bilde. Det er et program: en strøm av operatorer som bygger baner, velger fonter, setter farger og plasserer glyfer, utført mot grafikksmodellen definert i ISO 32000-1 §8. Ingenting i filen sier hvordan noen piksel ser ut. For å produsere en bitmap må du kjøre det programmet — vedlikeholde en gjeldende transformasjonsmatrise, en grafikkstatus-stakk for q/Q, en klippebane, fyll- og strekfargerom — og rasterisere resultatet. Det er derfor "bare vis side 3 som et bilde" er en innholdsstrømtolk, ikke en filformatkonvertering

HotPDFs rendrer, introdusert i v2.253.0, er bygd som seks frakoblede enheter som speiler denne modellen: en affin-matrise-kjerne for PDF [a b c d e f] transformasjonsalgebra, a graphics-state stack, a color-space resolver (DeviceRGB, DeviceGray, DeviceCMYK, Indexed), a path builder that bridges PDF path operators to GDI, a font-metrics layer that reads /Widths arrays for correct advances, and the interpreter that dispatches operators and drives the other five. Image XObjects go through the same decode stack the library uses for extraction, so every image filter HotPDF can decode for extraction — including JPXDecode-compressed JPEG 2000 images — also appears in rendered output

Rendre en lastet side til en TBitmap

RenderLoadedPageToBitmap tar en nullbasert sideindeks og en DPI-verdi, der 72 DPI kartlegger én PDF-brukerromsenhet til én piksel. Den returnerer nil ved feil (indeks utenfor gyldig område, manglende ressurser) i stedet for å utløse unntak, slik at en visningsapplikasjon kan hoppe over en dårlig side og fortsette. Kaller eier den returnerte bitmapen og må frigi den

DPI-argumentet gjør skaleringsarbeidet for alle vanlige scenarier. En miniatyrbilde-stripe rendres ved 36 eller 48 DPI og gir små, raske bitmape; en forhåndsvisning på skjermen ved 96 eller 144 DPI matcher typisk skjermtetthet; en eksportbane ved 300 DPI produserer bilder av utskriftskvalitet. Siderotasjon fra /Rotate-oppføringen og /MediaBox-utgangspunkt-flippen (PDF plasserer utgangspunktet nede til venstre, GDI oppe til venstre) håndteres i side-til-enhet-matrisen, slik at en US Letter-side ved 72 DPI kommer tilbake som nøyaktig 612×792 piksler riktig vei opp

Hvorfor viser rendrede PDF-miniatyrbilder feil glyfer?

Feil eller omtrentlige glyfer i rendrede PDF-utdata betyr nesten alltid at rendreren erstatter med en systemfont i stedet for å bruke fonten som er bygd inn i filen. Den første HotPDF-rendreren gjorde akkurat det: den fjernet delsettprefikset fra /BaseFont (endret ABCDEF+Arial til Arial), ba GDI om en systemfont med det navnet, og tegnet teksten med den. For et dokument som bruker Arial eller Times New Roman med standard koding, ser resultatet nært ut. Men det er en tilnærming, og den feiler på veldefinerte måter

Delsett-innbygde fonter er det verste tilfellet. En delsett-font kan bare inneholde de førti glyfene et dokument faktisk bruker, med tegnkoder tildelt i en rekkefølge som er privat for den filen — kode 1 kan være "T", kode 2 "h" og så videre. En systemfont vet ingenting om denne private tildelingen, så tekst enten forsvinner eller kommer ut som helt feil tegn. Egendefinerte kodinger, symbolfonter, strekkodefonter og alle fonter som ikke er installert på rendringsenheten feiler på samme måte. En rendrer som stopper ved systemfont-erstatning produserer miniatyrbilder som gjenkjennelig er siden — helt til siden bruker fontene som gjorde innbygging nødvendig i utgangspunktet

Innebygd glyfrendring: tegning fra selve fontprogrammet

HotPDF lukket dette gapet over fem utgivelser (v2.268.0 til v2.272.0) ved å tolke de innebygde fontprogrammene og spille av glyfomrissene deres som fylte GDI-vektorbaner. Tekst i en rendret side kommer nå fra de samme omrissdataene en samsvarende visningsprogram bruker, noe som betyr at delsettfonter, egendefinerte kodinger og uinstallerte fonter rendres med sine nøyaktige former. Dekningen ble bygd opp etter fonttype:

For Type0/CIDFontType2-fonter med et innebygd TrueType-program (FontFile2), tolker rendreren tabellene glyf og loca direkte: kvadratiske konturer konverteres til de kubiske Bézier-kurvene GDI forstår, underforståtte on-curve-punkter mellom påfølgende off-curve-punkter rekonstrueres, og sammensatte glyfer spilles av rekursivt. Både Identity og eksplisitte CIDToGIDMap-strømoppsett støttes, og CID-fremrykk respekterer breddeoppføringene /W og /DW, slik at to-byte Identity-H-tekst skrider frem riktig

CFF-programmer (FontFile3, enten CIDFontType0C, Type1C eller en OpenType-wrapper) får en fullstendig Type 2-charstringtolk: linjer, kurver, flex-familien, hintmasker og lokale/globale subrutinekall med riktig subrutine-bias. CID-nøkkelbaserte CFF-programmer kartlegger tegnkoder gjennom fontens tegnsett (charset), noe som betyr mye for delsettfonter der glyfrekkefølgen avviker fra CID-rekkefølgen, og font-DICT-valg per glyf via FDArray/FDSelect respekteres. Enkle (ikke-CID) TrueType-fonter løser opp en-byte-koder via den innebygde fontens egen cmap-tabell med en robust deltabellkjede — Unicode-formatene 4 og 12 først, deretter symbol-deltabeller med F000-speilingen for privat bruk, og deretter eldre Macintosh-formater — og enkle Type1-fonter resolver one-byte codes through the CFF program's built-in encoding

To forbedringer fullfører bildet. For det første blir enkle fonters /Encoding-ordbøker løst opp etter prioriteten ISO 32000-1 §9.6.6 foreskriver: /Differences-tabeller overstyrer basekodingen, som igjen overstyrer fontprogrammets eget kart — banen TeX- og PostScript-avledede verktøykjeder avhenger av, der glyfnavn løses opp via Adobe Glyph List, CFF-tegnsettet eller TrueType cmap. For det andre blir Type3-fonter, hvis glyfer i seg selv er små innholdsstrømmer, blir spilt av gjennom rendreren med fontmatrisen, skriftstørrelsen og tekstmatrisen sammensatt; glyf-rom /Widths tolkes gjennom /FontMatrix slik ISO 32000-1 §9.6.5 krever, og glyf-prosedyrer som erklærer en d1-ramme (bounding box) klippes til den, slik at en feilformet strekkodeglyf ikke kan tegne utenfor cellen sin. Når en kode ikke kan kartlegges — et skadet program, et ukartlagt tegn — faller rendreren tilbake på tegning med systemfont for den glyfen i stedet for å miste hele tekstkjøringen

Hvordan gjør du gjentatte rendringer raske?

Svaret HotPDF leverer med er en sidebuffer for sist brukte sider: RenderLoadedPageToBitmapCached beholder opptil RenderCacheCapacity rendrede sider (standard 8) indeksert etter sideindeks og DPI, og et treff i bufferen returnerer en ny kopi som eies av kaller uten å berøre innholdsstrømmen — typisk tusenvis av ganger raskere enn å tolke siden på nytt. Dette mønsteret passer perfekt for visningsprogrammer: en bruker som blar frem og tilbake mellom to sider, eller en størrelsesendring som ber om samme side på nytt ved samme DPI, treffer bufferen hver gang

Vær ærlig om minnekostnaden før du øker kapasiteten. En US Letter-side ved 300 DPI er 2550×3300 piksler, omtrent 25 MB som en 24-biters bitmap, så åtte bufrede sider ved eksportoppløsning holder omtrent 200 MB. Ved miniatyrbilde-DPI koster de samme åtte oppføringene godt under en megabyte. Tilpass RenderCacheCapacity til DPI-en du faktisk bufrer på, og kall InvalidateRenderedPageCache etter enhver redigering på stedet — bufferen indekseres kun etter side og DPI, og den kan ikke se at det underliggende innholdet ble endret. Innlasting av et nytt dokument tømmer den automatisk

En sekundær buffer fungerer under sidebufferen: dekodede bilde-XObjects oppbevares i et byte-begrenset lager avgrenset av ImageCacheMaxBytes (standard 32 MB) med utkastelse etter sist brukte prinsipp (LRU). En logo eller et brevhodebilde som gjentas på hver side dekodes én gang per dokumentinnlasting i stedet for én gang per Do-operator, noe som omtrent halverer rendringstiden for sider med delte bilder og fremskynder eksport av flersiders TIFF i samme grad. InvalidateRenderedPageCache tømmer denne bufferen også

Hva som fremdeles rendres tilnærmet

Rendreren retter seg mot det vanlige dokument-PDF-delsettet, og det er verdt å vite hvor grensene går. CalRGB-, Lab- og ICC-baserte fargerom tilnærmes i stedet for å fargestyres — enhetsfargerom, indekserte paletter og samplende Type 0-funksjonsfargeoppslag håndteres, men en fil for trykkproduksjon som er avhengig av ICC-rendringsintensjoner vil ikke være fargemessig nøyaktig. Skyggemønstre (sh) og blandingsmoduser utover enkel alfa er på samme måte utenfor omfanget, og Form XObject-rekursjon er dybdebegrenset som en syklusvakt. For fakturaer, rapporter, kontrakter og skjemaer — sider laget av tekst, baner og bilder — er utdataene troverdige; for en designprøve full av gradienter og gjennomsiktighetsgrupper bør du behandle bitmapen som en forhåndsvisning, ikke et bevis

Det praktiske poenget: hvis din pipeline genererer dokumenter med HotPDF eller forbruker typiske forretnings-PDF-er, vil RenderLoadedPageToBitmap gjenskape dem med de nøyaktige innebygde glyfformene, korrekte CID-fremrykk og korrekt sidegeometri. Tilnærmingene lever i hjørnene av grafikksmodellen som forretningsdokumenter sjelden besøker

RenderLoadedPageToBitmap, dens bufrede variant, og den innebygde glyfrendringspipelinen beskrevet her leveres som en del av HotPDF Component for Delphi og C++Builder — et innebygd VCL-bibliotek uten eksterne DLL-avhengigheter, som dekker PDF-opprettelse, redigering, tekstuthenting og siderendring i én pakke