C# AVI Image 转换
AVI视频库 http://download.csdn.net/download/qc_id_01/9970151
Avi视频文件的编码有很多,这个库只支持部分Avi文件,有些Avi文件不支持,具体哪些不支持还没搞清楚
AviFile库提供了
1、从视频流中图片的处理
2、视频中音频的处理
3、压缩和解压视频流
1、使用
1、从视频读取图片,还有一些参数可以通过aviStream查看到,可以把当前流信息输出到文件
//Avi文件读取
string filepath = @"D:\test.avi";
AviManager aviManager = new AviManager(filepath, true);
VideoStream aviStream = aviManager.GetVideoStream(); //获取和保存音频流到文件
AudioStream audioStream = aviManager.GetWaveStream();
audioStream.ExportStream(@"D:\test.wav"); aviStream.GetFrameOpen();
//获取视频总帧数
int framecount = aviStream.CountFrames;
//获取第5帧的图片
Bitmap bmp = aviStream.GetBitmap(5);
//视频速度
double rate = aviStream.FrameRate;
//直接保存帧图片到文件
//aviStream.ExportBitmap(5, @"D:\frame_05.jpg");
//保存当前流到文件
//aviStream.ExportStream(@"D:\currenttest.avi") aviStream.GetFrameClose();
aviManager.Close();
2、把图片和音频写入视频流(部分参数后面会说到,这里只是简单的演示)
//读取图片文件
string[] files = Directory.GetFiles(@"D:\test\", "*.jpg");
AviManager aviManager = new AviManager(@"D:\newtest.avi", false); //添加音频
String fileName = @"D:\audio.wav";
aviManager.AddAudioStream(fileName, 0); //读取第一张图片,设置每秒3帧
VideoStream aviStream = aviManager.AddVideoStream(true, 3, new Bitmap(files[0]));
for (int i = 1; i < files.Length; i++)
{
aviStream.AddFrame(new Bitmap(files[i]));
}
aviManager.Close();
3、从视频截取一段保存到AviManager
AviManager aviManager = new AviManager(filepath, true);
float startSecond = 0;
float stopSecond = 10;
//截取0-10s放到newManager
AviManager newManager = aviManager.CopyTo(@"D:\newtest_0-10.avi", startSecond, stopSecond);
4、对已压缩的视频进行解压缩,放到另一个VideoStream中
VideoStream newstream;
AviManager newManager = aviStream.DecompressToNewFile(@"D:\01.avi", false, out newstream);
newstream.GetFrameOpen();
Bitmap bitmap = newstream.GetBitmap(10);
newstream.GetFrameClose();
5、向视频流中添加一张图片帧,对于未压缩的视频流,我们可以直接进行添加,但是对于已经压缩过的视频流,添加的图片帧不能重新进行压缩,所以我们需要对其进行解压缩,操作完后在进行压缩
//读取图片文件
string[] files = Directory.GetFiles(@"D:\test\", "*.jpg"); //打开一个已存在的视频
AviManager aviManager = new AviManager(@"D:\test.avi", true);
VideoStream avistream = aviManager.GetVideoStream();
VideoStream newstream;
//解压视频到newstream中,最后已压缩的形式保存
AviManager newManager = avistream.DecompressToNewFile(@"newtest.avi", true, out newstream);
avistream = newManager.GetOpenStream(0); for (int i = 1; i < files.Length; i++)
{
avistream.AddFrame(new Bitmap(files[i]));
}
aviManager.Close();
//关闭和保存文件newtest.avi
newManager.Close();
6、编辑视频流 EditableVideoStream (可以对视频流的帧,进行cut,delete,paste等早错)
//打开一个已存在的视频
AviManager aviManager = new AviManager(@"D:\test.avi", true);
VideoStream avistream = aviManager.GetVideoStream(); EditableVideoStream editableStream = new EditableVideoStream(avistream);
int start = 0;
int length =10;
int position = 10;
//Copy
IntPtr copiedData = editableStream.Copy(start, length);
//Insert
editableStream.Paste(copiedData, 0, position, length);
//Delete
IntPtr deletedData = editableStream.Cut(start, length);
同时也可以把一个 VideoStream 流 Paste 到 EditableVideoStream
editableStream.Paste(stream, 0, position, stream.CountFrames);
7、对视频流进行一些参数设置
Avi.AVISTREAMINFO info = editableStream.StreamInfo;
//设置播放速度:每秒 3帧
info.dwRate = 3;
editableStream.SetInfo(info);
2、AviFile后台工作
AviManager 管理Avi文件的stream,构造函数传入文件名,当调用Close函数时,关闭所有打开的流和文件,并保存。
可以使用 AddVideoStream 和 AddAudioStream 把视频里和音频流添加到一个新的AviManager中,音频流只支持wav文件
Create a video stream
VideoStream 有两个构造函数
public VideoStream AddVideoStream(
bool isCompressed, //display the compression dialog, create a compressed stream
int frameRate, //frames per second
int frameSize, //size of one frame in bytes
int width, int height, PixelFormat format //format of the bitmaps
)
{ VideoStream stream = new VideoStream(aviFile, isCompressed, frameRate, frameSize, width, height, format);
streams.Add(stream);
return stream;
} public VideoStream AddVideoStream(
bool isCompressed, //display the compression dialog, create a compressed stream
int frameRate, //frames per second
Bitmap firstFrame //get the format from this image and add it to the new stream
)
{
VideoStream stream = new VideoStream(aviFile, isCompressed, frameRate, firstFrame);
streams.Add(stream);
return stream;
}
VideoStream使用格式化的数据创建新的流,调用 AVIFileCreateStream,如果 isCompressed参数为true,则调用 AVIMakeCompressedStream
public VideoStream(int aviFile, bool writeCompressed, int frameRate, ...)
{
//store format information
//... //create the stream
CreateStream();
} private void CreateStream()
{
//fill stream information
Avi.AVISTREAMINFO strhdr = new Avi.AVISTREAMINFO();
strhdr.fccType = Avi.mmioStringToFOURCC("vids", 0);
strhdr.fccHandler = Avi.mmioStringToFOURCC("CVID", 0);
strhdr.dwScale = 1;
strhdr.dwRate = frameRate;
strhdr.dwSuggestedBufferSize = frameSize;
strhdr.dwQuality = -1; //default
strhdr.rcFrame.bottom = (uint)height;
strhdr.rcFrame.right = (uint)width;
strhdr.szName = new UInt16[64]; //create the stream
int result = Avi.AVIFileCreateStream(aviFile, out aviStream, ref strhdr); if(writeCompressed)
{
//create a compressed stream from
CreateCompressedStream();
}
} private void CreateCompressedStream()
{
Avi.AVICOMPRESSOPTIONS_CLASS options = new Avi.AVICOMPRESSOPTIONS_CLASS();
options.fccType = (uint)Avi.streamtypeVIDEO;
options.lpParms = IntPtr.Zero;
options.lpFormat = IntPtr.Zero; //display the compression options dialog
Avi.AVISaveOptions(IntPtr.Zero, Avi.ICMF_CHOOSE_KEYFRAME | Avi.ICMF_CHOOSE_DATARATE, 1, ref aviStream, ref options); //get a compressed stream
Avi.AVICOMPRESSOPTIONS structOptions = options.ToStruct();
int result = Avi.AVIMakeCompressedStream(out compressedStream, aviStream, ref structOptions, 0); //format the compressed stream
SetFormat(compressedStream);
}
其中使用 AVICOMPRESSOPTIONS_CLASS 类代替
AVICOMPRESSOPTIONS 结构体,使用类代替结构体在使用指针的时候更加容易,如果你看不懂,你可能没在.Net使用过
AVISaveOptions
或 AVISaveV
,下面看看 AVISaveOptions 的声明
BOOL AVISaveOptions(
HWND hwnd,
UINT uiFlags,
int nStreams,
PAVISTREAM * ppavi,
LPAVICOMPRESSOPTIONS * plpOptions);
LPAVICOMPRESSOPTIONS
是一个指向 AVICOMPRESSOPTIONS 结构体指针的指针(指向指针的指针)
在C#中,结构体是值传递的,如果使用ref来传递结构体,则传递的是指向结构体的指针
而类使用的是引用,实际传递的是指针,地址,所以使用ref传递类时,实际传递的是指向类指针的指针(指向指针的指针),
所以这里使用类代替结构体,下面是在C#中声明 AVISaveOptions 和
AVICOMPRESSOPTIONS
[DllImport("avifil32.dll")]
public static extern bool AVISaveOptions(
IntPtr hwnd,
UInt32 uiFlags,
Int32 nStreams,
ref IntPtr ppavi,
ref AVICOMPRESSOPTIONS_CLASS plpOptions
); [StructLayout(LayoutKind.Sequential, Pack=1)]
public struct AVICOMPRESSOPTIONS
{
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery;
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond;
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery;
} [StructLayout(LayoutKind.Sequential, Pack=1)]
public class AVICOMPRESSOPTIONS_CLASS
{
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery;
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond;
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery; public AVICOMPRESSOPTIONS ToStruct()
{
AVICOMPRESSOPTIONS returnVar = new AVICOMPRESSOPTIONS();
returnVar.fccType = this.fccType;
returnVar.fccHandler = this.fccHandler;
returnVar.dwKeyFrameEvery = this.dwKeyFrameEvery;
returnVar.dwQuality = this.dwQuality;
returnVar.dwBytesPerSecond = this.dwBytesPerSecond;
returnVar.dwFlags = this.dwFlags;
returnVar.lpFormat = this.lpFormat;
returnVar.cbFormat = this.cbFormat;
returnVar.lpParms = this.lpParms;
returnVar.cbParms = this.cbParms;
returnVar.dwInterleaveEvery = this.dwInterleaveEvery;
return returnVar;
}
}
在这个工作区,可以调用 AVISaveOptions ,来设置Avi文件的一些参数
通过AddFrame函数可以用图片填充视频流
public void AddFrame(Bitmap bmp)
{
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); if (countFrames == 0)
{
// the format of the first frame defines the format of the stream
CopyPalette(bmp.Palette);
SetFormat(writeCompressed ? compressedStream : aviStream,
countFrames);
} //lock the memory block
BitmapData bmpDat = bmp.LockBits(
new Rectangle(0,0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly, bmp.PixelFormat); //add the bitmap to the (un-)compressed stream
int result = Avi.AVIStreamWrite(
writeCompressed ? compressedStream : aviStream,
countFrames, 1,
bmpDat.Scan0,
(Int32)(bmpDat.Stride * bmpDat.Height),
0, 0, 0); //unlock the memory block
bmp.UnlockBits(bmpDat); //count the frames, so that we don't have to call AVIStreamLength for every new frame
countFrames++;
}
Add frames to an existing stream
public VideoStream(int aviFile, IntPtr aviStream)
{
this.aviFile = aviFile;
this.aviStream = aviStream; //read the stream's format
Avi.BITMAPINFOHEADER bih = new Avi.BITMAPINFOHEADER();
int size = Marshal.SizeOf(bih);
Avi.AVIStreamReadFormat(aviStream, 0, ref bih, ref size);
Avi.AVISTREAMINFO streamInfo = GetStreamInfo(aviStream); //store the important format values
this.frameRate = streamInfo.dwRate / streamInfo.dwScale;
this.width = (int)streamInfo.rcFrame.right;
this.height = (int)streamInfo.rcFrame.bottom;
this.frameSize = bih.biSizeImage;
this.countBitsPerPixel = bih.biBitCount; //get the count of frames that are already there
int firstFrame = Avi.AVIStreamStart(aviStream.ToInt32());
countFrames =
firstFrame + Avi.AVIStreamLength(aviStream.ToInt32());
}
如果视频流是未压缩的,可以直接调用AddFrame,否则,需要对其进行解压缩,并重新压缩到一个新的流
public AviManager DecompressToNewFile(String fileName, bool recompress)
{
//create a new AVI file
AviManager newFile = new AviManager(fileName, false); //create a video stream in the new file
this.GetFrameOpen();
Bitmap frame = GetBitmap(0);
VideoStream newStream = newFile.AddVideoStream(recompress, frameRate, frame); //decompress each frame and add it to the new stream
for(int n=1; n<countFrames; n++)
{
frame = GetBitmap(n);
newStream.AddFrame(frame);
}
this.GetFrameClose();
return newFile;
}
DecompressToNewFile 创建一个可编辑的拷贝到一个新的文件流,可以添加frames到该流
Separate a stream
有时,我们可能只想要视频的声音,或是只要没有声音的视频,我们没有必要重新创建视频,添加每一帧到视频流中,可以通过使用 AviSaveV 把当前流到处到文件,AVISaveV只是所有类型的流,只是压缩参数不一样而已
public override void ExportStream(String fileName)
{
Avi.AVICOMPRESSOPTIONS_CLASS opts = new Avi.AVICOMPRESSOPTIONS_CLASS(); //for video streams
opts.fccType = (UInt32)Avi.mmioStringToFOURCC("vids", 0);
opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("CVID", 0); //for audio streams
//opts.fccType = (UInt32)Avi.mmioStringToFOURCC("auds", 0);
//opts.fccHandler = (UInt32)Avi.mmioStringToFOURCC("CAUD", 0); //export the stream
Avi.AVISaveV(fileName, 0, 0, 1, ref aviStream, ref opts);
}
Import sound from a Wave file
现在,我们可以通过Bitmap来生成视频,也可以从视频中导出声音,那么当我们导入wav文件的时候,底层是如何工作的呢,我们还是可以用 AVISaveV 这个方法,来组合视频和音频成一个文件,但这里我们有更简单的方法,打开音频文件作为Avi文件,然后拷贝到另一个流中
public void AddAudioStream(String waveFileName)
{
//open the wave file
AviManager audioManager = new AviManager(waveFileName, true);
//get the wave sound as an audio stream...
AudioStream newStream = audioManager.GetWaveStream();
//...and add it to the file
AddAudioStream(newStream);
audioManager.Close();
} public void AddAudioStream(AudioStream newStream)
{
Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
int streamLength = 0; //read header info, format and length,
//and get a pointer to the wave data
IntPtr waveData = newStream.GetStreamData(
ref streamInfo,
ref streamFormat,
ref streamLength); //create new stream
IntPtr aviStream;
Avi.AVIFileCreateStream(aviFile, out aviStream, ref streamInfo); //add format new stream
Avi.AVIStreamSetFormat(
aviStream, 0,
ref streamFormat,
Marshal.SizeOf(streamFormat)); //copy the raw wave data into the new stream
Avi.AVIStreamWrite(
aviStream, 0,
streamLength,
waveData,
streamLength,
Avi.AVIIF_KEYFRAME, 0, 0); Avi.AVIStreamRelease(aviStream);
}
截取视频流
public AviManager CopyTo(String newFileName, int startAtSecond, int stopAtSecond)
{
AviManager newFile = new AviManager(newFileName, false);
try
{
//copy video stream
VideoStream videoStream = GetVideoStream(); int startFrameIndex = videoStream.FrameRate * startAtSecond;
int stopFrameIndex = videoStream.FrameRate * stopAtSecond; videoStream.GetFrameOpen();
Bitmap bmp = videoStream.GetBitmap(startFrameIndex); VideoStream newStream = newFile.AddVideoStream(false, videoStream.FrameRate, bmp); for (int n = startFrameIndex + ; n <= stopFrameIndex; n++)
{
bmp = videoStream.GetBitmap(n);
newStream.AddFrame(bmp);
}
videoStream.GetFrameClose(); //copy audio stream
AudioStream waveStream = GetWaveStream(); Avi.AVISTREAMINFO streamInfo = new Avi.AVISTREAMINFO();
Avi.PCMWAVEFORMAT streamFormat = new Avi.PCMWAVEFORMAT();
int streamLength = ;
IntPtr ptrRawData = waveStream.GetStreamData(ref streamInfo, ref streamFormat, ref streamLength); int startByteIndex = waveStream.CountSamplesPerSecond * startAtSecond * waveStream.CountBitsPerSample / ;
int stopByteIndex = waveStream.CountSamplesPerSecond * stopAtSecond * waveStream.CountBitsPerSample / ; ptrRawData = new IntPtr(ptrRawData.ToInt32() + startByteIndex); byte[] rawData = new byte[stopByteIndex - startByteIndex];
Marshal.Copy(ptrRawData, rawData, , rawData.Length); streamInfo.dwLength = rawData.Length;
streamInfo.dwStart = ; IntPtr unmanagedRawData = Marshal.AllocHGlobal(rawData.Length);
Marshal.Copy(rawData, , unmanagedRawData, rawData.Length); newFile.AddAudioStream(unmanagedRawData, streamInfo, streamFormat, rawData.Length);
}
catch (Exception ex)
{
newFile.Close();
throw ex;
}
return newFile;
}
转自:http://blog.csdn.net/jane_sl/article/details/8693395
C# AVI Image 转换的更多相关文章
- 使用ffmpeg 对视频截图,和视频转换格式
//执行CMD命令方法 public static void CmdProcess(string command)//调用CMD { //实例化一个进程类 ...
- ffmpeg转换参数和对几种视频格式的转换分析
我们在将多种格式的视频转换成flv格式的时候,我们关注的就是转换后的flv视频的品质和大小.下面就自己的实践所得来和大家分享一下,主要针对avi.3gp.mp4和wmv四种格式来进行分析.通常在使用f ...
- ffmpeg.exe dos下怎么用 放在哪里
系统:windows 7 1.先看dos界面,win7下这里输入cmd, 看路径 2.把下载的ffmpeg.exe复制到这个路径下 3.这就可以用命令了 1.mp4说明这个文件是跟ffmpeg.ex ...
- 转载:ffmpeg 音视频合成分割
http://blog.csdn.net/jixiuffff/article/details/5709976 当然先安装了 gentoo 下一条命令搞定 emerge ffmpeg 格式转换 (将f ...
- ffmpeg 命令的使用
当然先安装了 gentoo 下一条命令搞定 emerge ffmpeg 格式转换 (将file.avi 转换成output.flv) ffmpeg -i file.avi output.flv ...
- windows下使用ffmpeg进行视频转换和截图。
author:fanfq(xiaoban) Email:fangqing.fan#gmail.comlink:http://fanfq.iteye.com/admin/blogs/655569chan ...
- videoconverter转换
以前录制的avi用vfw可以解码的,但是现在变成win7系统了,无法解码了.只好用视频转换软件把avi转成无压缩的. 选择losses uncompressed avi,点进去选UYVY就行了.
- 视频文件写入转换之图像处理-OpenCV应用学习笔记五
在<笔记二>中我们做了视频播放和控制的实现,仅仅算是完成了对视频文件的读取操作:今天我们来一起练习下对视频文件的写入操作:格式转换. 实现功能: 打开一个视频文件play.avi,读取文件 ...
- IO流(三)__字节流 标准输入输出流 转换流
一.字节流:FileInputStream 和FileOutputStream 基本操作和字符流类相同,没有flush,但是close还是要的 复制一个字节流文件 private static voi ...
随机推荐
- MSF魔鬼训练营-3.5.4Nmap与渗透测试数据库
MSF中可以直接使用db_nmap,它是namp的一个封装与NMAP用法完全一致.其执行结果会自动导入至数据库中. 当然也可以在使用 nmap 的 -oX参数输出一个XML格式的文件.这可以是你在本机 ...
- [Python3] 041 文件 持久化
目录 文件 持久化 1. pickle 1.1 例子1 1.2 例子2 1.3 注意 2. shelve 2.1 举例 2.2 特性 2.3 强制写回 2.4 使用 with 管理上下文环境 文件 持 ...
- HighGo瀚高数据库4.3版本安装说明
1. 通过与瀚高同事沟通, 获取到安装文件(点赞一下瀚高的同事, 效率很高并且说明的很完整) 瀚高是基于postgresql数据库做的深度定制开发的国产数据库. 不仅仅支持x86 也支持龙芯等全国产安 ...
- [转帖]英特尔的 ME 或侵犯 Minix3 的自由软件许可证
英特尔的 ME 或侵犯 Minix3 的自由软件许可证 [日期:2017-12-11] 来源:Linux公社 作者:非非然 [字体:大 中 小] https://www.linuxidc.com/L ...
- C# 实体之间转换
记录一下方便自己下次使用 public class ConvertHelper { public static List<T2> ConvertToList<T1, T2>(L ...
- 记一些使用mpvue时遇到的问题
一.在mpvue中使用vuex(和在vue中使用不同) 1.vue中使用vuex,在main.js中: import store from './store' new Vue({ store }) ...
- LVS、Nginx及HAProxy
本文转载自 linkedkeeper.com 当前大多数的互联网系统都使用了服务器集群技术,集群是将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是 Web 应用服务器集群, ...
- PPT中准确插入公式
Mathtype直接输入到PPT中的公式,漂移且太小.一般的文本公式不美观. 将Mathtype的公式作为文本形式出现,既解决了漂移和大小的问题,也兼顾的美观. 具体操作如下: 1 打开Mathtyp ...
- wordcloud:让你的词语变成黑云
介绍 对文本中出现频率较高的关键词给予视觉化的显示 使用 import jieba import codecs import wordcloud file = r"C:\Users\Admi ...
- wannacry分析--20199319
病毒概况 WannaCry病毒利用前阵子泄漏的方程式工具包中的"永恒之蓝"漏洞工具,进行网络端口扫描攻击,目标机器被成功攻陷后会从攻击机下载WannaCry病毒进行感染,并作为攻击 ...