如何从 System.Drawing.Bitmap 对象中提取原始图像流?

发布于 2024-08-31 00:08:52 字数 243 浏览 9 评论 0原文

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

或者也许我的错误是首先从 Resource 中将它们读取为 Bitmap

I am embedding images into my assembly using .resx files. Upon runtime, I need to save the images into standalone files, restoring the original content. How can I extract the original file stream from an System.Drawing.Bitmap instance? I know I can create a stream using Bitmap.Save(), but this transcodes (and in effect - inflates) the images, even when saving a PNG back as PNG.

Or perhaps my mistake is reading them from Resource as Bitmap in the first place?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

云裳 2024-09-07 00:08:52

是的,一旦您将其作为 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.FromStream() 从它创建一个 Image

Yes, once you have read it as a Bitmap object, you can't get the original file stream back. The Bitmap object only contains the uncompressed data, not the original data.

You should read the resource as byte data intead. You can read from the resource stream and write to a file:

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);
    }
  }
}

Note: this requires adding the image as an embedded resource, not a managed resource. You can create an Image from it using Image.FromStream().

岁月无声 2024-09-07 00:08:52

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

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

I don't get the problem. PNG is a loss-less format, you'll get the exact same image back. Yes, you don't necessarily get the exact same bytes when you Save(). It is a compressed format and the amount of time spent by the compressor on getting the best balance between compression and speed might not be the same. But, so what?

If it is a real problem then you shouldn't add the image as a managed resource. You can add it to your project as an embedded resource and read it from the metadata with Assembly.GetManifestResourceStream(). You'll get the raw image file bytes. Convertible to an Image with Image.FromStream().

荒人说梦 2024-09-07 00:08:52

如果您实际上并未将位图用于应用程序中的显示目的(即您只是将资源提取为位图,以便将其保存为文件),那么最简单的方法是只需以 Stream 形式获取资源并将其保存到文件中即可。

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

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

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

If you're not actually using the Bitmap for display purposes in your appliction (i.e. you're just extracting the resource as a bitmap so you can save it as a file), then the simplest approach is to just get the resource as a Stream and save it to a file.

This tutorial shows how to get resources as streams:

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

In the sample, the author gets a stream and passes it to the Bitmap.FromStream method. What you would do instead is just save that stream directly to a file (bypassing Bitmap entirely).

感受沵的脚步 2024-09-07 00:08:52

事实证明,问题在于使用托管资源 - resx 生成器从图像文件创建 Bitmap 对象并序列化这些对象,它不存储原始文件流。但是,嵌入式资源可以存储平面二进制文件。

我现在使用以下 .csproj 条目嵌入图像文件夹中的所有文件:

<EmbeddedResource Include="Images\*.jpg" />
<EmbeddedResource Include="Images\*.png" />
<EmbeddedResource Include="Images\*.gif" />

Visual Studio 将它们显示为正常的项目内文件,并将 Build Action 设置为 Embedded资源

然后,从我的代码中,我使用以下命令加载原始文件流:

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
}

It turns out the problem was in using managed resources - resx builder creates Bitmap objects from image files and serializes those objects, it does not store the original file stream. However, embedded resources can store flat binary files.

I am now embedding all files from my images folder using the following .csproj entries:

<EmbeddedResource Include="Images\*.jpg" />
<EmbeddedResource Include="Images\*.png" />
<EmbeddedResource Include="Images\*.gif" />

Visual Studio shows them as normal in-project files with Build Action set to Embedded Resource.

Then, from my code, I load the original file streams with:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文