File size: 2,375 Bytes
94241e7
 
 
 
 
a1f30f8
 
 
 
 
94241e7
a1f30f8
 
 
 
 
 
94241e7
a1f30f8
 
94241e7
a1f30f8
94241e7
 
 
 
 
 
 
a1f30f8
 
 
94241e7
a1f30f8
94241e7
 
 
a1f30f8
 
 
94241e7
a1f30f8
 
 
 
94241e7
 
 
a1f30f8
 
 
94241e7
a1f30f8
94241e7
a1f30f8
94241e7
a1f30f8
 
 
 
 
94241e7
 
a1f30f8
 
 
94241e7
a1f30f8
 
94241e7
a1f30f8
 
 
 
 
 
94241e7
a1f30f8
 
94241e7
a1f30f8
 
94241e7
 
 
 
 
 
 
a1f30f8
 
94241e7
a1f30f8
 
94241e7
 
a1f30f8
94241e7
a1f30f8
 
94241e7
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
Note, this heavily builds upon
https://gist.github.com/goelashwin36/6847a974c9b7b2ca500154d5c89d1d76
"""

from email.mime import base
import glob
import random
from PIL import Image


def random_base_img():
    img_fn = random.choice(glob.glob("./base_images/*.jpg"))
    return Image.open(img_fn, "r")


def modify_pixel(pixel, data):
    data_lst = [format(ord(d), "08b") for d in data]
    data_len = len(data_lst)
    imdata = iter(pixel)

    for i in range(data_len):
        pix = [
            value
            for value in imdata.__next__()[:3]
            + imdata.__next__()[:3]
            + imdata.__next__()[:3]
        ]

        # Pixel value should be made
        # odd for 1 and even for 0
        for j in range(0, 8):
            if data_lst[i][j] == "0" and pix[j] % 2 != 0:
                pix[j] -= 1

            elif data_lst[i][j] == "1" and pix[j] % 2 == 0:
                if pix[j] != 0:
                    pix[j] -= 1
                else:
                    pix[j] += 1

        # Eighth pixel of every set tells
        # whether to stop ot read further.
        # 0 means keep reading; 1 means thec
        # message is over.
        if i == data_len - 1:
            if pix[-1] % 2 == 0:
                if pix[-1] != 0:
                    pix[-1] -= 1
                else:
                    pix[-1] += 1

        else:
            if pix[-1] % 2 != 0:
                pix[-1] -= 1

        pix = tuple(pix)
        yield pix[0:3]
        yield pix[3:6]
        yield pix[6:9]


def encode(data):
    base_img = random_base_img()
    w = base_img.size[0]
    (x, y) = (0, 0)

    for pixel in modify_pixel(base_img.getdata(), data):
        base_img.putpixel((x, y), pixel)
        if x == w - 1:
            x = 0
            y += 1
        else:
            x += 1

    return base_img.copy()


def decode(img):
    data = ""
    imgdata = iter(img.getdata())

    while True:
        pixels = [
            value
            for value in imgdata.__next__()[:3]
            + imgdata.__next__()[:3]
            + imgdata.__next__()[:3]
        ]

        # string of binary data
        binstr = ""

        for i in pixels[:8]:
            if i % 2 == 0:
                binstr += "0"
            else:
                binstr += "1"

        data += chr(int(binstr, 2))
        if pixels[-1] % 2 != 0:
            return data