So I was wandering the internet when I found an article about steganography, which is the art of hiding something in plain sight. Such as hiding a message inside a picture. Specifically the least significant bit method where you take the RGB color values of the pixel and set them based off a message in binary your encoding. So I figured I’d work something up and see if I could do that. This is a first attempt and it only encodes the message, right now it’ll truncate it if it doesn’t have enough pixels to work with or if the message length in binary isn’t divisible by three. Obviously this is a first attempt and a very simple one at that.
So basically you give it a picture and a text file and it reads the text file as a single string, converts it to binary then for each pixel it sets each of the RGB values based off the binary message value for that position. In this example if the binary message is odd for this position we set the color to an odd number (in effect setting the least significant bit to 1) else we make sure its an even number.
I have a few plans for expanding this project. It would be nice to decode the messages first of all, it would also be nice to have some options for encoding such as skipping a certain number of pixels between parts of the message, Only using certain color channels etc. But for now this is what I have.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Steganography
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
op.CheckPathExists = true;
op.CheckFileExists = true;
op.Filter = "JPG image |*.jpg";
op.ShowDialog();
textBox1.Text = op.FileName;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
try
{
Preview.ImageLocation = textBox1.Text ;
}
catch
{
}
}
private void BrowseMessage_Click(object sender, EventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
op.CheckPathExists = true;
op.CheckFileExists = true;
op.ShowDialog();
textBox2.Text = op.FileName;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Your image will be saved as " + textBox1.Text +".new");
//Get message as a binary string;
string message = LoadMessage(textBox2.Text);
string binmessage = "";
foreach (char letter in message.ToCharArray())
{
binmessage += Convert.ToString(letter, 2);
}
//get bitmap of image.
Bitmap bitm = (Bitmap)Preview.Image.Clone();
int mPosition = 0;
//Embed message
#region embed
for (int height = 0; height < bitm.Height; height++)
{
for (int width = 0; width < bitm.Width; width++)
{
if (mPosition + 3 <= binmessage.Length)
{
Color pixelColor = bitm.GetPixel(width, height);
int R = int.Parse(pixelColor.R.ToString());
int G = int.Parse(pixelColor.G.ToString());
int B = int.Parse(pixelColor.B.ToString());
int m1 = int.Parse(binmessage[mPosition].ToString());
mPosition++;
int m2 = int.Parse(binmessage[mPosition].ToString());
mPosition++;
int m3 = int.Parse(binmessage[mPosition].ToString());
mPosition++;
if (m1 % 2 == 0)
{
if (R % 2 != 0 && R > 0)
{
R -= 1;
}
else
{
R += 1;
}
}
else
{
if (R % 2 != 1 && R > 0)
{
R -= 1;
}
else
{
R += 1;
}
}
if (m2 % 2 == 0)
{
if (G % 2 != 0 && G > 0)
{
G -= 1;
}
else
{
G += 1;
}
}
else
{
if (G % 2 != 1 && G > 0)
{
G -= 1;
}
else
{
G += 1;
}
}
if (m3 % 2 == 0)
{
if (B % 2 != 0 && B > 0)
{
B -= 1;
}
else
{
B += 1;
}
}
else
{
if (B % 2 != 1 && B > 0)
{
B -= 1;
}
else
{
B += 1;
}
}
Color pc = Color.FromArgb(R, G, B);
bitm.SetPixel(width, height, pc);
}
else
{
}
}
}
#endregion embed
bitm.Save(textBox1.Text + ".new");
}
private string LoadMessage(string p)
{
string RetValue = "";
StreamReader sr;
sr = File.OpenText(p);
RetValue = sr.ReadToEnd();
sr.Close();
return RetValue;
}
}
}