Reputation: 6466
I need to generate images (the format of images does not matter) of a given size (For example, 10KB
, 100KB
, 1MB
, 10MB
, etc), using Java. The image can be any shape which is filled a background color, no restrictions for the content of images.
Edit #1: The sizes of the images which are going to be created are changeable, so I am looking for an efficient way in terms of memory usage in order to be safe from the Java heap space
exception while creating images.
Edit #2: I am getting the java.lang.IllegalArgumentException: Dimensions (width=48000 height=48000) are too large
exception when I try to generate an image with the dimensions 48000x48000
using the Graphics2D library, which is necessary in order to generate images with large file sizes.
Edit #3: When the dimensions get bigger, I experience the java.lang.OutOfMemoryError: Java heap space
exception even though I have manually configured the -Xmx
parameter of the Java program that does this.
Upvotes: 2
Views: 5030
Reputation: 27054
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:
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.
Upvotes: 1
Reputation: 368
One way to generate a Gray Scale image(of width : width and height : height) :-
1) Create a BufferedImage object :-
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
2) Populate your BufferedImage object (here I am assuming that you have proper input to the image stored in a 2-d array of int called img):-
for (int y = 0; y < image.getHeight(); y++)
{
for (int x = 0; x < image.getWidth(); x++)
{
image.setRGB(x, y, img[y][x]<<16 | img[y][x] << 8 | img[y][x]);
}
}
3) Write the BufferedImage object to disk :-
ImageIO.write(image, "jpg", new FileOutputStream(new File("SomePath/Name-of-Image.jpg")));
Upvotes: 2
Reputation: 347184
Upvotes: -3