2015-04-02 14 views
0

我正在寻找一个教程,其中描述了如何使用C#将图像文件写入/读取隐藏文本,但不幸的是,我不能找到关于此的任何好帖子,所以我决定询问这里介绍这个小窍门。向图像文件c写入隐藏的消息#

假设我有一个名为test.jpg的图像文件,是否有任何方法可以将“Hello word”这样的隐藏文本写入此文件?我已经阅读了关于图像元数据的内容,并且我想我应该尝试以某种方式写入这个元数据,但我不知道如何。 如果有人知道如何去做,请帮助我了解如何去做。 谢谢。

+0

是的,有这样的方法。你正在寻找的术语是隐写术,但有许多算法可以实现你的愿望。您是否特别要求如何通过在元数据中嵌入文本或通用的任何方法来实现此目的?你必须更具体地了解你想要达到的目标,如何以及在哪里遇到困难。如果您只需要一种方法,那么在SO或Google中进行搜索将最终获得一些兼容的结果。 – Reti43 2015-04-02 12:13:50

+0

我需要的是将隐藏文本写入/读取到图像文件中。好的,我会的,谢谢。 – MDDDC 2015-04-02 12:24:13

回答

1

正确的术语是“隐写术”。

下面的文章状态是隐写术的定义:

隐写术是别人中嵌入信息隐藏信息的艺术和科学。隐写术通过用普通的计算机文件中的一些无用或未使用的数据替换不同的,不可见的信息。这种隐藏的信息可以是纯文本,密文,甚至图像

一步一步的解释上的隐写的工作原理:通过图像的像素

  • 循环。在每次迭代中,将RGB值分别放在一个单独的整数中。
  • 对于R,G和B中的每一个,使LSB等于0.这些位将用于隐藏字符。
  • 获取当前字符并将其转换为整数。然后将它的8位隐藏在R1,G1,B1,R2,G2,B2,R3,G3中,其中数字表示像素的数量。在这些元素的每个LSB(从R1到G3)中,连续隐藏字符的位。
  • 处理字符的8位时,跳转到下一个字符,并重复该过程,直到处理完整个文本。
  • 根据文本的长度,文本可以隐藏在图像的一小部分。所以,我们必须有一些东西来表明我们到达了文本的末尾。该指标只是8个连续的零。当从图像中提取文本时,这将是需要的。

这比隐藏更简单。只需穿过 图像的像素,直到找到8个连续的零。在您通过时,从每个像素元素(R,G,B)中选取 LSB并将其附加到空值 值。当该值的8位完成后,将其转换回 字符,然后将该字符添加到要查找的结果文本中。

一个例子源代码是::

class SteganographyHelper 
{ 
    public enum State 
    { 
     Hiding, 
     Filling_With_Zeros 
    }; 

    public static Bitmap embedText(string text, Bitmap bmp) 
    { 
     // initially, we'll be hiding characters in the image 
     State state = State.Hiding; 

     // holds the index of the character that is being hidden 
     int charIndex = 0; 

     // holds the value of the character converted to integer 
     int charValue = 0; 

     // holds the index of the color element (R or G or B) that is currently being processed 
     long pixelElementIndex = 0; 

     // holds the number of trailing zeros that have been added when finishing the process 
     int zeros = 0; 

     // hold pixel elements 
     int R = 0, G = 0, B = 0; 

     // pass through the rows 
     for (int i = 0; i < bmp.Height; i++) 
     { 
      // pass through each row 
      for (int j = 0; j < bmp.Width; j++) 
      { 
       // holds the pixel that is currently being processed 
       Color pixel = bmp.GetPixel(j, i); 

       // now, clear the least significant bit (LSB) from each pixel element 
       R = pixel.R - pixel.R % 2; 
       G = pixel.G - pixel.G % 2; 
       B = pixel.B - pixel.B % 2; 

       // for each pixel, pass through its elements (RGB) 
       for (int n = 0; n < 3; n++) 
       { 
        // check if new 8 bits has been processed 
        if (pixelElementIndex % 8 == 0) 
        { 
         // check if the whole process has finished 
         // we can say that it's finished when 8 zeros are added 
         if (state == State.Filling_With_Zeros && zeros == 8) 
         { 
          // apply the last pixel on the image 
          // even if only a part of its elements have been affected 
          if ((pixelElementIndex - 1) % 3 < 2) 
          { 
           bmp.SetPixel(j, i, Color.FromArgb(R, G, B)); 
          } 

          // return the bitmap with the text hidden in 
          return bmp; 
         } 

         // check if all characters has been hidden 
         if (charIndex >= text.Length) 
         { 
          // start adding zeros to mark the end of the text 
          state = State.Filling_With_Zeros; 
         } 
         else 
         { 
          // move to the next character and process again 
          charValue = text[charIndex++]; 
         } 
        } 

        // check which pixel element has the turn to hide a bit in its LSB 
        switch (pixelElementIndex % 3) 
        { 
         case 0: 
          { 
           if (state == State.Hiding) 
           { 
            // the rightmost bit in the character will be (charValue % 2) 
            // to put this value instead of the LSB of the pixel element 
            // just add it to it 
            // recall that the LSB of the pixel element had been cleared 
            // before this operation 
            R += charValue % 2; 

            // removes the added rightmost bit of the character 
            // such that next time we can reach the next one 
            charValue /= 2; 
           } 
          } break; 
         case 1: 
          { 
           if (state == State.Hiding) 
           { 
            G += charValue % 2; 

            charValue /= 2; 
           } 
          } break; 
         case 2: 
          { 
           if (state == State.Hiding) 
           { 
            B += charValue % 2; 

            charValue /= 2; 
           } 

           bmp.SetPixel(j, i, Color.FromArgb(R, G, B)); 
          } break; 
        } 

        pixelElementIndex++; 

        if (state == State.Filling_With_Zeros) 
        { 
         // increment the value of zeros until it is 8 
         zeros++; 
        } 
       } 
      } 
     } 

     return bmp; 
    } 

    public static string extractText(Bitmap bmp) 
    { 
     int colorUnitIndex = 0; 
     int charValue = 0; 

     // holds the text that will be extracted from the image 
     string extractedText = String.Empty; 

     // pass through the rows 
     for (int i = 0; i < bmp.Height; i++) 
     { 
      // pass through each row 
      for (int j = 0; j < bmp.Width; j++) 
      { 
       Color pixel = bmp.GetPixel(j, i); 

       // for each pixel, pass through its elements (RGB) 
       for (int n = 0; n < 3; n++) 
       { 
        switch (colorUnitIndex % 3) 
        { 
         case 0: 
          { 
           // get the LSB from the pixel element (will be pixel.R % 2) 
           // then add one bit to the right of the current character 
           // this can be done by (charValue = charValue * 2) 
           // replace the added bit (which value is by default 0) with 
           // the LSB of the pixel element, simply by addition 
           charValue = charValue * 2 + pixel.R % 2; 
          } break; 
         case 1: 
          { 
           charValue = charValue * 2 + pixel.G % 2; 
          } break; 
         case 2: 
          { 
           charValue = charValue * 2 + pixel.B % 2; 
          } break; 
        } 

        colorUnitIndex++; 

        // if 8 bits has been added, 
        // then add the current character to the result text 
        if (colorUnitIndex % 8 == 0) 
        { 
         // reverse? of course, since each time the process occurs 
         // on the right (for simplicity) 
         charValue = reverseBits(charValue); 

         // can only be 0 if it is the stop character (the 8 zeros) 
         if (charValue == 0) 
         { 
          return extractedText; 
         } 

         // convert the character value from int to char 
         char c = (char)charValue; 

         // add the current character to the result text 
         extractedText += c.ToString(); 
        } 
       } 
      } 
     } 

     return extractedText; 
    } 

    public static int reverseBits(int n) 
    { 
     int result = 0; 

     for (int i = 0; i < 8; i++) 
     { 
      result = result * 2 + n % 2; 

      n /= 2; 
     } 

     return result; 
    } 
} 

来源的文章:http://www.codeproject.com/Tips/635715/Steganography-Simple-Implementation-in-Csharp

+0

欢迎来到StackOverflow。只有链接的答案不好,因为链接可能会断开或服务器可能关闭。请记住链接所说的内容,并将其张贴在您的答案中,以便其他用户可以保留该链接。 – 2015-04-02 11:15:11

+0

此方法不适用于jpeg文件,并且在提问者放弃此要求之前,您的建议无法使用。 – Reti43 2015-04-02 12:53:11

+0

它cleary返回一个位图。您可以将这些位图保存为JPG或任何其他常见文件格式。 – Syntasu 2015-04-02 13:06:11

-2

您也可以参考这个.. Image Steganography Application C#

+0

请避免仅链接回答,因为它们可能会过时。此外,您建议的方法似乎并不相关,因为它是关于将图像隐藏在另一个图像中的方式,秘密不能存储在jpeg文件中。 – Reti43 2015-04-02 13:02:10

+0

明白了。我只想帮助 – 2015-04-03 05:33:41

+0

@ Reti43位图速记工作在字节数组级别,并且在相同的字节数组级别,“秘密消息”和“位图图像”都被视为相同且相同。至少可以说,你的无关论点是荒谬的。 – Visar 2017-01-15 17:43:45