vorba.ch

Über Subpixel

von Paul Vorbach, 08.12.2012

Zum Thema Subpixel-Rendering von Fonts auf Rasterbildschirmen ist vor kurzem ein Artikel im Webkrauts-Adventskalender erschienen.

In einem Kommentar regt sich ein Leser darüber auf, dass das Beispielbild zur Subpixel-Glättung schlecht gewählt ist. Es wird nicht deutlich, dass die verschiedenen Farben bei üblichen Display-Panels horizontal nebeneinander angeordnet sind und durch diese Anordnung theoretisch die dreifache Auflösung erreicht werden kann.

Subpixel-Beispiel

Subpixel-Beispiel

Da es gar nicht so ohne weiteres möglich ist, einen Screenshot so zu vergrößern, dass die Subpixel sichtbar werden, habe ich ein Programm dafür geschrieben: Subpixel Illustrator. Damit lässt sich ein Screenshot im PNG-Format öffnen und vergrößern.

Der Kern des Programms ist – dank Scala – recht kurz:

def scaleUp(input: BufferedImage, factor: Int) = {
  require(factor > 1, "factor not greater than one")
  require(factor % 3 == 0,
    "factor not divisible by three")

  val width = input.getWidth
  val height = input.getHeight
  val step = factor / 3

  // Erzeuge leeres Bild mit `factor`-facher Größe
  val out = new BufferedImage(input.getWidth * factor,
    input.getHeight * factor,
    BufferedImage.TYPE_INT_RGB)

  // Durchlaufe das Bild Zeilenweise, von links nach
  // rechts
  for {
    _y <- 0 until height
    (yMin, yMax) = (_y * factor, (_y + 1) * factor)
                              // Vergrößere Ausschnitt
    _x <- 0 until width
    (xMin, xMax) = (_x * factor, (_x + 1) * factor)
                              // Vergrößere Ausschnitt
    _rgb = input.getRGB(_x, _y)
                              // Lies RGB-Wert
    y <- yMin until yMax
    x <- xMin until xMax
    component = {
      if (x < xMin + step) _rgb && 0xFF0000
                              // Maskiere Rotanteil
      else if (xMax - step <= x) _rgb && 0x0000FF
                              // Maskiere Blauanteil
      else _rgb && 0x00FF00
                              // Maskiere Grünanteil
    }
  } {
    out.setRGB(x, y, component)
                              // Setze neuen Farbwert
  }

  out
}
Das Ergebnis mit 15-facher Vergrößerung

Das Ergebnis mit 15-facher Vergrößerung