Here's some very simple sample code that should match your requirements as far as I can understand. The program should work very efficiently with almost no memory at all, but will still create image files of sizes up to (roughly) 2GB (you can also easily adapt it to create much larger images, if you like).
Assumptions:
- The image format does not matter, so we'll choose the PGM format (in binary 'P5' mode)
- The image can be any shape/color, so we'll just do the simplest thing and write one line of all black.
- The size that matters is the image file size (the code below doesn't write to the byte this size, but could easily be modified by subtracting the size of the minimal file header before writing to be exact).
Input is file size, followed by file name (you want to use .pgm
as extension). As an example:
$ java -cp ... WritePGM 2147483640 foo.pnm
The above will create the largest possible image my JVM permits to read back, which is roughly 2 GB.
Code:
public class WritePGM {
public static void main(String[] args) throws IOException {
int size = Integer.parseInt(args[0]);
File file = new File(args[1]);
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
// Format P5/binary gray
out.write("P5\n".getBytes(StandardCharsets.UTF_8));
// Dimensions (width/height)
out.write(String.format("%s 1\n", size).getBytes(StandardCharsets.UTF_8));
// MaxSample
out.write("255\n".getBytes(StandardCharsets.UTF_8));
// Just write a single line of 0-bytes
for (int i = 0; i < size; i++) {
out.write(0);
}
}
}
}
PS: If you need an ImageIO plugin to read the generated file using Java, you can use JAI ImageIO or my own PNM plugin, but you will of course experience the same memory issues as when you tried to generate such images using Java2D (BufferedImage
).
In theory, you could also use similar techniques for creating files in formats like JPEG or PNG, but these formats are much harder to implement. Also, they are compressed, so predicting the file size is hard.
Perhaps you could pad a minimal JPEG with extra non-image data, like XMP or so. PNG does allow writing Deflate blocks with no compression, which might be an option. Or use extra chunks for padding.
An uncompressed format like BMP will be simpler. You could use the same technique as above, just write a fixed, minimal BMP header, set the correct width and write the image data almost as above. BMP does need row padding, and doesn't support gray data, so you need to do some extra work. But certainly doable.