# BufferedImage transparent löschen



## agentone (13. Feb 2010)

Hi,
ich habe ein Spiel mit mehreren Layern programmiert. Also mehreren Bildebenen, die in einer bestimmten Reihenfolge übereinander gelegt werden. 
Dazu verwende ich 

```
BufferedImage bimg=new BufferedImage(Constants.WIDTH,Constants.HEIGHT,BufferedImage.TYPE_INT_ARGB);
```
Wenn ich allerdings bei jedem Zeichenvorgang die BufferedImages neu erstelle, wird das Spiel zu langsam. Wenn ich das BufferedImage nur einmal erstelle und immer nur mit fillRect die Graphics "zurücksetze", wird das BufferedImage ja nie mehr transparent!

Ich brauche also eine Möglichkeit, mit der ich ein Bild, in welches bereits gezeichnet wurde, wieder vollständig transparent machen kann. Danke schon mal...


----------



## Marco13 (13. Feb 2010)

Mit
g.setColor(new Color(0,0,0,0));
g.fillRect(0,0,w,h);
müßt's doch gehen? (Color mit 4 Werten: RGB und A)


----------



## Steev (13. Feb 2010)

Hi agentone,

ich würde mir das Graphics-Objekt deines Bildes nehmen und dann mithilfe der Methode clear-Rect die Zeichfläche wieder löschen.

Gruß
Steev

[EDIT:]@Marco: Nein, das sollte eigendlich nicht funktionieren, weil dann einfach nur ein transparentes Rechteck über alles gezeichnet wird. Es müsste rein gar nichts passieren...


----------



## agentone (14. Feb 2010)

Nein,
clearRect und fillRect habe ich schon mit transparenten Farben ausprobiert. Da passiert nichts, wie du selber geschrieben hast...
und wenn ich erst setColor(Color.BLACK) und dann fillRect(), dann wird das Bild ja bloß schwarz, aber nicht transparent!


----------



## Schandro (14. Feb 2010)

wie wärs denn mit 
	
	
	
	





```
BufferedImage#getRaster#setPixels
```
    ?


----------



## Steev (14. Feb 2010)

@Schandro:
Das sollte funktionieren, ich hatte vergessen, dass mit clearRect nur die Hintergrundfarbe wieder zurückgesetzt wird. Was man vieleicht noch ausprobieren kann ist die Hintergrundfarbe auf Transparent zu setzen, dann sollte clearRect auch funktionieren (k.A. habe es nicht ausprobiert...  ).


```
img.getRaster().setPixels(x, y, width, height, new double[] {0, 0, 0, 0}); // new double ist unschön ;-)
```


----------



## Marco13 (14. Feb 2010)

Steev hat gesagt.:


> [EDIT:]@Marco: Nein, das sollte eigendlich nicht funktionieren, weil dann einfach nur ein transparentes Rechteck über alles gezeichnet wird. Es müsste rein gar nichts passieren...



Najaaaa... man muss (natürlich    ) ... das richtige Composite setzen, bevor man das Rechteck malt...

```
import java.awt.image.*;
import java.awt.*;

class TransparentPaintTest
{
    public static void main(String args[])
    {
        BufferedImage image = new BufferedImage(10,10, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();

        g.setColor(Color.RED);
        g.fillRect(0,0,10,10);
        System.out.println(Integer.toHexString(image.getRGB(0,0)));


        g.setComposite(AlphaComposite.Src); //------------------------- Composite setzen...
        g.setColor(new Color(0,0,0,0));
        g.fillRect(0,0,10,10);
        System.out.println(Integer.toHexString(image.getRGB(0,0)));

        g.dispose();
    }
}
```


----------



## agentone (18. Feb 2010)

Sorry, dass ich erst so spät geantwortet habe.

@Marco13: Vielen Dank! Dein Beispiel-Programm funktioniert und ich konnte es auch in mein Programm umsetzen.

@Steev: Deine Idee war zwar gut, aber ich habe diesen Fehler bekommen:

Exception in thread "Thread-6" java.lang.ArrayIndexOutOfBoundsException: 4
        at java.awt.image.SinglePixelPackedSampleModel.setPixels(SinglePixelPackedSampleModel.java:671)
        at java.awt.image.WritableRaster.setPixels(WritableRaster.java:550)
        at sun.awt.image.SunWritableRaster.setPixels(SunWritableRaster.java:176)
        at GamePanel.drawBuffer(GamePanel.java:199)
        at GamePanel.run(GamePanel.java:72)
        at java.lang.Thread.run(Thread.java:619)


----------



## Steev (18. Feb 2010)

Hi agentone,

ich nehme mal an, dass entweder die X- oder die Y-Position in Verbindung mit der Breite oder Höhe zu einer Exception führen.
Guck doch bitte mal, an welcher Position in den beiden Klassen er stehen bleibt (Debugen) hier müsste ein Array mithilfe ins Index ausgelesen werden. Wenn du im Debuger die Variablenwerte anguckst, dann müsstest du eigendlich relativ schnell dahinter kommen, welcher Wert falsch ist.

Oder hast du als Farbe vieleicht einen Array mit der Länge 3 anstatt 4 angegeben?

Gruß
Steev


----------



## agentone (18. Feb 2010)

Hi Steev,
1. x,y,Breite und Höhe liegen zusammen nicht über der Image-Größe.
2. Das Array hat die Länge 4.
3. "at GamePanel.drawBuffer(GamePanel.java:199)" ist bimg.getRaster().setPixels(10, 10, 80, 80, new int[]{0, 0, 0, 0});
Das BufferedImage wurde konstruiert durch new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);


----------



## Steev (18. Feb 2010)

agentone hat gesagt.:


> Hi Steev,
> 1. x,y,Breite und Höhe liegen zusammen nicht über der Image-Größe.
> 2. Das Array hat die Länge 4.
> 3. "at GamePanel.drawBuffer(GamePanel.java:199)" ist bimg.getRaster().setPixels(10, 10, 80, 80, new int[]{0, 0, 0, 0});
> Das BufferedImage wurde konstruiert durch new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);



Hmm, dass ist jetzt schwer zu sagen, wo da der Fehler liegt. Der Code sieht soweit eigendlich in Ordnung aus. (Er hat bei mir ja auch funktioniert ;-) )

> new int[]{0, 0, 0, 0}

Das war eigendlich nur als Beispiel gedacht. Normalerweise solltest du dir hier eine Konstante anlegen und diese Verwenden, damit du nicht pro Renderung einen neuen Array erzeugst.


----------



## Marco13 (18. Feb 2010)

Ähm... *räusper*.... ???:L bei
setPixels(10, 10, 80, 80, new int[]{0, 0, 0, 0});
versucht er doch, ein 80x80 großes Stück des Bildes zu füllen - und die Daten dafür aus einen Array mit 4 Elementen zu holen... oder?
setPixels(10, 10, 80, 80, new int[80*80]);
könnte gehen....


----------



## Steev (19. Feb 2010)

@Marco13:
Jaaa, :-( Du hast natürlich Recht (wie immer).


----------

