将 Java 2d 图形图像保存为 .png 文件
Posted
技术标签:
【中文标题】将 Java 2d 图形图像保存为 .png 文件【英文标题】:Saving a Java 2d graphics image as .png file 【发布时间】:2012-01-02 09:18:18 【问题描述】:我正在绘制模拟正在生成的信息的图形表示。我有图表显示,但我遇到的问题是能够将其保存为.png。当它保存png时,文件全是黑色的,所以它不是保存我的图形而是创建一些空白的png文件。问题是我很难弄清楚如何转换为 BufferedImage 或 RenderedImage 我在 eclipse 中的所有尝试都会抛出错误,当我编译它时,它就像我上面描述的那样工作。有什么想法或建议吗?我已经坚持了几个星期,要么这是一个明显的修复,要么我无法将它保存为 png。但是根据我进行的研究,可以将 java 2d 图形 img 保存为 png 文件,我不知道我错过了什么?一双新鲜的眼睛将不胜感激!在此先感谢您,感谢您对此提出的任何建议或建议。
public class GraphDisplay extends JPanel implements RenderedImage
final int PAD = 20;
Primate p;
public GraphDisplay()
public GraphDisplay(Primate p)
this.p = p;
protected void paintComponent(Graphics g)
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// now we can get x1,y1,x2,y2
double tlx= p.getMap().getX1();
double tly= p.getMap().getY1();
double brx= p.getMap().getX2();
double bry= p.getMap().getY2();
int w = getWidth();
int h= getHeight();
ArrayList <Tree> t= p.getMap().getTrees();
ArrayList<Double> xHist = p.getXHist();
ArrayList<Double> yHist = p.getYHist();
ArrayList<Double> testxHist = new ArrayList();
ArrayList<Double> testyHist = new ArrayList();
for(double i=34;i<1000;i+=5)
testxHist.add(i);
for(double i=34;i<1000;i+=5)
testyHist.add(i);
// Draw lines.
double scale=.45;
g2.setBackground(Color.WHITE);
g2.setPaint(Color.green.darker());
for(int i = 0; i < xHist.size()-1; i++)
double x1 = PAD + (xHist.get(i)-tlx)*scale;
double y1 = (tly-yHist.get(i))*scale-PAD;
double x2 = PAD + (xHist.get(i+1)-tlx)*scale;
double y2 = (tly-yHist.get(i+1))*scale-PAD;
g2.draw(new Line2D.Double(x1, y1, x2, y2));
// Mark path points
if(p.getRoute()!=null)
ArrayList<Double> routeX= p.getRoute().getX();
ArrayList<Double> routeY= p.getRoute().getY();
g2.setPaint(Color.pink);
for(int i = 0; i < routeX.size()-1; i++)
double x1 = PAD + (routeX.get(i)-tlx)*scale;
double y1 = (tly-routeY.get(i))*scale-PAD;
double x2 = PAD + (routeX.get(i+1)-tlx)*scale;
double y2 = (tly-routeY.get(i+1))*scale-PAD;
g2.draw(new Line2D.Double(x1, y1, x2, y2));
g2.setPaint(Color.red);
for(int i = 0; i < xHist.size(); i++)
double x = PAD + (xHist.get(i)-tlx)*scale;
double y = (tly-yHist.get(i))*scale-PAD;
g2.fill(new Ellipse2D.Double(x-.75, y-.75, 1.5, 1.5));
//testing purposes
g2.setPaint(Color.BLACK);
for(int i=0;i<t.size();i++)
double x= PAD+(t.get(i).getX()-tlx)*scale;
double y= (tly-t.get(i).getY())*scale-PAD;
g2.fill(new Ellipse2D.Double(x-1,y-1,2,2));
public class GraphListener implements ActionListener
public void actionPerformed(ActionEvent event)
saveGraph(p);
public void saveGraph(Primate p)
ImageIcon saveIcon = new ImageIcon("save.png");
GraphDisplay graphImg = new GraphDisplay(p);
Object graph = new GraphDisplay(p);
BufferedImage buffGraph = new BufferedImage(500,500, BufferedImage.TYPE_INT_RGB);
graph = buffGraph.createGraphics();
RenderedImage rendGraph = (RenderedImage) graphImg;
String graphFileName = JOptionPane.showInputDialog("Please enter a name for the S1Mian graphical output file: ");
File f;
f = new File(graphFileName + ".png");
//every run is unique so do not allow the user to overwrite previously saved files...
if(!f.exists())
try
ImageIO.write(buffGraph, "png", f);
JOptionPane.showMessageDialog(null, graphFileName + ".png has been created and saved to your directory...", "File Saved", JOptionPane.INFORMATION_MESSAGE, saveIcon);
catch (IOException e)
e.printStackTrace();
else
JOptionPane.showMessageDialog(null, graphFileName +".png already exists please use a different file name...", "File Exists", JOptionPane.INFORMATION_MESSAGE, saveIcon);
public void createGraph(Primate p)
JFrame frame = new JFrame("S1Mian Graphical Output");
//frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //disabled now that graphical output is integrated into GUI as when clicked shut down entire program...
JPanel savePanel = new JPanel();
ImageIcon saveIcon = new ImageIcon("saveIcon.png");
JButton save = new JButton("Save");
save.setToolTipText("Saves the S1Mian graphical output to a .png file");
save.setIcon(saveIcon);
GraphListener gl = new GraphListener();
save.addActionListener(gl);
GraphDisplay graph = new GraphDisplay(p);
graph.setPreferredSize(new Dimension(950, 900));
JScrollPane graphScrollPane = new JScrollPane();
graphScrollPane.setViewportView(graph);
graphScrollPane.setViewportBorder(BorderFactory.createLineBorder(Color.black));
frame.getContentPane().add(graphScrollPane, BorderLayout.CENTER);
savePanel.add(save);
frame.getContentPane().add(savePanel, BorderLayout.NORTH);
frame.setSize(900,850);
frame.setLocation(200,200);
frame.setVisible(true);
【问题讨论】:
【参考方案1】:JPanel dPanel;
...
public void save()
BufferedImage bImg = new BufferedImage(dPanel.getWidth(), dPanel.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D cg = bImg.createGraphics();
dPanel.paintAll(cg);
try
if (ImageIO.write(bImg, "png", new File("./output_image.png")))
System.out.println("-- saved");
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
【讨论】:
【参考方案2】:请参阅此示例:Draw an Image and save to png。
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class WriteImageType
static public void main(String args[]) throws Exception
try
int width = 200, height = 200;
// TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed
// into integer pixels
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig2 = bi.createGraphics();
Font font = new Font("TimesRoman", Font.BOLD, 20);
ig2.setFont(font);
String message = "www.java2s.com!";
FontMetrics fontMetrics = ig2.getFontMetrics();
int stringWidth = fontMetrics.stringWidth(message);
int stringHeight = fontMetrics.getAscent();
ig2.setPaint(Color.black);
ig2.drawString(message, (width - stringWidth) / 2, height / 2 + stringHeight / 4);
ImageIO.write(bi, "PNG", new File("c:\\yourImageName.PNG"));
ImageIO.write(bi, "JPEG", new File("c:\\yourImageName.JPG"));
ImageIO.write(bi, "gif", new File("c:\\yourImageName.GIF"));
ImageIO.write(bi, "BMP", new File("c:\\yourImageName.BMP"));
catch (IOException ie)
ie.printStackTrace();
【讨论】:
【参考方案3】:Screen Image 将创建面板的缓冲图像并将图像写入文件。
【讨论】:
感谢您提供的链接,我可以同时使用它们来使其工作,但由于图像美学,最终使用了屏幕图像。非常感谢各位,问题解决了!【参考方案4】:您似乎从未在 saveGraph(..) 例程中实际绘制到 BufferedImage。
创建 BufferedImage 并检索该图像的 Graphics 对象后,调用传递该图形上下文的主类的 paintComponent 方法。您还创建了两个 GraphDisplay 对象,但从不使用任何一个。
GraphDisplay graphImg = new GraphDisplay(p);
//You don't need this one, you created one above named graphImg
// Object graph = new GraphDisplay(p);
BufferedImage buffGraph = new BufferedImage(500,500, BufferedImage.TYPE_INT_RGB);
//get the graphics context for the BufferedImage
Graphics2D graph = buffGraph.createGraphics();
//now tell your main class to draw the image onto the BufferedImage
graphImg.paintComponent(graph);
此时,您的 BufferedImage 现在应该与您的面板具有相同的绘图,并且您应该能够保存内容。
【讨论】:
我实现了你的建议,但它仍然呈现黑色 .png 文件,有什么建议吗?谢谢! 这是我最初尝试实现的方法,但是,当我使用 TYPE_INT_RGB 时,我得到一个全黑的 .png,而当我使用 TYPE_INT_ARGB 时,我得到一个灰色的 png 文件,其中没有任何渲染。一定是我想念的东西......再次感谢!以上是关于将 Java 2d 图形图像保存为 .png 文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在保持分辨率的同时将2D float numpy数组无损保存到灰度图像中?
Python 中 Trimesh 模块的 .to_planar() 函数将 Path2D 保存为 .PNG 或 .JPEG