我正在使用.resx
文件将图像嵌入到我的程序集中。在运行时,我需要将图像保存到独立文件中,恢复原始内容。如何从System.Drawing.Bitmap
实例中提取原始文件流?我知道我可以使用创建流Bitmap.Save()
,但这会转码(实际上是膨胀)图像,即使将 PNG 保存为 PNG。
或者也许我的错误是从一开始就阅读Resource
它们Bitmap
?
我正在使用.resx
文件将图像嵌入到我的程序集中。在运行时,我需要将图像保存到独立文件中,恢复原始内容。如何从System.Drawing.Bitmap
实例中提取原始文件流?我知道我可以使用创建流Bitmap.Save()
,但这会转码(实际上是膨胀)图像,即使将 PNG 保存为 PNG。
或者也许我的错误是从一开始就阅读Resource
它们Bitmap
?
是的,一旦您将其作为Bitmap
对象读取,就无法取回原始文件流。该Bitmap
对象只包含未压缩的数据,不包含原始数据。
您应该将资源作为字节数据读取。您可以从资源流中读取并写入文件:
using (Stream source = this.GetType().Assembly.GetManifestResourceStream("WindowsApplication1.filename.jpg")) {
using (FileStream dest = File.Create(fileName)) {
byte[] buffer = new byte[4096];
while (true) {
int len = source.Read(buffer, 0, buffer.Length);
if (len == 0) break;
dest.Write(buffer, 0, len);
}
}
}
注意:这需要将图像添加为嵌入式资源,而不是托管资源。您可以Image
使用Image.FromStream()
.
我不明白这个问题。PNG 是一种无损格式,您将获得完全相同的图像。是的,当您保存()时,您不一定会获得完全相同的字节。它是一种压缩格式,压缩器在压缩和速度之间获得最佳平衡所花费的时间可能不同。但是,那又怎样?
如果这是一个真正的问题,那么您不应该将图像添加为托管资源。您可以将其作为嵌入式资源添加到您的项目中,并使用 Assembly.GetManifestResourceStream() 从元数据中读取它。您将获得原始图像文件字节。可使用 Image.FromStream() 转换为图像。
如果您实际上并未在应用程序中使用Bitmap
用于显示目的(即,您只是将资源提取为位图,以便将其保存为文件),那么最简单的方法是将资源作为 aStream
并保存它到一个文件。
本教程展示了如何以流的形式获取资源:
http://devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=75
在示例中,作者获取了一个流并将其传递给Bitmap.FromStream
方法。您要做的只是将该流直接保存到文件中(Bitmap
完全绕过)。
事实证明,问题在于使用托管资源 - resx builder 从图像文件创建位图对象并序列化这些对象,它不存储原始文件流。但是,嵌入式资源可以存储平面二进制文件。
我现在使用以下.csproj
条目嵌入我的图像文件夹中的所有文件:
<EmbeddedResource Include="Images\*.jpg" />
<EmbeddedResource Include="Images\*.png" />
<EmbeddedResource Include="Images\*.gif" />
Visual Studio 将它们显示为Build Action
设置为Embedded Resource
.
然后,从我的代码中,我加载原始文件流:
var assembly = GetType().Assembly;
var regex = new Regex("\\.(png|jpg|gif))$");
foreach (var bitmap in assembly.GetManifestResourceNames())
{
if(!regex.IsMatch(bitmap)
continue;
var stream = assembly.GetManifestResourceStream(bitmap);
//handle the stream here
}