1

我正在使用.resx文件将图像嵌入到我的程序集中。在运行时,我需要将图像保存到独立文件中,恢复原始内容。如何从System.Drawing.Bitmap实例中提取原始文件流?我知道我可以使用创建流Bitmap.Save(),但这会转码(实际上是膨胀)图像,即使将 PNG 保存为 PNG。

或者也许我的错误是从一开始就阅读Resource它们Bitmap

4

5 回答 5

2

是的,一旦您将其作为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().

于 2010-04-28T15:28:57.130 回答
2

我不明白这个问题。PNG 是一种无损格式,您将获得完全相同的图像。是的,当您保存()时,您不一定会获得完全相同的字节。它是一种压缩格式,压缩器在压缩和速度之间获得最佳平衡所花费的时间可能不同。但是,那又怎样?

如果这是一个真正的问题,那么您不应该将图像添加为托管资源。您可以将其作为嵌入式资源添加到您的项目中,并使用 Assembly.GetManifestResourceStream() 从元数据中读取它。您将获得原始图像文件字节。可使用 Image.FromStream() 转换为图像。

于 2010-04-28T16:48:30.467 回答
1

如何:使用 Visual C# 从资源中加载位图或图像

于 2010-04-28T15:20:37.630 回答
1

如果您实际上并未在应用程序中使用Bitmap用于显示目的(即,您只是将资源提取为位图,以便将其保存为文件),那么最简单的方法是将资源作为 aStream并保存它到一个文件。

本教程展示了如何以流的形式获取资源:

http://devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=75

在示例中,作者获取了一个流并将其传递给Bitmap.FromStream方法。您要做的只是将该流直接保存到文件中(Bitmap完全绕过)。

于 2010-04-28T15:28:01.960 回答
0

事实证明,问题在于使用托管资源 - 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
}
于 2010-04-29T07:26:34.703 回答