繁体   English   中英

Java2D / Swing:呈现具有对BufferedImage文本反别名的组件

[英]Java2D/Swing: Rendering a component with text anti aliasing to a BufferedImage

我想将Java Swing组件(例如JButton,我也放在JFrame上)呈现到BufferedImage。 这通常可以正常工作,但有一个主要缺点:渲染到BufferedImage时,文本抗锯齿,特别是“ LCD”抗锯齿模式不起作用。

我将一些示例代码放在一起以演示该问题,但首先要了解我的系统信息:

  • 操作系统 :Windows 7 64 Bit
  • JVM :1.6.0_26-b03(32位)

以下示例代码将创建一个简单的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();
  }
}

下图显示了屏幕上JFrame中的JButton与图像文件中相同的渲染JButton之间的区别:

在此处输入图片说明

实际上,图像中有一些文本抗锯齿,但JFrame的屏幕上没有显示LCD优化的抗锯齿(默认的LookAndFeel也会发生此问题,不仅是WindowsLookAndFeel)。

我已经尝试在“ g2d”(即BufferedImage的Graphics2D上下文)上显式设置RenderingHint来进行文本抗锯齿:

g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, 
    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB );

但这根本没有效果。

我迫切需要将JButton渲染为图像文件,就像在屏幕上渲染的一样(这只是一个示例,实际上我需要渲染一些更复杂的组件,所有这些组件都受到该抗锯齿问题的困扰),我希望有一个真正的解决方案,无需采取任何令人讨厌的解决方法,例如截屏或其他操作。

我非常感谢您的帮助-非常感谢!

这是一个JVM错误

我遇到了与您相同的问题。 而且我已经得出结论,问题确实在于绘制半透明的位图。 我相当确定我们会遇到: http : //bugs.sun.com/bugdatabase/view_bug.do? bug_id= 6749069

解决方法

现在,我绘制一个不透明的位图并将其blit到我的目标位图中。 如果文本后面的背景颜色是纯色,则应该可以使用:

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);
}

如果您的背景不是纯色,则必须将文本以黑底白字呈现为位图A 然后用您的文本颜色C填充另一个位图。 然后将其映射到目标图像, D为: D += A*CD = D*(1-A)+A*C或其他合适的混合功能。

反正可能为时已晚。 问题可能与您使用的半透明BufferedImage图像有关。 以下似乎可以正常工作:

BufferedImage image = new BufferedImage( 800, 600, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);

在环顾四周时,我发现了类似的抱怨

您要么希望(a)您的半透明BufferedImage看上去与JButton一样好,要么(b)您希望JButton和BufferedImage看上去相同。

如果是(b),您可以拥有半透明的JButton吗? 它看起来和您的半透明BufferedImage一样吗?

如果(a)是一个困难的方法,则可以将JButton绘制为不透明的BufferedImage(如果Java具有灰度BufferedImage,请使用此方法)。 这最终将成为最终BufferedImage的alpha通道的负值(黑色像素变为完全不透明,白色变为完全透明。)要获得BufferedImage中像素的颜色,您需要设置任何不透明的像素变为黑色-像素的透明度应使其变为所需的灰色。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM