我使用.resx
文件将图像嵌入到我的程序集中。在运行时,我需要将图像保存到独立文件中,恢复原始内容。如何从System.Drawing.Bitmap
实例中提取原始文件流?我知道我可以使用Bitmap.Save()
创建一个流,但这会对图像进行转码(实际上是膨胀),即使将PNG保存为PNG也是如此。
或许我的错误是首先从Resource
读取Bitmap
?
答案 0 :(得分:2)
是的,一旦您将其作为Bitmap
对象读取,就无法恢复原始文件流。 Bitmap
对象仅包含未压缩的数据,而不包含原始数据。
您应该将资源读取为字节数据intead。您可以从资源流中读取并写入文件:
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
从<{1}}创建Image.FromStream()
。
答案 1 :(得分:2)
我没有遇到问题。 PNG是一种无损格式,您将获得完全相同的图像。是的,当你保存()时,你不一定得到完全相同的字节。它是一种压缩格式,压缩器在压缩和速度之间达到最佳平衡所花费的时间可能不一样。但是,那又怎么样?
如果这是一个真正的问题,那么您不应该将图像添加为托管资源。您可以将其作为嵌入式资源添加到项目中,并使用Assembly.GetManifestResourceStream()从元数据中读取它。您将获得原始图像文件字节。使用Image.FromStream()转换为图像。
答案 2 :(得分:1)
答案 3 :(得分:1)
如果您实际上没有在应用程序中使用Bitmap
进行显示(即您只是将资源提取为位图,以便将其保存为文件),那么最简单的方法是只需将资源作为Stream
并将其保存到文件中。
本教程介绍如何将资源作为流获取:
http://devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=75
在示例中,作者获取一个流并将其传递给Bitmap.FromStream
方法。您要做的只是将该流直接保存到文件中(完全绕过Bitmap
)。
答案 4 :(得分:0)
事实证明问题在于使用托管资源--resx builder从图像文件创建 Bitmap 对象并序列化这些对象,不存储原始文件流。但是,嵌入式资源可以存储平面二进制文件。
我现在使用以下.csproj
条目嵌入我的images文件夹中的所有文件:
<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
}