Relates :
|
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)