private const int SizeSegment = 8; // размер сегмента // функция сокрытия текста в изображении public static StegoBitmap Hide(StegoBitmap stgbmap, string txt, Colours colour, int CoefDif) { var bmap = stgbmap.GetImage(); if ((bmap.Width % SizeSegment) != 0 || (bmap.Height % SizeSegment) != 0) //если изображение не делится на сегменты ровно { CommonFunc.Cut(ref bmap, SizeSegment); } var arrForHiding = new byte[bmap.Width, bmap.Height]; // массив байтов, где будет хранится текст в соотвествии с выбранным цветом //выбираем из изображения пиксели в соответствии с переданным цветом for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { if (colour == Colours.Red) { arrForHiding[i, j] = bmap.GetPixel(i, j).R; } else if (colour == Colours.Green) { arrForHiding[i, j] = bmap.GetPixel(i, j).G; } else if (colour == Colours.Blue) { arrForHiding[i, j] = bmap.GetPixel(i, j).B; } else { throw new NullReferenceException(); } } } int numSegm = bmap.Width * bmap.Height / (SizeSegment * SizeSegment); //общее число сегментов var stgByte = Encoding.GetEncoding(1251).GetBytes(txt); // перевод строки в массив байтов byte[] len = CommonFunc.LenInBytes(txt.Length, CommonFunc.Size(txt.Length)); // массив байтов из длины текста в соответвии с размером его длины byte[] txtByte = new byte[2 + len.Length + stgByte.Length]; //массив для скрытого текста размером в длину текста + размер длины + два дополнительных байта txtByte[0] = Convert.ToByte('Z'); // первый элемент массива содержит пометку, что в изображении скрыт текст txtByte[1] = CommonFunc.Size(txt.Length); // второй элемент массива размер длины int ind = 0; for (int i = 0; i < len.Length; i++) { txtByte[i + 2] = len[ind++]; // сохраняем в массив байты из длины текста в соответвии с размером его длины } ind = 0; for (int i = 0; i < stgByte.Length; i++) { txtByte[i + 2 + len.Length] = stgByte[ind++]; // сохраняем в массив скрываемый текст } var segm = new List <byte[, ]>(); Separate(arrForHiding, segm, bmap.Width, bmap.Height, SizeSegment);// разбиваем массив на сегменты // дискретное косинусное преобразование var dctList = new List <double[, ]>(); foreach (var b in segm) { dctList.Add(DCT(b)); // список из коэффициентов ДКП } SetText(txtByte, ref dctList, CoefDif); // внедрение текста // обратное дискретное косинусное преобразование var idctList = new List <double[, ]>(); foreach (var d in dctList) { idctList.Add(IDCT(d)); } var newArr = new double[bmap.Width, bmap.Height]; // новый массив значений Join(ref newArr, idctList, bmap.Width, bmap.Height, SizeSegment); //соединяем сегменты Normalize(ref newArr); // модификация коэффициентов ДКП иногда приводит к выходу значений интенсивностей пикселей изображения за пределы допустимого диапазона [0,255], проводим нормирование указанных значений return(new StegoBitmap(bmap, newArr, colour)); }
// функция находит скрытый текст public static string GetHiddenText(StegoBitmap stgbmap, Colours c) { var bmap = stgbmap.GetImage(); int width = bmap.Width; int height = bmap.Height; var arrWhereHide = new byte[bmap.Width, bmap.Height]; // массив байтов, где будет хранится текст в соотвествии с выбранным цветом //выбираем из изображения пиксели в соответствии с переданным цветом for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { if (c == Colours.Red) { arrWhereHide[i, j] = bmap.GetPixel(i, j).R; } else if (c == Colours.Green) { arrWhereHide[i, j] = bmap.GetPixel(i, j).G; } else if (c == Colours.Blue) { arrWhereHide[i, j] = bmap.GetPixel(i, j).B; } else { throw new NullReferenceException(); } } } int numSegm = bmap.Width * bmap.Height / (SizeSegment * SizeSegment); //общее число сегментов var segm = new List <byte[, ]>(); Separate(arrWhereHide, segm, bmap.Width, bmap.Height, SizeSegment);// разбиваем массив на сегменты // дискретное косинусное преобразование var dctList = new List <double[, ]>(); foreach (var b in segm) { dctList.Add(DCT(b)); // список из коэффициентов ДКП } var txtByte = new List <byte>(); List <int> possibPos = new List <int>(); // возможные позиции в соответствии с размером списка коэффициентов ДКП for (int i = 0; i < dctList.Count; i++) { possibPos.Add(i); } int end = 2; //конец прохода bool LenDone = true; for (int i = 0; i < end; i++) { var bits = new bool[8]; // булевый массив битов символа for (int j = 0; j < 8; j++) { int pos = possibPos[0]; // позиция possibPos.RemoveAt(0); double AbsPoint1 = Math.Abs(dctList[pos][p1.X, p1.Y]); double AbsPoint2 = Math.Abs(dctList[pos][p2.X, p2.Y]); // бит выделяем в соответсвии с тем, какое абслютное значение больше if (AbsPoint1 > AbsPoint2) { bits[j] = false; } else if (AbsPoint1 < AbsPoint2) { bits[j] = true; } } txtByte.Add(CommonFunc.BoolArrByte(bits)); if (i == 0 && txtByte.ToArray()[0] != Convert.ToByte('Z')) // в случае отсутвия метки возвращаем пустую строку { return(""); } else if (i == 1) //увеличиваем конец прохода, узнав размер длины { end = txtByte.ToArray()[1] + 2; txtByte.Clear(); } else if (LenDone && i + 1 == end) //увеличиваем конец прохода, узнав длину { end += CommonFunc.IntBytes(txtByte); txtByte.Clear(); LenDone = false; } } return(Encoding.GetEncoding(1251).GetString(txtByte.ToArray())); //преобразуем массив }
// проверка на налчие скрытого текста public static bool IsHiddenText(StegoBitmap stgbmap, Colours c) { var bmap = stgbmap.GetImage(); int width = bmap.Width; int height = bmap.Height; var arrWhereHide = new byte[bmap.Width, bmap.Height]; // массив байтов, где будет хранится текст в соотвествии с выбранным цветом //выбираем из изображения пиксели в соответствии с переданным цветом for (int i = 0; i < bmap.Width; i++) { for (int j = 0; j < bmap.Height; j++) { if (c == Colours.Red) { arrWhereHide[i, j] = bmap.GetPixel(i, j).R; } else if (c == Colours.Green) { arrWhereHide[i, j] = bmap.GetPixel(i, j).G; } else if (c == Colours.Blue) { arrWhereHide[i, j] = bmap.GetPixel(i, j).B; } else { throw new NullReferenceException(); } } } int numSegm = bmap.Width * bmap.Height / (SizeSegment * SizeSegment); //общее число сегментов var segm = new List <byte[, ]>(); Separate(arrWhereHide, segm, bmap.Width, bmap.Height, SizeSegment);// разбиваем массив на сегменты // дискретное косинусное преобразование var dctList = new List <double[, ]>(); foreach (var b in segm) { dctList.Add(DCT(b)); // список из коэффициентов ДКП } var txtByte = new List <byte>(); List <int> possibPos = new List <int>(); // возможные позиции в соответствии с размером списка коэффициентов ДКП for (int i = 0; i < dctList.Count; i++) { possibPos.Add(i); } var bits = new bool[8]; // булевый массив битов символа for (int j = 0; j < 8; j++) { int pos = possibPos[0]; // позиция possibPos.RemoveAt(0); if (ValidMoonotony(dctList[pos]) && ValidSharpness(dctList[pos])) { double P1 = dctList[pos][p1.X, p1.Y]; double P2 = dctList[pos][p2.X, p2.Y]; double P3 = dctList[pos][p3.X, p3.Y]; //бит выделяем в соответсвии с тем, какое абслютное значение больше if (Math.Min(P1, P2) - P3 >= 0.001) { bits[j] = false; } else if (P3 - Math.Max(P1, P2) >= 0.001) { bits[j] = true; } j++; } j--; } txtByte.Add(CommonFunc.BoolArrByte(bits)); if (txtByte.ToArray()[0] != Convert.ToByte('B')) // в случае отсутвия метки возвращаем пустую строку { return(false); } return(true); }