简体   繁体   English

如何在Java中生成特定大小的图像?

[英]How do you generate an image of a specific size in Java?

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 . 我需要使用Java生成给定大小(例如10KB100KB1MB10MB等)的图像(图像的格式无关紧要)。 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. 编辑#1:将要创建的图像的大小是可变的,因此我正在寻找一种有效内存使用方式 ,以便在创建图像时避免Java heap space异常。

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. 编辑#2:我得到java.lang.IllegalArgumentException: Dimensions (width=48000 height=48000) are too large当尝试使用Graphics2D库生成尺寸为48000x48000的图像时, java.lang.IllegalArgumentException: Dimensions (width=48000 height=48000) are too large ,这是生成异常的必要条件文件大的图像。

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. 编辑#3:当尺寸变大时,即使我手动配置了执行此操作的Java程序的-Xmx参数,也遇到了java.lang.OutOfMemoryError: Java heap space异常。

One way to generate a Gray Scale image(of width : width and height : height) :- 一种生成灰度图像(宽度:宽度和高度:高度)的方法:-

1) Create a BufferedImage object :- 1)创建一个BufferedImage对象:

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):- 2)填充您的BufferedImage对象(这里我假设您对存储在名为img的int二维数组中的图像具有正确的输入):

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 :- 3)将BufferedImage对象写入磁盘:-

ImageIO.write(image, "jpg", new FileOutputStream(new File("SomePath/Name-of-Image.jpg")));

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). 该程序应该几乎没有内存就可以非常高效地运行,但是仍然会创建大小高达(大约)2GB的图像文件(如果愿意,您也可以轻松地使其适应以创建更大的图像)。

Assumptions: 假设:

  • The image format does not matter, so we'll choose the PGM format (in binary 'P5' mode) 图片格式无关紧要,因此我们将选择PGM格式 (在二进制“ P5”模式下)
  • 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). 输入的是文件大小,后跟文件名(您想使用.pgm作为扩展名)。 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. 上面的代码将创建我的JVM允许读取的最大映像,大约为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 ). PS:如果您需要ImageIO插件才能使用Java读取生成的文件,则可以使用JAI ImageIO或我自己的PNM插件 ,但是您当然会遇到与尝试使用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. 从理论上讲,你也可以使用类似技术的格式,如JPEG或PNG创建文件,但这些格式更难实现。 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. 也许您可以使用额外的非图像数据(例如XMP等)填充最小的JPEG。 PNG does allow writing Deflate blocks with no compression, which might be an option. PNG确实允许编写不压缩的Deflate块,这可能是一个选择。 Or use extra chunks for padding. 或者使用额外的块进行填充。

An uncompressed format like BMP will be simpler. 像BMP这样的未压缩格式会更简单。 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标头,设置正确的宽度并几乎如上所述地写入图像数据。 BMP does need row padding, and doesn't support gray data, so you need to do some extra work. BMP确实需要行填充,并且不支持灰色数据,因此您需要做一些额外的工作。 But certainly doable. 但肯定是可行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM