Ответ 1
Сначала ответьте на ваши вопросы. Да, будут записи на "некоторых" фотографиях. На самом деле появится текст, написанный человеком, который подходит в 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.");
}
}
Помните, что это займет некоторое время. Так что не беспокойтесь, ожидая и наслаждайтесь своей жизнью!;)
EDIT: поскольку мое решение немного нечеткое, я объясню алгоритм.
- Я определил метод под названием
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();
}
теперь мы модифицируем цикл 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.