예제 #1
0
        //статическая функция для замены НЗБ (внедрения текста в изображение путем замены битов)
        public static StegoBitmap Hide(StegoBitmap bitmap, string text, Colours colour)
        {
            byte[] sourceColour = bitmap.GetColour(colour);                   // массив байтов указанного цвета для данного StegoBitmap
            byte[] stgText      = StringByteArr(text);                        // массив байтов введеных символов
            byte[] len          = LenInBytes(text.Length, Size(text.Length)); // массив байтов из длины текста в соответвии с размером его длины
            byte[] stgBytes     = new byte[2 + len.Length + stgText.Length];  //массив для скрытого текста размером в длину текста + размер длины + два дополнительных байта
            stgBytes[0] = Convert.ToByte('L');                                // первый элемент массива содержит пометку, что в изображении скрыт текст
            stgBytes[1] = Size(text.Length);                                  // второй элемент массива размер длины
            int ind = 0;

            for (int i = 0; i < len.Length; i++)
            {
                stgBytes[i + 2] = len[ind++]; // сохраняем в массив байты из длины текста в соответвии с размером его длины
            }
            ind = 0;
            for (int i = 0; i < stgText.Length; i++)
            {
                stgBytes[i + 2 + len.Length] = stgText[ind++]; // сохраняем в массив скрываемый текст
            }
            // булевский массив из массива байтов
            bool[] stgBoolBits = stgBytes.SelectMany(e => ByteBoolArr(e)).ToArray(); // SelectMany используется для создания выходной последовательности с проекцией "один ко многим" из входной последовательности. Select вернет один выходной элемент для каждого входного элемента, SelectMany - ноль или более выходных элементов для каждого входного
            // проходим по элементам булевского массива текста. если бит текста true и байт цвета четен, то увеличиваем его на 1, в обратной ситуации - уменьшаем на 1, в остальный случаях байт цвета остается не изменным  (0 и 0 => 0, 1 и 1 => 1, 0 и 1 => 1, 1 и 0 => 0)
            for (int i = 0; i < stgBoolBits.Length; i++)
            {
                if ((sourceColour[i] % 2 == 0) && stgBoolBits[i])
                {
                    sourceColour[i]++;
                }
                else if ((sourceColour[i] % 2 == 1) && !stgBoolBits[i])
                {
                    sourceColour[i]--;
                }
            }
            return(new StegoBitmap(bitmap, sourceColour, colour));
        }
예제 #2
0
 //функция проверяет наличие скрытого текста, в случае его нахождения, возвращает true и цвет байтов со скрытым текстом
 public static bool IsHiddenText(StegoBitmap stg, out Colours c)
 {
     if (Mark(stg.RedColour))
     {
         c = Colours.Red;
     }
     else if (Mark(stg.GreenColour))
     {
         c = Colours.Green;
     }
     else if (Mark(stg.BlueColour))
     {
         c = Colours.Blue;
     }
     else
     {
         c = 0;
         return(false);
     }
     return(true);
 }
예제 #3
0
        // функция возвращает скрытый текст
        public static string GetHiddenText(StegoBitmap bitmap, Colours colour)
        {
            byte[] txt     = bitmap.GetColour(colour);                                                  // массив байтов указанного цвета для данного StegoBitmap
            byte   mark    = BoolArrByte(txt.Take(8).SelectMany(e => LastBit(e, 1)).ToArray());         // байт метки
            byte   sizeLen = BoolArrByte(txt.Skip(8).Take(8).SelectMany(e => LastBit(e, 1)).ToArray()); // байт размера длины

            bool[] lenBool  = txt.Skip(16).Take(sizeLen * 8).SelectMany(e => LastBit(e, 1)).ToArray();  // массив из булевых элементов длины скрытого текста (каждый элемент в отдельном байте)
            var    lenBytes = new List <byte>();

            for (int i = 0; i < lenBool.Length; i += 8)
            {
                lenBytes.Add(BoolArrByte(lenBool.Skip(i).Take(8).ToArray()));                                                    // список байтов длины (использовуется список, т.к. длина текста может быть разной), добавляем элементы путем прохода по 8 битам, а затем берем следующие восемь
            }
            bool[] textBool  = txt.Skip(16 + sizeLen * 8).Take(IntBytes(lenBytes) * 8).SelectMany(x => LastBit(x, 1)).ToArray(); // массив из булевых элементов скрытого текста (каждый элемент в отдельном байте)
            var    textBytes = new List <byte>();

            for (int i = 0; i < textBool.Length; i += 8)
            {
                textBytes.Add(BoolArrByte(textBool.Skip(i).Take(8).ToArray())); // список байтов текста, добавляем элементы путем прохода по 8 битам, а затем берем следующие восемь
            }
            return(ByteArrString(textBytes.ToArray()));
        }
예제 #4
0
        // функция находит скрытый текст
        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())); //преобразуем массив
        }
예제 #5
0
        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));
        }
예제 #6
0
        // проверка на налчие скрытого текста
        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);
        }