This repository was archived by the owner on Jan 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPython.ImageEncoder.py
More file actions
153 lines (125 loc) · 4.4 KB
/
Python.ImageEncoder.py
File metadata and controls
153 lines (125 loc) · 4.4 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Image encoder
""" Because I can't get my head around jpg compression and it often leads to
them behaving oddly, this program seems better suited to uncompressed images.
Admittedly this is far less useful in the wild but will still allow me to
practice some steganography. It will be best to use bmp images here"""
import os
# Define application constants
HEADER_SIZE = 1024
FOOTER_SIZE = 1024
MAX_SECRET_LEN = 1024
""" I've done an MD5 hash of "CLEAN" and appended it to the filename to reduce
the chance of overwriting an important file """
CLEAN_IMG_NAME = "CLEANa88a6a0c276fd853999a1faedf19c00e.bmp"
# Read image file in
def readImg(imageName):
image = open(imageName, "rb")
return image
# Write image file out
def writeImg(imageName):
image = open(imageName, "wb")
return image
# Get the size of the image in bytes to prevent overwriting footer
def getSize(imageName):
return os.path.getsize(imageName)
# Replace the least significant bit with a 0
def writeCleanImg(inputImgName, outputImgName):
# Take the input image and get its size
inputImg = readImg(inputImgName)
inputImgSize = getSize(inputImgName)
# Create/ overwrite the output image
outputImg = writeImg(outputImgName)
# Copy the header
outputImg.write(inputImg.read(HEADER_SIZE))
# For the bytes not in the Header or Footer
for _byte in range(inputImgSize - (HEADER_SIZE + FOOTER_SIZE)):
# Set the LSB to 0 and write it to the output image
partAsInt = (inputImg.read(1)[0] & 254)
partAsByte = ((partAsInt).to_bytes(1, byteorder='big'))
outputImg.write(partAsByte)
# Copy the footer across
outputImg.write(inputImg.read(FOOTER_SIZE))
return 0
# Write a secret message to the image
def writeEncodedImg(inputImgName, outputImgName, secretMsg):
# Take the input image and get its size
inputImg = readImg(inputImgName)
inputImgSize = getSize(inputImgName)
# Create/ overwrite the output image
outputImg = writeImg(outputImgName)
# Copy the header across
outputImg.write(inputImg.read(HEADER_SIZE))
# For the bytes not in the Header or Footer
for byte in range(inputImgSize - (HEADER_SIZE + FOOTER_SIZE)):
# Set the LSB to a part of the text and write it to the output image
partAsInt = (inputImg.read(1)[0] | calculateLSB(byte, secretMsg))
partAsByte = ((partAsInt).to_bytes(1, byteorder='big'))
outputImg.write(partAsByte)
# Copy the footer across
outputImg.write(inputImg.read(FOOTER_SIZE))
return 0
def calculateLSB(byte, secretMsg):
# Get the character to write
try:
charToWrite = secretMsg[byte // 8]
except:
# No character so nothing to write
return 0
# Select the correct bit
bit = byte % 8
# Get the bit to write
charBit = (ord(charToWrite) >> bit) & 1
return charBit
def readEncodedImg(inputImgName):
# Take the input image and get its size
inputImg = readImg(inputImgName)
inputImg.read(HEADER_SIZE)
# For the bytes not in the Header or Footer
outString = ""
for _byte in range(MAX_SECRET_LEN):
charInt = 0
for bit in range(8):
# Read the LSB
lsb = inputImg.read(1)[0] & 1
charInt += lsb << bit
outString += chr(charInt)
print(outString)
return 0
def cli():
print("Clean, Encode, Clean and Encode (.bmp only), Decode or Quit? " +
"(C, e, a, d, q)")
choice = input(">")[0].lower()
# Quit application
if choice == "q":
return True
# All functions require the path to the input image
print("Type the name of the input image (include the file extension " +
"and path if required)")
inputImgName = input(">")
# Some functions require additional parameters
if choice != "d":
print("Type the name of the output image (include the file extension "+
"and path if required)")
outputImgName = input(">")
if choice in ["e", "a"]:
print("Type the secret message (max " + str(MAX_SECRET_LEN) +
" characters)")
secretMsg = input(">")
# Run the required function for each choice
# ENCODE
if choice == "e":
writeEncodedImg(inputImgName, outputImgName, secretMsg)
# CLEAN AND ENCODE
elif choice == "a":
writeCleanImg(inputImgName, CLEAN_IMG_NAME)
writeEncodedImg(CLEAN_IMG_NAME, outputImgName, secretMsg)
# DECODE
elif choice == "d":
readEncodedImg(inputImgName)
# DEFAULT = CLEAN
else:
writeCleanImg(inputImgName, outputImgName)
# Run the cli while the user has not finished
finished = False
while not finished:
finished = cli()