如何从 C# 项目中的单独图像创建视频文件
How can I create a video file from separate images on a c# project
我想用 c# 中的列表创建一个视频文件,它可以是媒体播放器可以打开的任何格式。
我已经尝试过 Aforge 和 Avi 文件包装器,但不幸的是它们只能在 x86 上工作,而且我有很多依赖项,所以我无法更改项目类型。所以,它必须是 x64。
我所有的位图都在一个列表中(大约 50 个左右)
public 列表 tv_ImageData = 新列表();
我是 c# 的新手,不太了解我的方法。我用谷歌搜索,找不到解决方案。如果有人能指出正确的方向(或图书馆),我将不胜感激。
(我觉得这作为评论会更好,但我还没有这方面的声誉。如果这是不好的做法,我很抱歉!)
由于您使用 AForge 的唯一问题似乎是它是为 x86 编译的,我会提到您可以自己为 x64 目标重新编译它。
https://github.com/andrewkirillov/AForge.NET
快速搜索发现此 link 为包含 64 位版本的 AForge 的重新编译:
https://archive.codeplex.com/?p=aforgeffmpeg
我不知道它是否是最新的,所以我可能建议您自己编译它。
希望对您有所帮助!
在使用 SharpAvi 后,我解决了我的问题。
我有一个名为
的列表
List<ushort[]> tv_data = new List<ushort> tv_data();
其中包含作为原始数据的帧(值在 0-255 范围内)。
我尝试使用文档提供的示例,但它给了我一个好的 avi(我猜是因为 SharpAvi 需要 DIB 位图)。所以我对它做了一些修改,并从这里借鉴了一些 (How to create bitmap from byte array?) top 得到一个可行的解决方案。
这是我的函数:
using SharpAvi;
using SharpAvi.Output;
这可能不是最好的方法,但它确实有效。希望有人会发现它有用。
private void SaveAsVideo(object sender, RoutedEventArgs e)
{
if (loadedFileName != "")
{
try
{
var writer = new AviWriter(string.Format("{0}.avi", fullPath))
{
FramesPerSecond = (decimal)VI.FrameRate,
EmitIndex1 = true
};
var stream = writer.AddVideoStream();
stream.Width = (int)VI.VideoWidth;
stream.Height = (int)VI.VideoHeight;
stream.Codec = KnownFourCCs.Codecs.Uncompressed;
stream.BitsPerPixel = BitsPerPixel.Bpp8;
var frameData = new byte[stream.Width * stream.Height];
int frameNo = 0;
foreach (ushort[] data in tv_Data)
{
byte[] byteData = tv_Data.ElementAt(frameNo);
byte[] newbytes = PadLines(byteData, stream.Height, stream.Width);
stream.WriteFrame(true, newbytes, 0, frameData.Length);
frameNo++;
}
writer.Close();
MessageBox.Show("Video file saved.");
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Failed to save video. \n {0}", ex.Message));
}
}
}
static byte[] PadLines(byte[] bytes, int rows, int columns)
{
int currentStride = columns;
int newStride = columns;
byte[] newBytes = new byte[newStride * rows];
byte[] tempBytes = new byte[newStride];
for (int i = 0; i < rows; i++)
{
Buffer.BlockCopy(bytes, currentStride * i, tempBytes, 0, currentStride);
Array.Reverse(tempBytes);
Buffer.BlockCopy(tempBytes, 0, newBytes, newStride * i, currentStride);
}
Array.Reverse(newBytes);
return newBytes;
}
我想用 c# 中的列表创建一个视频文件,它可以是媒体播放器可以打开的任何格式。
我已经尝试过 Aforge 和 Avi 文件包装器,但不幸的是它们只能在 x86 上工作,而且我有很多依赖项,所以我无法更改项目类型。所以,它必须是 x64。
我所有的位图都在一个列表中(大约 50 个左右) public 列表 tv_ImageData = 新列表();
我是 c# 的新手,不太了解我的方法。我用谷歌搜索,找不到解决方案。如果有人能指出正确的方向(或图书馆),我将不胜感激。
(我觉得这作为评论会更好,但我还没有这方面的声誉。如果这是不好的做法,我很抱歉!)
由于您使用 AForge 的唯一问题似乎是它是为 x86 编译的,我会提到您可以自己为 x64 目标重新编译它。
https://github.com/andrewkirillov/AForge.NET
快速搜索发现此 link 为包含 64 位版本的 AForge 的重新编译:
https://archive.codeplex.com/?p=aforgeffmpeg
我不知道它是否是最新的,所以我可能建议您自己编译它。
希望对您有所帮助!
在使用 SharpAvi 后,我解决了我的问题。 我有一个名为
的列表List<ushort[]> tv_data = new List<ushort> tv_data();
其中包含作为原始数据的帧(值在 0-255 范围内)。 我尝试使用文档提供的示例,但它给了我一个好的 avi(我猜是因为 SharpAvi 需要 DIB 位图)。所以我对它做了一些修改,并从这里借鉴了一些 (How to create bitmap from byte array?) top 得到一个可行的解决方案。
这是我的函数:
using SharpAvi;
using SharpAvi.Output;
这可能不是最好的方法,但它确实有效。希望有人会发现它有用。
private void SaveAsVideo(object sender, RoutedEventArgs e)
{
if (loadedFileName != "")
{
try
{
var writer = new AviWriter(string.Format("{0}.avi", fullPath))
{
FramesPerSecond = (decimal)VI.FrameRate,
EmitIndex1 = true
};
var stream = writer.AddVideoStream();
stream.Width = (int)VI.VideoWidth;
stream.Height = (int)VI.VideoHeight;
stream.Codec = KnownFourCCs.Codecs.Uncompressed;
stream.BitsPerPixel = BitsPerPixel.Bpp8;
var frameData = new byte[stream.Width * stream.Height];
int frameNo = 0;
foreach (ushort[] data in tv_Data)
{
byte[] byteData = tv_Data.ElementAt(frameNo);
byte[] newbytes = PadLines(byteData, stream.Height, stream.Width);
stream.WriteFrame(true, newbytes, 0, frameData.Length);
frameNo++;
}
writer.Close();
MessageBox.Show("Video file saved.");
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Failed to save video. \n {0}", ex.Message));
}
}
}
static byte[] PadLines(byte[] bytes, int rows, int columns)
{
int currentStride = columns;
int newStride = columns;
byte[] newBytes = new byte[newStride * rows];
byte[] tempBytes = new byte[newStride];
for (int i = 0; i < rows; i++)
{
Buffer.BlockCopy(bytes, currentStride * i, tempBytes, 0, currentStride);
Array.Reverse(tempBytes);
Buffer.BlockCopy(tempBytes, 0, newBytes, newStride * i, currentStride);
}
Array.Reverse(newBytes);
return newBytes;
}