Combine multiple jpeg images with low or persistent memory

I have multiple images and each image has a resolution of about 2560x10000, I want to combine all of these images to make one image. I cannot use the BufferedImage method as the final image, and the image that I have to merge will be in memory while calling OutOfMemory at the same time. So I tried the approach below:

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());
    }
}

      

This method is called for every image I want to join.
The problem with this approach is that the size of the final image grows and is equal to the sum of the sizes of all the images I have joined, but only the first image is displayed when I open the final image. I still can't figure out what I am doing wrong and I also couldn't find any example code to attach to jpegs other than the BufferedImage and ImageIO.write approach. I read on the newsgroup that it works for tiff format, but I need it to work in jpeg / png formats.

+3


source to share


1 answer


I assume that you have already solved this or have worked around it in some way, but .. In case anyone else needs to solve a similar problem:

A bit unclear what you are trying to achieve here. Are you sure you want to create one large image or create one file containing multiple images?

Several images in one file:

Your code seems to add multiple standalone JPEGs to a single file. The JPEG format (JFIF) does not support this, and most programs will probably just see your file as the first JPEG with the downloaded junk added to it. PNG doesn't allow you to store multiple images in one file AFAIK. A format like TIFF allows for multiple images (it even allows them to be stored as JPEG streams), which is likely due to the fact that TIFF was raised.

However, the JPEG standard has a concept of Abbreviated Streams , which is very similar to how JPEGs are usually stored in pyramidal TIFFs. ImageIO JPEGImageWriter

supports this feature:

"Abbreviated streams are written using ImageWriter sequence methods. Stream metadata is used to write an image only for tables at the beginning of the stream, and tables are configured for use using ImageWriter.prepareWriteSequence. If no stream metadata is passed to ImageWriter.prepareWriteSequence, then only the image with table. If stream metadata containing tables is not passed to ImageWriter.prepareWriteSequence, then only the table image containing tables is written with no visible default loss. "



I'm not sure how other software will interpret these files and according to the libjpeg docs it probably won't even work

"While abbreviated data streams can be useful in a closed environment, their use is strongly discouraged in any situation where communication with other applications may be required. Designer Caveat."

So, this may or may not be appropriate for your use case.

Compose multiple images into one large image:

If, on the other hand, you really want to compose multiple images into one large image (and then store as one JPEG), you can look at some code I wrote a long time ago to allow working with large images without using heap memory.

It uses memory mapped byte buffers and can be very slow if you don't have enough memory to store data in RAM. Also, the resulting BufferedImage

one will always be there TYPE_CUSTOM

, so it will miss most of the potentially hardware or native speedups you would normally win, and some operations might not work on it. However, at least you are not limited by heap size and physical RAM.

+1


source







All Articles