生成640 x 360维所有可能的黑白像素图像的算法



我的编程经验非常少。

我想写一个程序,它将生成并保存为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.");
    }
}

请注意,这需要一些时间。所以,不要麻烦等待,而是享受你的生活!)

编辑:由于我的解决方案有点不清楚,我将解释算法。

  1. 我定义了一个名为increase的方法。此方法获取BufferedImage并更改图像的位模式,以便显示下一个位模式。这个方法只是添加了一点。如果图像遇到最后一个位模式(所有像素都设置为黑色),则该方法将返回false
  2. 只要可以增加比特模式(即increase()返回true),我们就会将图像保存为新帧,并再次增加图像
  3. 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万次,你至少会看到一组有趣的图片,但要得到每一个可能的排列是不可行的。

然后,您可以删除所有相同的文件,以将该集减少为唯一的图像。

最新更新