Tehnični članak

Barvni filtri PDF za slabovidne v Delphiju s PDFium

Slaboviden bralec pri privzetem kontrastu ne razloči črnega besedila na beli strani, zato prosi za temni način. Naivni odgovor je obrniti vsako slikovno piko izrisane strani. Odpremi se v tednu dni in se pokvari naslednji dan: skenirane fotografije se vrnejo videti kot filmski negativi, bralčeve rumene oznake z markerjem se spremenijo v neberljiv moder madež, nekdo pa vpraša, zakaj je izpis prišel ven povsem črn. Zmožnost je resnično vredna gradnje in jo je resnično lahko narediti napol prav, razlika med obema izidoma pa je ena zamisel: vsaka barvna odločitev sodi na določeno točko izrisovalnega cevovoda, obračanje pa je napačno orodje, uporabljeno na napačni stopnji. Koda tukaj uporablja PDFium Component, pregledovalnik na osnovi PDFium za Delphi, C++Builder in Lazarus, katerega izrisovalni vmesnik te stopnje izpostavlja ločeno

Filtri so stanje predstavitve, nikoli stanje dokumenta

Eno pravilo prepreči najhujši razred hroščev tukaj: način branja spremeni, kako se bitna slika ustvari ali naknadno obdela, in nič drugega. Bajti PDF ostanejo nedotaknjeni, vsak način je povraten s ponovnim izrisom, »shrani« pa filtriranega videza nikoli ne zapiše nazaj v datoteko. To zveni očitno, dokler pravni pregledovalec pod dejavnim filtrom ne natisne pogodbe in vloži obrnjene različice. Na tej točki se izkaže, da vprašanje »ali tiskanje uporabi dokumentov lastni videz ali zaslonovega« zasluži izrecen odgovor v vaši specifikaciji in ne naključja kodne poti. Nastavitev filtra hranite v stanju pregledovalnika, jo uveljavite ob izrisu in poskrbite, da vsaka izvozna pot razglasi, kateri videz uporablja

Pravilo se povrne dvakrat. Povratnost pride zastonj, ker preklop načina znova izriše iz nespremenjenega vira: ni sklada razveljavitev, ki bi ga bilo treba vzdrževati, in ni načina, da bi niz sprememb načina stran poslabšal. Iz istega razloga ostanejo večokenski scenariji dosledni. Dva pogleda na en dokument lahko tečeta v različnih načinih, saj je vsak pogled lastnik svojega stanja predstavitve, objekt dokumenta pa ostane skupen

Najprej izris, nato preslikava

Podprti vzorec je obdelava bitne slike po izrisu: RenderPage ustvari raster strani, nato pa ga preslikovalni prehod prilagodi. Komponenta prinaša tri preslikave kot operacije na bitni sliki na mestu, InvertPdfBitmap, DuotonePdfBitmap in GrayscalePdfBitmap, zaradi česar je preklop načina čista dvostopenjska funkcija:

Diagram cevovoda načinov branja v pregledovalniku PDF v Delphiju, kjer en sam klic PDFium RenderPage napaja štiri načine branja, vsak pa je preslikava bitne slike na mestu, denimo InvertPdfBitmap ali DuotonePdfBitmap
RenderPage raster ustvari enkrat, dejavni način branja pa izbere eno preslikavo bitne slike na mestu
function TViewerForm.RenderWithMode(W, H: Integer): TBitmap;
begin
  Result := Pdf.RenderPage(0, 0, W, H, ro0, [reAnnotations]);
  case FReadingMode of
    rmInverted:     InvertPdfBitmap(Result);
    rmHighContrast: DuotonePdfBitmap(Result, clBlack, $0000C8FF);  // temno ozadje, jantarno besedilo
    rmGrayscale:    GrayscalePdfBitmap(Result);
  end;
  // rmNormal pade skozi: dokument obdrži svoje barve
end;

Iz te zasnove sledita dve stvari. Prvič, strošek preslikave je sorazmeren z velikostjo bitne slike, zato delo sodi tja, kjer se hranijo vaši izrisani rezultati: predpomnjeno bitno sliko filtrirajte enkrat, ne pri vsakem risanju. Drugič, ker preslikava teče na dokončanem rastru, enako zadene besedilo, vektorsko grafiko, slike in videze anotacij. Prav ta enakomernost je tisto, kar navadno obračanje zgreši pri fotografijah. To je razlog, da je preslikava duotone boljša privzeta izbira za dokumente, bogate z besedilom, saj svetlost preslika na izbrano barvno rampo od temne do svetle, namesto da bi negirala odtenke; obračanje ostane na voljo kot izrecna izbira za bralce, ki ga želijo. Ostrejši robovi pismenk so ločen vzvod. Izrisovalna možnost reNoSmoothText ob izrisu izklopi glajenje besedila in se dobro ujema z visokokontrastnim načinom pri veliki povečavi

Dvoje sivin, ki se ne strinjata

Med izrisovalnimi možnostmi je reGrayscale, ki je videti kot bližnjica mimo koraka naknadne obdelave. Ni ista operacija:

Diagram, ki primerja izrisovalno možnost PDFium reGrayscale, ki razbarva slike, a pusti obarvane naslove, z naknadno obdelavo GrayscalePdfBitmap v Delphiju, ki pretvori celotno stran
Možnost pogona razbarva vsebino slik, naknadna obdelava pa pretvori vsako slikovno piko dokončane bitne slike
// Na ravni pogona: sivine, uporabljene med rasterizacijo
GrayA := Pdf.RenderPage(0, 0, W, H, ro0, [reGrayscale]);

// Naknadna obdelava: izriši v barvah, pretvori dokončano bitno sliko
GrayB := Pdf.RenderPage(0, 0, W, H);
GrayscalePdfBitmap(GrayB);

Možnost na ravni pogona velja za rastrski izhod slikovne vsebine, ne seže pa do vektorskih polnil ali barv besedila, zato se stran z obarvanimi naslovi lahko vrne s sivimi fotografijami in trmasto modrimi naslovi. GrayscalePdfBitmap na dokončani bitni sliki pretvori vse, brezpogojno. Izrisovalna možnost si mesto vseeno zasluži, kadar želite razbarvane slike ob ohranjeni barvi besedila kot signalu, kar nekateri slabovidni bralci izrecno raje imajo. Če pa zahteva pravi »stran v sivinah«, jo zadovolji različica z naknadno obdelavo. Katero koli pot izberete, imejte v mislih oba sloga preobložitve RenderPage. Funkcijska oblika vrne bitno sliko, katere lastnik je klicatelj in jo mora sprostiti, kar postane pomembno takoj, ko filtri pomnožijo število izrisanih bitnih slik v obtoku

Ozadja, oznake izbora in past PageColor

Ni vsaka prilagoditev udobja preslikava. Zamenjava belega ozadja strani s toplim odtenkom je za bralce, občutljive na bleščanje, pogosto že sama po sebi dovolj in ima namensko lastnost. Ta lastnost nosi pravilo dosega, ki ljudi ujame:

Diagram pasti dosega PageColor v pregledovalniku PDF v Delphiju: odtenek se pokaže na zaslonu, izhod RenderPage pa ostane bel, razen če se barva poda izrecno
PageColor obarva le pogled na zaslonu, RenderPage pa ohrani belo stran, razen če se barva poda izrecno
// Vpliva le na pogled na zaslonu
PdfView.PageColor := $00D9EDF2;  // topel papirnat ton za vsebino strani

// izhod RenderPage prezre PageColor; barvo podajte izrecno
Bmp := Pdf.RenderPage(0, 0, W, H, ro0, [], $00D9EDF2);

PageColor spremeni, kaj prikazuje TPdfView, bitne slike, ustvarjene prek RenderPage, pa ohranijo privzeto belo, razen če parameter Color pove drugače. Simptom je zanesljiv: zaslon kaže obarvano stran, uporabnik izvozi ali natisne, izhod pa se vrne v belo. To uvrstite pod isto odločitev o izvozni politiki iz prvega razdelka

Preostale barvne lastnosti določajo prekrivne oznake: HighlightColor za zadetke iskanja, SelectionColor za uporabnikov izbor besedila, ReadingWordColor za kazalec izgovorjene besede. Vsako od njih je treba znova preveriti pod vsakim filtrom, ki ga ponujate. Jantarni bralni kazalec, ki deluje na belem, po obračanju izgine; bledo moder izbor se izgubi v visokokontrastnem ozadju. Vzdržujte prekrivne palete za posamezen način namesto enega globalnega nabora in kombinacije preizkusite namenoma. Filtri skupaj s pretvorbo besedila v govor so za bralce, ki jim ta zmožnost služi, običajna konfiguracija in ne robni primer. Samo mehaniko prekrivanja pokriva članek o dostopnem bralniku

Številke, preverjanje in vprašanje tiskanja

WCAG 2.1 to zmožnost spremeni v nekaj, kar lahko izmerite. Merilo uspešnosti 1.4.3 zahteva razmerje kontrasta 4,5:1 za besedilo telesa, 1.4.6 pa ga za izboljšan kontrast dvigne na 7:1. Svoj visokokontrastni način naključno preverite proti tema razmerjema z analizatorjem kontrasta, pognanim na dejanskem izrisanem izhodu. Besedilo čez slike in besedilo v poljih obrazcev sta mesti, kjer razmerja tiho padejo, tudi ko besedilo telesa prestane

Tiskanje si zasluži svojo odločitev, zagovorljiva privzeta izbira pa je dokumentov lastni videz, pri čemer se »natisni, kot je prikazano« ponudi kot izrecna uporabnikova izbira. Natisnjena stran je dokaz v več potekih dela, kot avtorji pregledovalnikov ponavadi pričakujejo, obrnjen izpis pogodbe pa je podporni incident s pravnim priokusom. Za zmogljivost je pomembno še eno parjenje: filtriran izris ob vsakem preklopu načina podvoji delo z bitnimi slikami, zato preslikave ne uporabljajte ob vsakem sporočilu za risanje. Filtrirano bitno sliko predpomnite in preslikavo znova poženite le tedaj, ko se stran, povečava ali način resnično spremenijo. Strategija predpomnjenja, ki to poceni, živi v članku o predpomnilniku izrisa in zmogljivosti povečave

Eno stvar razrešite v svojem uporabniškem vmesniku in ne v kodi: kateri način je pravi privzeti. Enotnega odgovora ni, zato ponudite nabor in pustite bralcu izbrati. Visok kontrast ustreza večini branja, bogatega z besedilom, obračanje se prilega bralcem, ki izrecno želijo svetlo na temnem, sivine odrežejo barvni šum, odtenek ozadja pa poskrbi za občutljivost na bleščanje. Izbiro shranite za vsakega uporabnika, jo ob zagonu obnovite in ohranite pot nazaj v običajni način z enim pritiskom tipke, saj bralec, ki pristane v načinu, ki ga ne more brati, potrebuje hiter izhod

Uporabljene izrisovalne možnosti, preslikave bitnih slik in barvne lastnosti pogleda so priložene paketu PDFium Component za Delphi, C++Builder in Lazarus/FPC, skupaj s polno izvorno kodo, tako da je mogoče izvedbe preslikav revidirati ali razširiti