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

时间:2013-12-10 00:46:34

标签: image algorithm matrix permutation

我的编程经验很少。

我想编写一个程序,生成并保存为gif图像的每个可能的图像,只能使用640 x 360像素尺寸的黑白像素。

换句话说,每个像素可以是黑色或白色。 640 x 360 = 230,400像素。所以我相信总共可以生成460,800张图像(黑色/白色为230,400 x 2)。

我想要一个程序自动执行此操作。

请帮忙!

3 个答案:

答案 0 :(得分:8)

首先回答你的问题。是的,会有#34;一些"图片。实际上,任何符合640x360像素的人类文字都会出现。还有其他所有文本(尚未写入的文本或永远不会被写入的文本)。你也会看到每个人的照片,现在或将要活着。有关详细信息,请参阅Infinite Monkey Theorem

创建你想要的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 =&gt;黑色像素)。之后我们从方法返回,因为我们只想增加一个位置。它返回true,因为可能会增加。如果我们遇到黑色像素,则会出现溢出(1 + 1 = 2或二进制10)。因此,我们必须将当前像素设置为白色,并将1添加到下一个像素。这将持续到我们找到第一个白色像素为止。
  4. 示例: 首先我们创建一个print方法:此方法将图像打印为二进制数。注意数字是相反的,最重要的位是右侧的位。

    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();
    }
    

    现在我们修改main-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.
    

答案 1 :(得分:4)

  

换句话说,每个像素可以是黑色或白色。 640 x 360 =   230,400像素。所以我相信总共有460,800张图片是可能的   生成(黑色/白色230,400 x 2)。

你的信仰有一点缺陷。你的像素数是对的:230,400。不幸的是,这意味着没有2 * 230,400,但是2 ^ 230,400张可能的图片,这是一个超过60,000位的数字(恐怕比允许的答案大小更长)。为了比较,45位数的特定数字表示可观察宇宙的直径,以厘米为单位(大致为小指的宽度)。

为了理解为什么你的图片数量计算错误,请考虑这个例子:如果你的图片只包含三个像素,你可以有8个不同的图片(2 ^ 3),而不是6(2 * 3)。以下是所有这些:BBB,BBW,BWB,BWW,WBB,WBW,WWB,WWW。添加另一个像素会使可能的图片大小翻倍,因为所有3像素的情况都可以为白色,对于所有3像素的情况,可以为黑色。加倍1(这是你可以拥有0像素的图片数量)230,400次给你2 ^ 230,400。

这个问题很有价值,但如果它只是四月的傻瓜玩笑那么它会让人分心和适得其反。

答案 2 :(得分:2)

我将继续前进并从相关问题中捏一些代码,只是为了好玩。

from itertools import product
for matrix in product([0, 1], repeat=(math,pow(2,230400)):
    # render and save your .gif

正如所有评论已经说明的那样,祝你好运!

更严重的是,如果你不想绝对确定你有所有的排列,你可以生成一个随机的640x360矩阵并将其存储为图像。

执行此操作说100k次,你将至少看到一组有趣的图片,但是获得所有可能的排列是不可行的。

然后,您可以删除所有相同的文件,以将设置简化为唯一的图像。