Geschwindigkeitssteigerung für Malprogramm

  • Themenstarter Themenstarter mitsung
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
M

mitsung

Gast
Hallo,

ich programmiere gerade an einem Mal- und Bildbearbeitungsprogramm. Offensichtlich sind meine Malmethoden(Klassen) jedoch zu rechen- und Speicheraufwendig. Geschwindigkeitsprobleme treten beim Zeichnen aller elementaren Grundformen in größeren Projekten auf. Stellvertretend hier mal der Code für das Linien zeichnen:

Code:
class LineTool extends MouseAdapter{
        private int x;
        private int y;
        BufferedImage back; // puffert das aktuell angezeigte Bild (ausgabe)
        private Graphics2D g2;
        
        public void mousePressed(MouseEvent e){
            x = e.getX();
            y = e.getY();
            back = new BufferedImage(ausgabe.getWidth(),
                    ausgabe.getHeight(), BufferedImage.TYPE_INT_RGB);
            g2 = back.createGraphics();
            g2.drawImage(ausgabe,0,0,null);
            g2.dispose();
        }

        public void mouseDragged(MouseEvent e){ 
            BufferedImage temp = new BufferedImage(back.getWidth(),
                    back.getHeight(), BufferedImage.TYPE_INT_RGB);
            g2 = temp.createGraphics();
            g2.setStroke(new BasicStroke(strokeFloat, kappe, verbindung));
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialias);
            g2.drawImage(back, 0, 0,null);
            g2.setColor(g2d.getColor());
            g2.drawLine(x, y, e.getX(), e.getY());
            g2.dispose();
            setImage(temp);           
        }
    }

Möglicherweise sieht ja jemand eine bessere Lösung. Es soll jedoch auch eine Linie auf einem komplexen Farbhintergrund , etwa einem Digitalfoto, gezeichnet werden können.
Das Zeichnen in kleinen Bildern bis 1000 x 1000 px funktioniert ganz gut, aber alles darüber wird ziemlich träge und bei hochauflösenden Fotos (ca. 3000 x 3000 px) bekomme ich ein out of Heap Space Exception. (getestet auf AMD Athlon 1,8GHz, 500MB)
Auf einem Core 2 Duo mit 1GB tritt keines der Probleme auf.
Ich hoffe jemand kann mir einen Tip geben.

Micha
 
Wenn du ein Foto hast, und willst da mit einem Edding einen Stich drauf malen, wirst du wohl kaum
Das Foto machen und entwickeln
Einen Punkt auf das Foto malen
Ein neues Foto von dem Foto mit dem Punkt machen, und das alte wegwerfen
Einen zweiten Punkt auf das Foto malen
Ein neues Foto von dem Foto mit den Punkte machen, und das alte wegwerfen
Einen drittenPunkt auf das Foto malen
...

Du solltest entweder die gemalten linien speichern, und nur in der paintComponent über das Image malen, oder (wenn es eher ein "paint-Programm" sein soll) die gemalten Sachen direkt in EIN BufferedImage malen (aber eben nicht bei jeder Mausbewegung ein neues Bild anlegen!!!)
 
Das klingt theoretisch ganz gut, aber ich möchte ja die Linie oder auch jede andere Figur in Bezug auf Grösse und Lage verändern können und zwar mit jeder Mausbewegung bis dieselbe losgelassen wird; also wie in jedem Malprogramm. Dazu brauche ich doch aber immer ein unverändertes Ausgangsbild, oder? Sonst sehe ich doch statt einer Linie, die sich ständig verändert x Linien unterschiedlicher Grösse und Lage. Deine Lösung funktioniert meines Erachtens nach nur bei Freihandzeichnungen, dort habe ich es jedenfalls genauso programmiert. Aber für diesen Fall ist das doch nicht anwendbar, oder?
Ausserdem funktioniert dieser Algorithmus so:
Ich mach ein Backup vom aktuell angezeigten Bild.
Danach ziehe ich von diesem Backup immer eine Kopie, die verändert und als neues aktuelles Bild angezeigt wird.(Es wird also kein Foto vom Foto mit Punkt gemacht usw.). Es wird immer ein unverändertes Ausgangsbild solangesolange mit einer Linie gezeichnet und als neues Ausgangsbild gesetzt, bis die endgültige Lage und Grösse bestimmt ist(die Maus losgelassen wird).
 
ich möchte ja die Linie oder auch jede andere Figur in Bezug auf Grösse und Lage verändern können und zwar mit jeder Mausbewegung bis dieselbe losgelassen wird; also wie in jedem Malprogramm.
Genau das ist der Punkt: "wie in jedem Malprogramm". Es gibt Bitmap-Basierte Malprogramme, und Vektor-Basierte. (Der Unterschied verwischt in letzter Zeit aber). Und die Frage, wie die Abläufe sein müssen, ist bei meidem Sehr unterschiedlich.

Es macht aber auf jeden Fall (egal, was du vorhast) keinen Sinn, bei jeder Mausbewegung eine Kopie des Bildes zu erstellen.

Sinngemäß könntest du ja sowas machen wie
Code:
    BufferedImage hintergrund = ...
    Point linieStart;
    Point linieEnde;

    // Durch die MouseEvents werden nur start- und endpunkt der "akutellen Linie" verändert
    public void mousePressed(...)
    {
        linieStart = event.getPoint();
        linieEnd = lineStart;
        repaint();
    }

    public void mouseDragged(...)
    {
        linieEnd = event.getPoint();
        repaint();
    }

    // Gemalt wird immer das hintergrundbild, und die aktuelle linie (falls vorhanden)
    public void paintComponent(...)
    {
        g.drawImage(hintergrund);
        if (linieStart != null)
        {
             g.drawLine(linieStart.x, ....);
        }
    }

    // Erst wenn man die Maus losläßt, wird die aktuelle linie in das hintergrundbild übertragen
    public void mouseReleased(...)
    {
        Graphics g = hintergrund.getGraphics();
        g.drawLine(linieStart.x, ...);
        lineStart = null;
    }

Aber je nachdem, was du machen willst, gibt's natürlich noch 1000 andere (evtl. geeignetere) Ansätze.
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben