如何在 Java 中生成特定尺寸的图像?
How do you generate an image of a specific size in Java?
我需要生成给定大小的图像(图像格式无关紧要)(例如,10KB
、100KB
、1MB
、10MB
等),使用 Java。图片可以是任意形状,填充背景色,图片内容不限。
编辑#1:要创建的图像的大小是可变的,所以我正在寻找一种有效的方法 在 内存使用 方面,以便在创建图像时免受 Java heap space
异常的影响。
编辑 #2: 当我尝试使用 Graphics2D 库生成尺寸为 48000x48000
的图像时出现 java.lang.IllegalArgumentException: Dimensions (width=48000 height=48000) are too large
异常,它是生成具有大文件大小的图像所必需的。
编辑 #3: 当维度变大时,我遇到了 java.lang.OutOfMemoryError: Java heap space
异常,即使我手动配置了 -Xmx
参数=42=] 执行此操作的程序。
For example
生成灰度图像(宽度:宽度和高度:高度)的一种方法:-
1) 创建一个 BufferedImage 对象 :-
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
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) 将 BufferedImage 对象写入磁盘:-
ImageIO.write(image, "jpg", new FileOutputStream(new File("SomePath/Name-of-Image.jpg")));
这是一些非常简单的示例代码,据我所知应该符合您的要求。该程序应该在几乎没有内存的情况下非常有效地工作,但仍会创建大小高达(大约)2GB 的图像文件(如果您愿意,您也可以轻松地调整它来创建更大的图像)。
假设:
- 图像格式无关紧要,所以我们选择 PGM format(二进制 'P5' 模式)
- 图像可以是任何图像shape/color,所以我们只做最简单的事情,写一行全黑。
- 重要的是图像文件的大小(下面的代码不会写入这个大小的字节,但可以通过在写入之前减去最小文件的大小 header 来轻松修改准确)。
输入文件大小,后跟文件名(您要使用 .pgm
作为扩展名)。例如:
$ java -cp ... WritePGM 2147483640 foo.pnm
以上将创建我的 JVM 允许读回的最大可能图像,大约为 2 GB。
代码:
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:如果你需要一个ImageIO插件来读取使用Java生成的文件,你可以使用JAI ImageIO或者my own PNM plugin,但是你当然会遇到同样的内存当您尝试使用 Java2D (BufferedImage
).
生成此类图像时出现的问题
理论上,您也可以使用类似的技术创建 JPEG 或 PNG 等格式的文件,但这些格式 更难实现。此外,它们是压缩的,因此很难预测文件大小。
也许您可以用额外的 non-image 数据填充最小的 JPEG,例如 XMP 等。 PNG 确实允许在不压缩的情况下编写 Deflate 块,这可能是一个选项。或者使用额外的块进行填充。
像BMP这样的未压缩格式会更简单。您可以使用与上述相同的技术,只需编写一个固定的、最小的 BMP header,设置正确的宽度并写入几乎与上述相同的图像数据。 BMP确实需要行填充,而且不支持灰度数据,所以你需要做一些额外的工作。但肯定可行。
我需要生成给定大小的图像(图像格式无关紧要)(例如,10KB
、100KB
、1MB
、10MB
等),使用 Java。图片可以是任意形状,填充背景色,图片内容不限。
编辑#1:要创建的图像的大小是可变的,所以我正在寻找一种有效的方法 在 内存使用 方面,以便在创建图像时免受 Java heap space
异常的影响。
编辑 #2: 当我尝试使用 Graphics2D 库生成尺寸为 48000x48000
的图像时出现 java.lang.IllegalArgumentException: Dimensions (width=48000 height=48000) are too large
异常,它是生成具有大文件大小的图像所必需的。
编辑 #3: 当维度变大时,我遇到了 java.lang.OutOfMemoryError: Java heap space
异常,即使我手动配置了 -Xmx
参数=42=] 执行此操作的程序。
For example
生成灰度图像(宽度:宽度和高度:高度)的一种方法:-
1) 创建一个 BufferedImage 对象 :-
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
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) 将 BufferedImage 对象写入磁盘:-
ImageIO.write(image, "jpg", new FileOutputStream(new File("SomePath/Name-of-Image.jpg")));
这是一些非常简单的示例代码,据我所知应该符合您的要求。该程序应该在几乎没有内存的情况下非常有效地工作,但仍会创建大小高达(大约)2GB 的图像文件(如果您愿意,您也可以轻松地调整它来创建更大的图像)。
假设:
- 图像格式无关紧要,所以我们选择 PGM format(二进制 'P5' 模式)
- 图像可以是任何图像shape/color,所以我们只做最简单的事情,写一行全黑。
- 重要的是图像文件的大小(下面的代码不会写入这个大小的字节,但可以通过在写入之前减去最小文件的大小 header 来轻松修改准确)。
输入文件大小,后跟文件名(您要使用 .pgm
作为扩展名)。例如:
$ java -cp ... WritePGM 2147483640 foo.pnm
以上将创建我的 JVM 允许读回的最大可能图像,大约为 2 GB。
代码:
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:如果你需要一个ImageIO插件来读取使用Java生成的文件,你可以使用JAI ImageIO或者my own PNM plugin,但是你当然会遇到同样的内存当您尝试使用 Java2D (BufferedImage
).
理论上,您也可以使用类似的技术创建 JPEG 或 PNG 等格式的文件,但这些格式 更难实现。此外,它们是压缩的,因此很难预测文件大小。
也许您可以用额外的 non-image 数据填充最小的 JPEG,例如 XMP 等。 PNG 确实允许在不压缩的情况下编写 Deflate 块,这可能是一个选项。或者使用额外的块进行填充。
像BMP这样的未压缩格式会更简单。您可以使用与上述相同的技术,只需编写一个固定的、最小的 BMP header,设置正确的宽度并写入几乎与上述相同的图像数据。 BMP确实需要行填充,而且不支持灰度数据,所以你需要做一些额外的工作。但肯定可行。