# Malen auf Buffered Image



## ulr!ch (19. Jun 2005)

Hi JavaGemeinde,

habe hier ein Riesenproblem, über das ich bereits die halbe Nacht nachgedacht habe. 
Jedoch leider ohne nennenswertes Resultat.
Ich habe (mittels einer funktionierenden Klasse aus dem Internet) einen gif-File in ein BufferedImage eingelesen. Dieses "bimage" draw ich dann. Auf dem bimage möchte ich gerne irgendetwas zeichnen, was aber leider nicht funktioniert.  Vielleicht wird die Linie vom Bild überzeichnet, ich habe keine Ahnung. So sieht der Code grob aus.

```
public class Zeichnen
    extends JLabel  {
  Image image;
  BufferedImage bimage;
  
  public Zeichnen() {
    setPreferredSize(new Dimension(500, 500));
    repaint();
  }

  public void paintComponent(Graphics g) {
// bimage zeichnen, das funktioniert auch, Bild wird angezeigt
    Graphics2D matrix = (Graphics2D) g;
    image = Toolkit.getDefaultToolkit().getImage("images/matrix1.gif");
    bimage = toBufferedImage(image);
    matrix.drawImage(bimage, null, 0, 0);

// einfache Linie zwichnen
    Graphics2D Linie = bimage.createGraphics();
    Linie.setColor(Color.blue);
    Linie.drawLine(0,0,100, 100);
  }
}
```
Ich kann nicht einfach ein ImageIcon oder Image nehmen, weil ich später mit der PixelGrabber-Klasse den Farbwert eines Pixels ergattern möchte. Dabei ist allerdings diese unlösbare (?) Problem aufgetreten...
Für Hilfe bin ich echt dankbar.

By<e Ulrich


----------



## ulr!ch (19. Jun 2005)

Hi JavaGemeinde,

habe mittlerweile gemerkt, dass, wenn ich den drawImage-Befehl hinter die blaue Linie-Anweisung schreibe, diese gezeichnet wird. Aber wie kann ich das Bild updaten, da später mal alles auf Mauszeigereingaben reagieren soll.
super.repaint(); oder repaint(); habe ich bereits ausprobiert und es funktioniert nicht. 

By<e Ulrich


----------



## ulr!ch (19. Jun 2005)

Hi JavaGemeinde,

ich bin's noch einmal, habe den Code verändert und wollte nun noch einmal das Update posten:

```
public class Zeichnen
    extends JLabel implements MouseListener {
  int i=1;
  int[] plX = new int[1000];
  int[] plY = new int[1000];

  boolean released;
  Image image;
  BufferedImage bimage;
  
  public Zeichnen() {
    setPreferredSize(new Dimension(500, 500));
    addMouseListener(this);
    repaint();
  }

  public void paintComponent(Graphics g) {

    Graphics2D matrix = (Graphics2D) g;
    image = Toolkit.getDefaultToolkit().getImage("images/matrix1.gif");
    bimage = toBufferedImage(image);

// Linienzug
    if (released) {
      Graphics2D Linie = bimage.createGraphics();
      Linie.drawPolyline(plX, plY, i);
    }
    matrix.drawImage(bimage, null, 0, 0);
  }

  public void mouseMoved(MouseEvent e) {}
  public void mouseDragged(MouseEvent e) {}
  public void mousePressed(MouseEvent e) {}
  public void mouseReleased(MouseEvent e) {
    released = true;
    plX[i] = e.getX();
    plY[i] = e.getY();
  }
  public void mouseClicked(MouseEvent e){}
  public void mouseEntered(MouseEvent e) {}
  public void mouseExited(MouseEvent e) {}
}
```

Und nun kann ich leider keinen Linienzug, durch Anklicken verschiedener Punkte auf dem bimage, zeichnen. Als ich noch ein Image verwendet habe, funktionierte alles. Wo liegt der Fehler?
Wo muss wie ich die Graphic updaten?

Please help!  :bahnhof: 
By<e Ulrich


----------



## Beni (19. Jun 2005)

Also, was du genau willst, weiss ich nicht. Aber wie man Linien auf einem Bild zeichnet, kann ich dir sagen  

So (Maus drücken, mit gedrückter Taste Maus bewegen, dann loslassen; gibt eine blaue Linie):

```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Zeichnen extends JPanel {
    private BufferedImage bimage;
    private int x, y;
    
    public Zeichnen() {
        setPreferredSize(new Dimension(500, 500));
        bimage = new BufferedImage( 500, 500, BufferedImage.TYPE_INT_RGB );
        
        addMouseListener( new MouseAdapter(){
            @Override
            public void mousePressed( MouseEvent e ) {
                x = e.getX();
                y = e.getY();
            }
            @Override
            public void mouseReleased( MouseEvent e ) {
                Graphics g = bimage.getGraphics();
                g.setColor( Color.BLUE );
                g.drawLine( x, y, e.getX(), e.getY() );
                repaint();
            }
        });
    }

    public void paintComponent( Graphics g ) {
        g.drawImage( bimage, 0, 0, this );
    }
    
    // nur zum testen
    // -------------------------------------------
    public static void main( String[] args ) {
        JFrame frame = new JFrame();
        frame.add( new Zeichnen() );
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }
}
```

*Der* wichtige Unterschied: ich lade nicht jedesmal ein neues Bild, wenn ich zeichne (bei deinem Code wird bei jedem Aufruf von paintComponent ein Bild geladen, und das alte damit überschrieben. P.S. und sehr performant ist es nicht, alle paar Millisekunden ein Bild von der HD zu lesen...)


----------



## ulr!ch (19. Jun 2005)

:applaus:  Danke Ben,
Klappt super! 

Nur eine kleine Frage habe ich noch: Den ganzen Aufwand mit dem BufferedImage hatte ich ja nur betrieben, um mir die RGB-Werte bei einem bestimmten Pixel (Maus-Cursor-Position) ausgeben lassen zu können.
Wenn ich allerdings die Zeile:

```
System.out.println(bimage.getRGB(e.getX(), e.getY()));
```
einfüge, dann gibt er mir immer den Wert -16776961 raus, egal wohin ich klicke, obwohl eigentlich unterschiedliche Farbwerte zurückgeliefert werden sollten.
Hast du vielleicht eine Ahnung, woran das liegen könnte.
Wäre dir sehr dankbar.

Ciao,
Ulrich


----------



## Beni (19. Jun 2005)

Also der Wert -16776961 hört sich irgendwie nach weiss an.

Bist du sicher, dass du das richtige Bild erwischt hast (ich weiss ja nicht, wie dein neuer Code aussieht)? Lässt du bimage zeichnen (und wird was sinnvolles gezeichnet)?


----------



## ulr!ch (19. Jun 2005)

Beni hat gesagt.:
			
		

> Also der Wert -16776961 hört sich irgendwie nach weiss an.
> 
> Bist du sicher, dass du das richtige Bild erwischt hast (ich weiss ja nicht, wie dein neuer Code aussieht)? Lässt du bimage zeichnen (und wird was sinnvolles gezeichnet)?


Ja, an weiss oder schwarz hatte ich auch gedacht.
Also das Bild wird nun angezeigt und ich kann auch darauf zeichnen.
Der Code sieht nun wie folgt aus:

```
public class Zeichnen
  extends JLabel {
  int i=1;
  int[] plX = new int[1000];
  int[] plY = new int[1000];

  Image image;
  BufferedImage bimage;
  
  public Zeichnen() {
    setPreferredSize(new Dimension(500, 500));
    image = Toolkit.getDefaultToolkit().getImage("images/matrix1.gif");
    bimage = toBufferedImage(image);
 
    addMouseListener( new MouseAdapter(){
      public void mouseMoved(MouseEvent e) {}
      public void mouseDragged(MouseEvent e) {}
      public void mousePressed(MouseEvent e) {}
      public void mouseReleased(MouseEvent e) {
// Startpunkt
	plX[0] = 90;
	plY[0] = 100;
	plX[i] = e.getX();
	plY[i] = e.getY();
	i++;

// Linie
	Graphics g = bimage.getGraphics(); 
	Graphics2D linie = (Graphics2D) g;
	linie.setColor(Color.blue);
	BasicStroke thick = new BasicStroke (3f);
	linie.setStroke(thick);
	linie.drawPolyline(plX, plY, i);

	repaint();
	System.out.println(bimage.getRGB(e.getX(), e.getY()));
      }
    
      public void mouseClicked(MouseEvent e){}
      public void mouseEntered(MouseEvent e) {}
      public void mouseExited(MouseEvent e) {}
    });
  }

  public void paintComponent(Graphics g) {
    g.drawImage(bimage, 0, 0, this);
  }
}
```
Hast du eine Ahnung, woran das liegen kann?
Wäre echt super! 

Ciao,
Ulrich


----------



## Beni (19. Jun 2005)

Hm, _zuerst_ zeichnest du, _danach_ fragst du die Farbe ab. Da ist die Farbe natürlich das, was du vorhin gezeichnet hast :wink: 
Einfach die Abfrage vor dem "g.draw..." machen.


----------



## ulr!ch (19. Jun 2005)

Beni hat gesagt.:
			
		

> Hm, _zuerst_ zeichnest du, _danach_ fragst du die Farbe ab. Da ist die Farbe natürlich das, was du vorhin gezeichnet hast :wink:
> Einfach die Abfrage vor dem "g.draw..." machen.


Hm, das soll ja auch so sein, weil ich die Farbbestimmung abhängig von der aktuellen Cursor-Position machen möchte. Der Sinn, der dahintersteckt, ist so etwas wie eine verweissensitive Graphik: Die Linie soll nur von bestimmten Punkten zu anderen gezogen werden. Deswegen soll der Farbwert des releasedCursorPosition abgefragt werden, wenn dann gleich Color X, soll die Linie gezeichnet werden.
Ich glaube, irgendwas habe ich da noch nicht ganz verstanden: Wieso funktioniert deine Eingabe, die ich einfach mal ausprobiert habe, obwohl die Graphik _noch nicht_ gezeichnet wurde?
Und wieso funktioniert es andersherum nicht?
Komme ich vielleicht mit der Grabber-Klasse weiter?

```
PixelGrabber pg = new PixelGrabber(bimage, e.getX(), e.getY(), 1, 1, false);
	try {
	  pg.grabPixels();
	  ColorModel cm = pg.getColorModel();
//	  cm.getRGB(pg);
	}
	catch (InterruptedException egb) {}
```
Fliege dabei aber mit einer NullpointerException raus. 

Bitte um Hinweise. Thx, Beni!

By<e Ulrich


----------



## ulr!ch (19. Jun 2005)

OK, Beni,

danke für die ganze Hilfe.
Jetzt scheint es zu funktionieren.
Nun muss ich nur noch die Ganzzahlen in RGB-Farben umkodieren, aber das bekomme ich jetzt auch noch hin.
Danke noch einmal für die Hilfe. 

By<e Ulrich


----------

