java - 加入多个具有低内存占用或恒定内存占用的 jpeg 图像

标签 java jpeg javax.imageio

我有多张图片,每张图片的分辨率约为 2560x10000,我想将所有这些图片拼接成一张图片。我不能使用 BufferedImage 方法作为最终图像,我必须加入的图像将同时位于内存中,导致 OutOfMemory。所以我尝试了以下方法:

public static void joinJpegFiles(File infile, File outfile, float compQuality,int i) {
    try {
        RenderedImage renderedImage = ImageIO.read(infile);
        ImageWriter Iwriter = null;

        Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
        if (iter.hasNext()) {
            Iwriter = (ImageWriter)iter.next();
        }

        ImageOutputStream IOStream = ImageIO.createImageOutputStream(outfile);
        Iwriter.setOutput(IOStream);
        IOStream.seek( IOStream.length());
        JPEGImageWriteParam JIWP=new JPEGImageWriteParam(Locale.getDefault());
        JIWP.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
        JIWP.setCompressionQuality(compQuality);
        Iwriter.write(null, new IIOImage(renderedImage,null,null), JIWP);               
        IOStream.flush();
        IOStream.close();
        Iwriter.dispose();
    } catch (IOException e) {
        System.out.println("write error: " + e.getMessage());
    }
}

我要加入的每个图像都会调用此方法。
这种方法的问题是最终图像的大小在增加并且等于我加入的所有图像的大小总和,但是当我打开最终图像时只有第一张图像是可见的。 我仍然无法弄清楚我做错了什么,除了 BufferedImage 和 ImageIO.write 方法之外,我也找不到任何示例代码来加入 jpeg。我在新闻组读到它适用于 tiff 格式,但我需要它适用于 jpeg/png 格式。

最佳答案

我假设您已经解决了这个问题,或者以某种方式解决了这个问题,但是..万一其他人需要解决类似的问题:

有点不清楚您要在这里实现什么。您真的要创建一个大图像,还是创建包含多个图像的单个文件?

单个文件中的多个图像:

您的代码似乎将多个独立的 JPEG 文件附加到一个文件中。 JPEG (JFIF) 格式不支持这一点,大多数软件可能会将您的文件视为第一个 JPEG,最后附加大量垃圾字节。 PNG 不允许在一个文件 AFAIK 中存储多个图像。像 TIFF 这样的格式确实允许多个图像(它甚至允许您将它们存储为 JPEG 流),这可能就是提出 TIFF 的原因。

但是,JPEG 标准有一个概念叫做 Abbreviated Streams ,这非常类似于 JPEG 通常存储在金字塔形 TIFF 中的方式。 ImageIO JPEGImageWriter 确实支持此功能:

"Abbreviated streams are written using the sequence methods of ImageWriter. Stream metadata is used to write a tables-only image at the beginning of the stream, and the tables are set up for use, using ImageWriter.prepareWriteSequence. If no stream metadata is supplied to ImageWriter.prepareWriteSequence, then no tables-only image is written. If stream metadata containing no tables is supplied to ImageWriter.prepareWriteSequence, then a tables-only image containing default visually lossless tables is written."

我不确定其他软件将如何解释这些类型的文件,根据 the libjpeg docs它甚至可能不会工作:

"While abbreviated datastreams can be useful in a closed environment, their use is strongly discouraged in any situation where data exchange with other applications might be needed. Caveat designer."

所以..它可能适合也可能不适合您的用例。

将多张图片合成一张大图:

另一方面,如果您真的想将多张图片组合成一张大图片(稍后存储为一张 JPEG),您可以查看 some code我很久以前写过,允许在不使用堆内存的情况下处理大图像。

它使用 memory-mapped byte buffers ,如果您没有足够的内存将数据存储在 RAM 中,则速度可能会非常慢。此外,生成的 BufferedImage 将始终为 TYPE_CUSTOM,因此它会错过大多数您通常会受益的潜在硬件或 native 加速,并且某些操作可能无法在其上运行.但是,至少您不受堆大小或物理 RAM 的限制。

关于java - 加入多个具有低内存占用或恒定内存占用的 jpeg 图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9781763/

相关文章:

java.lang.IllegalArgumentException : There is no queue named default 异常

java - 使用 Jackson 解析器将 JSON 数组转换为 HashMap<String,Object>

.net - 使用 mono 的 gdi+ 库的相同方法在不同机器上给出非常不同的结果

java - ImageIO - 获取图像类型和 exif 数据

Java ImageIO IIOException : Unsupported image type?

java - 创建集合或从列表中删除哪个更快?

java - 提交分数排行榜 Google Play 时应用程序崩溃

floating-point - JPEG-XL:无损模式支持32位浮点吗?

c# - 以渐进格式保存 JPEG

java - 奇怪的 PNG 错误 : Bad length for IHDR chunk