Как извлечь исходный поток изображений из объекта System.Drawing.Bitmap? - PullRequest
1 голос
/ 28 апреля 2010

Я встраиваю изображения в свою сборку, используя .resx файлы. После выполнения мне нужно сохранить изображения в автономные файлы, восстановив исходный контент. Как извлечь исходный поток файлов из экземпляра System.Drawing.Bitmap? Я знаю, что могу создать поток, используя Bitmap.Save(), но это перекодирует (и фактически - раздувает) изображения даже при сохранении PNG обратно в формате PNG.

Или, возможно, моя ошибка - читать их из Resource как Bitmap в первую очередь?

Ответы [ 5 ]

2 голосов
/ 28 апреля 2010

У меня нет проблем.PNG - это формат без потерь, вы получите то же самое изображение обратно.Да, вы не обязательно получите точно такие же байты при сохранении ().Это сжатый формат, и количество времени, затрачиваемое компрессором на получение наилучшего баланса между сжатием и скоростью, может не совпадать.Но что с того?

Если это реальная проблема, вам не следует добавлять изображение в качестве управляемого ресурса.Вы можете добавить его в свой проект как встроенный ресурс и прочитать его из метаданных с помощью Assembly.GetManifestResourceStream ().Вы получите необработанные байты файла изображения.Конвертируем в изображение с помощью Image.FromStream ().

2 голосов
/ 28 апреля 2010

Да, если вы прочитали его как объект 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 из него, используя Image.FromStream().

1 голос
/ 28 апреля 2010

Если вы на самом деле не используете Bitmap для отображения в вашем приложении (т.е. вы просто извлекаете ресурс в виде растрового изображения, чтобы сохранить его в виде файла), тогда самый простой подход - просто получить ресурс как Stream и сохраните его в файл.

В этом руководстве показано, как получить ресурсы в виде потоков:

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

В примере автор получает поток и передает его методу Bitmap.FromStream. Вместо этого вы просто сохраните этот поток непосредственно в файл (полностью минуя Bitmap).

0 голосов
/ 29 апреля 2010

Оказывается, проблема заключалась в использовании управляемых ресурсов - 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
}
...