This repository has been archived by the owner on May 5, 2018. It is now read-only.
/
encoding.pde
215 lines (167 loc) · 7.12 KB
/
encoding.pde
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/////////////////////////////////////////////////////////////////////////////////////////
// Encoding a simple steganography image
// Dan Schellenberg
// Jan 2, 2016
//
// User must first select a .txt file that contains the secret message, then
// select an image file to insert the secret message into.
// Image containing the secret message is saved in
// the file 'nothingToSeeHere.png', in the same directory as this program.
//
// The basic algorithm used here is as follows:
// - set all red component values of pixels to even numbers, by subtracting by 1 if neccesary
// - convert the message to be hidden into binary
// - loop through the pixels of the image, continuing until message bits have been applied, by:
// - leaving red component as is (if the bit is a 0)
// - adding 1 to the red component (if the bit is a 1)
//
/////////////////////////////////////////////////////////////////////////////////////////
PImage source, encoded;
String secretMessage, encodedMessage;
color bgColor;
void setup() {
size(300, 300);
secretMessage = "";
bgColor = color(255, 255, 255);
}
void draw() {
//display the simple instructions
background(bgColor);
fill(0);
textAlign(CENTER);
text("t - select txt file of secret message\ne - encode and save into selected image", width/2, height/2);
}
void keyPressed() {
if (key == 't') {
selectInput("Select a file to process:", "selectMessage");
}
if (key == 'e') {
selectInput("Select a file to process:", "selectImage");
}
}
/////////////////////////////////////////////////////////////////////////////////////////
void selectMessage(File selection) {
//choose a .txt file that contains the secret message
//if a non .txt file is chosen, garbage output will occur
if (selection == null) {
println();
println("Window was closed or the user hit cancel.");
println();
} else {
//set background to red while loading the text file
bgColor = color(255, 0, 0);
println("Secret message chosen: " + selection.getAbsolutePath());
println();
//open the file and concatenate each line onto the string
String theText = "";
String lines[] = loadStrings( selection.getAbsolutePath() );
for (int i = 0; i < lines.length; i++) {
theText = theText + lines[i] + "\n";
}
//set the global variable secret message to the loaded message, and convert it to binary
secretMessage = theText;
encodedMessage = encodeMessageToBinary(secretMessage);
//return background color to white
bgColor = color(255, 255, 255);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
void selectImage(File selection) {
//choose an image file that the secret message should be inserted into
//if a non image file is chosen, craziness will ensue
if (selection == null) {
println();
println("Window was closed or the user hit cancel.");
println();
} else {
//set background to red while inserting the message into the image
bgColor = color(255, 0, 0);
println("Image to hide message in: " + selection.getAbsolutePath());
println();
source = loadImage(selection.getAbsolutePath());
//before attempting to insert message, confirm that it will actually fit
if (messageFits(source, encodedMessage)) {
//insert message, and save result as a file in the same directory as this program
encoded = initalizedImage(source);
encoded = attachMessageToImage(encoded, encodedMessage);
encoded.save("nothingToSeeHere.png");
println("Message successfully inserted into image.");
println("The image has been saved in the same directory as this program.");
println();
} else {
println("Message does not fit inside image. Need to use a larger image to fit that size of message");
}
//reset the background to white when done
bgColor = color(255, 255, 255);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
PImage initalizedImage(PImage source) {
//take in the source image and remove the least important bit from the red color component
//return version of image where all red color components are even numbers (subtracted by 1 if req'd)
PImage dest = createImage(source.width, source.height, RGB);
source.loadPixels();
dest.loadPixels();
for (int i = 0; i < source.pixels.length; i++) {
dest.pixels[i] = initializeLastBit(source.pixels[i]);
}
dest.updatePixels();
return dest;
}
/////////////////////////////////////////////////////////////////////////////////////////
color initializeLastBit(color thisColor) {
//reset last bit to 0 for the red color component
//algorithm could be adjusted to utilize all 3 color components, which would allow for
//much more message storage space in the same source file
float red = red(thisColor);
float green = green(thisColor);
float blue = blue(thisColor);
if (red % 2 != 0) { //if it's odd, the last bit is on. Turn off by subtracting 1.
red = red - 1;
}
color lastBitRemoved = color(red, green, blue);
return lastBitRemoved;
}
/////////////////////////////////////////////////////////////////////////////////////////
boolean messageFits(PImage source, String message) {
//check if the currently selected message will fit into the currently selected image
//message is a string of bits, and we'll store one per pixel
if (message.length()*8 < (source.width * source.height) ) {
return true;
} else {
return false;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
String encodeMessageToBinary(String secretMessage) {
//convert message into it's binary representation
String encodedMessage = "";
for (int i=0; i<secretMessage.length(); i++) {
char thisChar = secretMessage.charAt(i);
encodedMessage = encodedMessage + binary(thisChar, 8); //use 8 bits for every character (ASCII-like)
}
return encodedMessage;
}
/////////////////////////////////////////////////////////////////////////////////////////
PImage attachMessageToImage(PImage source, String message) {
//create a new image, and hide the message in the red color component values of the new image
//assumes the source image has already been "cleaned up" (all red color component values set to even numbers)
//start the destination image as an exact copy of the "cleaned up" source
PImage dest = createImage(source.width, source.height, RGB);
dest.copy(source, 0, 0, source.width, source.height, 0, 0, source.width, source.height);
source.loadPixels();
dest.loadPixels();
//go through the message one character at a time (mapping this loop to a pixel loop),
//adding one to the current pixel's red component value if the binary value is a 1
for (int i = 0; i < message.length(); i++ ) {
if (message.charAt(i) == '1') {
float redAmount = red(source.pixels[i]) + 1;
float greenAmount = green(source.pixels[i]);
float blueAmount = blue(source.pixels[i]);
dest.pixels[i] = color(redAmount, greenAmount, blueAmount);
}
}
dest.updatePixels();
return dest;
}
/////////////////////////////////////////////////////////////////////////////////////////