我的编程经验非常少。
我想写一个程序,它将生成并保存为gif图像,所有可能的图像都可以只使用640乘360像素的黑白像素创建。
换句话说,每个像素可以是黑色或白色。640 x 360=230400像素。因此,我相信总共可以生成460800张图像(230400 x 2用于黑色/白色)。
我想要一个程序来自动完成这项工作。
请帮忙!
首先回答您的问题。是的,会有关于"一些"图片的文章。实际上,人类编写的640x360像素的文本都会显示出来。还有每隔一段文字(尚未书写的文字或永远不会书写的文字)。你还会看到每一个活着、曾经活着或将要活着的人的照片。有关更多信息,请参阅无限猴子定理。
创建所需gif的代码相当简单。为此,我使用了Java。请注意,您需要一个额外的类:AnimatedGifEncoder。"代码"不受内存限制,因为一旦计算出每个映像,AanimatedGifEncoder
就会将其写入磁盘。但请确保您有足够的可用磁盘空间。
import java.awt.Color;
import java.awt.image.BufferedImage;
public class BigPicture {
private final int width;
private final int height;
private final int WHITE = Color.WHITE.getRGB();
private final int BLACK = Color.BLACK.getRGB();
public BigPicture(int width, int height) {
this.width = width;
this.height = height;
}
public void process(String outFile) {
AnimatedGifEncoder gif = new AnimatedGifEncoder();
gif.setSize(width, height);
gif.setTransparent(null); // no transparency
gif.setRepeat(-1); // play only once
gif.setDelay(0); // 0 ms delay between images,
// 'cause ain't nobody got time for that!
gif.start(outFile);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
// set the image to all white
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
bufferedImage.setRGB(x, y, WHITE);
}
}
// add white image
gif.addFrame(bufferedImage);
// add all other combinations
while (increase(bufferedImage)) {
gif.addFrame(bufferedImage);
}
gif.finish();
}
/**
* @param bufferedImage
* the image to increase
* @return false if last pixel set to black => image is complete black
*/
private boolean increase(BufferedImage bufferedImage) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (bufferedImage.getRGB(x, y) == WHITE) {
bufferedImage.setRGB(x, y, BLACK);
return true;
}
bufferedImage.setRGB(x, y, WHITE);
}
}
return false;
}
public static void main(String[] args) {
new BigPicture(640, 360).process("C:\temp\bigpicture.gif");
System.out.println("finished.");
}
}
请注意,这需要一些时间。所以,不要麻烦等待,而是享受你的生活!)
编辑:由于我的解决方案有点不清楚,我将解释算法。
- 我定义了一个名为
increase
的方法。此方法获取BufferedImage并更改图像的位模式,以便显示下一个位模式。这个方法只是添加了一点。如果图像遇到最后一个位模式(所有像素都设置为黑色),则该方法将返回false
- 只要可以增加比特模式(即
increase()
返回true),我们就会将图像保存为新帧,并再次增加图像 increase()
方法的工作原理:该方法首先在图像上沿x方向运行,然后沿y方向运行。我假设白色像素是0
,而黑色像素是1
。因此,我们想要获取图像的比特模式,并添加1
。我们检查第一个像素:如果它是白色的(0
),我们可以在没有溢出的情况下添加1
,因此我们将像素变为黑色(0 + 1 = 1
=>黑色像素)。之后我们从方法返回,因为我们只想增加一个位置。它返回true
,因为可能会增加。如果我们遇到黑色像素,我们会出现溢出(1 + 1 = 2
或二进制10
)。因此,我们必须将当前像素设置为白色,并将1
添加到下一个像素。这将一直持续到我们找到第一个白色像素
示例:首先,我们创建了一个打印方法:该方法将图像打印为二进制数。请注意,数字是相反的,最有效的位是右侧的位。
public void print(BufferedImage bufferedImage) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (bufferedImage.getRGB(x, y) == WHITE) {
System.out.print(0); // white pixel
} else {
System.out.print(1); // black pixel
}
}
}
System.out.println();
}
现在我们修改主while循环:
print(bufferedImage); // this one prints the empty image
while (increase(bufferedImage)) {
print(bufferedImage);
}
现在设置一些测试的简短示例:
new BigPicture(1, 5).process("C:\temp\bigpicture.gif");
最后输出:
00000 // 0 this is the first print before the loop -> "white image"
10000 // 1 the first white pixel is set to black
01000 // 2 the first overflow, so the second pixel is set to black "2"
11000 // 3
00100 // 4
10100 // 5
01100
11100
00010 // 8
10010
01010
11010
00110
10110
01110
11110
00001 // 16
10001
01001
11001
00101
10101
01101
11101
00011
10011
01011
11011
00111
10111
01111
11111 // 31 == 2^5 - 1
finished.
换句话说,每个像素可以是黑色或白色。640 x 360=230400像素。所以我相信总共有460800张图片可以生成(黑色/白色为230400 x 2)。
你的信仰有一点瑕疵。您对像素数的看法是正确的:230400。不幸的是,这意味着没有2*230400,而是2^230400可能的图片,这是一个超过60000位的数字(恐怕比允许的答案大小还长)。为了进行比较,一个有45位数字的特定数字表示可观测宇宙的直径,单位为厘米(大致相当于小指的宽度)。
为了理解为什么你对图片数量的计算是错误的,请考虑这个例子:如果你的图片只包含三个像素,你可以有8个不同的图片(2^3),而不是6个(2*3)。以下是所有这些:BBB、BBW、BWB、BWW、WBB、WBW、WWB、WWW。添加另一个像素会使可能的图片大小翻倍,因为您可以将其设置为所有3像素情况下的白色,或将所有3像素条件下的黑色。将1(即0像素的图片数量)加倍230400次会得到2^230400。
这个问题有很多好处,这很好,但如果它只是一个愚人节的笑话,那就相当分散注意力,适得其反。
我将继续从一个相关问题中提取一些代码,只是为了好玩。
from itertools import product
for matrix in product([0, 1], repeat=(math,pow(2,230400)):
# render and save your .gif
正如所有评论已经指出的那样,祝你好运!
更重要的是,如果你不想绝对确定你有所有的排列,你可以生成一个随机的640x360矩阵,并将其存储为图像。
执行这个动作,比如10万次,你至少会看到一组有趣的图片,但要得到每一个可能的排列是不可行的。
然后,您可以删除所有相同的文件,以将该集减少为唯一的图像。