14

I have very minimal programming experience.

I would like to write a program that will generate and save as a gif image every possible image that can be created using only black and white pixels in 640 by 360 px dimensions.

In other words, each pixel can be either black or white. 640 x 360 = 230,400 pixels. So I believe total of 460,800 images are possible to be generated (230,400 x 2 for black/white).

I would like a program to do this automatically.

Please help!

fabrizioM
  • 46,639
  • 15
  • 102
  • 119
user3084984
  • 149
  • 1
  • 3
  • 1
    See this question, yours is just on a different scale: http://stackoverflow.com/questions/5357171/how-to-generate-all-possible-combinations-of-a-14x10-matrix-containing-only-1s Note, it doesn't relate to storing images at all. – damienc88 Dec 10 '13 at 00:54
  • 19
    You're actually generating 2^230,400 images, as you've just counted the number of pixels that could possibly be on, and doubled it, which is only two images (one all black, one all white), or effectively one permutation and its inverse – damienc88 Dec 10 '13 at 00:58
  • 7
    Are you trying to create a new type of barcode that will catalog every atom on our planet? – RustyToms Dec 10 '13 at 00:59
  • Oh GOD :-O... So is it 230,400^2 instead of 230,400 x 2? So 53,084,160,000 possible images? Maybe I can scale the dimensions down, by a lot... – user3084984 Dec 10 '13 at 01:01
  • No, it's a lot more than 53 billion, try typing 2^230400 into your calculator. Windows calc returns "Invalid input". The algorithm can be written, sure. Will it complete in a timely fashion? Probably not. – damienc88 Dec 10 '13 at 01:02
  • My calculator says 53 billion. :( – user3084984 Dec 10 '13 at 01:04
  • 5
    It's 2^230400, not 230500^2 – justhalf Dec 10 '13 at 01:06
  • Oh... 2 ^ 230,400.... and Not 230,400 ^ 2??? ?_? – user3084984 Dec 10 '13 at 01:06
  • I'm just going to go ahead and say that number might as well be infinity. It would be difficult to prove that it wasn't infinity. Your calculator probably cannot even print out the number that is represented by 2 ^ 230,400. – RustyToms Dec 10 '13 at 01:07
  • 8
    Yes, each pixel can be either black or white. If there are only 3 pixels, you have 8 combinations (000, 001, 010, 011, 100, 101, 110, 111), which is 2x2x2. If you have 230400 pixels, you have 2^230400, which according to [WolframAlpha](http://www.wolframalpha.com/input/?i=2%5E230400) it is 69,358 digits long – justhalf Dec 10 '13 at 01:08
  • LOL, more replies show up before I finish replying to previous posts. Thanks to all for your input in my humiliating first attempt. :) – user3084984 Dec 10 '13 at 01:09
  • 2
    I was mistaken earlier, you could use this to create a unique barcode for every atom in the known universe. – RustyToms Dec 10 '13 at 01:09
  • maybe it would be helpful if you explain WHY you're trying to do this. – Jherico Dec 10 '13 at 01:10
  • 6
    Someone set a bounty on this. – RustyToms Dec 10 '13 at 01:10
  • 4
    @Jherico, I'm a digital artist and I had two different purposes in mind. First, I wanted to see as many possible basic layouts that could be done (perhaps this can be achieved via a more elegant way?). Second, I wanted to see what sorts of images computer could generate... Perhaps some of the images would have writings on them? And some might have people's faces? – user3084984 Dec 10 '13 at 01:17
  • 1
    Try it with a 3×3 matrix and see how many pictures result. Whether you have the patience and time to look through all of them. – Abhishek Bansal Dec 10 '13 at 03:16
  • The basic algorithm to do this is fairly simple - for each pixel, try to set it as black and recurse, then white and recurse. If the problem is to save as a GIF, that's another story - it's going to look fundamentally different in different languages. So you really should pick a language and you really should try something and show your attempt in the question. – Bernhard Barker Dec 10 '13 at 04:31
  • here's one lead: http://code.google.com/p/random-pixel-generator/ – גלעד ברקן Dec 11 '13 at 04:09
  • Related fun: http://thechessboardclock.com/ – Mitch Apr 04 '14 at 01:28

3 Answers3

10

First to answer your questions. Yes there will be writings on "some" pictures. Actually ever text written by human which fits in 640x360 pixels will show up. Also every other text (text not yet written or text that never will be written). Also you will see pictures of every human which is, was or will be alive. See Infinite Monkey Theorem for further information.

The code to create your wanted gif is fairly easy. I used Java for this. Note that you need an extra class: AnimatedGifEncoder. The Code is not memory-bound because the AanimatedGifEncoder will write each image to disk as soon it is computed. But make sure that you have enough disk space available.

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.");
    }
}

Please be aware that this will take some time. So don't bother waiting and enjoy your life instead! ;)

EDIT: Since my solution is a bit unclear i will explain the algorithm.

  1. I have defined a method called increase. This method takes the BufferedImage and changes the bit pattern of the image so that the next bit pattern appears. The method is just a bit addition. The method will return false if the image encounters the last bit pattern (all pixels are set to black).
  2. As long as it is possible to increase the bit pattern (i.e. increase() returns true) we will save the image as new frame and increase the image again.
  3. How the increase() method works: The method runs over the image first in x-direction then in y-direction. I assume that white pixels are 0 and black pixels are 1. So, we want to take the bit pattern of the image and add 1. We inspect the first pixel: if it is white (0) we can add 1 without an overflow so we turn the pixel to black (0 + 1 = 1 => black pixel). After that we return from the method because we want to increase only one position. It returns true because an increase was possible. If we encounter a black pixel we have an overflow (1 + 1 = 2 or in binary 10). So we have to set the current pixel to white and add the 1 to the next pixel. This will continue until we find the first white pixel.

example: first we create a print method: this method prints the image as binary number. Attention the number is reversed and the most significant bit is the bit on the right side.

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

now we modify our main-while loop:

print(bufferedImage); // this one prints the empty image
while (increase(bufferedImage)) {
    print(bufferedImage);
}

and now set some short example to test:

new BigPicture(1, 5).process("C:\\temp\\bigpicture.gif");

and finally the output:

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.
Absurd-Mind
  • 7,884
  • 5
  • 35
  • 47
  • This will not render all possible combinations of pixels. This will only turn on one pixel at a time! So your animated gif will basically move one dot left to right, row by row... – Adrian Salazar Apr 08 '14 at 10:55
  • @AdrianSalazar I tested it, it worked like expected, but feel free to point my error out. – Absurd-Mind Apr 08 '14 at 11:04
  • @Absurd-Mind well, your error is easy to demonstrate. The two nested fors will give width x height number of images. Not 2 ^ width ^ height. – Adrian Salazar Apr 08 '14 at 11:21
  • @Absurd-Mind and the "I tested it" is barely real. You cannot wait for such amount of images to be outputed. – Adrian Salazar Apr 08 '14 at 11:22
  • @AdrianSalazar I tested it with 3x5 pixels. You are aware that the `increase` method is called until the last pixel is set to black? And you are aware that the method has a prematurely return in the for-loops? And yes, the loops run at most `width*height` but are run a lot more often. – Absurd-Mind Apr 08 '14 at 11:29
  • So output is width x height x width x height. Not 2 ^ width x height – Adrian Salazar Apr 08 '14 at 11:37
  • it took me a while to understand the logic here, but it is correct – fire in the hole Apr 08 '14 at 11:52
  • @AdrianSalazar I added an explanation and example. For me it looks still good. 32 outputs for 1x5, no duplicates, as expected. – Absurd-Mind Apr 08 '14 at 11:55
5

In other words, each pixel can be either black or white. 640 x 360 = 230,400 pixels. So I believe total of 460,800 images are possible to be generated (230,400 x 2 for black/white).

There is a little flaw in your belief. You are right about the number of pixels: 230,400. Unfortunately, this means there are not 2 * 230,400, but 2 ^ 230,400 possible pictures, which is a number with more than 60,000 digits (longer than the allowed answer size, I am afraid). For comparison a particular number with 45 digits signifies the diameter of the observable universe in centimeters (roughly the width of a pinkie).

In order to understand why your computation of the number of pictures is wrong consider this example: if your pictures contained only three pixels, you could have 8 different pictures (2 ^ 3), rather than 6 (2 * 3). Here are all of them: BBB, BBW, BWB, BWW, WBB, WBW, WWB, WWW. Adding another pixel doubles the size of possible pictures because you can have it white for all the 3-pixel cases, or black for all the 3-pixel cases. Doubling 1 (which is the amount of pictures you can have with 0 pixels) 230,400 times gives you 2 ^ 230,400.

It's great that there is a bounty for the question, but it is rather distracting and counter-productive if it was just as an April's Fool joke.

stanm
  • 3,201
  • 1
  • 27
  • 36
3

I'm going to go ahead and pinch some code from a related question, just for fun.

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

As all the comments have already stated, good luck!

On a more serious note, if you didn't want to be absolutely sure that you had all permutations, you could generate a random 640x360 matrix and store it as an image.

Perform this action say 100k times, and you'll have at least an interesting set of pictures to look at, but it's unfeasible to get every possible permutation.

You could then delete all identical files to reduce the set to just the unique images.

damienc88
  • 1,957
  • 19
  • 34