Net-Base Lehti

18.08.2026

VCL High-DPI: Kuvakkeiden skaalaus ajon aikana ja pikselisumennuksen välttäminen TImageListissä

High-DPI on VCL:ssä ei pelkkä valintaruutu, vaan ketju ImageList-asetuksista, DPI-vaihtotapahtumista ja puhtaasta renderöinnistä. Tässä käytännön artikkelissa näytetään, miten skaalaat kuvakkeita ajon aikana, vältät artefakteja ja jäljität tyypillisiä TImageList-loukkuja toistettavasti.

18.08.2026

Lehden aiheesta projektikäytäntöön

Artikkeliin liittyvät palvelu- ja tekniikkasivut

Kuka tahansa, joka ajaa VCL-sovelluksia moderneilla Windows-asiakkailla, törmää ennemmin tai myöhemmin samaan oireeseen: kuvakkeet näyttävät 125%/150%/200% skaalauksella sumeilta, repsottavilta tai niihin ilmestyy harmaa reuna. Juuri tässä VCL High-DPI Icons -aihe muuttuu käytännön ongelmaksi: ei siksi, että High-DPI olisi uusi asia, vaan siksi, että ongelmat ilmenevät yleensä vasta arjessa — terminaalipalvelimilla, kannettavan telakoinnin yhteydessä tai kun näytöittäin on eri DPI-arvot.

Keskeinen ongelma ei lähes koskaan ole, että PNG olisi rikki, vaan pipeline: mistä kuvake tulee (resurssi, tiedosto, SVG, fontti), missä koossa se tarjotaan, miten se päätyy TImageList:iin ja kuka skaalauksen tekee ja milloin. VCL:ssä kohtaa useita käsitteitä, jotka täytyy erottaa: DPI-Awareness (skaalaako Windows sovelluksen vai sovellus itse), Per-Monitor-DPI (jokainen näyttö voi olla erilainen) ja ImageList-Strategie (pitääkö tarjota useita resoluutioita vai rasteroida ajossa).

Tässä kirjoituksessa ei tarkoituksellisesti käydä läpi käyttöliittymäsuunnittelun keskusteluja, vaan esitellään puhdas, tuotantovarma lähestymistapa: kuvakkeiden skaalaus ajon aikana siten, että ne eivät muutu pikseliseksi mössöksi, että alpha-kanavat pysyvät ehjinä ja että DPI-muutokset toimivat ilman välkkymistä tai väärän kokoisia kuvia. Mukana ovat myös sudenkuopat, debug-vinkit ja rehellinen arvio siitä, milloin lisätyö kannattaa.

Miksi pikselimössö syntyy: skaalausketjun ymmärtäminen VCL:ssä

Grafik zur Icon-Skalierung: Master-Icon wird in mehrere Zielgrf6dfen gerastert, doppelte Skalierung ffchrt zu Unsche4rfe
Kerran master-lähteestä tehty skaalaus on hallittavissa — kaksinkertaiset resampling-vaiheet johtavat nopeasti näkyvään sumeuteen.

Yleisin syy epätarkkoihin kuvakkeisiin on kertaluonteinen down-/upscaling väärään aikaan. Perinteinen kulku legacy-VCL:ssä:

  • Sovellus toimittaa kuvakkeet vain 16×16- tai 24×24-kokoisina.
  • Windows tai VCL skaalaa ne 20×20 / 32×32 / 48×48 -kokoihin.
  • Skaalausalgoritmi käyttää interpolointia, joka sopii valokuville, mutta sumentaa reunoja pikselikuvituksessa.
  • Lisäksi läpinäkyvyys (alpha) ajetaan maskilogikaan tai muunnetaan useaan kertaan.

Tilanne pahenee erityisesti, kun useita skaalausvaiheita tapahtuu peräkkäin: esimerkiksi kun ImageList toimittaa jo skaalatun bitmappin, ja Windows skaalautuu uudelleen, koska sovellus on DPI-unaware tai järjestelmän DPI poikkeaa. Tuloksena on kaksinkertainen pehmennys.

Toinen projektissa usein aliarvostettu seikka on skaalauksen ajoitus. Per-Monitor-DPI:ssä (bzw. PMv2, eli Per-Monitor-DPI-Awareness v2) efektiivinen DPI voi muuttua, kun ikkuna siirtyy näytöltä toiselle tai kun etätyöpöytäasiakas säätää DPI:tä dynaamisesti. Jos tällöin TImageList tai välimuisti ei rakennu oikein uudelleen, kuvakkeet voivat yhtäkkiä näkyä väärässä koossa tai väärällä rasterilla.

TImageList High-DPI-tilanteessa: tyypilliset sudenkuopat oikeissa sovelluksissa

TImageList on historiallisesti suunniteltu pienille bitmapeille, kiinteillä mitoilla, indekseillä ja suhteellisen jäykällä tallennuslogiikalla. Korkean DPI:n ympäristössä tästä seuraa käytännön ansoja:

1) Kovakoodatut Width/Height

Monet VCL-lomakkeet asettavat ImageList.Width/Height suunnitteluaikana ja jättävät sen siihen. 150 %:n skaalauksessa Windows haluaisi esimerkiksi kasvattaa 16:sta 24:ään. Jos lista pysyy 16:ssa, kuva joko leikataan tai skaalaus tapahtuu muualla — molemmat epämiellyttäviä.

2) PNG-Alpha und Maskenlogik

Riippuen Delphi-versiosta ja käytetyistä VCL-komponenteista päädyt helposti sekakäyttöön: alfa-PNG:t pidetään sisäisesti osin 32-bittisinä bitmapeina, osin Mask+Color-muotoisina. Kun konvertoit useampaan kertaan (PNG → Bitmap → ImageList → Draw), syntyy harmaita haloja tai teräviä reunoja. Ilmiö on usein taustariippuvainen: tummalla työkalurivillä se näkyy pahemmin kuin vaalealla panelilla.

3) DPI-vaihdokset ajonaikana: Caches, Handles, OwnerDraw

Jotkin kontrollit välimuistittavat kuvan esityksen tai ottavat ImageList-kahvat käyttöön vaiheessa, jossa DPI ei ole vielä lopullinen. Erityisesti työkaluriveillä, TreeView/ ListView -komponenteissa ja OwnerDraw-skenaarioissa DPI-vaihdosten jälkeen nähdään ajoittaista väärän kokoisia kuvia tai tyhjiä kuvakkeita, kunnes suoritetaan repaint tai RecreateWnd.

4) Terminalserver und Remote-Desktop als Realitetstest

Kun sovellusta käytetään RDP:n kautta, DPI-vaihdokset ja istunnon uudelleenyhteydet eivät ole harvinaisia. Juuri siellä epäluja ImageList-strategia pettää: käyttäjä näkee uudelleenyhteyden jälkeen sumeita kuvakkeita tai väärin skaalattuja työkalurivejä, vaikka paikallisesti kaikki oli kunnossa.

Siisti lähestymistapa: Tarjoa useita resoluutioita brutaalin ylenskalauksen sijaan

Tärkein päätös on konseptuaalinen: Haluatko skaalata kuvakkeita ajonaikaisesti yhdestä peruskuvasta (esim. 16 → 32), vai tarjoatko useita natiiviresoluutioita ja valitset DPI:n mukaan sopivan?

Käytännössä lähes aina voittaa „useat resoluutiot“. Upscaling on hyväksyttävää, jos lähde on vektori (SVG, icon-font) tai tarvitset todella vain maltillisia kertoimia. Kun kasvatat pientä rasterikuvaa voimakkaasti, reunojen laatu kärsii, ja se näkyy nykyaikaisilla näytöillä välittömästi.

VCL-maailmassa tätä lähestymistapaa tukevat nykyään pääasiassa kaksi komponenttia:

  • TImageCollection: säiliö kuville useissa kooissa/variantteina.
  • TVirtualImageList: luo niistä ajonaikaisen ImageListin nykyiseen tarpeelliseen kokoon ja reagoi DPI-muutoksiin.

Tämä ei poista kaikkia ongelmia, mutta siirtää vastuun oikeaan paikkaan: määrittelet kuvavirrat selkeästi, ja skaalaus/valinta tapahtuu johdonmukaisesti.

VCL High-DPI -kuvakkeiden skaalaus ajonaikana: milloin se on järkevää (ja milloin ei)

On perusteltuja syitä skaalata kuvakkeita ajonaikaisesti:

  • Lataat kuvakkeita dynaamisesti (esim. plugin-kansiosta, asiakaskohtaisista brändipaketeista tai konfiguraatiopaketeista).
  • Haluat yhtenäisen pipelinein eri lähteille (ICO, PNG, SVG) etkä halua sitoa kaikkia variantteja build-aikana.
  • Luot kuvakkeita ohjelmallisesti (status-badget, overlayt, koostetut symbolit).

Ei ole järkevää tehdä ajonaikaista skaalausta, jos sinulla on käytössä vain perinteiset työkalurivin ikonit kiinteästä joukosta. Silloin vähiten ylläpitotyötä vaativa tapa on: toimittaa useita resoluutioita siististi ja antaa VCL:n valita.

Jos teet ajonaikaista skaalausta, tee se selkein säännöin:

  • Älä koskaan skaalaa jo skaalattua bitmapia uudelleen. Lähde aina master‑lähteestä (ihanteellisesti vektori tai korkearesoluutioinen).
  • Välimuisti kullekin kohdekoolle ja DPI:lle, muuten skaalaat joka Paintissa uudelleen — se kuluttaa CPU:ta ja voi nykiä.
  • Pidä alpha: minimoi konversiot, käytä 32‑bitistä RGBA:ta, älä rasteroi taustaa.

Pragmaattinen arkkitehtuuri: ikoniputki omana komponenttina

Suuremmissa sovelluksissa kannattaa aiheen sijaan hajauttamisen sijaan rakentaa pieni putki. Sen ei tarvitse olla framework — ennemminkin selkeä vastuualue:

  • Ikonin lähde: mistä master‑assetit tulevat (resurssit, tiedostot, tietokanta, API)?
  • Rasteroija/Skaalaaja: miten master muunnetaan kohdekokoon (interpolaatio, tarvittaessa SVG‑renderointi)?
  • Välimuisti: avain (Icon‑ID, kohdepikselit, DPI, Theme) ja elinkaari (invalidointi DPI‑vaihdossa, Theme‑vaihdossa, paketinvaihdossa).
  • Consumer‑Adapter: miten tulos päätyy VCL‑rakenteisiin (TImageList/TVirtualImageList, OwnerDraw, PaintBox)?

Etuna: voit toistettavasti debugata DPI‑bugit yhdestä paikasta sen sijaan, että etsisit 40 Formeista „missä taas skaalataan“.

DPI‑vaihdot käsitellään oikein: Ereignisse, Rebuild, Repaint

Kannettava, jossa kaksi erilaista DPI‑näyttöä, ikkunan vaihto näyttää työpöytäsovelluksessa eri ikonikoot
Per‑monitor DPI on todellisuustesti: näytön vaihtuessa ikoniputken täytyy rasternoida uudelleen, ei vain piirtää uudelleen.

Alustalla Windows DPI‑vaihdot muodostavat oman elinkaarensa. VCL:ssä on versiosta ja DPI‑awarenessista riippuen useita tapahtumia/mekanismeja, mutta perusperiaate säilyy:

  • Kun ikkunan DPI muuttuu, pikseleihin sidotut kuvaresurssit tulee tarjota uudelleen.
  • Jos täytät ImageLists dynaamisesti, pelkkä ‚Invalidate‘ ei usein riitä — tarvitset ein Rebuild kuville uuteen kohdekokoon.

Käytännöllinen malli: DPI‑muutoksen yhteydessä (esim. Form‑Scale/monitorinvaihto) invalidioit ikonivälimuistin kyseiselle DPI:lle ja rakennat vaikuttavat ImageListit uudelleen. Tärkeää on älä skaalaa Paint‑tapahtumissa, vaan tehdä se kontrolloidussa päivityslohkossa (Toolbar.BeginUpdate/EndUpdate, ListView‑Redraw pois päältä, sitten takaisin päälle). Näin vältät välkkymistä ja keskeneräisiä käyttöliittymätiloja.

Miksi TImageList usein muuttuu epäteräväksi: Interpolaatio, DPI‑pyöristys, reunat

Kun ymmärrät, ettei ongelmana ole pelkkä DPI vaan interpolaatio plus pyöristys, monet ilmiöt selittyvät:

  • DPI-pyöristys: 125 % ei ole siisti kaksinkertaistus. 16 px:stä tulee 20 px (16 * 1,25). 24 px:stä tulee 30 px. Nämä ovat epäsäännöllisiä arvoja, jotka vaikeuttavat pikselireunojen hallintaa.
  • Resampling-suodattimet: Bilinear/Bicubic pehmentää reunoja. Se sopii valokuville, mutta usein ei ikooneille.
  • Subpixel-ilmiöt: Windows voi renderöintipolusta riippuen hyödyntää subpixel-antialiasingia tai olla hyödyntämättä. Ikooneissa haluat hallitut reunat — ja mieluiten ei useita peräkkäisiä suodatusasteita.

Jos sinulla on rasteri-ikonit, on monissa tiimeissä yleinen käytäntö toimittaa kohdekokoja varten erilliset PNG:t (16/20/24/32/40/48). Kuulostaa paljon, mutta usein se on vähemmän työtä kuin vuosien ajan selvittää, miksi se näyttää kummalliselta juuri tällä näytöllä.

Debuggaus: Tee pikselimössöstä toistettava ongelma sen sijaan, että korjaat mutu-tuntumalta

Työasema debug-muistiinpanoineen ikonien skaalausta ja taustatestejä varten
Hyvät DPI-debuggausrutiinit testaavat kokoja, taustoja ja uudelleenrakennuksen ajankohtia — eivät vain ensimmäistä kuvakaappausta.

High-DPI-virheet vaikuttavat usein satunnaisilta. Muutamalla tarkistuksella ne muutuvat deterministisiksi:

1) Kirjaa suoritusaikaisesti DPI ja ImageList-koot

Kirjaa käynnistyksessä ja DPI-vaihdossa: Formin CurrentPPI, Screen.PixelsPerInch (huom: tämä voi olla järjestelmän DPI), sekä kohteena olevien listojen ImageList.Width/Height. Jos monitorinvaihdon jälkeen näet edelleen 16, vaikka odotat 32:ta, syy on selvä: uudelleenrakennus puuttuu tai tapahtuu liian myöhään.

2) Suurenna ikonit näkyvästi

Nopea testi on asettaa työkalurivin ikonit väliaikaisesti 48 px:iin. Huono skaalaus hyppää silloin heti silmään. Hyvät putket pysyvät myös 48 px:ssä terävinä, koska ne rasteroidaan sopivasta lähteestä.

3) Testaa teema- ja taustanvaihdot

Reunan haloilmiöt ovat usein alpha-/premultiply-ongelmia. Testaa vaalealla/tummalla taustalla ja liukuväripinnoilla. Jos reuna näyttää eri taustoilla erilaiselta, läpinäkyvyyden käsittely on väärin.

4) Remote Desktop / näyttöjen vaihto testiskriptinä

Laadi lyhyt testiskripti QS:lle: käynnistä sovellus näytöllä A (100 %), siirrä ikkuna näytölle B (150 %), palauta, tee RDP-yhteyden uudelleenmuodostus. Jos tämä toimii stabiilisti, monet asiakkaiden ongelmat ovat jo ratkaistu.

Migraatio olemassa olevissa sovelluksissa: vaiheittain ennemmin kuin Big Bang

Laajentuneissa Delphi-VCL-sovelluksissa ikonilogiikka on usein hajallaan monessa paikassa: valikot, työkalurivit, ActionLists, TreeViews, tilanäytöt. Big-Bang-uudistus tuo riskiä. Toimivaksi on osoittautunut vaiheittainen lähestymistapa:

  • Inventaario: Mitkä ImageListit on olemassa? Mitä kontrolleja ne käyttävät? Mitä kokoja odotetaan?
  • Priorisointi: Aloita näkyvimmistä alueista (päätyökalurivi, navigaatio, kontekstivalikot).
  • Yhtenäinen lähde: Keskitä ikonit (ImageCollection tai oma lataaja) sen sijaan, että jokaiselle lomakkeelle ladataan erilliset tiedostot.
  • DPI-vaihtojen testaus: Ensimmäisestä muutetusta moduulista alkaen aja johdonmukaisesti DPI-vaihtotestejä.

Tärkeää: Jos ylläpidät rinnakkain vanhaa ja uutta pipelinea, dokumentoi selkeät säännöt. Muussa tapauksessa syntyy sekamelska, jossa osa ikoneista on teräviä ja toiset näkyvästi epäteräviä.

Suorituskyky ja muisti: ajonaikainen skaalaus ilman sivuvaikutuksia

Skaalaus kuluttaa CPU:ta ja muistia. Liiketoimintaohjelmassa se harvoin näkyy tyhjäkäynnillä, mutta ikkunan siirtäminen uudelle näytölle tai käynnistys monilla lomakkeilla voi pätkiä. Kolme käytännön ohjetta:

  • Rajoita välimuistien kokoja: Älä pidä jokaista väliastetta ikuisesti. Jos tarvitset vain 100 % ja 150 %, välimuista vain näille.
  • Lazy Build: Rasteroi ikonit vasta, kun näyttö ne todella tarvitsee. Suurissa valikoissa se säästää käynnistysaikaa.
  • Batch-Rebuild: DPI-muutoksessa älä laukaise jokaisen kontrollin uudelleenrakennusta erikseen. Keskitetty rebuild estää päällekkäistä skaalausta.

Jos käytät TVirtualImageList:iä, suuri osa tästä on jo konseptina mukana, mutta sinun on silti varottava ettet lisää vielä omaa ylimääräistä skaalausta päälle.

Fallback-strategiat: mitä tehdä, jos kaikkia ikonikokoja ei ole saatavilla?

Reaaliolosuhteissa sinulla ei aina ole kaikkia assetteja kaikissa kooissa. Tarvitset selkeän fallback-strategian satunnaisten tulosten välttämiseksi:

  • Prefer Downscale: Mieluummin skaalataan alaspäin 64 px → 32 px kuin ylös 16 px → 32 px.
  • Määrittele tasot: Määrittele, mitä kohdekokoja todella tuet (esim. 16/20/24/32/40/48) ja kartoita DPI niihin johdonmukaisesti.
  • Testaa läpinäkyvyys: Fallbackeissa kiinnitä erityisesti huomiota alfadefekteihin, sillä juuri siellä syntyy haloja.

Tyypillinen virhe on käyttää vain „jonkin seuraavan“ kokoa. Silloin havaittu terävyys vaihtelee ikonista riippuen. Parempi on tiukka, dokumentoitu mapping-suunnitelma.

Milloin vaiva kannattaa oikeasti?

On kolme selkeää indikaattoria, että siisti High-DPI-ikoniputki kannattaa rakentaa:

  • Käyttäjäsi käyttävät sekoitettuja näyttöjä (kannettava + ulkoinen) tai paljon RDP-yhteyksiä.
  • Sovellus on pitkäikäinen ja sitä ylläpidetään vuosia — käyttöliittymän havaittavuus vaikuttaa hyväksyntään.
  • Sinulla on joka tapauksessa modernisointiaskeleita edessä (DPI-awarenessin nosto, kontrollien vaihto, työkalurivin layoutin uudelleenkatselu).

Jos sovellus sen sijaan ajetaan vain kiinteässä kiosk-järjestelmässä, jossa resoluutio on identtinen, voi aiheen pitää minimissään: toimita sopiva ikonikoko, aseta DPI-awareness oikein ja sillä selvä.

Yhteenveto: High-DPI ei ole kosmeettinen yksityiskohta vaan renderointipäätös

Epäterävät ikonit VCL:ssä eivät ole usein erillinen virhe, vaan osoitus epätäydellisestä ketjusta lähteistä, skaalauksesta ja cachingistä. Varmuin ratkaisu on tarjota ikonit useissa resoluutioissa ja toimittaa ne keskitetyn putken kautta (ImageCollection/VirtualImageList tai oma ikonikerros) johdonmukaisesti. Ajonaikainen skaalaus on järkevää, kun sinulla on dynaamisia lähteitä tai koostettuja symboleja, mutta vain silloin kun käytössä on ensisijainen lähde, DPI-perusteinen välimuisti ja selkeät uudelleenrakennussäännöt.

Jos sinulla on konkreettisia oireita (DPI-muutos rikkoo ikonit, haloja reunoilla, väärät koot RDP:n jälkeen), kannattaa aihe eristää ja käsitellä pienenä arkkitehtuurikomponenttina sen sijaan, että kasaat workaroundeja lomakkeittain. Jos tarvitset tukea debuggaamiseen tai vaiheittaiseen modernisointiin, löydät täältä sopivan aloituksen: Ota yhteyttä Net-Base Software GmbH.

Tämän aiheen kannalta myös Timagelist High Dpi ja Delphi Vcl Dpi-Awareness ovat tärkeitä. Artikkeli jäsentää nämä näkökohdat selkeästi ja näyttää, mihin arjessa on kiinnitettävä huomiota.

Keskustele projektista tai modernisointihankkeesta Net-Base kanssa.

Seuraava vaihe

Kun aiheesta muodostuu todellinen projekti, arkkitehtuuri, nykytila ja operointi on tarkasteltava yhdessä varhaisessa vaiheessa.

Emme tue pelkästään yksittäiskysymyksissä, vaan myös silloin, kun lähdekoodipalasista, legacy-aiheista tai portaali-ideoista halutaan muodostaa luotettava yrityshanke.

  • Nykytila, tavoitetila ja tekniset riskit arvioidaan yhdessä.
  • REST, tietojen käyttö, portaalit ja käyttöönotto eivät siirry myöhempään vaiheeseen.
  • Näette ajoissa, mikä vaihtoehto on taloudellisesti ja operatiivisesti kannattava.

Jaa artikkeli

Jaa tämä viesti suoraan

LinkedIn, X, XING, Facebook, WhatsApp ja sähköposti ovat välittömästi saatavilla. Instagramia varten valmistelemme linkin ja lyhyen tekstin.

Sähköposti

Instagram avautuu uuteen välilehteen. Linkki ja lyhyt teksti kopioidaan ensin leikepöydälle.