保存大图像 - 光栅问题

Posted

技术标签:

【中文标题】保存大图像 - 光栅问题【英文标题】:Saving large images - Raster problem 【发布时间】:2011-07-15 09:56:31 【问题描述】:

我已经问过一个如何保存大图像的问题,我认为我在正确的轨道上,但我仍然需要一些建议。

我有一个 12000 x 12000 的图像,我需要将其保存为 .png

BufferedImage 无法使用。

已经有人建议我使用 RenderedImage 接口,但不知何故我无法获得所需的结果。 (我还没有使用过栅格,所以可能我做错了什么)

图片保存方法代码:

   public static void SavePanel() 

    PanelImage IMAGE = new PanelImage(panel);

    try 
        ImageIO.write(IMAGE, "png", new File(ProjectNameTxt.getText() +  ".png"));
     catch (IOException e) 
    

   

以及 PanelImage 类的代码:

 public static class PanelImage implements RenderedImage 

    // some variables here

    public PanelImage(JImagePanel panel) 
       this.panel = panel;
    

  public Raster getData(Rectangle rect) 

        sizex = (int) rect.getWidth();
        sizey += (int) rect.getHeight();
        image = null;
        image = new BufferedImage(
                (int) sizex,
                (int) sizey,
                BufferedImage.TYPE_INT_RGB);
        g2 = image.createGraphics();
        panel.paintComponent(g2);
        return image.getData();
    

 // rest of the implemented methods - no problems here
 

我注意到 ImageIO 一次请求一行像素( 12000 x 1 )。 此方法有效,但我仍然需要 BufferedImage 中的整个图像。 每次 ImageIO 调用该方法时,我都必须增加 BImage 的大小,否则我会得到“坐标越界!”异常

谢谢

【问题讨论】:

首先你说BufferedImage 不能使用,但是在后面的代码中你仍然在使用它。所以你是什么意思?当您尝试使用BufferedImage 时,您是否收到错误消息(可能是OutOfMemoryError?)?确切的错误信息是什么? 是的,我首先使用了缓冲图像,但是尺寸太大了。有人建议我只使用缓冲图像来获取 ImageIO 请求的光栅的一部分,但我不知道该怎么做 【参考方案1】:

这个PNGJ 库对于读取/写入大图像很有用,因为它是按顺序执行的,它一次只在内存中保留一行。 (前段时间我自己写的,因为我也有类似的需求)

【讨论】:

非常感谢!我必须弄清楚如何从我的图像面板中获取像素,但我让它工作得非常好(比直接保存 BufferedImage 慢一点,但图像大小不再是问题)。我可以写一个教程如何使用你的库来保存这么大的图像吗? @lcki:当然。您可以自己添加一个 wiki 页面,或将文本发送给我【参考方案2】:

我刚刚破解了ComponentImage 的最小工作示例,它采用任意JComponent 并且可以传递给ImageIO 进行编写。为简洁起见,此处仅包含“有趣”的部分:

public final class ComponentImage implements RenderedImage     
    private final JComponent comp;
    private final ColorModel colorModel;
    private final SampleModel sampleModel;

    public ComponentImage(JComponent comp) 
        this.comp = comp;
            this.colorModel = comp.getColorModel();
        this.sampleModel = this.colorModel.createCompatibleWritableRaster(1, 1).
                getSampleModel();
    
    @Override
    public ColorModel getColorModel() 
        return this.comp.getColorModel();
    

    @Override
    public SampleModel getSampleModel() 
        return this.sampleModel;
    
    @Override
    public Raster getData(Rectangle rect) 
        final WritableRaster raster = this.colorModel.
                createCompatibleWritableRaster(rect.width, rect.height);

        final Raster result = raster.
                createChild(0, 0, rect.width, rect.height,
                rect.x, rect.y, null);

        final BufferedImage img = new BufferedImage(
                colorModel, raster, true, null);

        final Graphics2D g2d = img.createGraphics();
        g2d.translate(-rect.x, -rect.y);
        this.comp.paintAll(g2d);
        g2d.dispose();

        return result;

    

【讨论】:

我会试试的。我让它与这里提到的 PNGJ 库一起工作,但也许你的方法会更快。感谢您的帮助!

以上是关于保存大图像 - 光栅问题的主要内容,如果未能解决你的问题,请参考以下文章

PIL 将大图像保存为静态

使用缩小到 1/2 大小的大图像?对加载时间不利?

Python:如何将 shapefile 放在一个绘图中的光栅文件顶部,然后将绘图保存为 Jpeg 文件格式

android 仿头条 微信大图预览动画 双击缩放 保存至相册

即拿即用-选择头像,可以选择相册,拍照,查看大图,保存到本地

Texture的渲染大图裁剪成小图并保存下来