It'*_*eto 5 java bufferedimage java-2d antialiasing graphics2d
我想将一个Java Swing组件,例如一个JButton,我也放在JFrame上,渲染到BufferedImage.这通常有效,但有一个主要缺点:文本抗锯齿,尤其是"LCD"抗锯齿模式,在渲染到BufferedImage时不起作用.
我已经将一些示例代码放在一起来演示问题,但首先是我的系统信息:
下面的示例代码将创建一个简单的JFrame,在其上放置一个JButton,然后将JButton呈现为文件"test.png":
public class TextAntiAliasingTest
{
public TextAntiAliasingTest() throws IOException
{
// Create Test-Button which will be rendered to an image
JButton button = new JButton( "The Test-Button" );
button.setSize( 200, 70 );
button.setLocation( 200, 150 );
// Create JFrame
final JFrame frame = new JFrame();
frame.setSize( 800, 600 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setLayout( null );
frame.setLocationRelativeTo( null );
frame.add( button );
// Show JFrame
SwingUtilities.invokeLater( new Runnable() {
@Override public void run() {
frame.setVisible( true );
}
});
// Render JButton to an BufferedImage
BufferedImage image = new BufferedImage( 800, 600, BufferedImage.TYPE_INT_ARGB );
Graphics2D g2d = (Graphics2D)image.getGraphics();
button.paint( g2d );
// Write BufferedImage to a PNG file
ImageIO.write( image, "PNG", new File( "test.png" ) );
}
public static void main( String[] args ) throws Exception
{
UIManager.setLookAndFeel( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel" );
System.setProperty( "awt.useSystemAAFontSettings", "lcd" );
new TextAntiAliasingTest();
}
}
Run Code Online (Sandbox Code Playgroud)
下图显示了屏幕上JFrame中的JButton与图像文件中相同的呈现JButton之间的区别:

实际上有一些文本抗锯齿图像中的,但不是其在屏幕上在JFrame中所示(还与默认LookAndFeel发生此问题,不仅与"WindowsLookAndFeel")的LCD优化的抗混叠.
我已经尝试过明确地设置了"G2D"文本抗锯齿的RenderingHint,像这样BufferedImage的Graphics2D上下文:
g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB );
Run Code Online (Sandbox Code Playgroud)
但它根本没有效果.
我迫切需要渲染的JButton到图像文件就像是在屏幕上呈现的(这只是一个例子,其实我需要呈现一些更复杂的组件,而这一切从抗混叠问题的困扰),我希望有一个真正的没有任何令人讨厌的解决方法的解决方案,如截取屏幕截图等.
我非常感谢任何帮助 - 非常感谢!
我遇到了和你一样的问题。我得出的结论是,问题确实在于绘制半透明位图。我相当确定我们正在点击:https://bugs.java.com/bugdatabase/view_bug ?bug_id=6749069
现在,我绘制一个不透明的位图并将其传输到我的目标位图中。如果文本后面的背景颜色是纯色,那么这应该有效:
private void drawString(String text, int x, int y, Graphics2D g, Color bg){
// Prepare an off-screen image to draw the string to
Rectangle2D bounds = g.getFontMetrics().getStringBounds(text, g);
BufferedImage image = configuration.createCompatibleImage(
(int)(bounds.getWidth() + 1.0f),
(int)(bounds.getHeight() + 1.0f),
Transparency.OPAQUE);
Graphics2D ig = image.createGraphics();
// Fill the background color
ig.setColor(bg);
ig.fillRect(0, 0, image.getWidth(), image.getHeight());
// Draw the string
int x0 = 0;
int y0 = ig.getFontMetrics().getAscent();
ig.setColor(g.getColor());
ig.setRenderingHints(g.getRenderingHints());
ig.setFont(g.getFont());
ig.drawString(text, x0, y0);
ig.dispose();
// Blit the image to the destination
g.drawImage(image, x-x0, y-y0, null);
}
Run Code Online (Sandbox Code Playgroud)
如果您的背景不是纯色,则必须将文本渲染为位图上的黑底白字A。然后用您的文本颜色填充另一个位图C。然后将其传输到您的目标图像,D如:D += A*C或D = D*(1-A)+A*C或其他合适的混合函数。
| 归档时间: |
|
| 查看次数: |
2507 次 |
| 最近记录: |