[CodeProject每日一荐] 藏东西系列:在AVI文件中隐藏信息
2006-04-26 10:18
603 查看
这次要在AVI文件中隐藏信息了,AVI文件是一系列的位图.
Steganography IV - Reading and Writing AVI files By Corinna John
[读视频流]
Windows AVI 库是avifil32.dll中函数的集合. 使用之前先得用 AVIFileInit初始化. AVIFileOpen 打开文件, AVIFileGetStream 取得视频流. 这些函数申请的内存最后都必须释放. AVI文件可以包含四种不同类型的多个流,通常每种类型只有一个流,我们这里只关心视频流.
//Initialize the AVI library
[DllImport("avifil32.dll")]
public static extern void AVIFileInit();
//Open an AVI file
[DllImport("avifil32.dll", PreserveSig=true)]
public static extern int AVIFileOpen(
ref int ppfile,
String szFile,
int uMode,
int pclsidHandler);
//Get a stream from an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileGetStream(
int pfile,
out IntPtr ppavi,
int fccType,
int lParam);
//Release an open AVI stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamRelease(IntPtr aviStream);
//Release an ope AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileRelease(int pfile);
//Close the AVI library
[DllImport("avifil32.dll")]
public static extern void AVIFileExit();
private int aviFile = 0;
private IntPtr aviStream;
//Get the start position of a stream
[DllImport("avifil32.dll", PreserveSig=true)]
public static extern int AVIStreamStart(int pavi);
//Get the length of a stream in frames
[DllImport("avifil32.dll", PreserveSig=true)]
public static extern int AVIStreamLength(int pavi);
//Get header information about an open stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamInfo(
int pAVIStream,
ref AVISTREAMINFO psi,
int lSize);
调用以上函数我们可以填充位图信息头BITMAPINFOHEADER 结构,然后我们用以下函数来提取帧
//Get a pointer to a GETFRAME object (returns 0 on error)
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrameOpen(
IntPtr pAVIStream,
ref BITMAPINFOHEADER bih);
//Get a pointer to a packed DIB (returns 0 on error)
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrame(
int pGetFrameObj,
int lPos);
//Release the GETFRAME object
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrameClose(int pGetFrameObj);
准备工作就绪,现在解压帧
//get start position and count of frames
int firstFrame = AVIStreamStart(aviStream.ToInt32());
int countFrames = AVIStreamLength(aviStream.ToInt32());
//get header information
AVISTREAMINFO streamInfo = new AVISTREAMINFO();
result = AVIStreamInfo(aviStream.ToInt32(), ref streamInfo,
Marshal.SizeOf(streamInfo));
//construct the expected bitmap header
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih.biBitCount = 24;
bih.biCompression = 0; //BI_RGB;
bih.biHeight = (Int32)streamInfo.rcFrame.bottom;
bih.biWidth = (Int32)streamInfo.rcFrame.right;
bih.biPlanes = 1;
bih.biSize = (UInt32)Marshal.SizeOf(bih);
//prepare to decompress DIBs (device independend bitmaps)
int getFrameObject = AVIStreamGetFrameOpen(aviStream, ref bih);
//Export the frame at the specified position
//Create file header
Avi.BITMAPFILEHEADER bfh = new Avi.BITMAPFILEHEADER();
bfh.bfType = Avi.BMP_MAGIC_COOKIE;
//size of file as written to disk
bfh.bfSize = (Int32)(55 + bih.biSizeImage);
bfh.bfOffBits = Marshal.SizeOf(bih) + Marshal.SizeOf(bfh);
//Create or overwrite the destination file
FileStream fs = new FileStream(dstFileName, System.IO.FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
//Write header
bw.Write(bfh.bfType);
bw.Write(bfh.bfSize);
bw.Write(bfh.bfReserved1);
bw.Write(bfh.bfReserved2);
bw.Write(bfh.bfOffBits);
//Write bitmap info
bw.Write(bitmapInfo);
//Write bitmap data
bw.Write(bitmapData);
bw.Close();
fs.Close();
} //end of ExportBitmap
应用程序会把解出来的位图当作普通位图来隐藏信息,如果载体文件是AVI文件,则提取第一帧到一个临时位图文件,放入一些信息,接下来是第二帧...最后一帧之后则关闭AVI文件,删除临时位图文件,接下来处理下一个载体文件.
[写视频流]
应用程序块打开AVI 载体文件时, 它创建另一个AVI文件来保存新的位图,新的文件大小和帧频率都与原来的一样, 我们不能用
//Create a new stream in an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileCreateStream(
int pfile,
out IntPtr ppavi,
ref AVISTREAMINFO ptr_streaminfo);
//Set the format for a new stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamSetFormat(
IntPtr aviStream, Int32 lPos,
ref BITMAPINFOHEADER lpFormat, Int32 cbFormat);
//Write a sample to a stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamWrite(
IntPtr aviStream, Int32 lStart, Int32 lSamples,
IntPtr lpBuffer, Int32 cbBuffer, Int32 dwFlags,
Int32 dummy1, Int32 dummy2);
现在创建视频流:
//Create a new video stream
//Create an empty AVI file
//Add a sample to the stream - for first sample: create the stream
public void AddFrame(Bitmap bmp) {
public struct BitmapInfo{
//uncompressed image
public Bitmap bitmap;
//position of the frame in the AVI stream, -1 for non-avi bitmaps
public int aviPosition;
//count of frames in the AVI stream, or 0 for non-avi bitmaps
public int aviCountFrames;
//path and name of the bitmap file
//this file will be deleted later, if aviPosition is 0 or greater
public String sourceFileName;
//how many bytes will be hidden in this image
public long messageBytesToHide;
public void LoadBitmap(String fileName){
bitmap = new Bitmap(fileName);
sourceFileName = fileName;
}
}
MovePixelPosition需移到下一个载体位图时, 首先检查aviPosition. 如果aviPosition < 0, ,则保存位图且释放资源, 如果aviPosition >= 0, 则是AVI的一帧. 不保存为文件而是加到打开的AVI流中. 如果位图是简单位图或AVI的最后一帧, 该方法会移到下一个载体文件. 如果AVI中还有帧,则移到下一帧.
[使用代码]
工程中多了三个类
[注意]
如果安装了VirtualDub,有可能设置为不允许其它程序写AVI的头,导致本程序无法正确运行
Steganography IV - Reading and Writing AVI files By Corinna John
[读视频流]
Windows AVI 库是avifil32.dll中函数的集合. 使用之前先得用 AVIFileInit初始化. AVIFileOpen 打开文件, AVIFileGetStream 取得视频流. 这些函数申请的内存最后都必须释放. AVI文件可以包含四种不同类型的多个流,通常每种类型只有一个流,我们这里只关心视频流.
//Initialize the AVI library
[DllImport("avifil32.dll")]
public static extern void AVIFileInit();
//Open an AVI file
[DllImport("avifil32.dll", PreserveSig=true)]
public static extern int AVIFileOpen(
ref int ppfile,
String szFile,
int uMode,
int pclsidHandler);
//Get a stream from an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileGetStream(
int pfile,
out IntPtr ppavi,
int fccType,
int lParam);
//Release an open AVI stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamRelease(IntPtr aviStream);
//Release an ope AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileRelease(int pfile);
//Close the AVI library
[DllImport("avifil32.dll")]
public static extern void AVIFileExit();
private int aviFile = 0;
private IntPtr aviStream;
//Get the start position of a stream
[DllImport("avifil32.dll", PreserveSig=true)]
public static extern int AVIStreamStart(int pavi);
//Get the length of a stream in frames
[DllImport("avifil32.dll", PreserveSig=true)]
public static extern int AVIStreamLength(int pavi);
//Get header information about an open stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamInfo(
int pAVIStream,
ref AVISTREAMINFO psi,
int lSize);
调用以上函数我们可以填充位图信息头BITMAPINFOHEADER 结构,然后我们用以下函数来提取帧
//Get a pointer to a GETFRAME object (returns 0 on error)
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrameOpen(
IntPtr pAVIStream,
ref BITMAPINFOHEADER bih);
//Get a pointer to a packed DIB (returns 0 on error)
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrame(
int pGetFrameObj,
int lPos);
//Release the GETFRAME object
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrameClose(int pGetFrameObj);
准备工作就绪,现在解压帧
//get start position and count of frames
int firstFrame = AVIStreamStart(aviStream.ToInt32());
int countFrames = AVIStreamLength(aviStream.ToInt32());
//get header information
AVISTREAMINFO streamInfo = new AVISTREAMINFO();
result = AVIStreamInfo(aviStream.ToInt32(), ref streamInfo,
Marshal.SizeOf(streamInfo));
//construct the expected bitmap header
BITMAPINFOHEADER bih = new BITMAPINFOHEADER();
bih.biBitCount = 24;
bih.biCompression = 0; //BI_RGB;
bih.biHeight = (Int32)streamInfo.rcFrame.bottom;
bih.biWidth = (Int32)streamInfo.rcFrame.right;
bih.biPlanes = 1;
bih.biSize = (UInt32)Marshal.SizeOf(bih);
//prepare to decompress DIBs (device independend bitmaps)
int getFrameObject = AVIStreamGetFrameOpen(aviStream, ref bih);
//Export the frame at the specified position
//Create file header
Avi.BITMAPFILEHEADER bfh = new Avi.BITMAPFILEHEADER();
bfh.bfType = Avi.BMP_MAGIC_COOKIE;
//size of file as written to disk
bfh.bfSize = (Int32)(55 + bih.biSizeImage);
bfh.bfOffBits = Marshal.SizeOf(bih) + Marshal.SizeOf(bfh);
//Create or overwrite the destination file
FileStream fs = new FileStream(dstFileName, System.IO.FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
//Write header
bw.Write(bfh.bfType);
bw.Write(bfh.bfSize);
bw.Write(bfh.bfReserved1);
bw.Write(bfh.bfReserved2);
bw.Write(bfh.bfOffBits);
//Write bitmap info
bw.Write(bitmapInfo);
//Write bitmap data
bw.Write(bitmapData);
bw.Close();
fs.Close();
} //end of ExportBitmap
应用程序会把解出来的位图当作普通位图来隐藏信息,如果载体文件是AVI文件,则提取第一帧到一个临时位图文件,放入一些信息,接下来是第二帧...最后一帧之后则关闭AVI文件,删除临时位图文件,接下来处理下一个载体文件.
[写视频流]
应用程序块打开AVI 载体文件时, 它创建另一个AVI文件来保存新的位图,新的文件大小和帧频率都与原来的一样, 我们不能用
Open()来创建,而使用
AVIFileCreateStream,
AVIStreamSetFormatand
AVIStreamWrite:
//Create a new stream in an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileCreateStream(
int pfile,
out IntPtr ppavi,
ref AVISTREAMINFO ptr_streaminfo);
//Set the format for a new stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamSetFormat(
IntPtr aviStream, Int32 lPos,
ref BITMAPINFOHEADER lpFormat, Int32 cbFormat);
//Write a sample to a stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamWrite(
IntPtr aviStream, Int32 lStart, Int32 lSamples,
IntPtr lpBuffer, Int32 cbBuffer, Int32 dwFlags,
Int32 dummy1, Int32 dummy2);
现在创建视频流:
//Create a new video stream
//Create an empty AVI file
//Add a sample to the stream - for first sample: create the stream
public void AddFrame(Bitmap bmp) {
public struct BitmapInfo{
//uncompressed image
public Bitmap bitmap;
//position of the frame in the AVI stream, -1 for non-avi bitmaps
public int aviPosition;
//count of frames in the AVI stream, or 0 for non-avi bitmaps
public int aviCountFrames;
//path and name of the bitmap file
//this file will be deleted later, if aviPosition is 0 or greater
public String sourceFileName;
//how many bytes will be hidden in this image
public long messageBytesToHide;
public void LoadBitmap(String fileName){
bitmap = new Bitmap(fileName);
sourceFileName = fileName;
}
}
MovePixelPosition需移到下一个载体位图时, 首先检查aviPosition. 如果aviPosition < 0, ,则保存位图且释放资源, 如果aviPosition >= 0, 则是AVI的一帧. 不保存为文件而是加到打开的AVI流中. 如果位图是简单位图或AVI的最后一帧, 该方法会移到下一个载体文件. 如果AVI中还有帧,则移到下一帧.
[使用代码]
工程中多了三个类
AviReader打开已有的AVI 文件复制帧到位图
AviWriter创建新的AVI 文件,组合帧到视频流中.
Avi包含函数声明和结构定义.
[注意]
如果安装了VirtualDub,有可能设置为不允许其它程序写AVI的头,导致本程序无法正确运行
相关文章推荐
- [CodeProject每日一荐] 藏东西系列:在图片中隐藏信息
- [CodeProject每日一荐] 藏东西系列:在图片离散的bit中隐藏信息
- [CodeProject每日一荐] 基于xml的在线选择题小测试(调查问卷)
- [CodeProject每日一荐] SqlWhereBuilder ASP.NET 服务器控件
- [CodeProject每日一荐] NotifyWindow: 一个轻量级 MSN Messenger 风格的通知窗体
- [Codeproject每日一荐] VS.NET IDE Bugs & Workarounds
- [CodeProject每日一荐] ASP.NET 仿MSN Messenger Alert的弹出窗口控件
- [CodeProject每日一荐]实现Double Metaphone语音匹配算法[一]:介绍与C++实现
- [CodeProject每日一荐] ASP.NET 仿MSN Messenger Alert的弹出窗口控件
- [CodeProject每日一荐]实现Double Metaphone语音匹配算法[二]:Visual Basic的COM实现和关系数据库解决方案
- [CodeProject每日一荐] TaskbarNotifier: 可换肤的 MSN Messenger-like 风格窗体( C# & VB.NET)
- 在AVI文件中隐藏信息
- [CodeProject每日一荐] 两个C++实现的MSN Messenger弹出窗口风格的窗体
- [CodeProject每日一荐] TaskbarNotifier: 可换肤的 MSN Messenger-like 风格窗体( C# & VB.NET)
- [CodeProject每日一荐]实现Double Metaphone语音匹配算法[三,四] VBScript调用COM;存储过程实现及高级话题
- [CodeProject每日一荐] PopupNotifier: 一个Office 2003风格的通知控件(VB.NET)
- Linux下复制文件夹下所有东西到另一个文件夹(包括隐藏文件)
- 深入Atlas系列:Web Sevices Access in Atlas示例(6) - 在客户端隐藏服务器端类型信息
- SpringCloud系列九:SpringCloudConfig 基础配置(SpringCloudConfig 的基本概念、配置 SpringCloudConfig 服务端、抓取配置文件信息、客户端使用 SpringCloudConfig 进行配置、单仓库目录匹配、应用仓库自动选择、仓库匹配模式)
- Android Project from Existing Code 生成 R 文件错误、失败等问题解决办法 - 持续更新