# Pixel zeichnen



## Roland (15. Nov 2007)

Hallo Leute,

ich habe hier ein kleines Problem und komme nicht so recht dahinter.
Ich versuche ein Bild zeichnen zu lassen, dass ich vorher in ein int-Array gespeichert habe.
Breite und Höhe sind auch bekannt.
Die RGB-Werte sind entsprechend gespeichert, also x[0] = rot-Wert, x[1] = grün, x[2] = blau usw.

Wenn ich es so versuche wie bis jetzt, dann bekomme ich nen schwarzen Kasten raus und nicht
das schöne rote auto, dass das Bild zeigt 

Hier mal der Code:


```
import java.awt.BorderLayout;
import java.awt.Color;

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

public class PicViewer extends JFrame{
	public PicViewer () {

		this.setTitle("PicViewer");
		this.setSize(300, 200);
		this.setResizable(false);
		this.setBackground(new Color(100,100,100));
		this.setLocation(100, 50);
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		
		// content
		JPanel panel = new JPanel(new BorderLayout());
		
		this.add(panel);
		this.setVisible(true);
	}
	
	public void draw(int[] pixels, int width, int height) {
		 
		int widthm3 = width*3;  
         for (int i = 0; i < pixels.length; i+=3) {
        	 int r = pixels[i];
        	 int g = pixels[i+1];
        	 int b = pixels[i+2];
        	 	Color z = new Color(r, b, g);
                        this.getGraphics().setColor(z);  
                        this.getGraphics().drawLine((i%widthm3)/3, i/widthm3, (i%widthm3)/3, i/widthm3);  
         }
        
	}

}
```

Hat jemand nen vorschlag?
Oder einfach nur tipps wie man´s schöner machen könnte?

Prämisse ist aber, dass ich das Bild aus dem Int-Array lesen muss...

Vielen Dank schon mal,

MfG
Roland


----------



## Quaxli (15. Nov 2007)

Mal davon abgesehen, das mir die Funktionsweise der draw-Methode irgendwie nicht klar ist, folgende Anmerkungen:

- die draw-Methode wird nirgends aufgerufen
- damit etwas angezeigt wird, mußt Du nach dem Zeichnen einen repaint() machen
- getGraphics()... tutet man nicht - nie! (also fast nie, bevor wieder jemand weint.. ).

Nimm eine eigene Komponente, die von JPanel erbt und überschreibe die paintComponent-Methode. Dort packst Du dann rein, was Du jetzt in der draw-Methode hast (ohne den getGraphics()-Schlonz, da paintComponent() ein GrafikObjekt übergben bekommt).
Diese eigene Komponente addest Du dann anstelle des JPanel in Dein JFrame und dann solltest Du auch was angezeigt bekommen.


----------



## Roland (16. Nov 2007)

Danke für den Tipp.

Werds mal so probieren.

Die draw-Methode wird von nem Controller aufgerufen. Ich gebe zu, hätt ich erwähnen sollen 

drawLine() zeichnet ne Linie, in dem Fall halt nur eine die 1en Pixel lang ist. Hab keinen besseren Weg
gefunden einzelne Pixel zu zeichnen.


----------



## Marco13 (16. Nov 2007)

In diesem Fall wäre es vmtl. besser (d.h. DEUTLICH effizienter) den Array nur EIN mal in ein BufferedImage reinzumalen, und in der paintComponent dann nurnoch das BufferedImage zu malen. 

In einem BufferedImage kann man die Pixel direkt setzen, und braucht nicht drawLine zu machen.


```
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

public void updateImage(array...)
{
    for (x...)
    {
        for (y...)
        {
            int r = array[x,y,0];
            int g = array[x,y,1];
            int b = array[x,y,2];
            int rgb = (r<<16) | (g<<8) | b;
            image.setRGB(x,y, rgb);
        }
    }
}

...

public void paintComponent(Graphics g)
{
    g.drawImage(image,0,0,this);
}
```


----------



## Quaxli (16. Nov 2007)

In Bezug auf die einzelnen Pixel hätte ich folgenden Vorschlag: 

- erstelle Dir im Konstruktor ein BufferedImage in der Größe der Komponent/Zeichnung
- diese BufferedImage zeichnest Du in der paintComponent-Methode mit drawImage(...)
- Deine eigentliche Zeichenarbeit machst Du vorher in diesey BufferedImage
- in diesem BufferedImage kannst Du mit setRGB(int x, int y, int rgb) einzelnen Pixel einfärben
- den Integer rgb bekommt man z. B. über eine Color-Objekt mit getRGB()


----------



## Guest (17. Nov 2007)

Kannst du mir erklären, was das hier macht?


```
int r = array[x,y,0];
            int g = array[x,y,1];
            int b = array[x,y,2];
            int rgb = (r<<16) | (g<<8) | b;
```


----------



## Roland (17. Nov 2007)

*nach oben deut*

mein Post


----------



## Quaxli (17. Nov 2007)

Ohne zu Wissen, was jetzt x und y an der Ecke sind, wird hier offensichtlich über Bit-Verschiebung ein integer in der Form zusammen gebaut, wie Du ihn in der 3. Variable der Methode setRGB(...) benötigst.

Im Prinzip könnte man z.B. auch schreiben:

Color c = new Color(r,g,b);
c.getRGB();


----------



## Marco13 (17. Nov 2007)

Anonymous hat gesagt.:
			
		

> Kannst du mir erklären, was das hier macht?
> ...



Vielleicht sollte ich erwähnen, dass 

int r = array[x,y,0];

Pseudocode ist, und so viel bedeuten soll wie: "r ist die Rot-Komponente des Pixels an der Position x,y". (Wie genau das in deinem Array abgespeichert ist, hatte ich nicht nachvollzogen). Man kann sich das RGB auch so holen, wie Quaxli es beschrieben hat, aber das ist u.U. deutlich langsamer (weil jedes mal ein neues Color-Objekt erstellt wird, was eigentlich überflüssig ist)

Das 
int rgb = (r<<16) | (g<<8) | b; 
kombiniert die Rot- Grün und Blau-Anteile eines Pixels in EINEN int, so dass man diesen Pixel direkt im BufferedImage mit der gewünschten RGB-Farbe setzen kann.


----------



## Guest (17. Nov 2007)

Danke für die Erklärungen und die Hilfe 

Schon wieder was gelernt.

So funktionierts jetzt:


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

public class PicPanel extends JPanel{
	BufferedImage bufPic;
	int[] panPixels;
	int panWidth;
	int panHeight;
	
	public PicPanel(int[] pixels, int width, int height) {
		super();
		panPixels = new int[pixels.length];
		panPixels = pixels;
		panWidth = width;
		panHeight = height;
		bufPic = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		
		this.updateImage(panPixels, panWidth, panHeight);
	}
	
	public void updateImage(int[] panPixels, int panWidth, int panHeight)
	{
		int widthm3 = panWidth*3;  
        for (int i = 0; i < panPixels.length; i+=3) {
       	 int r = panPixels[i];
       	 int g = panPixels[i+1];
       	 int b = panPixels[i+2];

       	 int rgb = (r<<16) | (g<<8) | b;                 
            bufPic.setRGB((i%widthm3)/3, i/widthm3, rgb);  
        }       
		
	} 
	
	// called when painted
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		g.drawImage(bufPic,0,0,this);
	}
}
```

Grüße
Roland


----------

