简体   繁体   English

Java绘画到BufferedImage或ImageIO.write()不会阻塞,并且生成的png文件要么空白,要么空白

[英]Java painting to BufferedImage or ImageIO.write() do not block and png file produced is either blank of half-baked

I'm creating small png files with simple black and white line drawings within the servlet running on Tomcat 7 on Linux CentOS and using frame buffer Xvfb to provide graphic resources. 我正在在Linux CentOS上的Tomcat 7上运行的servlet中创建带有简单黑白线图的小png文件,并使用帧缓冲区Xvfb提供图形资源。 My goal is then to show this png file on the html page returned by the server. 然后,我的目标是在服务器返回的html页面上显示此png文件。 What I'm finding is that once in a while (say one picture out of 10) is shown as blank or sometimes even half-drawn. 我发现,有时(例如,每10张照片中的一张)显示为空白,有时甚至是半张。 I checked the corresponding .png files on the server and they are indeed generated in these cases either as blank or as half-drawn. 我检查了服务器上的相应.png文件,在这些情况下,它们的确确实是空白或半绘制的。

This is how my code looks (additional complication is that ChimePro is part of the proprietary class library, I don't have its code; it just extends Panel or Canvas): 这就是我的代码的样子(另外的复杂之处是ChimePro是专有类库的一部分,我没有它的代码;它只是扩展了Panel或Canvas):

Frame f = new Frame();
ChimePro cp = new ChimePro();
f.add(cp);
f.addNotify();
cp.setBounds(0,0,200,200);

BufferedImage bi = new BufferedImage (200,200,BufferedImage.TYPE_BYTE_INDEXED); 
Graphics g = bi.createGraphics()
cp.paint(g);
File ffjj = new File("file.png");


ImageIO.write(bi, "png", ffjj);

So it looks as if paint(g) or, perhaps less probable, ImageIO.write() methods are not blocking as they should be doing, and the program goes forward even though the proper file has not yet been created. 因此,似乎paint(g)或可能不太可能的ImageIO.write()方法没有像应做的那样阻塞,并且即使尚未创建正确的文件,程序也继续前进。 It is also interesting that depending on how I point DISPLAY variable before the Tomcat startup - either to Xvfb screen emulating the X environment on the same server, or to some real X display running on the remote machine - the probability of blank or corrupted pictures changes. 有趣的是,取决于我在Tomcat启动之前如何指向DISPLAY变量-指向模拟同一服务器上X环境的Xvfb屏幕,或者指向远程计算机上运行的某些真实X显示-图片发生空白或损坏的可能性发生了变化。

Any ideas of how to deal with this issue to insure that my users do not see blank or corrupted drawings? 关于如何处理此问题以确保用户看不到空白或损坏的图形的任何想法? I'm actually writing small number of short files, so this is not about speed, just about avoiding showing incorrectly drawn pictures. 我实际上是在写少量的短文件,所以这与速度无关,只是为了避免显示错误绘制的图片。 Would be thankful for any suggestions. 谢谢您的任何建议。

This is the exception (happens only in some drawings arbitrarily - not depending on the contents of drawing but on some tinming probably): 这是例外(仅在某些图形中偶然发生-不取决于图形的内容,而可能取决于某些着色):

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerExceptio
at com.mdli.chime.ChimePro.paint(ChimePro.java)
at java.awt.Canvas.update(Canvas.java:142)
at sun.awt.RepaintArea.updateComponent(RepaintArea.java:255)
at sun.awt.X11.XRepaintArea.updateComponent(XRepaintArea.java:60)
at sun.awt.RepaintArea.paint(RepaintArea.java:232)
at sun.awt.X11.XComponentPeer.handleEvent(XComponentPeer.java:591)
at java.awt.Component.dispatchEventImpl(Component.java:4937)

Have g.dispose() before ImageIO.write and see if it helps: 在ImageIO.write之前使用g.dispose(),看看是否有帮助:

Frame f = new Frame();
ChimePro cp = new ChimePro();
f.add(cp);
f.addNotify();
cp.setBounds(0,0,200,200);

BufferedImage bi = new BufferedImage (200,200,BufferedImage.TYPE_BYTE_INDEXED); 
Graphics g = bi.createGraphics()
cp.paint(g);
File ffjj = new File("file.png");
g.dispose();

ImageIO.write(bi, "png", ffjj);

You need to make sure that you... 您需要确保自己...

  1. Set the size of the component 设置组件的大小
  2. Layout the child components of the container if required 如果需要,布局容器的子组件
  3. Use printAll rather the print as it will attempt to ensure the content is painted fully and doesn't double buffer the process (making it faster) 使用printAll而不是print ,因为它将尝试确保内容被完整绘制,并且不会对流程进行双重缓冲(使其更快)
  4. dispose of the Graphics context once you are completed. dispose Graphics上下文。

The following shows the panel when displayed on a frame and when printed using the sample code... 下面显示了在框架上显示和使用示例代码打印时的面板...

在此处输入图片说明在此处输入图片说明

import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class PrintComponent {

    public static void main(String[] args) {
        new PrintComponent();
    }

    public PrintComponent() {

        Example example = new Example();
        example.setSize(example.getPreferredSize());
        example.doLayout();
        BufferedImage bi = new BufferedImage (example.getWidth(), example.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
        Graphics2D g2d = bi.createGraphics();
        example.printAll(g2d);
        g2d.dispose();

        try {
            ImageIO.write(bi, "png", new File("D:/PrintExample.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public class Example extends JPanel {

        public Example() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(new JLabel("Hello"), gbc);
            add(new JTextField("'ello", 20), gbc);
            add(new JButton("g'day"), gbc);
        }

    }

}

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

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