Quick-Tipp: HiDPI und nicht-ganzzahlige Skalierungen

Dies ist wieder eine Übersetzung eines Xojo-Blogbeitrags, und sie dürfte vor allem Entwickler von Windows- und Linux-Software betreffen. Dort kann der Vergrößerungsfaktor für den Bildschirm frei gewählt werden, und es können auch „krumme“ Faktoren gewählt werden, 1,5fach zum Beispiel.

Was flexibel klingt, führt in der Praxis allerdings manchmal zu Problemen. Fließkomma-Werte sind ja immer nur Näherungswerte, und so mag es passieren, dass das Antialiasing, die Kantenglättung des Graphics-Objekts, einem sprichwörtlich einen Strich durch die Rechnung macht. Oder mehrere.

Kleines Beispiel: Legen Sie ein neues Desktop-Projekt an und geben Sie dem Fenster diesen Paint-Eventhandler:

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
 // Ein Abschnitt, der Einfachheit halber Schwarz, 15 px hoch:
 Dim Abschnitt As New Picture(Self.Width, 15, 32)
 Abschnitt.Graphics.FillRect(0, 0, Abschnitt.Width, Abschnitt.Height)
 
 // Das Ausgabe-Gesamtbild für den Hintergrund, Scalefactor 1.5:
 Dim AusgabeBild As New Picture(Self.Width, Self.Height, 32)
 AusgabeBild.Graphics.ScaleX = 1.5
 AusgabeBild.Graphics.ScaleY = 1.5
 
 // Jetzt so viele Abschnitte in das Ausgabebild einfügen, wie für die Fensterhöhe benötigt:
 For y As Integer = 0 To AusgabeBild.Height Step Abschnitt.Height
  AusgabeBild.Graphics.DrawPicture(Abschnitt, 0, y)
 Next 
 
 g.DrawPicture(AusgabeBild, 0, 0) // Zeichnen
End Sub

Freilich keine sehr sinnvolle Geschichte – eigentlich müsste das Fenster jetzt einen komplett schwarzen Hintergrund haben, oder?

Lassen Sie das Programm ausführen, wird das Ergebnis aber eher so aussehen:

scalefactor1-5

Wo kommen die Linien her?

Standardmäßig verwendet das Graphics-Objekt Antialiasing. Kanten werden also glatt gerechnet, was in den meisten Fällen auch absolut im Sinne des Erfinders ist – sieht einfach schöner aus als harte Pixelkanten.

Mit dem Skalierungsfaktor von 1.5 werden Pixel adressiert, die es gar nicht gibt. Der Abschnitt auf y= 15 z.B. beginnt in diesem Fall bei 15 * 1,5 = 22,5. Ein halber Pixel lässt sich schwerlich ansprechen. In diesem Fall glättet das Graphics-Objekt die Kanten durch Hinzurechnen vom Grauwerten.

Erfreulicherweise lässt sich das Antialiasing ausschalten. Wenn Sie die Zeilen, in denen Ausgabebild initialisiert wird, noch durch

AusgabeBild.Graphics.AntiAlias = false

ergänzen, wird alles wieder lückenlos dargestellt.

Und wenn Sie Antialiasing benötigen, aber keine Rundungslinien wollen?

Dann müssen Sie die Methode zur Abschnittserzeugung auslagern und in der Erstellungsschleife des Ausgabebilds die gerundete Höhe übergeben. Eine Möglichkeit sieht so aus:

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Handles Paint
 // Das Ausgabe-Gesamtbild für den Hintergrund, Scalefactor 1.5:
 dim ScaleFactor as double = 1.5
 dim Bildhöhe as Integer = 15
 Dim AusgabeBild As New Picture(Self.Width, Self.Height, 32)
 AusgabeBild.Graphics.ScaleX = ScaleFactor
 AusgabeBild.Graphics.ScaleY = ScaleFactor
 // Jetzt so viele Abschnitte in das Ausgabebild einfügen, wie für die Fensterhöhe benötigt:
 For y As Integer = 0 To AusgabeBild.Height Step 15
  dim nexty as double= ( y+1) *Bildhöhe * ScaleFactor
  dim dif as Double = nexty mod Bildhöhe*(y+1)
  AusgabeBild.Graphics.DrawPicture(Abschnitt(Bildhöhe+if (dif > 0, 1, 0), y), 0,y)
 Next 
 
 g.DrawPicture(AusgabeBild, 0, 0) 
End Sub

Die Methode zur Abschnittsberechnung, jetzt in bunt, z.B.:

Public Function Abschnitt(y as integer, col as integer) as Picture
 Dim Abschnitt As New Picture(Self.Width, y, 32)
 Abschnitt.Graphics.ForeColor = HSV(0.0005*col, 1,1)
 Abschnitt.Graphics.FillRect(0, 0, Abschnitt.Width, Abschnitt.Height)
 return Abschnitt
End Function

scalefactor-bunt

Erinnert ein bisschen an die guten alten RainbowColors zu Atari-Zeiten, oder?

Wenn Sie damit spielen mögen: Das Projekt ist hier..

 

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s