├── README.rst ├── generate.py └── show.py /README.rst: -------------------------------------------------------------------------------- 1 | Inspired by http://www.datagenetics.com/blog/november32013/index.html 2 | 3 | Takes an input image, flips a coin for each pixel, and "encrypts" to one of two 4 | output images. Image can only be viewed when output images are lined up. 5 | Ideally, you need all the component images (2 in this case) to recover the 6 | original. However, if your random number generator is poor, I suspect this is 7 | one potential attack vector. 8 | 9 | Works best on high-contrast images. Small details will probably be lost. For 10 | example, Lenna didn't turn out so great. 11 | 12 | Usage: 13 | ``python generate.py mysourceimage.jpg`` 14 | - Generates ``out1.jpg`` and ``out2.jpg`` 15 | ``python show.py out1.jpg out2.jpg`` 16 | - Shows the two images merged together 17 | 18 | Requirements: 19 | pillow (or PIL) 20 | -------------------------------------------------------------------------------- /generate.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | 3 | import random 4 | import sys 5 | 6 | 7 | image = Image.open(sys.argv[1]) 8 | image = image.convert('1') 9 | 10 | outfile1 = Image.new("1", [dimension * 2 for dimension in image.size]) 11 | 12 | outfile2 = Image.new("1", [dimension * 2 for dimension in image.size]) 13 | 14 | for x in range(0, image.size[0], 2): 15 | for y in range(0, image.size[1], 2): 16 | sourcepixel = image.getpixel((x, y)) 17 | assert sourcepixel in (0, 255) 18 | coinflip = random.random() 19 | if sourcepixel == 0: 20 | if coinflip < .5: 21 | outfile1.putpixel((x * 2, y * 2), 255) 22 | outfile1.putpixel((x * 2 + 1, y * 2), 0) 23 | outfile1.putpixel((x * 2, y * 2 + 1), 0) 24 | outfile1.putpixel((x * 2 + 1, y * 2 + 1), 255) 25 | 26 | outfile2.putpixel((x * 2, y * 2), 0) 27 | outfile2.putpixel((x * 2 + 1, y * 2), 255) 28 | outfile2.putpixel((x * 2, y * 2 + 1), 255) 29 | outfile2.putpixel((x * 2 + 1, y * 2 + 1), 0) 30 | else: 31 | outfile1.putpixel((x * 2, y * 2), 0) 32 | outfile1.putpixel((x * 2 + 1, y * 2), 255) 33 | outfile1.putpixel((x * 2, y * 2 + 1), 255) 34 | outfile1.putpixel((x * 2 + 1, y * 2 + 1), 0) 35 | 36 | outfile2.putpixel((x * 2, y * 2), 255) 37 | outfile2.putpixel((x * 2 + 1, y * 2), 0) 38 | outfile2.putpixel((x * 2, y * 2 + 1), 0) 39 | outfile2.putpixel((x * 2 + 1, y * 2 + 1), 255) 40 | elif sourcepixel == 255: 41 | if coinflip < .5: 42 | outfile1.putpixel((x * 2, y * 2), 255) 43 | outfile1.putpixel((x * 2 + 1, y * 2), 0) 44 | outfile1.putpixel((x * 2, y * 2 + 1), 0) 45 | outfile1.putpixel((x * 2 + 1, y * 2 + 1), 255) 46 | 47 | outfile2.putpixel((x * 2, y * 2), 255) 48 | outfile2.putpixel((x * 2 + 1, y * 2), 0) 49 | outfile2.putpixel((x * 2, y * 2 + 1), 0) 50 | outfile2.putpixel((x * 2 + 1, y * 2 + 1), 255) 51 | else: 52 | outfile1.putpixel((x * 2, y * 2), 0) 53 | outfile1.putpixel((x * 2 + 1, y * 2), 255) 54 | outfile1.putpixel((x * 2, y * 2 + 1), 255) 55 | outfile1.putpixel((x * 2 + 1, y * 2 + 1), 0) 56 | 57 | outfile2.putpixel((x * 2, y * 2), 0) 58 | outfile2.putpixel((x * 2 + 1, y * 2), 255) 59 | outfile2.putpixel((x * 2, y * 2 + 1), 255) 60 | outfile2.putpixel((x * 2 + 1, y * 2 + 1), 0) 61 | 62 | outfile1.save('out1.jpg') 63 | outfile2.save('out2.jpg') 64 | -------------------------------------------------------------------------------- /show.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import sys 3 | 4 | infile1 = Image.open(sys.argv[1]) 5 | infile2 = Image.open(sys.argv[2]) 6 | 7 | outfile = Image.new('1', infile1.size) 8 | 9 | for x in range(infile1.size[0]): 10 | for y in range(infile1.size[1]): 11 | outfile.putpixel((x, y), max(infile1.getpixel((x, y)), infile2.getpixel((x, y)))) 12 | 13 | outfile.show() 14 | --------------------------------------------------------------------------------