Kornkreise im Pixelfeld
4. Juli 2013 von Yhoko
Obwohl Vektorgrafiken ihre Vorzüge haben und die Display-Auflösungen immer feiner werden gibt es noch zahlreiche Fälle, in denen kleine Kreise auf einem groben Pixelraster dargestellt werden müssen. Windows leistet sich einige Patzer dabei, diese glaubhaft darzustellen.
Pixel sind die Essenz des (Computer-)Lebens. Immer mehr Geräte versuchen heutzutage durch "HD" Displays die Pixel zu kaschieren. Zweifellos sind die schrägen Linien beim "V" hübscher anzusehen, je mehr Pixel sie umfassen. Das lässt sich leicht mit jedem Monitor überprüfen, indem man einfach die Schrift grösser macht. Aber Vorsicht: Je nach Betriebssystem werden kleine Schriftarten verpixelt dargestellt, ab einer bestimmten Grösse jedoch (sobald genügend Pixel dafür vorhanden sind) kommt Anti-Alias ins Spiel. Anti-Alias bedeutet, dass bei Linien, die nicht genau auf dem Pixelraster liegen, zusätzliche, transparente Pixel angesetzt werden, um für das Auge den Eindruck zu verbessern. Neuerdings werden diese auch eingefärbt, um die Optik noch weiter aufzupolieren - der Microsoft-Begriff dafür lautet "ClearType" und dürfte den meisten bekannt sein. So sieht das übrigens in Aktion aus, links im Original und rechts stark vergrössert:
Dass in meinen Augen der untere Text einfach nur verschwommen daherkommt, besprechen wir ein anderes Mal. Bevor wir uns also in Antialias verlieren wieder ein Sprung zurück in die Pixelwelt, um genau zu sein in die Pixelwelt der Kreise. Kreise sind rund, Pixel sinds i.d.R. nicht, und wie schon die alten Ägypter kämpft auch die moderne Technik mit diesem Problem. Wie bildet man also den handelsüblichen Kreis auf einem Pixelraster ab? Das Prinzip dürfte jedem klar sein, der schonmal einen Zirkel bedient hat: Man wählt einen Mittelpunkt, definiert den Radius und färbt dann alle Punkte ein, die sich auf diesem Radius um den Mittelpunkt herum befinden. In der Realität ein Kinderspiel, aber auf dem Bildschirm?
Eine Möglichkeit besteht darin, mit sin() und cos() zu arbeiten - keine Panik! Das ist zwar Mathematik aber wirklich nicht schwer. Im Grunde gibt man diesen Funktionen einfach nur einen Winkel und sie liefern die y- und x-Position des dazugehörigen Punktes auf dem Einheitskreis. Warum Einheitskreis? Ganz einfach: Egal wie gross ein Kreis ist, er sieht immer genau gleich aus, nämlich rund. Anders ausgedrückt, wenn man den Punkt erstmal gefunden hat, muss man das ganze nur noch auf die gewünschte Grösse skalieren und genau das geschieht, indem man den Einheitskreis mit dem gewünschten Radius multipliziert. Oder bildlich ausgedrückt:
PS: Der Radius zeigt nach rechts zu 0° weil man das so festgelegt hat. In der Mathematik und daher auch beim Programmieren ist 0° nicht oben sondern rechts.
Oh nein, Geometrie! Also in wenigen Worten: Ausgehend vom Mittelpunkt M gibt uns cos() und sin() die Position des violetten Punktes auf dem Einheitskreis. Multipliziert man diese mit dem Radius r erhält man den roten Punkt, der beim selben Winkel auf dem gewünschten Kreis liegt. Das wars auch schon.
Ausgehend davon könnte man jetzt also einfach alle Winkel von 0° bis 360° durchgehen und die Punkte auf dem Pixelraster einzeichnen. Das sieht dann etwa so aus:
Okay, das sind nicht 360 Punkte sondern nur 12. Warum? Die Anzahl hängt von der Grösse des Pixelrasters ab und um den Effekt besser zeigen zu können, habe ich ein ziemlich grosses Raster gewählt. Nun sieht man auch schon das erste Problem, nämlich dass 4 Punkte genau auf dem Raster liegen. Nimmt man da jetzt besser die inneren oder äusseren Pixel? Je nachdem sieht der Kreis dann so oder so aus:
Links haben wir nichts anderes als ein Quadrat, dass auf der Ecke steht und rechts eines mit abgerundeten Ecken. Ich persönlich bevorzuge das Rechte. Die Ecken sind aber nur abgerundet, weil lediglich 12 Punkte berechnet wurden. Bei 24 Punkten hätte es diese Ecken auch erwischt:
Eindeutig klobiger, aber diesmal ist das Raster links irgendwie runder als das Quadrat rechts.
Und damit sind wir auch schon beim Kern der Sache angelangt: Die Formel, wie ein Kreis gerastert wird. In der Praxis gibt es natürlich bessere Methoden als für jeden Punkt sin() und cos() zu bemühen, denn diese Funktionen sind vergleichsweise rechenintensiv. Das soll uns jetzt aber nicht weiter kümmern, denn letztendlich geht es nur darum, wie der Kreis auf dem Raster abgebildet wird und zwar insbesondere bei kleinen Radien. Microsoft hat sich bei mir besonders unbeliebt gemacht, indem sie das Vorgehen von Windows 98 zu Windows XP geändert haben. Und damit ist auch dieser Beitrag in der Praxis angekommen, denn nun zeige ich euch einige Kreise, wie sie beispielsweise in MS Paint unter Windows XP entstehen:
Unter den Kreisen steht jeweils der Durchmesser in Pixeln. Bezeichnend: Kreise mit einem Durchmesser von 1 bis 2 Pixeln gibt es für Microsoft nicht - die sind wohl einfach nicht wichtig genug (ein Kreis mit Durchmesser 1 ist für mich ein einzelner Pixel, aber was solls...). Erst bei 2x3 oder 3x3 Pixeln darf der Pinsel endlich loslegen, auch wenn dabei nur ein kleiner Strich herauskommt (übrigens in beiden Fällen exakt derselbe Strich). Moment mal. Ein Kreis ist doch rund, müsste der Strich also nicht zumindest gleich breit wie hoch sein? ... Hat das denn niemand getestet? Die Geburten bei 9, 10 und 13 Pixeln Durchmesser sind immerhin regelmässig, wenn auch eher sternförmig als rund. Skurril wirds wieder bei 14 (oval..?) und 15 (rechts abgeflacht..?) Pixeln, ein klares Versagen seitens der Entwickler. Über die beste Formel lässt sich streiten, aber Kreise haben definitiv regelmässig zu sein. Die letzten drei Exemplare zeigen noch, dass auch grössere Kreise an 4 Stellen recht kantig werden - bei 16 und 18 ist alles in Ordnung, bei 17 jedoch kleben dort seltsame "Ecken" am Kreis.
Wer jetzt denkt, das wären nur ausgesuchte Negativbeispiele, den muss ich enttäuschen - die kommen erst noch. Zwar nicht kreisrund aber dennoch schön anzusehen. Zum Abschluss also ein paar wunderbare Beispiele, generiert von Windows XP:
Asymmetrisch, Lücken zwischen den Pixeln, meine Güte... Bei diesem Anblick drängt sich mir nur das Wort "Versager" auf. Übrigens handelt es sich dabei nicht um eine reine Windows XP Macke - auch Windows 7 läuft hier nicht wirklich "rund". Zwar hat sich Microsoft der alten Formel angenähert, aber Kreise mit einem Durchmesser von 1 (inexistent), 2 (skurril deformiert), 6 (lustig deformiert), 14 (wie oben 15) sowie Ovale à la 5x13 oder 5x18 sind auch weiterhin einfach nur traurige Pixelhaufen.
Ich habe fertig.
Nachtrag: Wer malt denn nun eigentlich die Kreise? Nein, der schwarze Peter liegt nicht bei MS Paint sondern in der Windows API selbst. Betroffen sind also auch sämtliche Anwendungen, welche die API zum Zeichnen verwenden.
Dass in meinen Augen der untere Text einfach nur verschwommen daherkommt, besprechen wir ein anderes Mal. Bevor wir uns also in Antialias verlieren wieder ein Sprung zurück in die Pixelwelt, um genau zu sein in die Pixelwelt der Kreise. Kreise sind rund, Pixel sinds i.d.R. nicht, und wie schon die alten Ägypter kämpft auch die moderne Technik mit diesem Problem. Wie bildet man also den handelsüblichen Kreis auf einem Pixelraster ab? Das Prinzip dürfte jedem klar sein, der schonmal einen Zirkel bedient hat: Man wählt einen Mittelpunkt, definiert den Radius und färbt dann alle Punkte ein, die sich auf diesem Radius um den Mittelpunkt herum befinden. In der Realität ein Kinderspiel, aber auf dem Bildschirm?
Eine Möglichkeit besteht darin, mit sin() und cos() zu arbeiten - keine Panik! Das ist zwar Mathematik aber wirklich nicht schwer. Im Grunde gibt man diesen Funktionen einfach nur einen Winkel und sie liefern die y- und x-Position des dazugehörigen Punktes auf dem Einheitskreis. Warum Einheitskreis? Ganz einfach: Egal wie gross ein Kreis ist, er sieht immer genau gleich aus, nämlich rund. Anders ausgedrückt, wenn man den Punkt erstmal gefunden hat, muss man das ganze nur noch auf die gewünschte Grösse skalieren und genau das geschieht, indem man den Einheitskreis mit dem gewünschten Radius multipliziert. Oder bildlich ausgedrückt:
PS: Der Radius zeigt nach rechts zu 0° weil man das so festgelegt hat. In der Mathematik und daher auch beim Programmieren ist 0° nicht oben sondern rechts.
Oh nein, Geometrie! Also in wenigen Worten: Ausgehend vom Mittelpunkt M gibt uns cos() und sin() die Position des violetten Punktes auf dem Einheitskreis. Multipliziert man diese mit dem Radius r erhält man den roten Punkt, der beim selben Winkel auf dem gewünschten Kreis liegt. Das wars auch schon.
Ausgehend davon könnte man jetzt also einfach alle Winkel von 0° bis 360° durchgehen und die Punkte auf dem Pixelraster einzeichnen. Das sieht dann etwa so aus:
Okay, das sind nicht 360 Punkte sondern nur 12. Warum? Die Anzahl hängt von der Grösse des Pixelrasters ab und um den Effekt besser zeigen zu können, habe ich ein ziemlich grosses Raster gewählt. Nun sieht man auch schon das erste Problem, nämlich dass 4 Punkte genau auf dem Raster liegen. Nimmt man da jetzt besser die inneren oder äusseren Pixel? Je nachdem sieht der Kreis dann so oder so aus:
Links haben wir nichts anderes als ein Quadrat, dass auf der Ecke steht und rechts eines mit abgerundeten Ecken. Ich persönlich bevorzuge das Rechte. Die Ecken sind aber nur abgerundet, weil lediglich 12 Punkte berechnet wurden. Bei 24 Punkten hätte es diese Ecken auch erwischt:
Eindeutig klobiger, aber diesmal ist das Raster links irgendwie runder als das Quadrat rechts.
Und damit sind wir auch schon beim Kern der Sache angelangt: Die Formel, wie ein Kreis gerastert wird. In der Praxis gibt es natürlich bessere Methoden als für jeden Punkt sin() und cos() zu bemühen, denn diese Funktionen sind vergleichsweise rechenintensiv. Das soll uns jetzt aber nicht weiter kümmern, denn letztendlich geht es nur darum, wie der Kreis auf dem Raster abgebildet wird und zwar insbesondere bei kleinen Radien. Microsoft hat sich bei mir besonders unbeliebt gemacht, indem sie das Vorgehen von Windows 98 zu Windows XP geändert haben. Und damit ist auch dieser Beitrag in der Praxis angekommen, denn nun zeige ich euch einige Kreise, wie sie beispielsweise in MS Paint unter Windows XP entstehen:
Unter den Kreisen steht jeweils der Durchmesser in Pixeln. Bezeichnend: Kreise mit einem Durchmesser von 1 bis 2 Pixeln gibt es für Microsoft nicht - die sind wohl einfach nicht wichtig genug (ein Kreis mit Durchmesser 1 ist für mich ein einzelner Pixel, aber was solls...). Erst bei 2x3 oder 3x3 Pixeln darf der Pinsel endlich loslegen, auch wenn dabei nur ein kleiner Strich herauskommt (übrigens in beiden Fällen exakt derselbe Strich). Moment mal. Ein Kreis ist doch rund, müsste der Strich also nicht zumindest gleich breit wie hoch sein? ... Hat das denn niemand getestet? Die Geburten bei 9, 10 und 13 Pixeln Durchmesser sind immerhin regelmässig, wenn auch eher sternförmig als rund. Skurril wirds wieder bei 14 (oval..?) und 15 (rechts abgeflacht..?) Pixeln, ein klares Versagen seitens der Entwickler. Über die beste Formel lässt sich streiten, aber Kreise haben definitiv regelmässig zu sein. Die letzten drei Exemplare zeigen noch, dass auch grössere Kreise an 4 Stellen recht kantig werden - bei 16 und 18 ist alles in Ordnung, bei 17 jedoch kleben dort seltsame "Ecken" am Kreis.
Wer jetzt denkt, das wären nur ausgesuchte Negativbeispiele, den muss ich enttäuschen - die kommen erst noch. Zwar nicht kreisrund aber dennoch schön anzusehen. Zum Abschluss also ein paar wunderbare Beispiele, generiert von Windows XP:
Asymmetrisch, Lücken zwischen den Pixeln, meine Güte... Bei diesem Anblick drängt sich mir nur das Wort "Versager" auf. Übrigens handelt es sich dabei nicht um eine reine Windows XP Macke - auch Windows 7 läuft hier nicht wirklich "rund". Zwar hat sich Microsoft der alten Formel angenähert, aber Kreise mit einem Durchmesser von 1 (inexistent), 2 (skurril deformiert), 6 (lustig deformiert), 14 (wie oben 15) sowie Ovale à la 5x13 oder 5x18 sind auch weiterhin einfach nur traurige Pixelhaufen.
Ich habe fertig.
Nachtrag: Wer malt denn nun eigentlich die Kreise? Nein, der schwarze Peter liegt nicht bei MS Paint sondern in der Windows API selbst. Betroffen sind also auch sämtliche Anwendungen, welche die API zum Zeichnen verwenden.
4 Kommentare
warum sollte man da arbeit investieren, wenn jeder der so'n werkzeug braucht sich was besseres runterlädt. Dass es überhaupt noch dabei ist... wahrscheinlich hat nur jemand vergessen, es aus dem installer zu streichen. ;) ... und ja, ich benutze es manchmal, als ein werkzeug von vielen und ohne hohe erwartungen, ich weiss was es kann. kleine kreise gehören nunmal nicht dazu.
Also danke für den Hinweis, das gabe einen kleinen Nachtrag.