2D-Grafik Bresenham's line algorithm

Bitte aktiviere JavaScript!
K

kneitzel

Wenn die Informationen in einem eindimensionalen Array liegen, dann ist die Prüfung der Werte durchaus wichtig. Denn bei einem gedachten Bild von 10x10 Pixeln (Eindimensionales Array der Länger 100) würde sonst ein Aufruf von 12, 2 eben kein Fehler auslösen sondern das Pixel im Index 2*10 + 12 = 32 setzen.
==> Der Check ist somit sehr wohl gut und notwendig und Deine Bewertung, dass der Code bei falschem Aufruf eh eine Exception wirft, offensichtlich falsch,
 
Total unnötig, der Code schmeißt eh eine Exception, so man diesen falsch aufruft.
Sehr gut, du hast das Problem also erkannt - das ist der erste Schritt zur Besserung ;)


Aha, man kann die (einzige) richtige Lösung natürlich in Abrede stellen... die schönste Art ist das allerdings nicht.
Deine Lösung hat genau das gleiche Problem (was du einfach uU aufgrund deines Monitors nicht siehst).

Der Grund ist die Art des Hochskalierens, das Muster sieht mit Nearest-Neighbor anders aus als bei @Meeresgott, Artefakte durchs Skalieren sieht man trotzdem.
Zeichne einfach mal ein Linienmuster und wähle einen entsprechenden Faktor, das ist 10px Abstand und Factor 1,23:

12364


Die Skalierung mir 4 produziert keine Artefakte (weil N*4 immer eine grade Zahl bleibt), aber wenn danach noch mal skaliert wird (zB zur Darstellung auf dem Bildschirm), hat man wieder Artefakte. Weniger auffällig (1px ist im Verhältnis zu 4px einfach weniger als zu 1px), aber da ist es trotzdem.



Den Effekt kann man oftmals sogar bei einfacher Schrift sehen: IIIIIIIII (<- alles "große i's")
Auf vielen Bildschirmen mit "logischer" != nativer Auflösung sehen die nicht alle genau gleich groß aus, hier als Bildschirmfoto:
12365
 
dass der Code bei falschem Aufruf eh eine Exception wirft, offensichtlich falsch
Bitte erst denken, dann posten...

Deine Lösung hat genau das gleiche Problem (was du einfach uU aufgrund deines Monitors nicht siehst)
Was entspricht hier nicht Bresenham? (Bis auf, dass das Fenster nicht schließt :().

Java:
public static BufferedImage bresenham(int x0, int y0, int x1, int y1, BufferedImage i, Color c, int f) {
    int dx = Math.abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
    int dy = -Math.abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
    int err = dx + dy, e2; /* error value e_xy */

    while (true) {
        i.setRGB(x0, y0, c.getRGB());
        if (x0 == x1 && y0 == y1)
            break;
        e2 = 2 * err;
        if (e2 > dy) {
            err += dy;
            x0 += sx;
        } /* e_xy+e_x > 0 */
        if (e2 < dx) {
            err += dx;
            y0 += sy;
        } /* e_xy+e_y < 0 */
    }

    BufferedImage b = new BufferedImage(i.getWidth() * f, i.getHeight() * f, BufferedImage.TYPE_INT_ARGB);
    AffineTransform at = new AffineTransform();
    at.scale(f, f);
    AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
    b = scaleOp.filter(i, b);
    return b;
}

public static void main(String[] args) throws IOException {
    JFrame f = new JFrame();
    f.add(new JLabel(new ImageIcon(bresenham(1, 1, 34, 20, new BufferedImage(36, 22, BufferedImage.TYPE_INT_ARGB), Color.RED, 20))));
    f.pack();
    f.setVisible(true);
}
12367

Habe eine native Auflösung.

Das erkennt doch sogar ein Blinder oder?
 
Die Skalierung mir 4 produziert keine Artefakte
Das ist richtig... Ich kann doch aber nichts dafür, wenn er so eine komische Bildschirmauflösung wählt, bei der man nichts mehr erkennen kann. Oder wenn sein Monitor zu klein ist oder what ever. :(

Jedenfalls sollte die Skalierung immer so gewählt werden daß bei der Skalierung keine Artefakte entstehen imo.
 
Was entspricht hier nicht Bresenham? (Bis auf, dass das Fenster nicht schließt :().
Der Code ist schon richtig, "schräge" Linien sehen damit genau so aus.

Das Problem von @Meeresgott ist allerdings ein anderes und tritt auch bei senkrechten Linien auf.

Habe eine native Auflösung.

Das erkennt doch sogar ein Blinder oder?
Gehören die Aussagen irgendwie zusammen? Oder beziehen die sich auf irgendwas anderes?


Das ist richtig... Ich kann doch aber nichts dafür, wenn er so eine komische Bildschirmauflösung wählt, bei der man nichts mehr erkennen kann. Oder wenn sein Monitor zu klein ist oder what ever. :(

Jedenfalls sollte die Skalierung immer so gewählt werden daß bei der Skalierung keine Artefakte entstehen imo.
Die meisten aktuellen Monitore dürften mit irgendeinem Skaling genutzt werden, da ist nichts dran "komisch"...

Skalierung *sollte* im Idealfall natürlich so gewählt werden, ist aber leider in den wenigsten Fällen passend.
 
K

kneitzel

Bitte erst denken, dann posten...
Wie wäre es, wenn Du Deinen Ratschlag selbst beherzigst? Und dann bitte einmal versuchen, Argumente zu bringen statt solcher pers. Angriffe.

Ansonsten finde ich es schon recht mies: immer wieder lieferst Du so schöne Steilvorlagen und da muss ich mich manchmal richtig zwingen, nicht drauf ein zu gehen und sachlich zu bleiben...
 
Nur ich wundere mich warum das so bei mir funktioniert bei ihm aber nicht. :(
Hab ich doch schon gesagt.

Nimm erstmal ein Linienmuster zum testen, da sieht man den Effekt deutlich besser als bei so einem Treppenmuster, am besten 1px Breite Linien mit einem "krummen" Abstand wie zB 7.
Dann skalier das ganze nicht mit 20, Fehler im Bereich von 1px sieht man logischerweise schlechter, wenn die Linie 20px breit ist.
Anstatt das direkt anzuzeigen, speicher das Bild einfach (die Anzeige bringt uU andere Fehler rein).

Den Effekt siehst du dann, wenn das ganze mit 1,5 skaliert wird (was ein durchaus üblicher Faktor ist).


Wenn dir das zu klein ist, kannst du *nachträglich* noch hochskalieren mit einer *ganzen Zahl* als Faktor.

Original (1px Breite Linien alle 7px):
12373

Skaliert mit 1,5:
12374
 
Guten Morgen,

@mrBrown Ich verwende Windows 10 und für die Skalierung benutze ich den Faktor 1,5.

Ja bin ich! Also mit dem Ansatz auf den ich selber gekommen bin nach dem klar war, dass es am Alignement lag funktioniert alles sehr gut ist aber doch merklich langsamer.

Java:
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Wohingegen der Ansatz von @Thallius auch funktioniert und das Problem komplett beseitigt und trotz der größeren Datenmenge im Schnitt ca. 1.2ms raus holt im Gegensatz zu der bilinearen Interpolation.

Hier ist nochmal ein Screenshot von meiner Applikation aber diesmal mit der implementierten Lösung von Thallius:
12376

Glaubt ihr, dass das Problem nur ensteht, weil ich meine Skalierung von Apps auf 150% gestellt habe ?

Edit: Auch hier das Bild bitte wieder in Vollbild betrachten die Komprimierung der Vorschau scheint Artefakte zu erzeugen :)
 
Zuletzt bearbeitet:
Glaubt ihr, dass das Problem nur ensteht, weil ich meine Skalierung von Apps auf 150% gestellt habe ?
Ja, hängt ziemlich sicher damit zusammen, mit dem direkt gespeicherten Bild (wo keinerlei Skalierung greift) hast du ja den Vergleich.
Keine Ahnung, was genau das zum Skalieren genutzt wird, das genau dieses Muster auftritt, und ob das auf Swing oder auf Java-Seite liegt, aber das dürfte der Grund sein.



Du kannst einmal testen, die Skalierung explizit auf 1 festzusetzen (mit sun.java2d.uiScale), dann sollten die Linien wirklich 1px breit sein
 
Ja, hängt ziemlich sicher damit zusammen, mit dem direkt gespeicherten Bild (wo keinerlei Skalierung greift) hast du ja den Vergleich.
Keine Ahnung, was genau das zum Skalieren genutzt wird, das genau dieses Muster auftritt, und ob das auf Swing oder auf Java-Seite liegt, aber das dürfte der Grund sein.
Ja ist richtig, stelle ich es auf 100% oder setzte die Skalierung fest tritt das Problem nicht mehr auf. Wirklich komisch..

Vielen Dank für eure Hilfe !
 
Ja ist richtig, stelle ich es auf 100% oder setzte die Skalierung fest tritt das Problem nicht mehr auf. Wirklich komisch..
Ne, komisch nicht :p

Mit 150% muss er aus zwei Pixeln die du gezeichnet hast drei zum Darstellen machen - ein Pixel muss also irgendwie aus den zweien hergeleitet werden, das verursacht den Fehler.

Bei 100% werden deine zwei gezeichneten Pixel auch als zwei dargestellt, sieht also genauso aus wie es sollte :)
 
Wie kann man denn bei einer Skalierung um 1.5 noch eine genau gezeichnete Linie erwarten? Das ist logisch unmöglich. Aber gut... Man kann die anderen ja mal zum Narren halten.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben