[引用]该C#程序可将文本文件藏于位图中,也可导出之!

类别:.NET开发 点击:0 评论:0 推荐:
http://blog.csdn.net/yiruoyun/archive/2004/10/18/141514.aspx

//使用方法:
// BmpSafe.exe /file2bmp (input BMP) (input file to hide) [output file]
//BmpSafe.exe /bmp2file (data BMP) [output file]

using System;
using System.IO;
using System.Drawing;

public class Bitmap24Writer
{
 protected Bitmap bmp;
 protected int curX, curY, iRGB;
 protected uint bitsLeft, bitsTotal;
 protected byte r, g, b;

 public Bitmap24Writer(Bitmap bmp)
 {
  if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
   throw new ArgumentException();
  // assign vars
  curX       = curY = iRGB = 0;
  this.bmp   = bmp;
  bitsLeft   = bitsTotal = (uint)bmp.Height * (uint)bmp.Width * 3;
 }

 public uint GetUnusedBitCount()
 {
  return bitsLeft;
 }

 public uint GetMaxBitStorageCount()
 {
  return bitsTotal;
 }

 public Bitmap GetBitmap()
 {
  return bmp;
 }

 public bool WriteByte(byte by)
 {
  if (bitsLeft < 8)
   return false;

  uint bits2Do = 8;

  for (; curX < bmp.Width; curX++)
  {
   if (curY >= bmp.Height)
    curY = 0;

   for (; curY < bmp.Height; curY++)
   {
    if (bits2Do == 0)
     return true;

    Color col = bmp.GetPixel(curX, curY);
    r = col.R;
    g = col.G;
    b = col.B;

    for ( ; ; )
    {
     byte curBit = (byte)(by & 1);

     switch( iRGB )
     {
      case 0:
       r = (byte)(r & 0xFE);
       r |= curBit;
       break;

      case 1:
       g = (byte)(g & 0xFE);
       g |= curBit;
       break;

      case 2:
       b = (byte)(b & 0xFE);
       b |= curBit;
       break;
     }
     --bits2Do;
     --bitsLeft;
     by >>= 1;
     bmp.SetPixel(curX, curY, Color.FromArgb(r, g, b));
     if (iRGB == 2)
     {
      iRGB = 0;
      break;
     }
     iRGB++;
     if (bits2Do == 0)
      return true;
    }
   }
  }
  return true;
 }
}

public class Bitmap24Reader
{
 protected Bitmap bmp;
 protected int curX, curY, iRGB;
 protected uint bitsLeft, bitsTotal;

 public Bitmap24Reader(Bitmap bmp)
 {
  if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
   throw new ArgumentException();
  curX       = curY = iRGB = 0;
  this.bmp   = bmp;
  bitsLeft   = bitsTotal = (uint)bmp.Height * (uint)bmp.Width * 3;
 }

 public uint GetUnusedBitCount()
 {
  return bitsLeft;
 }

 public uint GetMaxBitStorageCount()
 {
  return bitsTotal;
 }

 public Bitmap GetBitmap()
 {
  return bmp;
 }

 public bool ReadByte(out byte by)
 {
  by = 0;

  if (bitsLeft < 8)
   return false;

  byte bit = 0;
  uint bits2Do = 8;
  for (; curX < bmp.Width; curX++)
  {
   if (curY >= bmp.Height)
    curY = 0;

   for (; curY < bmp.Height; curY++)
   {
    if (bits2Do == 0)
     return true;

    Color col = bmp.GetPixel(curX, curY);
    for ( ; ; )
    {
     switch( iRGB )
     {
      case 0:
       bit = (byte)(col.R & 1);
       break;

      case 1:
       bit = (byte)(col.G & 1);
       break;

      case 2:
       bit = (byte)(col.B & 1);
       break;
     }
     --bits2Do;
     --bitsLeft;
     by |= (byte)(bit << 7);
     if (bits2Do != 0)
      by >>= 1;
     if (iRGB == 2)
     {
      iRGB = 0;
      break;
     }
     iRGB++;
     if (bits2Do == 0)
      return true;
    }
   }
  }
  return true;
 }
}

public class BitmapWorks
{
 public static bool Data2Bmp(FileStream dataStream, FileStream bmpStream, string outFName, out string error)
 {
  error = "";

  Bitmap bmp;
  try
  {
   bmp = new Bitmap(bmpStream);
  }
  catch
  {
   error = "Are you sure the specified bitmap is a valid bitmap ?";
   return false;
  }
  if (bmp.PixelFormat != System.Drawing.Imaging.PixelFormat.Format24bppRgb)
  {
   error = "Please drop only 24bit bitmaps,thanks !";
   return false;
  }

  error += "-> Bitmap info: height=" + bmp.Height + " width=" + bmp.Width + "...\n";

  if (dataStream.Length == 0)
  {
   error = "Input data has a not supported size of 0 !";
   return false;
  }
  uint maxByteStorage = ((uint)bmp.Height * (uint)bmp.Width * 3) / 8;
  error += "-> Up to " + (maxByteStorage-4) + " bytes could be stored in this bitmap...\n";
  if (maxByteStorage < dataStream.Length + 4)
  {
   error = "Not enough pixel in target bitmap to hide the input data block !";
   return false;
  }

  Bitmap24Writer bmpWriter = new Bitmap24Writer(bmp);
  uint dataSize = (uint)dataStream.Length;
  try
  {
   for (uint u = 0; u < 4; u++)
   {
    bmpWriter.WriteByte( (byte)dataSize );
    dataSize >>= 8;
   }
   for (uint u = 0; u < dataStream.Length; u++)
    bmpWriter.WriteByte( (byte)dataStream.ReadByte() );
  }
  catch
  {
   error = "Error while modifing the bitmap's pixels !";
   return false;
  }

  double maxBitStorage = bmpWriter.GetMaxBitStorageCount();
  double spaceUsed = (100 * (maxBitStorage - bmpWriter.GetUnusedBitCount())) / maxBitStorage;
        error += "-> Space used: " + Convert.ToUInt32(spaceUsed) + "%...\n";

  try
  {
   if ( File.Exists( outFName ) )
    File.Delete( outFName );
   bmpWriter.GetBitmap().Save(outFName);
  }
  catch
  {
   error = "Couldn't save output to " + outFName + " !";
   return false;
  }

  error += "-> Output saved to: " + outFName + "...\n";

  return true;
 }

 public static bool Bmp2Data(FileStream bmpStream, string outFName, out string error)
 {
  error = "";

  Bitmap bmp;
  try
  {
   bmp = new Bitmap(bmpStream);
  }
  catch
  {
   error = "Are you sure the specified bitmap is a valid bitmap ?";
   return false;
  }

  Bitmap24Reader bmpReader;
  try
  {
   bmpReader = new Bitmap24Reader(bmp);
  }
  catch (ArgumentException)
  {
   error = "This isn't a 24bit bitmap !";
   return false;
  }

  FileStream outStream;
  try
  {
   outStream = File.Create( outFName );
  }
  catch
  {
   error = "Couldn't create output file: " + outFName + " !";
   return false;
  }
  uint dataSize = 0;
  byte outByte;
  try
  {
   for (uint u = 0; u < 4; u++)
   {
    if ( !bmpReader.ReadByte( out outByte ) )
     throw new Exception();
    dataSize |= (uint)( outByte << 8*3 );
    if (u != 3)
     dataSize >>= 8;
   }
   error += "-> Size of hidden data: " + dataSize + " bytes...\n";
   for (uint u = 0; u < dataSize; u++)
   {
    if ( !bmpReader.ReadByte( out outByte ) )
     throw new Exception();
    outStream.WriteByte( outByte );
   }
  }
  catch
  {
   error = "Exception caught while reading the hidden data !";
   return false;
  }
  finally
  {
   outStream.Close();
  }

  error += "-> Output saved to: " + outFName + "...\n";

  return true;
 }

}

class BmpSafe
{
 public static string cmdLine =
  "Command line:\n" +
  "    BmpSafe.exe /file2bmp (input BMP) (input file to hide) [output file]\n" +
  "    BmpSafe.exe /bmp2file (data BMP) [output file]";

 private static string serviceOne = "/file2bmp";
 private static string serviceTwo = "/bmp2file";

 [STAThread]
 static void Main(string[] args)
 {
  Console.WriteLine(
   "BmpSafe - hide files in 24bit bitmaps\n" +
   "          a little steganografie implementation\n" +
   "          by yoda\n" +
   "-------------------------------------------------------------------------------\n");

  string inFile = "", inBmp, outFile;
  bool bFile2Bmp;
  if (args.Length < 2)
  {
   Console.WriteLine("!! Invalid number of arguments :(");
   Console.WriteLine(cmdLine);
   return; // ERR
  }
  if ( String.Compare(args[0], serviceOne, true) == 0 )
   bFile2Bmp = true;
  else if ( String.Compare(args[0], serviceTwo, true) == 0)
   bFile2Bmp = false;
  else
  {
   Console.WriteLine("!! First parameters must be either \"/file2bmp\" or \"/bmp2file\" !");
   return;
  }

  inBmp = args[1];
  if (bFile2Bmp)
  {
   if (args.Length < 3)
   {
    Console.WriteLine("!! Invalid number of arguments :(");
    Console.WriteLine(cmdLine);
    return;
   }
   inFile = args[2];
   if (args.Length > 3)
    outFile = args[3];
   else
    outFile = "Secret.BMP";
  }
  else
  {
   if (args.Length > 2)
    outFile = args[2];
   else
    outFile = "Secret.bin";
  }
  
  Console.WriteLine("-> Processing input...");
  try
  {
   string err;
   bool ret;

   if (bFile2Bmp)
    ret = BitmapWorks.Data2Bmp(
     File.OpenRead(inFile),
     File.OpenRead(inBmp),
     outFile,
     out err );
   else
    ret = BitmapWorks.Bmp2Data(
     File.OpenRead(inBmp),
     outFile,
     out err);
   if (!ret)
   {
    Console.WriteLine("!! " + err);
    return;
   }
   else
    Console.Write( err );
  }
  catch(FileNotFoundException)
  {
   Console.WriteLine("!! At least one file could not be found :(");
   return;
  }
  catch
  {
   Console.WriteLine("!! An exception occurred :(");
   return;
  }

  Console.WriteLine("-> Job done...");

  return;
 }
}

本文地址:http://com.8s8s.com/it/it43438.htm