public static void ChangeColor(Bitmap src, Color color, IEnumerable<Pixel> changedPixels) { var lockBitmap = new LockBitmap(src); lockBitmap.LockBits(); foreach (var changedPixel in changedPixels) { lockBitmap.SetPixel(changedPixel.X, changedPixel.Y, color); } lockBitmap.UnlockBits(); }
public static Bitmap ChangeColor(Bitmap src, Color color) { var result = new Bitmap(src); var lockBitmap = new LockBitmap(result); lockBitmap.LockBits(); var compareClr = Color.FromArgb(255, 255, 255, 255); for (var y = 0; y < lockBitmap.Height; y++) { for (var x = 0; x < lockBitmap.Width; x++) { if (lockBitmap.GetPixel(x, y) == compareClr) { lockBitmap.SetPixel(x, y, color); } } } lockBitmap.UnlockBits(); return result; }
/* * A small main method that will print out the message length * in percent of pixels. */ public static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: invisibleinktoolkit.benchmark.SamplePairs <imagefilename>"); Environment.Exit(1); } try { Console.WriteLine("\nSample Pairs Results"); Console.WriteLine("--------------------"); var sp = new SamplePairs(); using (var bitmap = new Bitmap(args[0])) { var image = new LockBitmap(bitmap); image.LockBits(); double average = 0; var results = sp.DoAnalysis(image, ANALYSIS_COLOUR_RED); Console.WriteLine("Result from red: " + results); average += results; results = sp.DoAnalysis(image, ANALYSIS_COLOUR_GREEN); Console.WriteLine("Result from green: " + results); average += results; results = sp.DoAnalysis(image, ANALYSIS_COLOUR_BLUE); Console.WriteLine("Result from blue: " + results); average += results; average = average/3; Console.WriteLine("Average result: " + average); Console.WriteLine(); image.UnlockBits(); } } catch (Exception e) { Console.WriteLine("ERROR: Cannot process that image type, please try another image."); Console.WriteLine(e.StackTrace); } }
public double Calculate(Bitmap originalBmp, Bitmap steganoBmp) { if (originalBmp == null) { throw new ArgumentNullException(nameof(originalBmp)); } if (originalBmp == null) { throw new ArgumentNullException(nameof(steganoBmp)); } var original = new LockBitmap(originalBmp); original.LockBits(); var stegano = new LockBitmap(steganoBmp); stegano.LockBits(); var result = Calculation(original, stegano); original.UnlockBits(); stegano.UnlockBits(); return result; }
//FUNCTIONS /** * Runs all the steganalysis. * * @param stego The stego image to test. * @return All the results as text. * @throws IllegalArgumentException If the stego image is null. * @throws Exception If it has problems reading the images. */ public string Run(Bitmap stego) { using (stego) { var image = new LockBitmap(stego); image.LockBits(); var results = new StringBuilder("Results of steganalysis\n" + "==========================\n\n"); string colour; double averageresults = 0, averagelength = 0; //RS Analysis if (mRunRsAnalysis) { results.Append("RS ANALYSIS\n" + "============\n\n"); results.Append("RS Analysis (Non-overlapping groups)\n"); for (var j = 0; j < 3; j++) { var rsa = new RsAnalysis(2, 2); var testresults = rsa.DoAnalysis(image, j, false); //get the right colour if (j == 0) { colour = "red"; } else if (j == 1) { colour = "green"; } else { colour = "blue"; } //Append the results results.Append("Percentage in " + colour + ": "); //Round and Append results results.Append(Round(testresults[26]*100, 5) + "\n"); //and the approximate length (in bytes) results.Append("Approximate length (in bytes) from " + colour + ": " + Round(testresults[27], 5) + "\n"); averageresults += testresults[26]; averagelength += testresults[27]; } //now do again for overlapping groups results.Append("\nRS Analysis (Overlapping groups)\n"); for (var j = 0; j < 3; j++) { var rsa = new RsAnalysis(2, 2); var testresults = rsa.DoAnalysis(image, j, true); //get the right colour if (j == 0) { colour = "red"; } else if (j == 1) { colour = "green"; } else { colour = "blue"; } //Append the results results.Append("Percentage in " + colour + ": "); //Round and Append results results.Append(Round(testresults[26]*100, 5) + "\n"); //and the approximate length (in bytes) results.Append("Approximate length (in bytes) from " + colour + ": " + Round(testresults[27], 5) + "\n"); averageresults += testresults[26]; averagelength += testresults[27]; } results.Append("\nAverage across all groups/colours: " + Round(averageresults/6*100, 5)); results.Append("\nAverage approximate length across all groups/colours: " + Round(averagelength/6, 5)); results.Append("\n\n\n"); } //Sample Pairs averageresults = 0; averagelength = 0; if (mRunSamplePairs) { results.Append("SAMPLE PAIRS\n" + "=============\n"); for (var j = 0; j < 3; j++) { var sp = new SamplePairs(); var estimatedlength = sp.DoAnalysis(image, j); var numbytes = image.Height*image.Width*3/8 *estimatedlength; //get the right colour if (j == 0) { colour = "red"; } else if (j == 1) { colour = "green"; } else { colour = "blue"; } //Append the results results.Append("Percentage in " + colour + ": "); //Round and Append results results.Append(Round(estimatedlength*100, 5) + "\n"); //and the approximate length (in bytes) results.Append("Approximate length (in bytes) from " + colour + ": " + Round(numbytes, 5) + "\n"); averageresults += estimatedlength; averagelength += numbytes; } //average results results.Append("\nAverage across all groups/colours: " + Round(averageresults/3*100, 5)); results.Append("\nAverage approximate length across all groups/colours: " + Round(averagelength/3, 5)); results.Append("\n\n\n"); } //Laplace graph if (mRunLaplaceGraph) { results.Append("LAPLACE GRAPH (CSV formatted)\n" + "==============================\n\n"); results.Append(LaplaceGraph.GetCSVGraph(image)); } //Append some new lines to make it look nice results.Append("\n\n\n\n"); mResultsString = results.ToString(); image.UnlockBits(); } return mResultsString; }
/** * Generates a CSV formatted string of steganalysis information. * <P> * The directory passed has all it's image files steganalysed and * the results are returned in a comma separated file format. No spaces * are used in column headings, and all bar the steganography type are * numerical values. * * @param directory The directory to steganalyse. * @param laplacelimit The number of laplace values to write out in total. * @return A string containing a csv file of results. */ public string GetCSV(string directory, int laplacelimit) { //output progress to console Console.WriteLine("\n\nCSV Progress: {"); var files = Directory.GetFiles(directory); var fivepercent = (int) Math.Floor((double) files.Length/20); var csv = new StringBuilder(); //add all the headings if (mRunRsAnalysis) { var rsa = new RsAnalysis(2, 2); var rflag = "(rs overlapping)"; string colour; //overlapping for (var i = 0; i < 3; i++) { IEnumerable<string> rnames = rsa.GetResultNames(); //get the right colour if (i == 0) { colour = " red "; } else if (i == 1) { colour = " green "; } else { colour = " blue "; } foreach (var rname in rnames) { var aname = rname; var towrite = aname + colour + rflag + ","; towrite = towrite.Replace(' ', '-'); csv.Append(towrite); } } //non overlapping rflag = "(rs non-overlapping)"; for (var i = 0; i < 3; i++) { IEnumerable<string> rnames = rsa.GetResultNames(); //get the right colour if (i == 0) { colour = " red "; } else if (i == 1) { colour = " green "; } else { colour = " blue "; } foreach (var rname in rnames) { var aname = rname; var towrite = aname + colour + rflag + ","; towrite = towrite.Replace(' ', '-'); csv.Append(towrite); } } } if (mRunSamplePairs) { string colour; //overlapping for (var i = 0; i < 3; i++) { //get the right colour if (i == 0) { colour = "-red-"; } else if (i == 1) { colour = "-green-"; } else { colour = "-blue-"; } csv.Append("SP-Percentage" + colour + ","); csv.Append("SP-Approximate-Bytes" + colour + ","); } } if (mRunLaplaceGraph) { for (var i = 0; i < laplacelimit; i++) { csv.Append("Laplace-value-" + i + ","); } } csv.Append("Steganography-Type,Image-Name\n"); //check all the files for (var i = 0; i < files.Length; i++) { //print progress if (i > 0 && fivepercent > 0) { if (i%fivepercent == 0) { Console.WriteLine("#"); } } if (files[i].EndsWith(".bmp") || files[i].EndsWith(".png") || files[i].EndsWith(".jpg")) { //file can be worked on. string flag; try { using (var bitmap = new Bitmap(files[i])) { var image = new LockBitmap(bitmap); image.LockBits(); //run RS analysis if (mRunRsAnalysis) { //overlapping for (var j = 0; j < 3; j++) { var rsa = new RsAnalysis(2, 2); var testresults = rsa.DoAnalysis(image, j, true); for (var k = 0; k < testresults.Length; k++) { csv.Append(testresults[k] + ","); } } //non-overlapping for (var j = 0; j < 3; j++) { var rsa = new RsAnalysis(2, 2); var testresults = rsa.DoAnalysis(image, j, false); for (var k = 0; k < testresults.Length; k++) { csv.Append(testresults[k] + ","); } } } //run Sample Pairs if (mRunSamplePairs) { //overlapping for (var j = 0; j < 3; j++) { var sp = new SamplePairs(); var estimatedlength = sp.DoAnalysis(image, j); var numbytes = image.Height*image.Width*3/8 *estimatedlength; csv.Append(estimatedlength + "," + numbytes + ","); } } //run LaplaceGraph if (mRunLaplaceGraph) { var lgres = LaplaceGraph.GetGraph(image); for (var j = 0; j < laplacelimit; j++) { if (lgres.Length <= laplacelimit && j >= lgres.Length) { csv.Append("0,"); } else { if (lgres[j][0] != j) { csv.Append("0,"); } else { csv.Append(lgres[j][1] + ","); } } } } if (files[i].IndexOf("_") >= 0 || files[i].IndexOf("-") >= 0) { if (files[i].IndexOf("_") >= 0) { flag = files[i].Substring(files[i].IndexOf("_") + 1, files[i].LastIndexOf(".")); } else { flag = files[i].Substring(files[i].IndexOf("-") + 1, files[i].LastIndexOf(".")); } } else { flag = "none"; } csv.Append(flag); //Append in the file name csv.Append("," + files[i]); if (csv[csv.Length - 1] == ',') { csv.Remove(csv.Length - 1, 1); } csv.Append("\n"); image.UnlockBits(); } } catch (Exception) { //skip the file... } //cleanup to speed up memory GC.Collect(); } } //all done Console.WriteLine("} Complete!"); csv.Append("\n"); return csv.ToString(); }
/** * Creates an ARFF file of steganography information. * <P> * An ARFF file is the natural internal format for WEKA - Waikato * Environment for Knowledge Analysis. WEKA can also handle CSV * files but it is much nicer to be able to produce the natural format. * The same information as per the CSV generator is produced here, just * in a different format. * * @param directory The directory to steganalyse. * @param laplacelimit The maximum number of laplace values to output. * @param relationname The internal name of the relation as it will be * seen in WEKA. * @return An ARFF formatted file full of the steganalysis information. * @see www.cs.waikato.ac.nz/ml/weka * */ public string GetARFF(string directory, int laplacelimit, string relationname) { var arff = new StringBuilder(); //output progress to console Console.WriteLine("\n\nARFF Progress: {"); var files = Directory.GetFiles(directory); var fivepercent = (int) Math.Floor((double) files.Length/20); arff.Append("% Steganography Benchmarking Data\n%\n"); arff.Append("% Sourced from automatic generation in Digital Invisible Ink Toolkit\n"); arff.Append("% Generator created by Kathryn Hempstalk.\n"); arff.Append("% Generator copyright under the Gnu General Public License, 2005\n"); arff.Append("\n"); arff.Append("\n@relation '" + relationname + "'\n\n"); //add all the headings if (mRunRsAnalysis) { var rsa = new RsAnalysis(2, 2); var rflag = "(rs overlapping)"; string colour; //overlapping for (var i = 0; i < 3; i++) { IEnumerable<string> rnames = rsa.GetResultNames(); //get the right colour if (i == 0) { colour = " red "; } else if (i == 1) { colour = " green "; } else { colour = " blue "; } foreach (var rname in rnames) { var aname = rname; var towrite = aname + colour + rflag; arff.Append("@attribute '" + towrite + "' numeric\n"); } } //non overlapping rflag = "(rs non-overlapping)"; for (var i = 0; i < 3; i++) { IEnumerable<string> rnames = rsa.GetResultNames(); //get the right colour if (i == 0) { colour = " red "; } else if (i == 1) { colour = " green "; } else { colour = " blue "; } foreach (var rname in rnames) { var aname = rname; var towrite = aname + colour + rflag; arff.Append("@attribute '" + towrite + "' numeric\n"); } } } if (mRunSamplePairs) { string colour; //overlapping for (var i = 0; i < 3; i++) { //get the right colour if (i == 0) { colour = " red "; } else if (i == 1) { colour = " green "; } else { colour = " blue "; } arff.Append("@attribute 'SP Percentage" + colour + "' numeric\n"); arff.Append("@attribute 'SP Approximate Bytes" + colour + "' numeric\n"); } } if (mRunLaplaceGraph) { for (var i = 0; i < laplacelimit; i++) { arff.Append("@attribute 'Laplace value " + i + "' numeric\n"); } } arff.Append("@attribute 'Steganography Type' {"); //iterate through all the hashmap values... var stegotypes = GetStegTypes(Directory.GetFiles(directory)); var valuesarray = stegotypes.Values.ToArray(); arff.Append(valuesarray[0]); for (var i = 1; i < valuesarray.Length; i++) { arff.Append("," + valuesarray[i]); } arff.Append("}\n"); arff.Append("@attribute 'Image Name' string\n"); arff.Append("\n@data\n"); //check all the files for (var i = 0; i < files.Length; i++) { //print progress if (i > 0 && fivepercent > 0) { if (i%fivepercent == 0 && i != 0) { Console.WriteLine("#"); } } if (files[i].EndsWith(".bmp") || files[i].EndsWith(".png") || files[i].EndsWith(".jpg")) { //file can be worked on. try { using (var bitmap = new Bitmap(files[i])) { var image = new LockBitmap(bitmap); image.LockBits(); //run RS analysis if (mRunRsAnalysis) { //overlapping for (var j = 0; j < 3; j++) { var rsa = new RsAnalysis(2, 2); var testresults = rsa.DoAnalysis(image, j, true); for (var k = 0; k < testresults.Length; k++) { arff.Append(testresults[k] + ","); } } //non-overlapping for (var j = 0; j < 3; j++) { var rsa = new RsAnalysis(2, 2); var testresults = rsa.DoAnalysis(image, j, false); for (var k = 0; k < testresults.Length; k++) { arff.Append(testresults[k] + ","); } } } //run Sample Pairs if (mRunSamplePairs) { //overlapping for (var j = 0; j < 3; j++) { var sp = new SamplePairs(); var estimatedlength = sp.DoAnalysis(image, j); var numbytes = image.Height*image.Width*3/8 *(estimatedlength/100); arff.Append(estimatedlength + "," + numbytes + ","); } } //run LaplaceGraph if (mRunLaplaceGraph) { var lgres = LaplaceGraph.GetGraph(image); for (var j = 0; j < laplacelimit; j++) { if (lgres.Length <= laplacelimit && j >= lgres.Length) { arff.Append("0,"); } else { if (lgres[j][0] != j) { arff.Append("0,"); } else { arff.Append(lgres[j][1] + ","); } } } } string flag; if (files[i].IndexOf("_") >= 0 || files[i].IndexOf("-") >= 0) { if (files[i].IndexOf("_") >= 0) { flag = files[i].Substring(files[i].IndexOf("_") + 1, files[i].LastIndexOf(".")); } else { flag = files[i].Substring(files[i].IndexOf("-") + 1, files[i].LastIndexOf(".")); } } else { flag = "none"; } arff.Append(flag); arff.Append("," + files[i]); if (arff[arff.Length - 1] == ',') { arff.Remove(arff.Length - 1, 1); } arff.Append("\n"); image.UnlockBits(); } } catch (Exception) { //skip the file... } //cleanup to speed up memory GC.Collect(); } } //all done Console.WriteLine("} Complete!"); return arff.ToString(); }