it-swarm.com.de

Java: Füllen eines gepufferten Bildes mit transparenten Pixeln

Ich habe ein off-screen BufferedImage, das mit dem Typ BufferedImage.TYPE_INT_ARGB erstellt wurde. Es kann alles enthalten, und ich suche nach einer Möglichkeit, das Bild (ziemlich effizient) vollständig mit transparenten Pixeln zu überschreiben, was zu einem "unsichtbaren" Bild führt.

So etwas verwenden:

    (bufimg.getGraphics()).setColor(new Color(10, 10, 100, 0));   
    (bufimg.getGraphics()).fillRect (0, 0, x, y);

Hat keine Wirkung Eine mögliche Methode könnte darin bestehen, jedes Pixel in BufferedImage zu überschreiben, aber ich bin nicht sicher, ob dies die beste Lösung ist. Wie würdest du es machen?

[bearbeiten]
Die Grafikdokumentation rät von der Verwendung von clearRect für Off-Screen-Bilder ab, aber ich habe es mit den gleichen Ergebnissen wie oben versucht.

[edit2]
Nachdem Sie mit MeBigFatGuys Code experimentiert haben (danke!), Wird ein Bild gelöscht. Es stoppt aber auch das weitere Malen zu diesem Bild (oder scheint zu). Dieser Code zum Beispiel:

    BufferedImage img = new BufferedImage (600, 600, BufferedImage.TYPE_INT_ARGB);
    Graphics g = img.createGraphics ()    
    g.drawLine (100, 100, 500, 500);
    AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
    g.setComposite(composite);
    g.setColor(new Color(0, 0, 0, 0));
    g.fillRect(0, 0, 600, 600);
    graphicsAI.setColor(new Color (10, 10, 10, 255));
    graphicsAI.drawLine (100, 100, 500, 500);

Ergebnis in nichts auf dem Bild gesehen (ich zeichne das Bild zu einem JPanel). Hat das etwas mit der Addition von Alpha-Werten zu tun?

19
JBenson

Sie könnten das zugrunde liegende int[] -Array Ihres BufferedImage erhalten (stellen Sie sicher, dass Sie ein kompatibles Format verwenden, dh eines, das durch einen int[] unterstützt wird).

Füllen Sie dann den int[] mit Ints, deren Alpha-Wert 0 ist (0 reicht aus;)

Ein System.arraycopy wird sehr schnell sein.

Sie müssen wissen, dass direktes Schreiben in int[] eine Menge schneller ist als die Verwendung von setRGB .

Jetzt BufferedImage sind in Java ein bisschen schwarz: Je nachdem, was Sie tun und auf welcher Plattform/JVM Sie es tun, können Sie Hardwarebeschleunigung verlieren (die möglicherweise ohnehin noch nie da gewesen ist). Darüber hinaus interessiert Sie die Hardwarebeschleunigung möglicherweise ohnehin überhaupt nicht, da Sie möglicherweise nicht an einem Spiel arbeiten, für das 60+ FPS erforderlich sind, um spielbar zu sein usw.

Dies ist ein sehr kompliziertes Thema und es gibt mehr als einen Weg, die BufferedImage Katze zu häuten. Was mich betrifft, arbeite ich direkt im int[], wenn ich mich auf Pixelebene herumschlagen muss, weil ich denke, dass es viel sinnvoller ist, Primitive für das Zeichnen auf höherer Ebene zu verwenden, und das tue ich - wirklich kümmert sich nicht um den potenziellen Verlust der Hardwarebeschleunigung.

9
SyntaxT3rr0r

Nachdem Sie den Hintergrund mit dem CLEAR-Composite gelöscht haben, müssen Sie ihn wieder auf SRC_OVER setzen, um wieder normal zu zeichnen. Ex:

//clear
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2.fillRect(0,0,256,256);

//reset composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//draw
g2.setPaint(Color.RED);
g2.fillOval(50,50,100,100);
24
Josh Marinacci

Wenn Sie das Graphics-Objekt in ein Graphics2D-Objekt umwandeln, können Sie ein Composite-Objekt durch setzen

AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setComposite(composite);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.fillRect(0, 0, 10, 10);
5
MeBigFatGuy

Den Hintergrund des Grafikobjekts einstellen scheint den Job zu erledigen:

g.setBackground(new Color(0, 0, 0, 0));

(zumindest beim Zeichnen von Bildern zur Skalierung)

0
Brad Mace

Obwohl Sie sagen, dass es nicht funktioniert, habe ich clearRect ziemlich gut verwendet. 

Löscht das angegebene Rechteck, indem es mit der Hintergrundfarbe Der aktuellen Zeichenfläche gefüllt wird. Dieser Vorgang verwendet nicht den aktuellen Malmodus .

Ab Java 1.1 kann die Hintergrundfarbe von Offscreen-Bildern Systemabhängig sein. Anwendungen sollten setColor gefolgt von FillRect verwenden, um sicherzustellen, dass ein Offscreen-Bild in einer bestimmten Farbe Gelöscht wird.


Füllt das angegebene Rechteck. Die linken und rechten Kanten des - Rechtecks ​​befinden sich bei x und x + width - 1. Die oberen und unteren Kanten befinden sich bei Y und y + height - 1. Das resultierende Rechteck deckt eine Bereichsbreite ab Pixel hoch und hoch Pixel hoch. Das Rechteck wird mit der aktuellen Farbe des Grafikkontexts gefüllt.

Es wird hier nicht eindeutig gesagt, dass man das Rechteck auf die Hintergrundfarbe set setzen wird, während der andere Paint mit der Vordergrundfarbe über den aktuellen Farben steht, aber es ist, wie es scheint machen.

Dies ist reine Spekulation, aber ich denke, der Hinweis über Offscreen-Bilder bezieht sich auf Graphics-Objekte, die von Offscreen-AWT-Komponenten abgerufen werden, da sie nativ sind. Ich kann mir kaum vorstellen, wie die Hintergrundfarbe einer BufferedImage systemabhängig sein könnte. Da das API-Dokument für Graphics ist, könnte dies eine Verallgemeinerung sein, die nicht für den Fall BufferedImage gilt.

Mein Testcode:

JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

BufferedImage img = new BufferedImage(200, 300, BufferedImage.TYPE_INT_ARGB);

Graphics2D g = img.createGraphics();

//fill right half with opaque white
g.setColor(Color.WHITE);
g.fillRect(100, 0, 100, 300);

//leave top third as it is

//fill middle third with transparent color
g.setColor(new Color(0, true));
g.fillRect(0, 100, 200, 100);

//clear bottom third with transparent color
g.setBackground(new Color(0, true));
g.clearRect(0, 200, 200, 100);

g.dispose();

jf.add(new JLabel(new ImageIcon(img)));

jf.pack();
jf.setVisible(true);

das Ergebnis sind zwei weiße Quadrate oben rechts. Wenn kein Weiß gezeichnet wurde oder clearRect zum Überschreiben des Weiß verwendet wurde, ist das Ergebnis hellgrau, die Standardhintergrundfarbe des Rahmens.

In Bezug auf die Leistung ist es das regelmäßige Zeichnen. arraycopy ist zwar möglicherweise schneller, ich weiß es nicht, aber zumindest wird die Hardware wahrscheinlich genauso beschleunigt wie jeder andere Zeichenvorgang.

Ein Pluspunkt gegenüber der Array-Lösung ist a) kein zusätzlicher Speicher und b) Unabhängigkeit vom Farbmodell; Dies sollte funktionieren, egal wie das Bild eingerichtet wurde.

Ein Minuspunkt gegenüber der Composite-Lösung besteht darin, dass nur Rechtecke gelöscht werden können. Wenn Sie den Verbund einstellen, können Sie jede Form löschen.

0
Silly Freak

Obwohl er das Vordergrundpixel auf transparent setzen möchte, ist Ihre Antwort definitiv die richtige Antwort.

private Farbe transparent = neue Farbe (0, wahr);

((Graphics2D) g) .setBackground (transparent);

g.clearRect (0, 0, w, h);

setzt den Hintergrund auf transparent. 

Übrigens: Die anderen Antworten sind meistens Müll oder einfach nur FUD. Bitte akzeptieren Sie keine Antworten, die über "gepuffertes Bild als schwarze Kunst" in einem Tech-Forum sprechen. 

0
user1135940