我有一个jPanel,其宽度为23500,高度为43000.我正在编写PNG图像文件,但收到OutOfMemoryError:Java堆空间。是否可以从同样大的jPanel中写出如此大的图像?我在网上花了大约8个小时,根本找不到答案。
从bufferedReader声明中抛出错误。任何帮助将不胜感激!当我弄明白时,我会发布解决方案。
我的代码如下:
try {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.createGraphics();
uMLDiagramPanelJScrollPane.getViewport().getView().print(bufferedImage.createGraphics());
g.dispose();
ImageIO.write(bufferedImage, "PNG", new File(System.getProperty("user.home") + "/Desktop/" + "image.png/"));
} catch (IOException e) {
e.printStackTrace();
}
答案 0 :(得分:1)
此答案产生的大PNG图片可能由于其(任意大)尺寸而无法打开。但是,您始终可以将PNG带到印刷厂(假设您没有海报打印机)。这是一个纯Java方法。工作原理:使用(任意大)组件的图形化转换,回收bufferedImage依次写入磁盘,即ARGB PNG文件。
public void putArbitrarilyLargeComponentPNGImageOnWeeComputerDesktop(Component component) throws Exception {
int width = component.getWidth();
int componentHeight = component.getHeight();
int clipHeight = 1000;
int pixelRowsDrawn = 0;
BufferedImage bufferedImage;
Graphics g = null;
ByteBuffer iHDRTypeAndDataPartsForCRCByteBuffer = ByteBuffer.allocate(17);
FileOutputStream fos = new FileOutputStream(new File(System.getProperty("user.home") + "/Desktop/arbitrarilyLargePNG.png"), true);
ByteArrayOutputStream compressed = new ByteArrayOutputStream(65536);
DeflaterOutputStream dos = new DeflaterOutputStream(compressed, new Deflater(9), true);
CRC32 crc = new CRC32();
// Write 8-bytes PNG file signature and 4-byte IHDR data part length.
fos.write(new byte[] { -119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13 });
iHDRTypeAndDataPartsForCRCByteBuffer.wrap(new byte[17]);
iHDRTypeAndDataPartsForCRCByteBuffer.put("IHDR".getBytes());
iHDRTypeAndDataPartsForCRCByteBuffer.put(ByteBuffer.allocate(4).putInt(width).array());
iHDRTypeAndDataPartsForCRCByteBuffer.put(ByteBuffer.allocate(4).putInt(componentHeight).array());
//See 4.1.1. at <https://www.w3.org/TR/PNG-Chunks.html> starting with "Bit depth"
iHDRTypeAndDataPartsForCRCByteBuffer.put(new byte[] { 8, 6, 0, 0, 0 });
fos.write(iHDRTypeAndDataPartsForCRCByteBuffer.array());
crc.update(iHDRTypeAndDataPartsForCRCByteBuffer.array());
fos.write(ByteBuffer.allocate(4).putInt((int) crc.getValue()).array());
while (pixelRowsDrawn < componentHeight) {
if (componentHeight - pixelRowsDrawn < clipHeight) clipHeight = componentHeight - pixelRowsDrawn;
bufferedImage = new BufferedImage(width, clipHeight, BufferedImage.TYPE_INT_ARGB);
g = bufferedImage.createGraphics();
g.translate(0, -pixelRowsDrawn);
component.paint(g);
compressed.reset();
int pixel, x = 0, y = 0;
while (y < clipHeight) {
x = 0;
dos.write(0);
while (x < width) {
pixel = bufferedImage.getRGB(x, y);
dos.write(new byte[] { (byte) ((pixel >> 16) & 0xff), (byte) ((pixel >> 8) & 0xff), (byte) (pixel & 0xff), (byte) ((pixel >> 24) & 0xff) });
x++;
}
y++;
}
if ((pixelRowsDrawn = pixelRowsDrawn + clipHeight) == componentHeight) dos.finish();
fos.write(ByteBuffer.allocate(4).putInt(compressed.size()).array());
fos.write("IDAT".getBytes());
crc.reset();
crc.update("IDAT".getBytes());
crc.update(compressed.toByteArray());
fos.write(compressed.toByteArray());
fos.write(ByteBuffer.allocate(4).putInt((int) crc.getValue()).array());
}
fos.write(new byte[] { 0, 0, 0, 0 });
fos.write("IEND".getBytes());
crc.reset();
crc.update("IEND".getBytes());
fos.write(ByteBuffer.allocate(4).putInt((int) crc.getValue()).array());
g.dispose();
}