Trije rasterizatorji lahko preberejo isti PDF in se ne strinjajo o tem, kaj v njem piše. Vgrajeni pogon v PDF Library for Delphi je tisti, ki pride brez dodatnih datotek in vse upodobi spodobno, in prav zato si prisluži privzeto mesto. Cairo prinaša drugačen cevovod za prosojnost in glajenje robov ter je običajno tisti, po katerem ljudje sežejo, kadar mehke maske ali načini zlivanja drugod pridejo ven narobe. PDFium nosi upodabljalno kodo Chroma, zato je stran, ki je videti prav v brskalniku, običajno videti prav tudi pod PDFium, za ceno obsežne knjižnice DLL in bitnosti, na ujemanju katere vztraja. Nobeden od treh ni pravilen na splošno. Pravilnost je stvar posameznega dokumenta, edini pošten način, da ugotovite, kateri pogon obvlada določen korpus, pa je, da ta korpus poženete skozi vsakega od njih
To je argument za to, da pogon obravnavate kot izbiro med izvajanjem in ne kot izbiro ob prevajanju. PDF Library for Delphi, knjižnica losLab za PDF v Delphiju in C++Builderju, vse tri postavi za eno samo upodabljalno površino, tako da odločitev stane eno celo število namesto veje v kodi. Preostanek se zvede na varno izbiranje med njimi, na potrjevanje, katere pogone nameščena binarna datoteka dejansko nosi, in na preprečevanje, da bi upodabljalno stanje tiho zastrupilo naslednje opravilo
Trije rasterizatorji za eno klicno površino
Knjižnica svoje pogone oštevilči. Pogon 1 je vgrajeni upodabljalnik, privzeti, z možnostmi glajenja GDI+ v sistemu Windows. Pogon 2 je Cairo, pogon 3 pa PDFium, oba izbrana med izvajanjem prek SelectRenderer. Zunanja pogona se naložita iz knjižnic DLL, katerih poti podate s SetCairoFileName in SetPDFiumFileName, preden ju izberete. Kateri koli pogon je dejaven, delo teče skozi iste klice: RenderPageToFile, RenderPageToStream, RenderDocumentToFile. Menjava pogona premakne eno število; preostanek vaše upodabljalne kode tega nikoli ne opazi
Model ciljev sega precej dlje od bitnih slik. Upodabljalni razred cilja tudi metadatoteke (WMF, EMF, EMF+), EPS, neposredne kontekste naprav, tiskalnike in HTML5, pri čemer se Cairo in PDFium pojavita kot dodatna cilja le, kadar sta bila vključena ob prevajanju. Rastrski izhod je tam, kjer se trije pogoni najbolj vidno razidejo, zato ga uporabljajo tudi primeri tukaj
Nikoli ne predpostavljajte, da pogon obstaja: sondirajte ob zagonu
Cairo in PDFium sta zmožnosti pogojnega prevajanja, kar pomeni, da je binarno datoteko mogoče zgraditi povsem brez njiju. Kadar se to zgodi, zahteva po pogonu 2 ali 3 ne sproži ničesar. SelectRenderer preprosto vrne vrednost, ki ni zahtevani ID, koda, ki vrnjeno vrednost prezre, pa upodablja naprej s tistim pogonom, ki je bil že dejaven. Obramba je zagonska sonda, ki vsak pogon prosi, naj se identificira, in odgovor zabeleži:
function ProbeEngines(PDF: TPDFlib): string;
begin
Result := 'built-in'; // pogon 1 je vedno prisoten
if (PDF.SetCairoFileName('cairo.dll') = 1) and (PDF.SelectRenderer(2) = 2) then
Result := Result + ', cairo';
if (PDF.SetPDFiumFileName('pdfium.dll') = 1) and (PDF.SelectRenderer(3) = 3) then
Result := Result + ', pdfium';
PDF.SelectRenderer(1); // pred pravim delom obnovi privzetega
end;
To sondo poženite enkrat ob zagonu in njen izid zapišite v dnevnik ob vsakem upodabljalnem opravilu. Najpogostejše vprašanje, kadar stranka poroča o razliki pri upodabljanju, je, katere pogone njena namestitev sploh ima, enovrstični odgovor v dnevniku pa to reši brez seje z oddaljenim namizjem. Koristen stranski učinek: če SetPDFiumFileName sam vrne 0, že veste, da je težava DLL (napačna pot, napačna bitnost, manjkajoča odvisnost) in ne binarna datoteka, prevedena brez podpore za PDFium, saj klic poti ni razrešil ničesar, še preden je SelectRenderer sploh stekel
Deset izhodnih zapisov za enim celim številom Options
Parameter Options pri upodabljalnih klicih izbere izhodno kodiranje: 0 je BMP, 1 JPEG, 2 WMF, 3 EMF, 4 EPS, 5 PNG, 6 GIF, 7 TIFF, 8 EMF+ in 9 HTML5. PNG (5) je smiselna privzeta izbira za predoglede in arhivske slike strani. JPEG (1), v paru s SetJPEGQuality, je boljša izbira za fotografske skene, kjer velikost datoteke šteje bolj kot ostri robovi
En zapis skriva zahtevo glede ciljnega toka. Pot za BMP najprej zapiše slikovne podatke, nato pa se vrne na odmik 0x26, da popravi polji ločljivosti v glavi. Če to usmerite v tok, ki gre samo naprej, v ovoj za stiskanje ali v omrežno vtičnico, klic odpove na način, ki se bere kot okvara pogona, a to ni. Kadar se cilju brez iskanja ni mogoče izogniti, upodobite raje PNG ali pa BMP pripravite prek pomnilniškega toka in ga prekopirajte naprej, ko je dokončan
DPI, ki ga podate, ni DPI, ki ga dobite
Vsak upodabljalni klic vzame argument DPI, ločljivost, ki jo dejansko dobite, pa je ta vrednost, pomnožena z globalnim upodabljalnim merilom. SetRenderScale se začne pri 1,0, in ko ga spremenite, novi faktor tiho velja za vsako poznejše upodabljanje na tem primerku:
PDF.SetRenderScale(2.0); // vsako poznejše upodabljanje je podvojeno
PDF.RenderPageToFile(150, 1, 5, 'p1.png'); // dejansko 300 DPI
PDF.SetRenderScale(1.0); // ponastavite, sicer bodo sličice ogromne
Enaka lepljivost velja za SetRenderCropType in za nastavitev kakovosti JPEG. V storitvi, ki iz enega skupnega primerka izdeluje sličice, predoglede in slike v tiskarski ločljivosti, so te preostale nastavitve tisto, kar v resnici stoji za občasno prijavo "sličice so nenadoma velike 40 MB". Dve čisti poti ven: ustrezno stanje ponastavite na začetku vsake operacije ali pa vsakemu izhodnemu profilu namenite ločen primerek, da nič ne pušča med njimi
Nastavljanje privzetega pogona, preden sežete po drugem
Presenetljiv delež zahtev "potrebujemo drug pogon" se izkaže za težave z nastavitvami v preobleki. Vgrajeni upodabljalnik svoje vedenje pri glajenju razkriva prek SetGDIPlusOptions in širše družine SetRenderOptions, SetGDIPlusFileName pa vam omogoča, da ga usmerite na določeno izvajalno okolje GDI+, kadar namestitveno okolje prinese nenavadnega. Nazobčane črtne risbe pri nizkem DPI, zabrisano besedilo v sličicah, pasovi po prelivih: vse to se odziva na te gumbe, njihovo obračanje pa v namestitvenem programu ne stane nič. Dodajanje Caira ali PDFium nasprotno pomeni odpremo dodatnih knjižnic DLL, sledenje drugi ali tretji različici glede na bitnost in prevzem obveznosti, da ju posodabljate
Pritožba glede kakovosti ima torej naraven vrstni red korakov. Najprej jo ponovite pri strankinem točnem DPI in merilu, saj razlika v polovici primerov izpuhti, brž ko se ta dva ujemata. Nato preizkusite možnosti glajenja vgrajenega pogona. Šele zatem stran postavite drugo ob drugo po pogonih, pri čemer je vsaka druga spremenljivka nespremenjena: upodobite jo v PNG skozi pogone 1, 2 in 3 pri enakem DPI ter priložite vse tri. Običajno se dva od treh ujemata, ta večina pa vam pove, ali je izstopajoči primer dokument, ki se razlaga drugače, ali vaše lastno izhodiščno pričakovanje, ki je zgrešeno. Tri konkretne slike spor o "napačnem upodabljanju" rešijo veliko hitreje kot odstavek pridevnikov
Veriga zasilnih poti, ki pojasni samo sebe
Ko sta sondiranje in disciplina glede stanja vzpostavljena, je veriga zasilnih poti sama kratka. Zaznavanje odpovedi se opira na LastRenderError, ki drži pogonovo lastno besedilo sporočila za zadnje upodabljanje in je prazno, kadar je upodabljanje uspelo:
procedure RenderPageWithFallback(PDF: TPDFlib; Page: Integer; const OutFile: string);
begin
PDF.SelectRenderer(1); // najprej vgrajeni
PDF.RenderPageToFile(200, Page, 5, OutFile); // 5 = PNG
if PDF.LastRenderError = '' then Exit;
LogEngineFailure('built-in', Page, PDF.LastRenderError);
if PDF.SelectRenderer(3) = 3 then // PDFium kot težka zasilna pot
begin
PDF.RenderPageToFile(200, Page, 5, OutFile);
if PDF.LastRenderError = '' then Exit;
LogEngineFailure('pdfium', Page, PDF.LastRenderError);
end;
raise Exception.CreateFmt('Page %d failed on all available engines', [Page]);
end;
Dve načrtovalski točki tu nosita težo. Veriga zabeleži, zakaj je do vsake menjave prišlo, saj je vrstica v dnevniku, ki se glasi "ta stran je od izdaje 3.7 padla na PDFium", regresijski signal, ki ga želite spremljati v nadzoru in ne izgubiti. Vrstni red zasilnih poti je sam po sebi politika, ki jo je vredno izbrati za vsako delovno breme posebej. Vgrajeni pogon se namesti brez dodatnih knjižnic DLL, kar ga v večini namestitev postavi za pravi prvi poskus, dokumenti, obloženi s skupinami prosojnosti ali nenavadnimi senčenji, pa so običajni razlog, da ekipa sploh vgradi nadomestni pogon. Noben pogon ni na splošno najhitrejši, kar je celoten smisel izbiranja pri vsakem klicu: vsakega izmerite na vzorcu svojih resničnih dokumentov pri svojem resničnem DPI in to meritev ponovite vsakič, ko se knjižnice DLL pogonov ali mešanica dokumentov spremenijo. Razpravo vsakič dobi korpus
Onkraj posameznih strani: paketi TIFF in živi konteksti naprav
Nabor orodij zaokrožita dva soseda klicev za posamezno stran. RenderAsMultipageTIFFToFile izraz z obsegom strani upodobi naravnost v večstranski TIFF, kar je naravna oblika za arhivske predaje sistemom za upravljanje dokumentov, ki so starejši od PDF. RenderPageToDC slika neposredno na kontekst naprave Windows za kontrolnike predogleda in jo vodi lastna trojica lepljivih nastavitev (SetRenderDCOffset, SetRenderDCErasePage ter vrsta obrezovanja), ki potrebujejo enako disciplino ponastavljanja kot faktor merila. Predogled na zaslonu in upodabljanje po tiskalniški poti nosita dovolj lastnih pasti, da si zaslužita svoj članek, povezan spodaj
Kam naprej
Ena navada je vredna, da jo odnesete s seboj: ker SelectRenderer velja za vsak poznejši klic na primerku, je mogoče eno trmasto stran znova poskusiti na drugem pogonu, medtem ko preostanek dokumenta ostane na privzetem. Za slikanje predogleda, izbiro tiskalnika in ravnanje z DevMode nadaljujte s člankom o predogledu tiskanja in kontekstu naprave. Kadar upodabljanja napajajo obsežen cevovod nad zelo velikimi datotekami, se pristop na osnovi ročic iz vodnika po neposrednem dostopu naravno poveže z upodabljanjem po straneh prek DARenderPageToFile
Pakiranje pogonov, podprti zapisi in preizkusne gradnje so podrobno opisani na strani izdelka PDF Library for Delphi