Merge small images into one without allocating ful

2020-07-26 10:44发布

问题:

I've to make a parallel image processing script in java, the idea is to divide the images into tiles of any size, process them, and reassemble the final image.

For now i've created a function:

public static BufferedImage readImg (String path, int startx, int starty, int w, int h)

that returns the region of an image as BufferedImage, then i'll process it and i want to place that region in the correct position of the final image.

So i've tried to make a function writeImg that uses replacePixels method to write just in the correct position without loading the whole image into memory:

public static void writeImg (String path, int startx, int starty, BufferedImage image){
    File output = new File(path);
    ImageOutputStream ios = null;
    try {
        ios = ImageIO.createImageOutputStream(output);
    } catch (IOException e){
        e.printStackTrace();
    }
    Iterator iter = ImageIO.getImageWritersByFormatName("JPEG");
    ImageWriter writer = (ImageWriter)iter.next();
    writer.setOutput(ios);

    try{
        if(writer.canReplacePixels(0)){
            System.out.println("True");
        }else{
            System.out.println("False");
        }
    }catch (IOException e) {
        e.printStackTrace();
    }

    ImageWriteParam param = writer.getDefaultWriteParam();
    Point destinationOffset = new Point(startx,starty);
    param.setDestinationOffset(destinationOffset);
    try {
        writer.replacePixels(image, param);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The problem is that canReplacePixels is always set as false, and i've no idea what should i use to do that.

The images can be very big so it's impossible to load the whole image in memory as it will cause a OutOfMemory exception.

回答1:

As long as you are fine with an 24 bit PNG file as output I have a working solution for you (under GPL license):

The class PngXxlWriter allows to write PNG files "line by line". That means that you can write an image of 10000x10000 (width * height) pixels in lines of e.g. 256 pixels (10000 * 256).

Usually this reduces the memory usage down to a level which is practically.

All required classes can be found here:

PngXxlWriter is the main class. By calling its method writeTileLine you can add a new line to the output image.

https://sourceforge.net/p/mobac/code/HEAD/tree/trunk/MOBAC/src/main/java/mobac/utilities/imageio/