图像上的Java文本

我在bufferedimage中加载一个图像,然后在上面写一些文字。在我添加文本后,它会使图像模糊,文本失真。 我有文本ANTIALIASING ON。 可以看作附件。

在此处输入图像描述

您应该能够使用其他响应中显示的呈现提示来控制文本质量。 我知道它有效,因为我已经做了很多,所以我认为它必须是导致这种情况下质量下降的其他因素。

  1. 你如何检查图像质量? 您是否将生成的BufferedImage直接绘制到Java应用程序中的屏幕图形中,还是保存到磁盘,即JPEG格式? 如果将其保存到磁盘,请尝试将其另存为PNG 24而不是JPEG。 我假设您的桌面屏幕以True Color(32或24位颜色深度)运行,对吧?
  2. 你确定图像实际上是作为BufferedImage.TYPE_INT_RGB创建的吗? 如果您无法控制代码中BufferedImage的创建,请尝试使用TYPE_INT_RGB创建一个新的BufferedImage并将源绘制到此处,然后将文本绘制到其中。
  3. 尝试将RenderingHints.KEY_DITHERING设置为RenderingHints.VALUE_DITHER_DISABLE(尽管真彩色图像不需要这样)。

如果这仍然无法帮助您找到原因,请提供更多信息(VM版本,操作系统)和源代码。 使用JDK 1.6 Update 10,文本呈现已经变得非常好,但早期版本也能够在图像中生成干净的文本,由于不太复杂的抗锯齿,它看起来不太好。

回应你的评论:

文本中的高对比度锐边是JPEG压缩的一般问题,因为它不是无损压缩。 如果您确实需要使用JPEG并且无法切换到PNG,则可以调整已保存图像的压缩质量,以便在图像质量和文件大小之间找到更好的折衷方案。 请参阅以下代码,了解如何在保存JPEG时设置压缩质量。

import javax.imageio.IIOImage; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.plugins.jpeg.JPEGImageWriteParam; import javax.imageio.stream.ImageOutputStream; //---- float quality = 0.85f; File outfile = new File( "MyImage.jpg" ); BufferedImage image = ...; ImageWriter imgWriter = ImageIO.getImageWritersByFormatName( "jpg" ).next(); ImageOutputStream ioStream = ImageIO.createImageOutputStream( outfile ); imgWriter.setOutput( ioStream ); JPEGImageWriteParam jpegParams = new JPEGImageWriteParam( Locale.getDefault() ); jpegParams.setCompressionMode( ImageWriteParam.MODE_EXPLICIT ); jpegParams.setCompressionQuality( quality ); imgWriter.write( null, new IIOImage( image, null, null ), jpegParams ); ioStream.flush(); ioStream.close(); imgWriter.dispose(); 
 import java.awt.image.BufferedImage; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.imageio.*; import java.io.*; import javax.imageio.stream.ImageOutputStream; import javax.imageio.plugins.jpeg.JPEGImageWriteParam; import java.util.Locale; class ImageCompressionDemo { private BufferedImage originalImage; private BufferedImage textImage; private JPanel gui; private JCheckBox antialiasing; private JCheckBox rendering; private JCheckBox fractionalMetrics; private JCheckBox strokeControl; private JCheckBox colorRendering; private JCheckBox dithering; private JComboBox textAntialiasing; private JComboBox textLcdContrast; private JLabel jpegLabel; private JLabel pngLabel; private JTextArea output; private JSlider quality; private int pngSize; private int jpgSize; final static Object[] VALUES_TEXT_ANTIALIASING = { RenderingHints.VALUE_TEXT_ANTIALIAS_OFF, RenderingHints.VALUE_TEXT_ANTIALIAS_ON, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB }; final static Object[] VALUES_TEXT_LCD_CONTRAST = { new Integer(100), new Integer(150), new Integer(200), new Integer(250) }; ImageCompressionDemo() { int width = 280; int height = 100; gui = new JPanel(new BorderLayout(3,4)); quality = new JSlider(JSlider.VERTICAL, 0, 100, 75); quality.setSnapToTicks(true); quality.setPaintTicks(true); quality.setPaintLabels(true); quality.setMajorTickSpacing(10); quality.setMinorTickSpacing(5); quality.addChangeListener( new ChangeListener(){ public void stateChanged(ChangeEvent ce) { updateImages(); } } ); gui.add(quality, BorderLayout.WEST); originalImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); textImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); JPanel controls = new JPanel(new GridLayout(0,1,0,0)); antialiasing = new JCheckBox("Anti-aliasing", false); rendering = new JCheckBox("Rendering - Quality", true); fractionalMetrics = new JCheckBox("Fractional Metrics", true); strokeControl = new JCheckBox("Stroke Control - Pure", false); colorRendering = new JCheckBox("Color Rendering - Quality", true); dithering = new JCheckBox("Dithering", false); controls.add(antialiasing); controls.add(fractionalMetrics); textLcdContrast = new JComboBox(VALUES_TEXT_LCD_CONTRAST); JPanel lcdContrastPanel = new JPanel(new FlowLayout(FlowLayout.LEADING)); lcdContrastPanel.add(textLcdContrast); lcdContrastPanel.add(new JLabel("Text LCD Contrast")); controls.add(lcdContrastPanel); textAntialiasing = new JComboBox(VALUES_TEXT_ANTIALIASING); controls.add(textAntialiasing); controls.add(dithering); controls.add(rendering); controls.add(colorRendering); controls.add(strokeControl); ItemListener itemListener = new ItemListener(){ public void itemStateChanged(ItemEvent e) { updateImages(); } }; antialiasing.addItemListener(itemListener); rendering.addItemListener(itemListener); fractionalMetrics.addItemListener(itemListener); strokeControl.addItemListener(itemListener); colorRendering.addItemListener(itemListener); dithering.addItemListener(itemListener); textAntialiasing.addItemListener(itemListener); textLcdContrast.addItemListener(itemListener); Graphics2D g2d = originalImage.createGraphics(); GradientPaint gp = new GradientPaint( 0f, 0f, Color.red, (float)width, (float)height, Color.orange); g2d.setPaint(gp); g2d.fillRect(0,0, width, height); g2d.setColor(Color.blue); for (int ii=0; ii 

屏幕截图

典型输出

 Fractional Metrics: true Nonantialiased text mode PNG size: 7390 bytes JPG size: 7036 bytes quality: 35 Fractional Metrics: true Antialiased text mode PNG size: 8741 bytes JPG size: 8663 bytes quality: 55 Fractional Metrics: false Antialiased text mode PNG size: 8720 bytes JPG size: 8717 bytes quality: 55 

那只是java。 只需关闭文本抗锯齿。 或者如果你真的需要它,在单独的图像上渲染文本,如果文本为黑色,则获得颜色大约在rgb(100,100,100)以下的所有像素并将它们设置为0.然后将该缓冲区绘制到主图像上。

尝试这个:

 public static void setGraphicsQuality(Graphics2D g2D) { g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); }