//使用方法:
// 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 (bi