-
Bug
-
Resolution: Fixed
-
P3
-
7u6
-
b22
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8048426 | 8u25 | Sergey Bylokhov | P3 | Resolved | Fixed | b05 |
JDK-8046837 | 8u20 | Sergey Bylokhov | P3 | Resolved | Fixed | b20 |
JDK-8053683 | emb-8u26 | Sergey Bylokhov | P3 | Resolved | Fixed | b17 |
JDK-8232492 | openjdk7u | Andrew Hughes | P3 | Resolved | Fixed | master |
FULL PRODUCT VERSION :
java version " 1.7.0_40-ea "
Java(TM) SE Runtime Environment (build 1.7.0_40-ea-b29)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b48, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Mac 10.8.3
EXTRA RELEVANT SYSTEM CONFIGURATION :
Graphics Card: Intel HD Graphics 3000.
This has also happened with other Macs, regardless of Graphics Card.
A DESCRIPTION OF THE PROBLEM :
When drawing a translucent VolatileImage to a BufferedImage (or calling VolatileImage.getSnapshot()) and then drawing that BufferedImage to the screen graphics, the translucent pixels are rendered incorrectly. Instead of being rendered as translucent, they are rendered with a black background.
If the VolatileImage is drawn right to the screen graphics, this problem does not occur.
REGRESSION. Last worked in version 6u45
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a translucent VolatileImage
2. Clear it
3. Fill with a half opaque color (such as rgba(255, 255, 255, 128))
4a. Create a BufferedImage of type INT_ARGB
4b. Draw the VolatileImage to the BufferedImage's graphics
-- or instead of doing steps 4a and 4b, do:
4. Create a BufferedImage by calling VolatileImage.getSnapshot()
---
5. Draw the BufferedImage obtained in steps 4a/4b or 4 to the screen graphics.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the BufferedImage created in steps 4 or 4a/4b to look exactly as if I had created a BufferedImage and filled it with the half opaque color and then painted it to the screen graphics.
I also expect the BufferedImage created in steps 4 or 4a/4b to look exactly like the VolatileImage when the VolatileImage is painted directly to the screen graphics.
ACTUAL -
The BufferedImage created in steps 4 or 4a/4b has a black tinge to it where the pixels are supposed to be translucent.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Shows the difference between the painting of a translucent BufferedImage and a translucent
* VolatileImage.
*
*
* On Java 6, this works fine. On Java 7, the VolatileImages are not painted correctly, when painted
* onto a BufferedImage prior to being painted to screen graphics.
*
* @author jfinley
*
*/
public class PaintTest {
public PaintTest() {
JPanel bufferedImagePanel = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
BufferedImage image = getBufferedImage();
g.drawImage(image, 0, 0, null);
};
};
JPanel bufferedImagePanel2 = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
BufferedImage bImage = getBufferedImage();
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
//not really necessary, but in there for completeness
g2.setComposite(AlphaComposite.Clear);
g2.setColor(new Color(255, 255, 255, 0));
g2.fillRect(0,0, image.getWidth(), image.getHeight());
g2.setComposite(AlphaComposite.SrcOver);
g2.drawImage(bImage, 0, 0, null);
g2.dispose();
g.drawImage(image, 0, 0, null);
};
};
JPanel volatileImagePanel = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
VolatileImage vImage = getVolatileImage();
/**
* If we draw the VolatileImage directly to g, it works fine... but
* if we draw VolatileImage.getSnapshot(), or otherwise convert the VolatileImage
* to a buffered image, we get the black halo funk of death.
*/
g.drawImage(vImage, 0, 0, null); //works
//g.drawImage(vImage.getSnapshot(), 0, 0, null); //black halo funk of death
};
};
JPanel volatileImagePanel2 = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
VolatileImage vImage = getVolatileImage();
/**
* If we draw the VolatileImage directly to g, it works fine... but
* if we draw VolatileImage.getSnapshot(), or otherwise convert the VolatileImage
* to a buffered image, we get the black halo funk of death.
*/
//g.drawImage(vImage, 0, 0, null); //works
g.drawImage(vImage.getSnapshot(), 0, 0, null); //black halo funk of death
};
};
JPanel volatileImagePanel3 = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
VolatileImage vImage = getVolatileImage();
/**
* If we draw the VolatileImage directly to g, it works fine... but
* if we draw VolatileImage.getSnapshot(), or otherwise convert the VolatileImage
* to a buffered image, we get the black halo funk of death.
*/
//g.drawImage(vImage, 0, 0, null); //works
//g.drawImage(vImage.getSnapshot(), 0, 0, null); //black halo funk of death
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
//not really necessary, but in there for completeness
g2.setComposite(AlphaComposite.Clear);
g2.setColor(new Color(255, 255, 255, 0));
g2.fillRect(0,0, image.getWidth(), image.getHeight());
g2.setComposite(AlphaComposite.SrcOver);
g2.drawImage(vImage, 0, 0, null);
g2.dispose();
g.drawImage(image, 0, 0, null);
};
};
final JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 1, 1, 1, 0, 0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
mainPanel.add(new JLabel( " Direct to g " ), gbc);
gbc.gridy++;
mainPanel.add(new JLabel( " BufferImage Proxy " ), gbc);
gbc.gridy++;
mainPanel.add(new JLabel( " BufferImage Proxy 2 " ), gbc);
gbc.gridx = 1; gbc.gridy = 0;
mainPanel.add(new JLabel( " BufferedImages " ), gbc);
gbc.gridx++;
mainPanel.add(new JLabel( " VolatileImages " ), gbc);
gbc.gridx = 1; gbc.gridy = 1; gbc.weightx = 1; gbc.weighty = 1;
mainPanel.add(bufferedImagePanel, gbc);
gbc.gridy++;
mainPanel.add(bufferedImagePanel2, gbc);
gbc.gridx = 2; gbc.gridy = 1;
mainPanel.add(volatileImagePanel, gbc);
gbc.gridy++;
mainPanel.add(volatileImagePanel2, gbc);
gbc.gridy++;
mainPanel.add(volatileImagePanel3, gbc);
JButton repaintButton = new JButton( " Repaint " );
repaintButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
mainPanel.repaint();
}
});
gbc.gridx = 1; gbc.gridy++; gbc.gridwidth = 2; gbc.weighty = 0;
mainPanel.add(repaintButton, gbc);
JFrame mainFrame = new JFrame( " O.M.G. " );
mainFrame.getContentPane().setLayout(new BorderLayout());
mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
mainFrame.setPreferredSize(new Dimension(400, 400));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setVisible(true);
}
private BufferedImage getBufferedImage() {
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TRANSLUCENT);
Graphics2D g = image.createGraphics();
//not really necessary, in here for completeness
g.setComposite(AlphaComposite.Clear);
g.setColor(new Color(255, 255, 255, 0));
g.fillRect(0,0, image.getWidth(), image.getHeight());
g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255, 0, 0, 128));
g.fillRect(10, 10, image.getWidth()-20, image.getHeight()-20);
g.dispose();
return image;
}
private VolatileImage getVolatileImage() {
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage vImage = gc.createCompatibleVolatileImage(100, 100, Transparency.TRANSLUCENT);
Graphics2D g = vImage.createGraphics();
//necessary, as VolatileImages start out filled opaque white
g.setComposite(AlphaComposite.Clear);
g.setColor(new Color(255, 255, 255, 0));
g.fillRect(0,0, vImage.getWidth(), vImage.getHeight());
g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255, 0, 0, 128));
g.fillRect(10, 10, vImage.getWidth()-20, vImage.getHeight()-20);
g.dispose();
return vImage;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new PaintTest();
}
});
}
}
---------- END SOURCE ----------
java version " 1.7.0_40-ea "
Java(TM) SE Runtime Environment (build 1.7.0_40-ea-b29)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b48, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Mac 10.8.3
EXTRA RELEVANT SYSTEM CONFIGURATION :
Graphics Card: Intel HD Graphics 3000.
This has also happened with other Macs, regardless of Graphics Card.
A DESCRIPTION OF THE PROBLEM :
When drawing a translucent VolatileImage to a BufferedImage (or calling VolatileImage.getSnapshot()) and then drawing that BufferedImage to the screen graphics, the translucent pixels are rendered incorrectly. Instead of being rendered as translucent, they are rendered with a black background.
If the VolatileImage is drawn right to the screen graphics, this problem does not occur.
REGRESSION. Last worked in version 6u45
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a translucent VolatileImage
2. Clear it
3. Fill with a half opaque color (such as rgba(255, 255, 255, 128))
4a. Create a BufferedImage of type INT_ARGB
4b. Draw the VolatileImage to the BufferedImage's graphics
-- or instead of doing steps 4a and 4b, do:
4. Create a BufferedImage by calling VolatileImage.getSnapshot()
---
5. Draw the BufferedImage obtained in steps 4a/4b or 4 to the screen graphics.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect the BufferedImage created in steps 4 or 4a/4b to look exactly as if I had created a BufferedImage and filled it with the half opaque color and then painted it to the screen graphics.
I also expect the BufferedImage created in steps 4 or 4a/4b to look exactly like the VolatileImage when the VolatileImage is painted directly to the screen graphics.
ACTUAL -
The BufferedImage created in steps 4 or 4a/4b has a black tinge to it where the pixels are supposed to be translucent.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Shows the difference between the painting of a translucent BufferedImage and a translucent
* VolatileImage.
*
*
* On Java 6, this works fine. On Java 7, the VolatileImages are not painted correctly, when painted
* onto a BufferedImage prior to being painted to screen graphics.
*
* @author jfinley
*
*/
public class PaintTest {
public PaintTest() {
JPanel bufferedImagePanel = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
BufferedImage image = getBufferedImage();
g.drawImage(image, 0, 0, null);
};
};
JPanel bufferedImagePanel2 = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
BufferedImage bImage = getBufferedImage();
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
//not really necessary, but in there for completeness
g2.setComposite(AlphaComposite.Clear);
g2.setColor(new Color(255, 255, 255, 0));
g2.fillRect(0,0, image.getWidth(), image.getHeight());
g2.setComposite(AlphaComposite.SrcOver);
g2.drawImage(bImage, 0, 0, null);
g2.dispose();
g.drawImage(image, 0, 0, null);
};
};
JPanel volatileImagePanel = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
VolatileImage vImage = getVolatileImage();
/**
* If we draw the VolatileImage directly to g, it works fine... but
* if we draw VolatileImage.getSnapshot(), or otherwise convert the VolatileImage
* to a buffered image, we get the black halo funk of death.
*/
g.drawImage(vImage, 0, 0, null); //works
//g.drawImage(vImage.getSnapshot(), 0, 0, null); //black halo funk of death
};
};
JPanel volatileImagePanel2 = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
VolatileImage vImage = getVolatileImage();
/**
* If we draw the VolatileImage directly to g, it works fine... but
* if we draw VolatileImage.getSnapshot(), or otherwise convert the VolatileImage
* to a buffered image, we get the black halo funk of death.
*/
//g.drawImage(vImage, 0, 0, null); //works
g.drawImage(vImage.getSnapshot(), 0, 0, null); //black halo funk of death
};
};
JPanel volatileImagePanel3 = new JPanel() {
protected void paintComponent(java.awt.Graphics g) {
super.paintComponent(g);
VolatileImage vImage = getVolatileImage();
/**
* If we draw the VolatileImage directly to g, it works fine... but
* if we draw VolatileImage.getSnapshot(), or otherwise convert the VolatileImage
* to a buffered image, we get the black halo funk of death.
*/
//g.drawImage(vImage, 0, 0, null); //works
//g.drawImage(vImage.getSnapshot(), 0, 0, null); //black halo funk of death
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
//not really necessary, but in there for completeness
g2.setComposite(AlphaComposite.Clear);
g2.setColor(new Color(255, 255, 255, 0));
g2.fillRect(0,0, image.getWidth(), image.getHeight());
g2.setComposite(AlphaComposite.SrcOver);
g2.drawImage(vImage, 0, 0, null);
g2.dispose();
g.drawImage(image, 0, 0, null);
};
};
final JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 1, 1, 1, 0, 0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
mainPanel.add(new JLabel( " Direct to g " ), gbc);
gbc.gridy++;
mainPanel.add(new JLabel( " BufferImage Proxy " ), gbc);
gbc.gridy++;
mainPanel.add(new JLabel( " BufferImage Proxy 2 " ), gbc);
gbc.gridx = 1; gbc.gridy = 0;
mainPanel.add(new JLabel( " BufferedImages " ), gbc);
gbc.gridx++;
mainPanel.add(new JLabel( " VolatileImages " ), gbc);
gbc.gridx = 1; gbc.gridy = 1; gbc.weightx = 1; gbc.weighty = 1;
mainPanel.add(bufferedImagePanel, gbc);
gbc.gridy++;
mainPanel.add(bufferedImagePanel2, gbc);
gbc.gridx = 2; gbc.gridy = 1;
mainPanel.add(volatileImagePanel, gbc);
gbc.gridy++;
mainPanel.add(volatileImagePanel2, gbc);
gbc.gridy++;
mainPanel.add(volatileImagePanel3, gbc);
JButton repaintButton = new JButton( " Repaint " );
repaintButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
mainPanel.repaint();
}
});
gbc.gridx = 1; gbc.gridy++; gbc.gridwidth = 2; gbc.weighty = 0;
mainPanel.add(repaintButton, gbc);
JFrame mainFrame = new JFrame( " O.M.G. " );
mainFrame.getContentPane().setLayout(new BorderLayout());
mainFrame.getContentPane().add(mainPanel, BorderLayout.CENTER);
mainFrame.setPreferredSize(new Dimension(400, 400));
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setVisible(true);
}
private BufferedImage getBufferedImage() {
BufferedImage image = new BufferedImage(100, 100, BufferedImage.TRANSLUCENT);
Graphics2D g = image.createGraphics();
//not really necessary, in here for completeness
g.setComposite(AlphaComposite.Clear);
g.setColor(new Color(255, 255, 255, 0));
g.fillRect(0,0, image.getWidth(), image.getHeight());
g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255, 0, 0, 128));
g.fillRect(10, 10, image.getWidth()-20, image.getHeight()-20);
g.dispose();
return image;
}
private VolatileImage getVolatileImage() {
GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage vImage = gc.createCompatibleVolatileImage(100, 100, Transparency.TRANSLUCENT);
Graphics2D g = vImage.createGraphics();
//necessary, as VolatileImages start out filled opaque white
g.setComposite(AlphaComposite.Clear);
g.setColor(new Color(255, 255, 255, 0));
g.fillRect(0,0, vImage.getWidth(), vImage.getHeight());
g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255, 0, 0, 128));
g.fillRect(10, 10, vImage.getWidth()-20, vImage.getHeight()-20);
g.dispose();
return vImage;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
new PaintTest();
}
});
}
}
---------- END SOURCE ----------
- backported by
-
JDK-8046837 [OGL] Translucent VolatileImages don't paint correctly
- Resolved
-
JDK-8048426 [OGL] Translucent VolatileImages don't paint correctly
- Resolved
-
JDK-8053683 [OGL] Translucent VolatileImages don't paint correctly
- Resolved
-
JDK-8232492 [OGL] Translucent VolatileImages don't paint correctly
- Resolved