/* Author: Brian Kennelly * Spring 2019 * The program allows the user to embed an image, the parasite image, into another, the host * to send to another user discretly. Run embeds the image and Extract retrives an image from the * left or host image section of the gui * */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Diagnostics; using System.Collections; using System.IO; namespace ImageViewer { public partial class Form1 : Form { private Image imgOriginal = null; private Image imgOriginal2 = null; private Image imgCurrent = null; private Image imgCurrent2 = null; private Point startingPoint = Point.Empty; private Point movingPoint = Point.Empty; private bool panning = false; public Form1() { InitializeComponent(); } /* * Takes a bitmap and an int, selection, that the user must choose from the steg method radio buttons * and attempts to rebuild an image from the pixel array of the combined image. * Retrieves height and width from the first 32 (or 64) second least significant bits of the first row * of the combined image. */ public static Bitmap ExtractImg(Bitmap pic, int selection) { int counter = 0; int Red = 0, Gr = 0, Bl = 0; int hei = 0, wid = 0; //gets height from first 16 pixels and width from next 16 * choice 1 or 2 Color[] dimensions = new Color[32]; for (int a = 0; a < 32; a++) { dimensions[a] = pic.GetPixel(a * selection, 0); } //builds height and width from the array by adding a value of 2^a * either 1 or 0 to the total for (int a = 0; a < 16; a++) { hei += ((int)Math.Pow(2, a) * ((dimensions[a].R >> 1) % 2)); wid += ((int)Math.Pow(2, a) * ((dimensions[a + 16].R >> 1) % 2)); } //string path = @"C:\Users\Brian\Desktop\capstone\project\bin\Debug\testing.txt"; //using (StreamWriter sw = File.AppendText(path)) //{ // sw.WriteLine(hei.ToString()); // sw.WriteLine(wid.ToString()); // for (int s = 0; s < 32; s++) // { // sw.WriteLine(((dimensions[s].R >> 1) % 2).ToString()); // } //} Bitmap mybmp = new Bitmap(wid, hei); for (int i = 0; i < hei; i++) {//1 for (int j = 0; j < wid; j++) {//2 Color[] pix = new Color[8]; for (int q = 0; q < 8; q++) { pix[q] = pic.GetPixel((counter * selection) % pic.Width, (counter * selection) / pic.Width); counter++; } for(int p = 0; p < 8; p++) { Red += ((int)Math.Pow(2, p) * (pix[p].R % 2)); Gr += ((int)Math.Pow(2, p) * (pix[p].G % 2)); Bl += ((int)Math.Pow(2, p) * (pix[p].B % 2)); } Color newPixel = Color.FromArgb(Red, Gr, Bl); mybmp.SetPixel(j, i, newPixel); Red = Gr = Bl = 0; } } return mybmp; } /*takes 2 images with the host being at least X (8, 16) times bigger than the parasite and saves all * of the parasite's pixels in the least significant bits of each of the color bytes of each pixel. * The height and width of the parasite is stored in the first 32 or 64 bytes of the host */ public static Bitmap EmbedImg(Bitmap Parasite, Bitmap Host, int selection) { //string path = @"C:\Users\Brian\Desktop\capstone\project\bin\Debug\testing.txt"; int counter = 0; int Red = 0, Gr = 0, Bl = 0; int wid = Parasite.Width, hei = Parasite.Height; Bitmap mybmp = new Bitmap(Host); for (int i = 0; i < hei; i++) {//hei //if (counter > Host.Width * 2) //{ // break; //} for (int j = 0; j < wid; j++) {//wid Color pixel = Parasite.GetPixel(j, i); //TESTING LINES, REMOVE AFTER FINISHING //using (StreamWriter sw = File.AppendText(path)) //{ // sw.WriteLine(pixel.ToString()); //} //REMOVE THIS STUFF //TESTING LINES, REMOVE AFTER FINISHING bool[] Rarr = new bool[8]; bool[] Garr = new bool[8]; bool[] Barr = new bool[8]; for(int p = 0; p < 8; p++) { Rarr[p] = (pixel.R & (1 << p)) != 0; Garr[p] = (pixel.G & (1 << p)) != 0; Barr[p] = (pixel.B & (1 << p)) != 0; } for(int q = 0; q < 8; q++) { Color hP = Host.GetPixel(counter * selection % Host.Width, counter * selection / Host.Width); //using (StreamWriter sw = File.AppendText(path)) //{ // sw.WriteLine(hP.ToString()); //} if (Rarr[q] == true) { Red = hP.R | 1; } else if(Rarr[q] == false) { int temp = ~hP.R; temp = temp | 1; Red = ~temp; } if (Garr[q] == true) { Gr = hP.G | 1; } else if (Garr[q] == false) { int temp = ~hP.G; temp = temp | 1; Gr = ~temp; } if (Barr[q] == true) { Bl = hP.B | 1; } else if (Barr[q] == false) { int temp = ~hP.B; temp = temp | 1; Bl = ~temp; } //SAVES HEIGHT if(counter < 16) {//i == 0 && j < 16 int a = hei; if(((a >> counter) % 2) == 1) { Red = Red | (1 << 1); } else { int temp = ~Red; temp = temp | (1 << 1); Red = ~temp; } } //SAVES WIDTH else if (counter > 15 && counter < 32) {//i == 0 && j > 15 && j < 32 int a = wid; if (((a >> (counter - 16)) % 2) == 1) { Red = Red | (1 << 1); } else { int temp = ~Red; temp = temp | (1 << 1); Red = ~temp; } } Color newPixel = Color.FromArgb(Red, Gr, Bl); //TESTING LINES, REMOVE AFTER FINISHING //using (StreamWriter sw = File.AppendText(path)) //{ // sw.WriteLine(newPixel.ToString()); //} mybmp.SetPixel(counter * selection % Host.Width, counter * selection / Host.Width, newPixel); counter++; } } } //using (StreamWriter sw = File.AppendText(path)) //{ // //sw.WriteLine(hei.ToString()); // //sw.WriteLine(wid.ToString()); // for (int s = 0; s < 32; s++) // { // sw.WriteLine(((mybmp.GetPixel(s, 0).R >> 1) % 2).ToString()); // } //} return mybmp; } /*on form load scroll bar setup * small and large change are the same to avoid unnecessary complexity */ private void Form1_Load(object sender, EventArgs e) { // set Picture Box Attributes PictureBox1.BackgroundImageLayout = ImageLayout.Stretch; PictureBox2.BackgroundImageLayout = ImageLayout.Stretch; // set Slider Attributes Scrollbar.Minimum = 1; Scrollbar.Maximum = 5; Scrollbar.SmallChange = 1; Scrollbar.LargeChange = 1; Scrollbar.UseWaitCursor = false; // reduce flickering this.DoubleBuffered = true; } //MOUSEDOWN, MOUSEUP, MOUSEMOVE, PAINT, ARE PAN FUNCTIONALITY /* * when the mouse is pressed down on a picture box this will tell the app that the user wants to pan the picture * and subsequently starts the panning process by checking the mouse movements after mousedown */ void PictureBox1_MouseDown(object sender, MouseEventArgs e) { panning = true; startingPoint = new Point(e.Location.X - movingPoint.X, e.Location.Y - movingPoint.Y); } /* * turn off panning after the user lets up on the mouse OR leaves the picturebox area * USED FOR BOTH PICTUREBOXES */ void PictureBox1_MouseUp(object sender, MouseEventArgs e) { panning = false; } /* * if the user moves their mouse inside the picturebox then the picture is moved with the mouse. the picturebox is redrawn * USED FOR BOTH PICTUREBOXES */ void PictureBox1_MouseMove(object sender, MouseEventArgs e) { if (panning) { movingPoint = new Point(e.Location.X - startingPoint.X, e.Location.Y - startingPoint.Y); PictureBox1.Invalidate(); } } /* the accompanying method to move the second picturebox in sync with the first */ void PictureBox2_MouseMove(object sender, MouseEventArgs e) { if (panning) { movingPoint = new Point(e.Location.X - startingPoint.X, e.Location.Y - startingPoint.Y); PictureBox2.Invalidate(); } } /* redraws the picturebox image if there is an image to draw and also draws a white background (on load and redraw etc) */ void PictureBox1_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(Color.White); if (imgCurrent != null) { e.Graphics.DrawImage(imgCurrent, movingPoint); } } /* the accompanying method to move the second picturebox in sync with the first */ void PictureBox2_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(Color.White); if (imgCurrent2 != null) { e.Graphics.DrawImage(imgCurrent2, movingPoint); } } //PICTUREBOXZOOM, SCROLLBARSCROLL, ARE ZOOM FUNCTIONALITY /* takes an image and a size object that the image will be changed to */ public Image PictureBoxZoom(Image img, Size size) { //string path = @"C:\Users\Brian\Desktop\capstone\project\bin\Debug\testing.txt"; //using (StreamWriter sw = File.AppendText(path)) //{ // sw.WriteLine(img.Width.ToString()); // sw.WriteLine(size.Width.ToString()); // sw.WriteLine(img.Height.ToString()); // sw.WriteLine(size.Height.ToString()); //} Size newSize = new Size(img.Width * size.Width, img.Height * size.Height); //Bitmap bm = new Bitmap(img, Convert.ToInt32(img.Width * size.Width), Convert.ToInt32(img.Height * size.Height)); Bitmap bm = new Bitmap(img, newSize); Graphics grap = Graphics.FromImage(bm); grap.InterpolationMode = InterpolationMode.HighQualityBicubic; GC.Collect(); return bm; } /* passes a size object along with the original image to the zoom function to create a new image to place in * both pictureboxes. original and current images are used to not multiply the already modified image as it * could cause resizing errors so original is always used with zoom */ private void Scrollbar_Scroll(object sender, EventArgs e) { //textBox1.Text = Scrollbar.Value.ToString(); if (Scrollbar.Value > 0 && PictureBox1.Image != null && PictureBox2.Image != null) { //PictureBox1.Image = null; imgCurrent = PictureBoxZoom(imgOriginal, new Size(Scrollbar.Value, Scrollbar.Value)); PictureBox1.Image = imgCurrent; // PictureBox2.Image = null; imgCurrent2 = PictureBoxZoom(imgOriginal2, new Size(Scrollbar.Value, Scrollbar.Value)); PictureBox2.Image = imgCurrent2; } else { Scrollbar.Value = 1; } } /* calls the function that embeds the right parasite image in picturebox2 into picturebox1 according to the * method chosen, 1 or 2, and saves it as EmbeddedImage.bmp */ private void RunButton_Click(object sender, EventArgs e) { if ((PictureBox1.Image != null) && (PictureBox2.Image != null) && ((imgCurrent2.Height * imgCurrent2.Width) < 65000)) { if (radioButton1.Checked == true) { //add validation here and below /* */ if (imgCurrent.Height > (imgCurrent2.Height * 8)) { Bitmap SaveImg = EmbedImg((Bitmap)imgCurrent2, (Bitmap)imgCurrent, 1); SaveImg.Save("EncodedImage.bmp", ImageFormat.Bmp); } } else if (radioButton2.Checked == true) { if (imgCurrent.Height > (imgCurrent2.Height * 16)) { Bitmap SaveImg = EmbedImg((Bitmap)imgCurrent2, (Bitmap)imgCurrent, 2); SaveImg.Save("EncodedImage.bmp", ImageFormat.Bmp); } } } } /* calls the function that extracts the image in the left, host, picturebox1 and saves it as ExtractedImage.bmp */ private void ExtractButton_Click(object sender, EventArgs e) { if (PictureBox1.Image != null) { if (radioButton1.Checked == true) { Bitmap SaveImg = ExtractImg((Bitmap)PictureBox1.Image, 1); SaveImg.Save("ExtractedImage.bmp", ImageFormat.Bmp); } else if (radioButton2.Checked == true) { Bitmap SaveImg = ExtractImg((Bitmap)PictureBox1.Image, 2); SaveImg.Save("ExtractedImage.bmp", ImageFormat.Bmp); } } } /* opens the file search filtering by PNG and BMP to load into picturebox1 */ private void Button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "png (*.png)|*.png|bmp (*.bmp)|*.bmp"; if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName.Length > 0) { imgOriginal = Image.FromFile(ofd.FileName); imgCurrent = imgOriginal; PictureBox1.Image = imgCurrent; //Size newSize = new Size(PictureBox1.Width, PictureBox1.Height); //PictureBox1.Image = ResizeImage(imgCurrent, newSize); } } /* opens the file search filtering by PNG and BMP to load into picturebox2 */ private void Button2_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "png (*.png)|*.png|bmp (*.bmp)|*.bmp"; if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName.Length > 0) { imgOriginal2 = Image.FromFile(ofd.FileName); imgCurrent2 = imgOriginal2; PictureBox2.Image = imgCurrent2; } } /* file menu exit button */ private void ExitToolStripMenuItem_Click(object sender, EventArgs e) { Application.Exit(); } //public static Image ResizeImage(Image image, Size size) //{ // int newWidth; // int newHeight; // int originalWidth = image.Width; // int originalHeight = image.Height; // float percentWidth = (float)size.Width / (float)originalWidth; // float percentHeight = (float)size.Height / (float)originalHeight; // float percent = percentHeight < percentWidth ? percentHeight : percentWidth; // newWidth = (int)(originalWidth * percent); // newHeight = (int)(originalHeight * percent); // Image newImage = new Bitmap(newWidth, newHeight); // using (Graphics graphicsHandle = Graphics.FromImage(newImage)) // { // graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic; // graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight); // } // return newImage; //} //private void OpenImageToModifyToolStripMenuItem_Click(object sender, EventArgs e) //{ // OpenFileDialog ofd = new OpenFileDialog(); // ofd.Filter = "png (*.png)|*.png|bmp (*.bmp)|*.bmp"; // if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName.Length > 0) // { // pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; // pictureBox1.Image = Image.FromFile(ofd.FileName); // imgOriginal = pictureBox1.Image; // } //} //private void OpenImageToHideToolStripMenuItem_Click(object sender, EventArgs e) //{ // OpenFileDialog ofd = new OpenFileDialog(); // ofd.Filter = "png (*.png)|*.png|bmp (*.bmp)|*.bmp"; // if (ofd.ShowDialog() == DialogResult.OK && ofd.FileName.Length > 0) // { // pictureBox2.SizeMode = PictureBoxSizeMode.Zoom; // pictureBox2.Image = Image.FromFile(ofd.FileName); // } //} } }