Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8045626 | 8u25 | Alexandr Scherbatiy | P3 | Resolved | Fixed | b01 |
JDK-8039897 | 8u20 | Alexandr Scherbatiy | P3 | Resolved | Fixed | b11 |
JDK-8053854 | emb-8u26 | Alexandr Scherbatiy | P3 | Resolved | Fixed | b17 |
A DESCRIPTION OF THE REQUEST :
When painting a component via component.paint(Graphics), it is impossible to paint the HiDPI version of the component (e.g. a JCheckBox) to a BufferedImage.
Even with a double-sized BufferedImage and a 2x scale factor, components are still rendered in their low/regular resolution variant.
JUSTIFICATION :
Sometimes it is necessary to paint a component to a BufferedImage, e.g. to use in an animation. One would expect to be able to achieve the same quality when painting to a buffer as it is possible when painting to the screen. Currently that's not possible with a BufferedImage.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When painting a component to a BufferedImage with a scale factor of 2x, I would expect the HiDPI version of the component to be rendered.
ACTUAL -
Even with a scale factor of 2x set, components are always painted in low/regular resolution, thus look pixely.
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
// Simple demo class. I'd expect both checkboxes to render in the same quality, but they don't using a BufferedImage.
public class RenderHiDPI {
public static void main(String[] args) {
final JFrame frame = new JFrame();
final JLabel label = new JLabel();
frame.getContentPane().setLayout(new FlowLayout());
final JCheckBox hiDPICheckBox = new JCheckBox("Hi DPI");
hiDPICheckBox.setFocusable(false);
frame.getContentPane().add(hiDPICheckBox);
frame.getContentPane().add(label);
final JCheckBox checkBox = new JCheckBox("Lo DPI");
checkBox.setSize(new Dimension(100, 100));
final BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
final Graphics g = image.getGraphics();
((Graphics2D)g).scale(2f, 2f);
checkBox.paint(g);
g.dispose();
label.setIcon(new Icon(){
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
final Graphics2D graphics = (Graphics2D)g.create();
graphics.scale(0.5f, 0.5f);
graphics.drawImage(image, x, y, c);
}
@Override
public int getIconWidth() {
return 100;
}
@Override
public int getIconHeight() {
return 100;
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.setBounds(100, 100, 100, 100);
frame.setVisible(true);
}
});
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use VolatileImage (scaling not necessary)
When painting a component via component.paint(Graphics), it is impossible to paint the HiDPI version of the component (e.g. a JCheckBox) to a BufferedImage.
Even with a double-sized BufferedImage and a 2x scale factor, components are still rendered in their low/regular resolution variant.
JUSTIFICATION :
Sometimes it is necessary to paint a component to a BufferedImage, e.g. to use in an animation. One would expect to be able to achieve the same quality when painting to a buffer as it is possible when painting to the screen. Currently that's not possible with a BufferedImage.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
When painting a component to a BufferedImage with a scale factor of 2x, I would expect the HiDPI version of the component to be rendered.
ACTUAL -
Even with a scale factor of 2x set, components are always painted in low/regular resolution, thus look pixely.
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
// Simple demo class. I'd expect both checkboxes to render in the same quality, but they don't using a BufferedImage.
public class RenderHiDPI {
public static void main(String[] args) {
final JFrame frame = new JFrame();
final JLabel label = new JLabel();
frame.getContentPane().setLayout(new FlowLayout());
final JCheckBox hiDPICheckBox = new JCheckBox("Hi DPI");
hiDPICheckBox.setFocusable(false);
frame.getContentPane().add(hiDPICheckBox);
frame.getContentPane().add(label);
final JCheckBox checkBox = new JCheckBox("Lo DPI");
checkBox.setSize(new Dimension(100, 100));
final BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
final Graphics g = image.getGraphics();
((Graphics2D)g).scale(2f, 2f);
checkBox.paint(g);
g.dispose();
label.setIcon(new Icon(){
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
final Graphics2D graphics = (Graphics2D)g.create();
graphics.scale(0.5f, 0.5f);
graphics.drawImage(image, x, y, c);
}
@Override
public int getIconWidth() {
return 100;
}
@Override
public int getIconHeight() {
return 100;
}
});
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
frame.setBounds(100, 100, 100, 100);
frame.setVisible(true);
}
});
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use VolatileImage (scaling not necessary)
- backported by
-
JDK-8039897 [macosx] Components cannot be rendered in HiDPI to BufferedImage
-
- Resolved
-
-
JDK-8045626 [macosx] Components cannot be rendered in HiDPI to BufferedImage
-
- Resolved
-
-
JDK-8053854 [macosx] Components cannot be rendered in HiDPI to BufferedImage
-
- Resolved
-
- relates to
-
JDK-7124410 [macosx] Lion HiDPI support
-
- Resolved
-