代码之家  ›  专栏  ›  技术社区  ›  skolima

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

  •  1
  • skolima  · 技术社区  · 16 年前

    我正在使用 .resx 文件夹。运行时,我需要将图像保存到独立文件中,恢复原始内容。如何从 System.Drawing.Bitmap 实例?我知道我可以用 Bitmap.Save() ,但这会对图像进行转码(实际上是膨胀),即使将PNG保存回PNG。

    或者我的错误是从 Resource 作为 Bitmap 首先呢?

    5 回复  |  直到 14 年前
        1
  •  2
  •   skolima    14 年前

    是的,一旦你把它读成 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() .

        2
  •  2
  •   Hans Passant    16 年前

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

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

        4
  •  1
  •   MusiGenesis    16 年前

    如果你没有真正使用 Bitmap 为了在应用程序中显示(即,您只是将资源提取为位图,以便将其保存为文件),最简单的方法是将资源获取为 Stream 并将其保存到文件中。

    本教程演示如何将资源获取为流:

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

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

        5
  •  0
  •   skolima    16 年前

    原来问题出在使用托管资源-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
    }